mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-02 22:45:35 +00:00
Merge branch 'next' of https://github.com/zinnschlag/openmw.git into AI
This commit is contained in:
commit
61e0d6b364
347 changed files with 9998 additions and 7559 deletions
|
@ -29,6 +29,7 @@ option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binarie
|
||||||
option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE)
|
option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE)
|
||||||
|
|
||||||
# Apps and tools
|
# Apps and tools
|
||||||
|
option(BUILD_BSATOOL "build BSA extractor" OFF)
|
||||||
option(BUILD_ESMTOOL "build ESM inspector" ON)
|
option(BUILD_ESMTOOL "build ESM inspector" ON)
|
||||||
option(BUILD_LAUNCHER "build Launcher" ON)
|
option(BUILD_LAUNCHER "build Launcher" ON)
|
||||||
option(BUILD_MWINIIMPORTER "build MWiniImporter" ON)
|
option(BUILD_MWINIIMPORTER "build MWiniImporter" ON)
|
||||||
|
@ -74,7 +75,6 @@ set(LIBDIR ${CMAKE_SOURCE_DIR}/libs)
|
||||||
set(OENGINE_OGRE
|
set(OENGINE_OGRE
|
||||||
${LIBDIR}/openengine/ogre/renderer.cpp
|
${LIBDIR}/openengine/ogre/renderer.cpp
|
||||||
${LIBDIR}/openengine/ogre/fader.cpp
|
${LIBDIR}/openengine/ogre/fader.cpp
|
||||||
${LIBDIR}/openengine/ogre/imagerotate.cpp
|
|
||||||
${LIBDIR}/openengine/ogre/selectionbuffer.cpp
|
${LIBDIR}/openengine/ogre/selectionbuffer.cpp
|
||||||
)
|
)
|
||||||
set(OENGINE_GUI
|
set(OENGINE_GUI
|
||||||
|
@ -183,7 +183,7 @@ endif()
|
||||||
# find boost without components so we can use Boost_VERSION
|
# find boost without components so we can use Boost_VERSION
|
||||||
find_package(Boost REQUIRED)
|
find_package(Boost REQUIRED)
|
||||||
|
|
||||||
set(BOOST_COMPONENTS system filesystem program_options thread)
|
set(BOOST_COMPONENTS system filesystem program_options thread date_time)
|
||||||
|
|
||||||
if (Boost_VERSION LESS 104900)
|
if (Boost_VERSION LESS 104900)
|
||||||
set(SHINY_USE_WAVE_SYSTEM_INSTALL "TRUE")
|
set(SHINY_USE_WAVE_SYSTEM_INSTALL "TRUE")
|
||||||
|
@ -300,6 +300,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||||
if (NOT WIN32 AND NOT APPLE)
|
if (NOT WIN32 AND NOT APPLE)
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
||||||
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
||||||
|
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.desktop
|
||||||
|
"${OpenMW_BINARY_DIR}/opencs.desktop")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compiler settings
|
# Compiler settings
|
||||||
|
@ -353,7 +355,7 @@ if(DPKG_PROGRAM)
|
||||||
Data files from the original game is required to run it.")
|
Data files from the original game is required to run it.")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_NAME "openmw")
|
SET(CPACK_DEBIAN_PACKAGE_NAME "openmw")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
|
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
|
||||||
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter")
|
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW bsatool;Bsatool esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
|
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
|
||||||
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
|
SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
|
||||||
|
@ -380,7 +382,6 @@ if(WIN32)
|
||||||
"${OpenMW_SOURCE_DIR}/OFL.txt"
|
"${OpenMW_SOURCE_DIR}/OFL.txt"
|
||||||
"${OpenMW_SOURCE_DIR}/DejaVu Font License.txt"
|
"${OpenMW_SOURCE_DIR}/DejaVu Font License.txt"
|
||||||
"${OpenMW_SOURCE_DIR}/Daedric Font License.txt"
|
"${OpenMW_SOURCE_DIR}/Daedric Font License.txt"
|
||||||
"${OpenMW_BINARY_DIR}/launcher.qss"
|
|
||||||
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
||||||
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
|
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
|
||||||
"${OpenMW_BINARY_DIR}/Release/omwlauncher.exe"
|
"${OpenMW_BINARY_DIR}/Release/omwlauncher.exe"
|
||||||
|
@ -448,6 +449,10 @@ add_subdirectory (components)
|
||||||
# Apps and tools
|
# Apps and tools
|
||||||
add_subdirectory( apps/openmw )
|
add_subdirectory( apps/openmw )
|
||||||
|
|
||||||
|
if (BUILD_BSATOOL)
|
||||||
|
add_subdirectory( apps/bsatool )
|
||||||
|
endif()
|
||||||
|
|
||||||
if (BUILD_ESMTOOL)
|
if (BUILD_ESMTOOL)
|
||||||
add_subdirectory( apps/esmtool )
|
add_subdirectory( apps/esmtool )
|
||||||
endif()
|
endif()
|
||||||
|
@ -534,6 +539,9 @@ if (WIN32)
|
||||||
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
endif (BUILD_LAUNCHER)
|
endif (BUILD_LAUNCHER)
|
||||||
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
|
if (BUILD_BSATOOL)
|
||||||
|
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
|
endif (BUILD_BSATOOL)
|
||||||
if (BUILD_ESMTOOL)
|
if (BUILD_ESMTOOL)
|
||||||
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
endif (BUILD_ESMTOOL)
|
endif (BUILD_ESMTOOL)
|
||||||
|
@ -567,8 +575,6 @@ if (APPLE)
|
||||||
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
|
||||||
|
|
||||||
install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
|
@ -660,6 +666,9 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
|
||||||
IF(BUILD_LAUNCHER)
|
IF(BUILD_LAUNCHER)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_LAUNCHER)
|
ENDIF(BUILD_LAUNCHER)
|
||||||
|
IF(BUILD_BSATOOL)
|
||||||
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
|
||||||
|
ENDIF(BUILD_BSATOOL)
|
||||||
IF(BUILD_ESMTOOL)
|
IF(BUILD_ESMTOOL)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_ESMTOOL)
|
ENDIF(BUILD_ESMTOOL)
|
||||||
|
@ -682,7 +691,4 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
|
||||||
|
|
||||||
# Install resources
|
# Install resources
|
||||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" )
|
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" )
|
||||||
IF(BUILD_LAUNCHER)
|
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${DATADIR}/resources" )
|
|
||||||
ENDIF(BUILD_LAUNCHER)
|
|
||||||
endif(NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
|
endif(NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
|
||||||
|
|
19
apps/bsatool/CMakeLists.txt
Normal file
19
apps/bsatool/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
set(BSATOOL
|
||||||
|
bsatool.cpp
|
||||||
|
)
|
||||||
|
source_group(apps\\bsatool FILES ${BSATOOL})
|
||||||
|
|
||||||
|
# Main executable
|
||||||
|
add_executable(bsatool
|
||||||
|
${BSATOOL}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(bsatool
|
||||||
|
${Boost_LIBRARIES}
|
||||||
|
components
|
||||||
|
)
|
||||||
|
|
||||||
|
if (BUILD_WITH_CODE_COVERAGE)
|
||||||
|
add_definitions (--coverage)
|
||||||
|
target_link_libraries(bsatool gcov)
|
||||||
|
endif()
|
288
apps/bsatool/bsatool.cpp
Normal file
288
apps/bsatool/bsatool.cpp
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
#include <components/bsa/bsa_file.hpp>
|
||||||
|
|
||||||
|
#define BSATOOL_VERSION 1.1
|
||||||
|
|
||||||
|
// Create local aliases for brevity
|
||||||
|
namespace bpo = boost::program_options;
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
|
struct Arguments
|
||||||
|
{
|
||||||
|
std::string mode;
|
||||||
|
std::string filename;
|
||||||
|
std::string extractfile;
|
||||||
|
std::string outdir;
|
||||||
|
|
||||||
|
bool longformat;
|
||||||
|
bool fullpath;
|
||||||
|
};
|
||||||
|
|
||||||
|
void replaceAll(std::string& str, const std::string& needle, const std::string& substitute)
|
||||||
|
{
|
||||||
|
int pos = str.find(needle);
|
||||||
|
while(pos != -1)
|
||||||
|
{
|
||||||
|
str.replace(pos, needle.size(), substitute);
|
||||||
|
pos = str.find(needle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseOptions (int argc, char** argv, Arguments &info)
|
||||||
|
{
|
||||||
|
bpo::options_description desc("Inspect and extract files from Bethesda BSA archives\n\n"
|
||||||
|
"Usages:\n"
|
||||||
|
" bsatool list [-l] archivefile\n"
|
||||||
|
" List the files presents in the input archive.\n\n"
|
||||||
|
" bsatool extract [-f] archivefile [file_to_extract] [output_directory]\n"
|
||||||
|
" Extract a file from the input archive.\n\n"
|
||||||
|
" bsatool extractall archivefile [output_directory]\n"
|
||||||
|
" Extract all files from the input archive.\n\n"
|
||||||
|
"Allowed options");
|
||||||
|
|
||||||
|
desc.add_options()
|
||||||
|
("help,h", "print help message.")
|
||||||
|
("version,v", "print version information and quit.")
|
||||||
|
("long,l", "Include extra information in archive listing.")
|
||||||
|
("full-path,f", "Create diretory hierarchy on file extraction "
|
||||||
|
"(always true for extractall).")
|
||||||
|
;
|
||||||
|
|
||||||
|
// input-file is hidden and used as a positional argument
|
||||||
|
bpo::options_description hidden("Hidden Options");
|
||||||
|
|
||||||
|
hidden.add_options()
|
||||||
|
( "mode,m", bpo::value<std::string>(), "bsatool mode")
|
||||||
|
( "input-file,i", bpo::value< std::vector<std::string> >(), "input file")
|
||||||
|
;
|
||||||
|
|
||||||
|
bpo::positional_options_description p;
|
||||||
|
p.add("mode", 1).add("input-file", 3);
|
||||||
|
|
||||||
|
// there might be a better way to do this
|
||||||
|
bpo::options_description all;
|
||||||
|
all.add(desc).add(hidden);
|
||||||
|
|
||||||
|
bpo::variables_map variables;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
|
||||||
|
.options(all).positional(p).run();
|
||||||
|
bpo::store(valid_opts, variables);
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n"
|
||||||
|
<< desc << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpo::notify(variables);
|
||||||
|
|
||||||
|
if (variables.count ("help"))
|
||||||
|
{
|
||||||
|
std::cout << desc << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (variables.count ("version"))
|
||||||
|
{
|
||||||
|
std::cout << "BSATool version " << BSATOOL_VERSION << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!variables.count("mode"))
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: no mode specified!\n\n"
|
||||||
|
<< desc << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.mode = variables["mode"].as<std::string>();
|
||||||
|
if (!(info.mode == "list" || info.mode == "extract" || info.mode == "extractall"))
|
||||||
|
{
|
||||||
|
std::cout << std::endl << "ERROR: invalid mode \"" << info.mode << "\"\n\n"
|
||||||
|
<< desc << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!variables.count("input-file"))
|
||||||
|
{
|
||||||
|
std::cout << "\nERROR: missing BSA archive\n\n"
|
||||||
|
<< desc << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
info.filename = variables["input-file"].as< std::vector<std::string> >()[0];
|
||||||
|
|
||||||
|
// Default output to the working directory
|
||||||
|
info.outdir = ".";
|
||||||
|
|
||||||
|
if (info.mode == "extract")
|
||||||
|
{
|
||||||
|
if (variables["input-file"].as< std::vector<std::string> >().size() < 2)
|
||||||
|
{
|
||||||
|
std::cout << "\nERROR: file to extract unspecified\n\n"
|
||||||
|
<< desc << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (variables["input-file"].as< std::vector<std::string> >().size() > 1)
|
||||||
|
info.extractfile = variables["input-file"].as< std::vector<std::string> >()[1];
|
||||||
|
if (variables["input-file"].as< std::vector<std::string> >().size() > 2)
|
||||||
|
info.outdir = variables["input-file"].as< std::vector<std::string> >()[2];
|
||||||
|
}
|
||||||
|
else if (variables["input-file"].as< std::vector<std::string> >().size() > 1)
|
||||||
|
info.outdir = variables["input-file"].as< std::vector<std::string> >()[1];
|
||||||
|
|
||||||
|
info.longformat = variables.count("long");
|
||||||
|
info.fullpath = variables.count("full-path");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list(Bsa::BSAFile& bsa, Arguments& info);
|
||||||
|
int extract(Bsa::BSAFile& bsa, Arguments& info);
|
||||||
|
int extractAll(Bsa::BSAFile& bsa, Arguments& info);
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
Arguments info;
|
||||||
|
if(!parseOptions (argc, argv, info))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
Bsa::BSAFile bsa;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bsa.open(info.filename);
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR reading BSA archive '" << info.filename
|
||||||
|
<< "'\nDetails:\n" << e.what() << std::endl;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.mode == "list")
|
||||||
|
return list(bsa, info);
|
||||||
|
else if (info.mode == "extract")
|
||||||
|
return extract(bsa, info);
|
||||||
|
else if (info.mode == "extractall")
|
||||||
|
return extractAll(bsa, info);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Unsupported mode. That is not supposed to happen." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int list(Bsa::BSAFile& bsa, Arguments& info)
|
||||||
|
{
|
||||||
|
// List all files
|
||||||
|
const Bsa::BSAFile::FileList &files = bsa.getList();
|
||||||
|
for(int i=0; i<files.size(); i++)
|
||||||
|
{
|
||||||
|
if(info.longformat)
|
||||||
|
{
|
||||||
|
// Long format
|
||||||
|
std::cout << std::setw(50) << std::left << files[i].name;
|
||||||
|
std::cout << std::setw(8) << std::left << std::dec << files[i].fileSize;
|
||||||
|
std::cout << "@ 0x" << std::hex << files[i].offset << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cout << files[i].name << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int extract(Bsa::BSAFile& bsa, Arguments& info)
|
||||||
|
{
|
||||||
|
std::string archivePath = info.extractfile;
|
||||||
|
replaceAll(archivePath, "/", "\\");
|
||||||
|
|
||||||
|
std::string extractPath = info.extractfile;
|
||||||
|
replaceAll(extractPath, "\\", "/");
|
||||||
|
|
||||||
|
if (!bsa.exists(archivePath.c_str()))
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: file '" << archivePath << "' not found\n";
|
||||||
|
std::cout << "In archive: " << info.filename << std::endl;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the target path (the path the file will be extracted to)
|
||||||
|
bfs::path relPath (extractPath);
|
||||||
|
bfs::path outdir (info.outdir);
|
||||||
|
|
||||||
|
bfs::path target;
|
||||||
|
if (info.fullpath)
|
||||||
|
target = outdir / relPath;
|
||||||
|
else
|
||||||
|
target = outdir / relPath.filename();
|
||||||
|
|
||||||
|
// Create the directory hierarchy
|
||||||
|
bfs::create_directories(target.parent_path());
|
||||||
|
|
||||||
|
bfs::file_status s = bfs::status(target.parent_path());
|
||||||
|
if (!bfs::is_directory(s))
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: " << target.parent_path() << " is not a directory." << std::endl;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a stream for the file to extract
|
||||||
|
Ogre::DataStreamPtr data = bsa.getFile(archivePath.c_str());
|
||||||
|
bfs::ofstream out(target, std::ios::binary);
|
||||||
|
|
||||||
|
// Write the file to disk
|
||||||
|
std::cout << "Extracting " << info.extractfile << " to " << target << std::endl;
|
||||||
|
out.write(data->getAsString().c_str(), data->size());
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int extractAll(Bsa::BSAFile& bsa, Arguments& info)
|
||||||
|
{
|
||||||
|
// Get the list of files present in the archive
|
||||||
|
Bsa::BSAFile::FileList list = bsa.getList();
|
||||||
|
|
||||||
|
// Iter on the list
|
||||||
|
for(Bsa::BSAFile::FileList::iterator it = list.begin(); it != list.end(); ++it) {
|
||||||
|
const char* archivePath = it->name;
|
||||||
|
|
||||||
|
std::string extractPath (archivePath);
|
||||||
|
replaceAll(extractPath, "\\", "/");
|
||||||
|
|
||||||
|
// Get the target path (the path the file will be extracted to)
|
||||||
|
bfs::path target (info.outdir);
|
||||||
|
target /= extractPath;
|
||||||
|
|
||||||
|
// Create the directory hierarchy
|
||||||
|
bfs::create_directories(target.parent_path());
|
||||||
|
|
||||||
|
bfs::file_status s = bfs::status(target.parent_path());
|
||||||
|
if (!bfs::is_directory(s))
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: " << target.parent_path() << " is not a directory." << std::endl;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a stream for the file to extract
|
||||||
|
// (inefficient because getFile iter on the list again)
|
||||||
|
Ogre::DataStreamPtr data = bsa.getFile(archivePath);
|
||||||
|
bfs::ofstream out(target, std::ios::binary);
|
||||||
|
|
||||||
|
// Write the file to disk
|
||||||
|
std::cout << "Extracting " << target << std::endl;
|
||||||
|
out.write(data->getAsString().c_str(), data->size());
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -23,8 +23,7 @@ struct ESMData
|
||||||
std::string author;
|
std::string author;
|
||||||
std::string description;
|
std::string description;
|
||||||
int version;
|
int version;
|
||||||
int type;
|
std::vector<ESM::Header::MasterData> masters;
|
||||||
ESM::ESMReader::MasterList masters;
|
|
||||||
|
|
||||||
std::deque<EsmTool::RecordBase *> mRecords;
|
std::deque<EsmTool::RecordBase *> mRecords;
|
||||||
std::map<ESM::Cell *, std::deque<ESM::CellRef> > mCellRefs;
|
std::map<ESM::Cell *, std::deque<ESM::CellRef> > mCellRefs;
|
||||||
|
@ -284,16 +283,13 @@ int load(Arguments& info)
|
||||||
info.data.author = esm.getAuthor();
|
info.data.author = esm.getAuthor();
|
||||||
info.data.description = esm.getDesc();
|
info.data.description = esm.getDesc();
|
||||||
info.data.masters = esm.getMasters();
|
info.data.masters = esm.getMasters();
|
||||||
info.data.version = esm.getVer();
|
|
||||||
info.data.type = esm.getType();
|
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
{
|
{
|
||||||
std::cout << "Author: " << esm.getAuthor() << std::endl
|
std::cout << "Author: " << esm.getAuthor() << std::endl
|
||||||
<< "Description: " << esm.getDesc() << std::endl
|
<< "Description: " << esm.getDesc() << std::endl
|
||||||
<< "File format version: " << esm.getFVer() << std::endl
|
<< "File format version: " << esm.getFVer() << std::endl;
|
||||||
<< "Special flag: " << esm.getSpecial() << std::endl;
|
std::vector<ESM::Header::MasterData> m = esm.getMasters();
|
||||||
ESM::ESMReader::MasterList m = esm.getMasters();
|
|
||||||
if (!m.empty())
|
if (!m.empty())
|
||||||
{
|
{
|
||||||
std::cout << "Masters:" << std::endl;
|
std::cout << "Masters:" << std::endl;
|
||||||
|
@ -430,9 +426,9 @@ int clone(Arguments& info)
|
||||||
esm.setAuthor(info.data.author);
|
esm.setAuthor(info.data.author);
|
||||||
esm.setDescription(info.data.description);
|
esm.setDescription(info.data.description);
|
||||||
esm.setVersion(info.data.version);
|
esm.setVersion(info.data.version);
|
||||||
esm.setType(info.data.type);
|
esm.setRecordCount (recordCount);
|
||||||
|
|
||||||
for (ESM::ESMReader::MasterList::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
|
for (std::vector<ESM::Header::MasterData>::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
|
||||||
esm.addMaster(it->name, it->size);
|
esm.addMaster(it->name, it->size);
|
||||||
|
|
||||||
std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);
|
std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);
|
||||||
|
|
|
@ -112,14 +112,11 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss)
|
||||||
case '5': oper_str = ">="; break;
|
case '5': oper_str = ">="; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string value_str = "??";
|
std::ostringstream stream;
|
||||||
if (ss.mType == ESM::VT_Int)
|
stream << ss.mValue;
|
||||||
value_str = str(boost::format("%d") % ss.mI);
|
|
||||||
else if (ss.mType == ESM::VT_Float)
|
|
||||||
value_str = str(boost::format("%f") % ss.mF);
|
|
||||||
|
|
||||||
std::string result = str(boost::format("%-12s %-32s %2s %s")
|
std::string result = str(boost::format("%-12s %-32s %2s %s")
|
||||||
% type_str % func_str % oper_str % value_str);
|
% type_str % func_str % oper_str % stream.str());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,31 +710,13 @@ void Record<ESM::Faction>::print()
|
||||||
template<>
|
template<>
|
||||||
void Record<ESM::Global>::print()
|
void Record<ESM::Global>::print()
|
||||||
{
|
{
|
||||||
// nothing to print (well, nothing that's correct anyway)
|
std::cout << " " << mData.mValue << std::endl;
|
||||||
std::cout << " Type: " << mData.mType << std::endl;
|
|
||||||
std::cout << " Value: " << mData.mValue << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void Record<ESM::GameSetting>::print()
|
void Record<ESM::GameSetting>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Value: ";
|
std::cout << " " << mData.mValue << std::endl;
|
||||||
switch (mData.mType) {
|
|
||||||
case ESM::VT_String:
|
|
||||||
std::cout << "'" << mData.mStr << "' (std::string)";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESM::VT_Float:
|
|
||||||
std::cout << mData.mF << " (float)";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESM::VT_Int:
|
|
||||||
std::cout << mData.mI << " (int)";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
std::cout << "unknown type";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -1,35 +1,55 @@
|
||||||
set(LAUNCHER
|
set(LAUNCHER
|
||||||
|
datafilespage.cpp
|
||||||
graphicspage.cpp
|
graphicspage.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
maindialog.cpp
|
maindialog.cpp
|
||||||
playpage.cpp
|
playpage.cpp
|
||||||
datafilespage.cpp
|
|
||||||
utils/profilescombobox.cpp
|
settings/gamesettings.cpp
|
||||||
|
settings/graphicssettings.cpp
|
||||||
|
settings/launchersettings.cpp
|
||||||
|
|
||||||
|
utils/checkablemessagebox.cpp
|
||||||
utils/textinputdialog.cpp
|
utils/textinputdialog.cpp
|
||||||
|
|
||||||
launcher.rc
|
launcher.rc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LAUNCHER_HEADER
|
set(LAUNCHER_HEADER
|
||||||
|
datafilespage.hpp
|
||||||
graphicspage.hpp
|
graphicspage.hpp
|
||||||
maindialog.hpp
|
maindialog.hpp
|
||||||
playpage.hpp
|
playpage.hpp
|
||||||
datafilespage.hpp
|
|
||||||
utils/profilescombobox.hpp
|
settings/gamesettings.hpp
|
||||||
|
settings/graphicssettings.hpp
|
||||||
|
settings/launchersettings.hpp
|
||||||
|
settings/settingsbase.hpp
|
||||||
|
|
||||||
|
utils/checkablemessagebox.hpp
|
||||||
utils/textinputdialog.hpp
|
utils/textinputdialog.hpp
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Headers that must be pre-processed
|
# Headers that must be pre-processed
|
||||||
set(LAUNCHER_HEADER_MOC
|
set(LAUNCHER_HEADER_MOC
|
||||||
|
datafilespage.hpp
|
||||||
graphicspage.hpp
|
graphicspage.hpp
|
||||||
maindialog.hpp
|
maindialog.hpp
|
||||||
playpage.hpp
|
playpage.hpp
|
||||||
datafilespage.hpp
|
|
||||||
utils/profilescombobox.hpp
|
utils/checkablemessagebox.hpp
|
||||||
utils/textinputdialog.hpp
|
utils/textinputdialog.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC})
|
set(LAUNCHER_UI
|
||||||
|
../../files/ui/datafilespage.ui
|
||||||
|
../../files/ui/graphicspage.ui
|
||||||
|
../../files/ui/mainwindow.ui
|
||||||
|
../../files/ui/playpage.ui
|
||||||
|
)
|
||||||
|
|
||||||
|
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})
|
||||||
|
|
||||||
find_package(Qt4 REQUIRED)
|
find_package(Qt4 REQUIRED)
|
||||||
set(QT_USE_QTGUI 1)
|
set(QT_USE_QTGUI 1)
|
||||||
|
@ -40,10 +60,12 @@ if(WIN32)
|
||||||
set(QT_USE_QTMAIN TRUE)
|
set(QT_USE_QTMAIN TRUE)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
QT4_ADD_RESOURCES(RCC_SRCS resources.qrc)
|
QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc)
|
||||||
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||||
|
QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
|
||||||
|
|
||||||
include(${QT_USE_FILE})
|
include(${QT_USE_FILE})
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
IF(OGRE_STATIC)
|
IF(OGRE_STATIC)
|
||||||
|
@ -58,8 +80,10 @@ ENDIF(OGRE_STATIC)
|
||||||
add_executable(omwlauncher
|
add_executable(omwlauncher
|
||||||
${GUI_TYPE}
|
${GUI_TYPE}
|
||||||
${LAUNCHER}
|
${LAUNCHER}
|
||||||
|
${LAUNCHER_HEADER}
|
||||||
${RCC_SRCS}
|
${RCC_SRCS}
|
||||||
${MOC_SRCS}
|
${MOC_SRCS}
|
||||||
|
${UI_HDRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(omwlauncher
|
target_link_libraries(omwlauncher
|
||||||
|
@ -74,18 +98,6 @@ if(DPKG_PROGRAM)
|
||||||
INSTALL(TARGETS omwlauncher RUNTIME DESTINATION games COMPONENT omwlauncher)
|
INSTALL(TARGETS omwlauncher RUNTIME DESTINATION games COMPONENT omwlauncher)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
|
|
||||||
"${APP_BUNDLE_DIR}/../launcher.qss")
|
|
||||||
else()
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
|
|
||||||
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/resources/launcher.qss")
|
|
||||||
|
|
||||||
# Fallback in case getGlobalDataPath does not point to resources
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
|
|
||||||
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (BUILD_WITH_CODE_COVERAGE)
|
if (BUILD_WITH_CODE_COVERAGE)
|
||||||
add_definitions (--coverage)
|
add_definitions (--coverage)
|
||||||
target_link_libraries(omwlauncher gcov)
|
target_link_libraries(omwlauncher gcov)
|
||||||
|
|
|
@ -1,445 +1,308 @@
|
||||||
#include <QtGui>
|
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
|
||||||
#include <components/fileorderlist/datafileslist.hpp>
|
|
||||||
#include <components/fileorderlist/utils/lineedit.hpp>
|
|
||||||
#include <components/fileorderlist/utils/naturalsort.hpp>
|
|
||||||
#include <components/fileorderlist/utils/filedialog.hpp>
|
|
||||||
|
|
||||||
////#include "model/datafilesmodel.hpp"
|
|
||||||
////#include "model/esm/esmfile.hpp"
|
|
||||||
|
|
||||||
#include "utils/profilescombobox.hpp"
|
|
||||||
////#include "utils/filedialog.hpp"
|
|
||||||
////#include "utils/naturalsort.hpp"
|
|
||||||
#include "utils/textinputdialog.hpp"
|
|
||||||
|
|
||||||
#include "datafilespage.hpp"
|
#include "datafilespage.hpp"
|
||||||
|
|
||||||
#include <boost/version.hpp>
|
#include <QtGui>
|
||||||
/**
|
|
||||||
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
#include <components/files/configurationmanager.hpp>
|
||||||
*/
|
|
||||||
#if (BOOST_VERSION <= 104600)
|
#include <components/fileorderlist/model/datafilesmodel.hpp>
|
||||||
namespace boost
|
#include <components/fileorderlist/model/pluginsproxymodel.hpp>
|
||||||
|
#include <components/fileorderlist/model/esm/esmfile.hpp>
|
||||||
|
|
||||||
|
#include <components/fileorderlist/utils/lineedit.hpp>
|
||||||
|
#include <components/fileorderlist/utils/naturalsort.hpp>
|
||||||
|
#include <components/fileorderlist/utils/profilescombobox.hpp>
|
||||||
|
|
||||||
|
#include "settings/gamesettings.hpp"
|
||||||
|
#include "settings/launchersettings.hpp"
|
||||||
|
|
||||||
|
#include "utils/textinputdialog.hpp"
|
||||||
|
|
||||||
|
DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent)
|
||||||
|
: mCfgMgr(cfg)
|
||||||
|
, mGameSettings(gameSettings)
|
||||||
|
, mLauncherSettings(launcherSettings)
|
||||||
|
, QWidget(parent)
|
||||||
{
|
{
|
||||||
|
setupUi(this);
|
||||||
|
|
||||||
template<>
|
// Models
|
||||||
inline boost::filesystem::path lexical_cast<boost::filesystem::path, std::string>(const std::string& arg)
|
mDataFilesModel = new DataFilesModel(this);
|
||||||
{
|
|
||||||
return boost::filesystem::path(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace boost */
|
mMastersProxyModel = new QSortFilterProxyModel();
|
||||||
#endif /* (BOOST_VERSION <= 104600) */
|
mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm"));
|
||||||
|
mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
mMastersProxyModel->setSourceModel(mDataFilesModel);
|
||||||
|
|
||||||
using namespace ESM;
|
mPluginsProxyModel = new PluginsProxyModel();
|
||||||
using namespace std;
|
mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp"));
|
||||||
|
mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
mPluginsProxyModel->setSourceModel(mDataFilesModel);
|
||||||
|
|
||||||
DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent)
|
mFilterProxyModel = new QSortFilterProxyModel();
|
||||||
: QWidget(parent)
|
mFilterProxyModel->setDynamicSortFilter(true);
|
||||||
, mCfgMgr(cfg)
|
mFilterProxyModel->setSourceModel(mPluginsProxyModel);
|
||||||
{
|
|
||||||
mDataFilesList = new DataFilesList(mCfgMgr, this);
|
|
||||||
|
|
||||||
// Bottom part with profile options
|
QCheckBox checkBox;
|
||||||
QLabel *profileLabel = new QLabel(tr("Current Profile: "), this);
|
unsigned int height = checkBox.sizeHint().height() + 4;
|
||||||
|
|
||||||
mProfilesComboBox = new ProfilesComboBox(this);
|
mastersTable->setModel(mMastersProxyModel);
|
||||||
mProfilesComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
|
mastersTable->setObjectName("MastersTable");
|
||||||
mProfilesComboBox->setInsertPolicy(QComboBox::NoInsert);
|
mastersTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
mProfilesComboBox->setDuplicatesEnabled(false);
|
mastersTable->setSortingEnabled(false);
|
||||||
mProfilesComboBox->setEditEnabled(false);
|
mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
mastersTable->setAlternatingRowColors(true);
|
||||||
|
mastersTable->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
mastersTable->horizontalHeader()->hide();
|
||||||
|
|
||||||
mProfileToolBar = new QToolBar(this);
|
// Set the row height to the size of the checkboxes
|
||||||
mProfileToolBar->setMovable(false);
|
mastersTable->verticalHeader()->setDefaultSectionSize(height);
|
||||||
mProfileToolBar->setIconSize(QSize(16, 16));
|
mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
||||||
|
mastersTable->verticalHeader()->hide();
|
||||||
|
|
||||||
mProfileToolBar->addWidget(profileLabel);
|
pluginsTable->setModel(mFilterProxyModel);
|
||||||
mProfileToolBar->addWidget(mProfilesComboBox);
|
pluginsTable->setObjectName("PluginsTable");
|
||||||
|
pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
pluginsTable->setSortingEnabled(false);
|
||||||
|
pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
pluginsTable->setAlternatingRowColors(true);
|
||||||
|
pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
|
||||||
|
pluginsTable->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
pluginsTable->horizontalHeader()->hide();
|
||||||
|
|
||||||
QVBoxLayout *pageLayout = new QVBoxLayout(this);
|
pluginsTable->verticalHeader()->setDefaultSectionSize(height);
|
||||||
|
pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
||||||
|
|
||||||
pageLayout->addWidget(mDataFilesList);
|
// Adjust the tableview widths inside the splitter
|
||||||
pageLayout->addWidget(mProfileToolBar);
|
QList<int> sizeList;
|
||||||
|
sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt();
|
||||||
|
sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt();
|
||||||
|
|
||||||
|
splitter->setSizes(sizeList);
|
||||||
|
|
||||||
// Create a dialog for the new profile name input
|
// Create a dialog for the new profile name input
|
||||||
mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this);
|
mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this);
|
||||||
|
|
||||||
|
connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
|
||||||
|
|
||||||
connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString)));
|
connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString)));
|
||||||
|
|
||||||
|
connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
||||||
|
connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
||||||
|
|
||||||
|
connect(pluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||||
|
connect(mastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||||
|
|
||||||
|
connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews()));
|
||||||
|
|
||||||
connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString)));
|
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
|
||||||
connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString)));
|
|
||||||
|
connect(splitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter()));
|
||||||
|
|
||||||
createActions();
|
createActions();
|
||||||
setupConfig();
|
setupDataFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::createActions()
|
void DataFilesPage::createActions()
|
||||||
{
|
{
|
||||||
// Refresh the plugins
|
|
||||||
QAction *refreshAction = new QAction(tr("Refresh"), this);
|
|
||||||
refreshAction->setShortcut(QKeySequence(tr("F5")));
|
|
||||||
connect(refreshAction, SIGNAL(triggered()), this, SLOT(refresh()));
|
|
||||||
|
|
||||||
// Profile actions
|
// Add the actions to the toolbuttons
|
||||||
mNewProfileAction = new QAction(QIcon::fromTheme("document-new"), tr("&New Profile"), this);
|
newProfileButton->setDefaultAction(newProfileAction);
|
||||||
mNewProfileAction->setToolTip(tr("New Profile"));
|
deleteProfileButton->setDefaultAction(deleteProfileAction);
|
||||||
mNewProfileAction->setShortcut(QKeySequence(tr("Ctrl+N")));
|
|
||||||
connect(mNewProfileAction, SIGNAL(triggered()), this, SLOT(newProfile()));
|
|
||||||
|
|
||||||
mDeleteProfileAction = new QAction(QIcon::fromTheme("edit-delete"), tr("Delete Profile"), this);
|
// Context menu actions
|
||||||
mDeleteProfileAction->setToolTip(tr("Delete Profile"));
|
mContextMenu = new QMenu(this);
|
||||||
mDeleteProfileAction->setShortcut(QKeySequence(tr("Delete")));
|
mContextMenu->addAction(checkAction);
|
||||||
connect(mDeleteProfileAction, SIGNAL(triggered()), this, SLOT(deleteProfile()));
|
mContextMenu->addAction(uncheckAction);
|
||||||
|
|
||||||
// Add the newly created actions to the toolbar
|
|
||||||
mProfileToolBar->addSeparator();
|
|
||||||
mProfileToolBar->addAction(mNewProfileAction);
|
|
||||||
mProfileToolBar->addAction(mDeleteProfileAction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::setupConfig()
|
void DataFilesPage::setupDataFiles()
|
||||||
{
|
{
|
||||||
// Open our config file
|
// Set the encoding to the one found in openmw.cfg or the default
|
||||||
QString config = QString::fromStdString((mCfgMgr.getUserPath() / "launcher.cfg").string());
|
mDataFilesModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252")));
|
||||||
mLauncherConfig = new QSettings(config, QSettings::IniFormat);
|
|
||||||
|
|
||||||
// Make sure we have no groups open
|
QStringList paths = mGameSettings.getDataDirs();
|
||||||
while (!mLauncherConfig->group().isEmpty()) {
|
|
||||||
mLauncherConfig->endGroup();
|
foreach (const QString &path, paths) {
|
||||||
|
mDataFilesModel->addFiles(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLauncherConfig->beginGroup("Profiles");
|
QString dataLocal = mGameSettings.getDataLocal();
|
||||||
QStringList profiles = mLauncherConfig->childGroups();
|
if (!dataLocal.isEmpty())
|
||||||
|
mDataFilesModel->addFiles(dataLocal);
|
||||||
|
|
||||||
// Add the profiles to the combobox
|
// Sort by date accessed for now
|
||||||
foreach (const QString &profile, profiles) {
|
mDataFilesModel->sort(3);
|
||||||
|
|
||||||
if (profile.contains(QRegExp("[^a-zA-Z0-9_]")))
|
QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/"));
|
||||||
continue; // Profile name contains garbage
|
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
|
||||||
|
|
||||||
|
if (!profiles.isEmpty())
|
||||||
|
profilesComboBox->addItems(profiles);
|
||||||
|
|
||||||
qDebug() << "adding " << profile;
|
// Add the current profile if empty
|
||||||
mProfilesComboBox->addItem(profile);
|
if (profilesComboBox->findText(profile) == -1)
|
||||||
}
|
profilesComboBox->addItem(profile);
|
||||||
|
|
||||||
// Add a default profile
|
if (profilesComboBox->findText(QString("Default")) == -1)
|
||||||
if (mProfilesComboBox->findText(QString("Default")) == -1) {
|
profilesComboBox->addItem(QString("Default"));
|
||||||
mProfilesComboBox->addItem(QString("Default"));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString currentProfile = mLauncherConfig->value("CurrentProfile").toString();
|
|
||||||
|
|
||||||
if (currentProfile.isEmpty()) {
|
|
||||||
// No current profile selected
|
|
||||||
currentProfile = "Default";
|
|
||||||
}
|
|
||||||
|
|
||||||
const int currentIndex = mProfilesComboBox->findText(currentProfile);
|
|
||||||
if (currentIndex != -1) {
|
|
||||||
// Profile is found
|
|
||||||
mProfilesComboBox->setCurrentIndex(currentIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DataFilesPage::readConfig()
|
|
||||||
{
|
|
||||||
QString profile = mProfilesComboBox->currentText();
|
|
||||||
|
|
||||||
// Make sure we have no groups open
|
|
||||||
while (!mLauncherConfig->group().isEmpty()) {
|
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
mLauncherConfig->beginGroup("Profiles");
|
|
||||||
mLauncherConfig->beginGroup(profile);
|
|
||||||
|
|
||||||
QStringList childKeys = mLauncherConfig->childKeys();
|
|
||||||
QStringList plugins;
|
|
||||||
|
|
||||||
// Sort the child keys numerical instead of alphabetically
|
|
||||||
// i.e. Plugin1, Plugin2 instead of Plugin1, Plugin10
|
|
||||||
qSort(childKeys.begin(), childKeys.end(), naturalSortLessThanCI);
|
|
||||||
|
|
||||||
foreach (const QString &key, childKeys) {
|
|
||||||
const QString keyValue = mLauncherConfig->value(key).toString();
|
|
||||||
|
|
||||||
mDataFilesList->setCheckState(keyValue, Qt::Checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DataFilesPage::showDataFilesWarning()
|
|
||||||
{
|
|
||||||
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setWindowTitle("Error detecting Morrowind installation");
|
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Cancel);
|
|
||||||
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
|
|
||||||
The directory containing the data files was not found.<br><br> \
|
|
||||||
Press \"Browse...\" to specify the location manually.<br>"));
|
|
||||||
|
|
||||||
QAbstractButton *dirSelectButton =
|
|
||||||
msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole);
|
|
||||||
|
|
||||||
msgBox.exec();
|
|
||||||
|
|
||||||
if (msgBox.clickedButton() == dirSelectButton) {
|
|
||||||
|
|
||||||
// Show a custom dir selection dialog which only accepts valid dirs
|
|
||||||
QString selectedDir = FileDialog::getExistingDirectory(
|
|
||||||
this, tr("Select Data Files Directory"),
|
|
||||||
QDir::currentPath(),
|
|
||||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
|
||||||
|
|
||||||
// Add the user selected data directory
|
|
||||||
if (!selectedDir.isEmpty()) {
|
|
||||||
mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString()));
|
|
||||||
mCfgMgr.processPaths(mDataDirs);
|
|
||||||
} else {
|
|
||||||
// Cancel from within the dir selection dialog
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (profile.isEmpty() || profile == QLatin1String("Default")) {
|
||||||
|
deleteProfileAction->setEnabled(false);
|
||||||
|
profilesComboBox->setEditEnabled(false);
|
||||||
|
profilesComboBox->setCurrentIndex(profilesComboBox->findText(QString("Default")));
|
||||||
} else {
|
} else {
|
||||||
// Cancel
|
profilesComboBox->setEditEnabled(true);
|
||||||
return false;
|
profilesComboBox->setCurrentIndex(profilesComboBox->findText(profile));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
// We do this here to prevent deletion of profiles when initializing the combobox
|
||||||
|
connect(profilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString)));
|
||||||
|
connect(profilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString)));
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataFilesPage::setupDataFiles()
|
void DataFilesPage::loadSettings()
|
||||||
{
|
{
|
||||||
// We use the Configuration Manager to retrieve the configuration values
|
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
|
||||||
boost::program_options::variables_map variables;
|
|
||||||
boost::program_options::options_description desc;
|
|
||||||
|
|
||||||
desc.add_options()
|
|
||||||
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
|
|
||||||
("data-local", boost::program_options::value<std::string>()->default_value(""))
|
|
||||||
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
|
|
||||||
("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
|
|
||||||
|
|
||||||
boost::program_options::notify(variables);
|
|
||||||
|
|
||||||
mCfgMgr.readConfiguration(variables, desc);
|
|
||||||
|
|
||||||
if (variables["data"].empty()) {
|
|
||||||
if (!showDataFilesWarning())
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string local = variables["data-local"].as<std::string>();
|
|
||||||
if (!local.empty()) {
|
|
||||||
mDataLocal.push_back(Files::PathContainer::value_type(local));
|
|
||||||
}
|
|
||||||
|
|
||||||
mCfgMgr.processPaths(mDataDirs);
|
|
||||||
mCfgMgr.processPaths(mDataLocal);
|
|
||||||
|
|
||||||
// Second chance to display the warning, the data= entries are invalid
|
|
||||||
while (mDataDirs.empty()) {
|
|
||||||
if (!showDataFilesWarning())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the charset for reading the esm/esp files
|
|
||||||
QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
|
|
||||||
|
|
||||||
Files::PathContainer paths;
|
|
||||||
paths.insert(paths.end(), mDataDirs.begin(), mDataDirs.end());
|
|
||||||
paths.insert(paths.end(), mDataLocal.begin(), mDataLocal.end());
|
|
||||||
mDataFilesList->setupDataFiles(paths, encoding);
|
|
||||||
readConfig();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::writeConfig(QString profile)
|
|
||||||
{
|
|
||||||
QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string());
|
|
||||||
QDir userPath(pathStr);
|
|
||||||
|
|
||||||
if (!userPath.exists()) {
|
|
||||||
if (!userPath.mkpath(pathStr)) {
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setWindowTitle("Error creating OpenMW configuration directory");
|
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
||||||
msgBox.setText(tr("<br><b>Could not create %0</b><br><br> \
|
|
||||||
Please make sure you have the right permissions and try again.<br>").arg(pathStr));
|
|
||||||
msgBox.exec();
|
|
||||||
|
|
||||||
qApp->quit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Open the OpenMW config as a QFile
|
|
||||||
QFile file(pathStr.append("openmw.cfg"));
|
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
|
||||||
// File cannot be opened or created
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setWindowTitle("Error writing OpenMW configuration file");
|
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
||||||
msgBox.setText(tr("<br><b>Could not open or create %0</b><br><br> \
|
|
||||||
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
|
|
||||||
msgBox.exec();
|
|
||||||
|
|
||||||
qApp->quit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream in(&file);
|
|
||||||
QByteArray buffer;
|
|
||||||
|
|
||||||
// Remove all previous entries from config
|
|
||||||
while (!in.atEnd()) {
|
|
||||||
QString line = in.readLine();
|
|
||||||
if (!line.startsWith("master") &&
|
|
||||||
!line.startsWith("plugin") &&
|
|
||||||
!line.startsWith("data") &&
|
|
||||||
!line.startsWith("data-local"))
|
|
||||||
{
|
|
||||||
buffer += line += "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
// Now we write back the other config entries
|
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setWindowTitle("Error writing OpenMW configuration file");
|
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
||||||
msgBox.setText(tr("<br><b>Could not write to %0</b><br><br> \
|
|
||||||
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
|
|
||||||
msgBox.exec();
|
|
||||||
|
|
||||||
qApp->quit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!buffer.isEmpty()) {
|
|
||||||
file.write(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream gameConfig(&file);
|
|
||||||
|
|
||||||
// First write the list of data dirs
|
|
||||||
mCfgMgr.processPaths(mDataDirs);
|
|
||||||
mCfgMgr.processPaths(mDataLocal);
|
|
||||||
|
|
||||||
QString path;
|
|
||||||
|
|
||||||
// data= directories
|
|
||||||
for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) {
|
|
||||||
path = QString::fromStdString(it->string());
|
|
||||||
path.remove(QChar('\"'));
|
|
||||||
|
|
||||||
// Make sure the string is quoted when it contains spaces
|
|
||||||
if (path.contains(" ")) {
|
|
||||||
gameConfig << "data=\"" << path << "\"" << endl;
|
|
||||||
} else {
|
|
||||||
gameConfig << "data=" << path << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// data-local directory
|
|
||||||
if (!mDataLocal.empty()) {
|
|
||||||
path = QString::fromStdString(mDataLocal.front().string());
|
|
||||||
path.remove(QChar('\"'));
|
|
||||||
|
|
||||||
if (path.contains(" ")) {
|
|
||||||
gameConfig << "data-local=\"" << path << "\"" << endl;
|
|
||||||
} else {
|
|
||||||
gameConfig << "data-local=" << path << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (profile.isEmpty())
|
|
||||||
profile = mProfilesComboBox->currentText();
|
|
||||||
|
|
||||||
if (profile.isEmpty())
|
if (profile.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Make sure we have no groups open
|
mDataFilesModel->uncheckAll();
|
||||||
while (!mLauncherConfig->group().isEmpty()) {
|
|
||||||
mLauncherConfig->endGroup();
|
QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly);
|
||||||
|
QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly);
|
||||||
|
|
||||||
|
foreach (const QString &master, masters) {
|
||||||
|
QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(master));
|
||||||
|
if (index.isValid())
|
||||||
|
mDataFilesModel->setCheckState(index, Qt::Checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLauncherConfig->beginGroup("Profiles");
|
foreach (const QString &plugin, plugins) {
|
||||||
mLauncherConfig->setValue("CurrentProfile", profile);
|
QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(plugin));
|
||||||
|
if (index.isValid())
|
||||||
// Open the profile-name subgroup
|
mDataFilesModel->setCheckState(index, Qt::Checked);
|
||||||
mLauncherConfig->beginGroup(profile);
|
|
||||||
mLauncherConfig->remove(""); // Clear the subgroup
|
|
||||||
|
|
||||||
// Now write the masters to the configs
|
|
||||||
const QStringList checkedFiles = mDataFilesList->checkedFiles();
|
|
||||||
for(int i=0; i < checkedFiles.size(); i++)
|
|
||||||
{
|
|
||||||
if (checkedFiles.at(i).lastIndexOf("esm") != -1)
|
|
||||||
{
|
|
||||||
mLauncherConfig->setValue(QString("Master%0").arg(i), checkedFiles.at(i));
|
|
||||||
gameConfig << "master=" << checkedFiles.at(i) << endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mLauncherConfig->setValue(QString("Plugin%1").arg(i), checkedFiles.at(i));
|
|
||||||
gameConfig << "plugin=" << checkedFiles.at(i) << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
file.close();
|
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
mLauncherConfig->sync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::saveSettings()
|
||||||
void DataFilesPage::newProfile()
|
|
||||||
{
|
{
|
||||||
if (mNewProfileDialog->exec() == QDialog::Accepted) {
|
if (mDataFilesModel->rowCount() < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
const QString text = mNewProfileDialog->lineEdit()->text();
|
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
|
||||||
mProfilesComboBox->addItem(text);
|
|
||||||
|
|
||||||
// Copy the currently checked items to cfg
|
if (profile.isEmpty()) {
|
||||||
writeConfig(text);
|
profile = profilesComboBox->currentText();
|
||||||
mLauncherConfig->sync();
|
mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile);
|
||||||
|
|
||||||
mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(text));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master"));
|
||||||
|
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin"));
|
||||||
|
|
||||||
|
mGameSettings.remove(QString("master"));
|
||||||
|
mGameSettings.remove(QString("plugin"));
|
||||||
|
|
||||||
|
QStringList items = mDataFilesModel->checkedItems();
|
||||||
|
|
||||||
|
foreach(const QString &item, items) {
|
||||||
|
|
||||||
|
if (item.endsWith(QString(".esm"), Qt::CaseInsensitive)) {
|
||||||
|
mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item);
|
||||||
|
mGameSettings.setMultiValue(QString("master"), item);
|
||||||
|
|
||||||
|
} else if (item.endsWith(QString(".esp"), Qt::CaseInsensitive)) {
|
||||||
|
mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item);
|
||||||
|
mGameSettings.setMultiValue(QString("plugin"), item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::updateOkButton(const QString &text)
|
void DataFilesPage::updateOkButton(const QString &text)
|
||||||
{
|
{
|
||||||
|
// We do this here because we need the profiles combobox text
|
||||||
if (text.isEmpty()) {
|
if (text.isEmpty()) {
|
||||||
mNewProfileDialog->setOkButtonEnabled(false);
|
mNewProfileDialog->setOkButtonEnabled(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(mProfilesComboBox->findText(text) == -1)
|
(profilesComboBox->findText(text) == -1)
|
||||||
? mNewProfileDialog->setOkButtonEnabled(true)
|
? mNewProfileDialog->setOkButtonEnabled(true)
|
||||||
: mNewProfileDialog->setOkButtonEnabled(false);
|
: mNewProfileDialog->setOkButtonEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::deleteProfile()
|
void DataFilesPage::updateSplitter()
|
||||||
{
|
{
|
||||||
QString profile = mProfilesComboBox->currentText();
|
// Sigh, update the saved splitter size in settings only when moved
|
||||||
|
// Since getting mSplitter->sizes() if page is hidden returns invalid values
|
||||||
|
QList<int> sizes = splitter->sizes();
|
||||||
|
|
||||||
|
mLauncherSettings.setValue(QString("General/MastersTable/width"), QString::number(sizes.at(0)));
|
||||||
|
mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::updateViews()
|
||||||
|
{
|
||||||
|
// Ensure the columns are hidden because sort() re-enables them
|
||||||
|
mastersTable->setColumnHidden(1, true);
|
||||||
|
mastersTable->setColumnHidden(2, true);
|
||||||
|
mastersTable->setColumnHidden(3, true);
|
||||||
|
mastersTable->setColumnHidden(4, true);
|
||||||
|
mastersTable->setColumnHidden(5, true);
|
||||||
|
mastersTable->setColumnHidden(6, true);
|
||||||
|
mastersTable->setColumnHidden(7, true);
|
||||||
|
mastersTable->setColumnHidden(8, true);
|
||||||
|
|
||||||
|
pluginsTable->setColumnHidden(1, true);
|
||||||
|
pluginsTable->setColumnHidden(2, true);
|
||||||
|
pluginsTable->setColumnHidden(3, true);
|
||||||
|
pluginsTable->setColumnHidden(4, true);
|
||||||
|
pluginsTable->setColumnHidden(5, true);
|
||||||
|
pluginsTable->setColumnHidden(6, true);
|
||||||
|
pluginsTable->setColumnHidden(7, true);
|
||||||
|
pluginsTable->setColumnHidden(8, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::setProfilesComboBoxIndex(int index)
|
||||||
|
{
|
||||||
|
profilesComboBox->setCurrentIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::slotCurrentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
emit profileChanged(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
QAbstractItemModel* DataFilesPage::profilesComboBoxModel()
|
||||||
|
{
|
||||||
|
return profilesComboBox->model();
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataFilesPage::profilesComboBoxIndex()
|
||||||
|
{
|
||||||
|
return profilesComboBox->currentIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::on_newProfileAction_triggered()
|
||||||
|
{
|
||||||
|
if (mNewProfileDialog->exec() == QDialog::Accepted) {
|
||||||
|
QString profile = mNewProfileDialog->lineEdit()->text();
|
||||||
|
profilesComboBox->addItem(profile);
|
||||||
|
profilesComboBox->setCurrentIndex(profilesComboBox->findText(profile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::on_deleteProfileAction_triggered()
|
||||||
|
{
|
||||||
|
QString profile = profilesComboBox->currentText();
|
||||||
|
|
||||||
if (profile.isEmpty())
|
if (profile.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
@ -456,49 +319,143 @@ void DataFilesPage::deleteProfile()
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
|
|
||||||
if (msgBox.clickedButton() == deleteButton) {
|
if (msgBox.clickedButton() == deleteButton) {
|
||||||
// Make sure we have no groups open
|
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master"));
|
||||||
while (!mLauncherConfig->group().isEmpty()) {
|
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin"));
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
mLauncherConfig->beginGroup("Profiles");
|
|
||||||
|
|
||||||
// Open the profile-name subgroup
|
|
||||||
mLauncherConfig->beginGroup(profile);
|
|
||||||
mLauncherConfig->remove(""); // Clear the subgroup
|
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
|
|
||||||
// Remove the profile from the combobox
|
// Remove the profile from the combobox
|
||||||
mProfilesComboBox->removeItem(mProfilesComboBox->findText(profile));
|
profilesComboBox->removeItem(profilesComboBox->findText(profile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::on_checkAction_triggered()
|
||||||
|
{
|
||||||
|
if (pluginsTable->hasFocus())
|
||||||
|
setPluginsCheckstates(Qt::Checked);
|
||||||
|
|
||||||
|
if (mastersTable->hasFocus())
|
||||||
|
setMastersCheckstates(Qt::Checked);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::on_uncheckAction_triggered()
|
||||||
|
{
|
||||||
|
if (pluginsTable->hasFocus())
|
||||||
|
setPluginsCheckstates(Qt::Unchecked);
|
||||||
|
|
||||||
|
if (mastersTable->hasFocus())
|
||||||
|
setMastersCheckstates(Qt::Unchecked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::setMastersCheckstates(Qt::CheckState state)
|
||||||
|
{
|
||||||
|
if (!mastersTable->selectionModel()->hasSelection()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes();
|
||||||
|
|
||||||
|
foreach (const QModelIndex &index, indexes)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
|
||||||
|
|
||||||
|
if (!sourceIndex.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mDataFilesModel->setCheckState(sourceIndex, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::setPluginsCheckstates(Qt::CheckState state)
|
||||||
|
{
|
||||||
|
if (!pluginsTable->selectionModel()->hasSelection()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes();
|
||||||
|
|
||||||
|
foreach (const QModelIndex &index, indexes)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
|
||||||
|
mFilterProxyModel->mapToSource(index));
|
||||||
|
|
||||||
|
if (!sourceIndex.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mDataFilesModel->setCheckState(sourceIndex, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::setCheckState(QModelIndex index)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QObject *object = QObject::sender();
|
||||||
|
|
||||||
|
// Not a signal-slot call
|
||||||
|
if (!object)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
if (object->objectName() == QLatin1String("PluginsTable")) {
|
||||||
|
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
|
||||||
|
mFilterProxyModel->mapToSource(index));
|
||||||
|
|
||||||
|
if (sourceIndex.isValid()) {
|
||||||
|
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
||||||
|
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
|
||||||
|
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object->objectName() == QLatin1String("MastersTable")) {
|
||||||
|
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
|
||||||
|
|
||||||
|
if (sourceIndex.isValid()) {
|
||||||
|
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
||||||
|
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
|
||||||
|
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataFilesPage::filterChanged(const QString filter)
|
||||||
|
{
|
||||||
|
QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString);
|
||||||
|
mFilterProxyModel->setFilterRegExp(regExp);
|
||||||
|
}
|
||||||
|
|
||||||
void DataFilesPage::profileChanged(const QString &previous, const QString ¤t)
|
void DataFilesPage::profileChanged(const QString &previous, const QString ¤t)
|
||||||
{
|
{
|
||||||
qDebug() << "Profile is changed from: " << previous << " to " << current;
|
|
||||||
// Prevent the deletion of the default profile
|
// Prevent the deletion of the default profile
|
||||||
if (current == QLatin1String("Default")) {
|
if (current == QLatin1String("Default")) {
|
||||||
mDeleteProfileAction->setEnabled(false);
|
deleteProfileAction->setEnabled(false);
|
||||||
mProfilesComboBox->setEditEnabled(false);
|
profilesComboBox->setEditEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
mDeleteProfileAction->setEnabled(true);
|
deleteProfileAction->setEnabled(true);
|
||||||
mProfilesComboBox->setEditEnabled(true);
|
profilesComboBox->setEditEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!previous.isEmpty()) {
|
if (previous.isEmpty())
|
||||||
writeConfig(previous);
|
|
||||||
mLauncherConfig->sync();
|
|
||||||
|
|
||||||
if (mProfilesComboBox->currentIndex() == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
mDataFilesList->uncheckAll();
|
if (profilesComboBox->findText(previous) == -1)
|
||||||
readConfig();
|
return; // Profile was deleted
|
||||||
|
|
||||||
|
// Store the previous profile
|
||||||
|
mLauncherSettings.setValue(QString("Profiles/currentprofile"), previous);
|
||||||
|
saveSettings();
|
||||||
|
mLauncherSettings.setValue(QString("Profiles/currentprofile"), current);
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::profileRenamed(const QString &previous, const QString ¤t)
|
void DataFilesPage::profileRenamed(const QString &previous, const QString ¤t)
|
||||||
|
@ -507,27 +464,85 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Save the new profile name
|
// Save the new profile name
|
||||||
writeConfig(current);
|
mLauncherSettings.setValue(QString("Profiles/currentprofile"), current);
|
||||||
|
saveSettings();
|
||||||
|
|
||||||
// Make sure we have no groups open
|
// Remove the old one
|
||||||
while (!mLauncherConfig->group().isEmpty()) {
|
mLauncherSettings.remove(QString("Profiles/") + previous + QString("/master"));
|
||||||
mLauncherConfig->endGroup();
|
mLauncherSettings.remove(QString("Profiles/") + previous + QString("/plugin"));
|
||||||
}
|
|
||||||
|
|
||||||
mLauncherConfig->beginGroup("Profiles");
|
// Remove the profile from the combobox
|
||||||
|
profilesComboBox->removeItem(profilesComboBox->findText(previous));
|
||||||
|
|
||||||
// Open the profile-name subgroup
|
loadSettings();
|
||||||
mLauncherConfig->beginGroup(previous);
|
|
||||||
mLauncherConfig->remove(""); // Clear the subgroup
|
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
mLauncherConfig->endGroup();
|
|
||||||
mLauncherConfig->sync();
|
|
||||||
|
|
||||||
// Remove the profile from the combobox
|
}
|
||||||
mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous));
|
|
||||||
|
void DataFilesPage::showContextMenu(const QPoint &point)
|
||||||
mDataFilesList->uncheckAll();
|
{
|
||||||
////mMastersModel->uncheckAll();
|
QObject *object = QObject::sender();
|
||||||
////mPluginsModel->uncheckAll();
|
|
||||||
readConfig();
|
// Not a signal-slot call
|
||||||
|
if (!object)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (object->objectName() == QLatin1String("PluginsTable")) {
|
||||||
|
if (!pluginsTable->selectionModel()->hasSelection())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPoint globalPos = pluginsTable->mapToGlobal(point);
|
||||||
|
QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes();
|
||||||
|
|
||||||
|
// Show the check/uncheck actions depending on the state of the selected items
|
||||||
|
uncheckAction->setEnabled(false);
|
||||||
|
checkAction->setEnabled(false);
|
||||||
|
|
||||||
|
foreach (const QModelIndex &index, indexes)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
|
||||||
|
mFilterProxyModel->mapToSource(index));
|
||||||
|
|
||||||
|
if (!sourceIndex.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
||||||
|
? uncheckAction->setEnabled(true)
|
||||||
|
: checkAction->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show menu
|
||||||
|
mContextMenu->exec(globalPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object->objectName() == QLatin1String("MastersTable")) {
|
||||||
|
if (!mastersTable->selectionModel()->hasSelection())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPoint globalPos = mastersTable->mapToGlobal(point);
|
||||||
|
QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes();
|
||||||
|
|
||||||
|
// Show the check/uncheck actions depending on the state of the selected items
|
||||||
|
uncheckAction->setEnabled(false);
|
||||||
|
checkAction->setEnabled(false);
|
||||||
|
|
||||||
|
foreach (const QModelIndex &index, indexes)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
|
||||||
|
|
||||||
|
if (!sourceIndex.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
||||||
|
? uncheckAction->setEnabled(true)
|
||||||
|
: checkAction->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
mContextMenu->exec(globalPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,78 +3,86 @@
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
#include "utils/profilescombobox.hpp"
|
|
||||||
#include <components/files/collections.hpp>
|
|
||||||
|
|
||||||
|
#include "ui_datafilespage.h"
|
||||||
|
|
||||||
class QTableView;
|
|
||||||
class QSortFilterProxyModel;
|
class QSortFilterProxyModel;
|
||||||
class QSettings;
|
class QAbstractItemModel;
|
||||||
class QAction;
|
class QAction;
|
||||||
class QToolBar;
|
|
||||||
class QMenu;
|
class QMenu;
|
||||||
class ProfilesComboBox;
|
|
||||||
class DataFilesModel;
|
|
||||||
|
|
||||||
|
class DataFilesModel;
|
||||||
class TextInputDialog;
|
class TextInputDialog;
|
||||||
class DataFilesList;
|
class GameSettings;
|
||||||
|
class LauncherSettings;
|
||||||
|
class PluginsProxyModel;
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files { struct ConfigurationManager; }
|
||||||
|
|
||||||
class DataFilesPage : public QWidget
|
class DataFilesPage : public QWidget, private Ui::DataFilesPage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DataFilesPage(Files::ConfigurationManager& cfg, QWidget *parent = 0);
|
DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0);
|
||||||
|
|
||||||
ProfilesComboBox *mProfilesComboBox;
|
QAbstractItemModel* profilesComboBoxModel();
|
||||||
|
int profilesComboBoxIndex();
|
||||||
|
|
||||||
void writeConfig(QString profile = QString());
|
void writeConfig(QString profile = QString());
|
||||||
bool showDataFilesWarning();
|
void saveSettings();
|
||||||
bool setupDataFiles();
|
|
||||||
|
signals:
|
||||||
|
void profileChanged(int index);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void setCheckState(QModelIndex index);
|
||||||
|
void setProfilesComboBoxIndex(int index);
|
||||||
|
|
||||||
|
void filterChanged(const QString filter);
|
||||||
|
void showContextMenu(const QPoint &point);
|
||||||
void profileChanged(const QString &previous, const QString ¤t);
|
void profileChanged(const QString &previous, const QString ¤t);
|
||||||
void profileRenamed(const QString &previous, const QString ¤t);
|
void profileRenamed(const QString &previous, const QString ¤t);
|
||||||
void updateOkButton(const QString &text);
|
void updateOkButton(const QString &text);
|
||||||
|
void updateSplitter();
|
||||||
|
void updateViews();
|
||||||
|
|
||||||
// Action slots
|
// Action slots
|
||||||
void newProfile();
|
void on_newProfileAction_triggered();
|
||||||
void deleteProfile();
|
void on_deleteProfileAction_triggered();
|
||||||
// void moveUp();
|
void on_checkAction_triggered();
|
||||||
// void moveDown();
|
void on_uncheckAction_triggered();
|
||||||
// void moveTop();
|
|
||||||
// void moveBottom();
|
private slots:
|
||||||
|
void slotCurrentIndexChanged(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataFilesList *mDataFilesList;
|
DataFilesModel *mDataFilesModel;
|
||||||
|
|
||||||
QToolBar *mProfileToolBar;
|
PluginsProxyModel *mPluginsProxyModel;
|
||||||
|
QSortFilterProxyModel *mMastersProxyModel;
|
||||||
|
|
||||||
QAction *mNewProfileAction;
|
QSortFilterProxyModel *mFilterProxyModel;
|
||||||
QAction *mDeleteProfileAction;
|
|
||||||
|
|
||||||
// QAction *mMoveUpAction;
|
QMenu *mContextMenu;
|
||||||
// QAction *mMoveDownAction;
|
|
||||||
// QAction *mMoveTopAction;
|
|
||||||
// QAction *mMoveBottomAction;
|
|
||||||
|
|
||||||
Files::ConfigurationManager &mCfgMgr;
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
Files::PathContainer mDataDirs;
|
|
||||||
Files::PathContainer mDataLocal;
|
|
||||||
|
|
||||||
QSettings *mLauncherConfig;
|
GameSettings &mGameSettings;
|
||||||
|
LauncherSettings &mLauncherSettings;
|
||||||
|
|
||||||
TextInputDialog *mNewProfileDialog;
|
TextInputDialog *mNewProfileDialog;
|
||||||
|
|
||||||
// const QStringList checkedPlugins();
|
void setMastersCheckstates(Qt::CheckState state);
|
||||||
// const QStringList selectedMasters();
|
void setPluginsCheckstates(Qt::CheckState state);
|
||||||
|
|
||||||
void createActions();
|
void createActions();
|
||||||
|
void setupDataFiles();
|
||||||
void setupConfig();
|
void setupConfig();
|
||||||
void readConfig();
|
void readConfig();
|
||||||
|
|
||||||
|
void loadSettings();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
|
#include "graphicspage.hpp"
|
||||||
|
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <boost/math/common_factor.hpp>
|
#include <boost/math/common_factor.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/files/ogreplugin.hpp>
|
#include <components/files/ogreplugin.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
|
||||||
#include <components/fileorderlist/utils/naturalsort.hpp>
|
#include <components/fileorderlist/utils/naturalsort.hpp>
|
||||||
|
|
||||||
#include "graphicspage.hpp"
|
#include "settings/graphicssettings.hpp"
|
||||||
|
|
||||||
QString getAspect(int x, int y)
|
QString getAspect(int x, int y)
|
||||||
{
|
{
|
||||||
|
@ -24,52 +25,22 @@ QString getAspect(int x, int y)
|
||||||
return QString(QString::number(xaspect) + ":" + QString::number(yaspect));
|
return QString(QString::number(xaspect) + ":" + QString::number(yaspect));
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
|
GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent)
|
||||||
: QWidget(parent)
|
: mCfgMgr(cfg)
|
||||||
, mCfgMgr(cfg)
|
, mGraphicsSettings(graphicsSetting)
|
||||||
|
, QWidget(parent)
|
||||||
{
|
{
|
||||||
QGroupBox *rendererGroup = new QGroupBox(tr("Renderer"), this);
|
setupUi(this);
|
||||||
|
|
||||||
QLabel *rendererLabel = new QLabel(tr("Rendering Subsystem:"), rendererGroup);
|
// Set the maximum res we can set in windowed mode
|
||||||
mRendererComboBox = new QComboBox(rendererGroup);
|
QRect res = QApplication::desktop()->screenGeometry();
|
||||||
|
customWidthSpinBox->setMaximum(res.width());
|
||||||
|
customHeightSpinBox->setMaximum(res.height());
|
||||||
|
|
||||||
// Layout for the combobox and label
|
connect(rendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&)));
|
||||||
QGridLayout *renderSystemLayout = new QGridLayout();
|
connect(fullScreenCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotFullScreenChanged(int)));
|
||||||
renderSystemLayout->addWidget(rendererLabel, 0, 0, 1, 1);
|
connect(standardRadioButton, SIGNAL(toggled(bool)), this, SLOT(slotStandardToggled(bool)));
|
||||||
renderSystemLayout->addWidget(mRendererComboBox, 0, 1, 1, 1);
|
|
||||||
|
|
||||||
// Display
|
|
||||||
QGroupBox *displayGroup = new QGroupBox(tr("Display"), this);
|
|
||||||
|
|
||||||
mVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), displayGroup);
|
|
||||||
mFullScreenCheckBox = new QCheckBox(tr("Full Screen"), displayGroup);
|
|
||||||
|
|
||||||
QLabel *antiAliasingLabel = new QLabel(tr("Antialiasing:"), displayGroup);
|
|
||||||
QLabel *resolutionLabel = new QLabel(tr("Resolution:"), displayGroup);
|
|
||||||
|
|
||||||
mResolutionComboBox = new QComboBox(displayGroup);
|
|
||||||
mAntiAliasingComboBox = new QComboBox(displayGroup);
|
|
||||||
|
|
||||||
QVBoxLayout *rendererGroupLayout = new QVBoxLayout(rendererGroup);
|
|
||||||
rendererGroupLayout->addLayout(renderSystemLayout);
|
|
||||||
|
|
||||||
QGridLayout *displayGroupLayout = new QGridLayout(displayGroup);
|
|
||||||
displayGroupLayout->addWidget(mVSyncCheckBox, 0, 0, 1, 1);
|
|
||||||
displayGroupLayout->addWidget(mFullScreenCheckBox, 1, 0, 1, 1);
|
|
||||||
displayGroupLayout->addWidget(antiAliasingLabel, 2, 0, 1, 1);
|
|
||||||
displayGroupLayout->addWidget(mAntiAliasingComboBox, 2, 1, 1, 1);
|
|
||||||
displayGroupLayout->addWidget(resolutionLabel, 3, 0, 1, 1);
|
|
||||||
displayGroupLayout->addWidget(mResolutionComboBox, 3, 1, 1, 1);
|
|
||||||
|
|
||||||
// Layout for the whole page
|
|
||||||
QVBoxLayout *pageLayout = new QVBoxLayout(this);
|
|
||||||
QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
|
||||||
|
|
||||||
pageLayout->addWidget(rendererGroup);
|
|
||||||
pageLayout->addWidget(displayGroup);
|
|
||||||
pageLayout->addItem(vSpacer1);
|
|
||||||
|
|
||||||
connect(mRendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsPage::setupOgre()
|
bool GraphicsPage::setupOgre()
|
||||||
|
@ -116,11 +87,11 @@ bool GraphicsPage::setupOgre()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::path absPluginPath = boost::filesystem::absolute(boost::filesystem::path(pluginDir));
|
QDir dir(QString::fromStdString(pluginDir));
|
||||||
|
pluginDir = dir.absolutePath().toStdString();
|
||||||
pluginDir = absPluginPath.string();
|
|
||||||
|
|
||||||
Files::loadOgrePlugin(pluginDir, "RenderSystem_GL", *mOgre);
|
Files::loadOgrePlugin(pluginDir, "RenderSystem_GL", *mOgre);
|
||||||
|
Files::loadOgrePlugin(pluginDir, "RenderSystem_GL3Plus", *mOgre);
|
||||||
Files::loadOgrePlugin(pluginDir, "RenderSystem_Direct3D9", *mOgre);
|
Files::loadOgrePlugin(pluginDir, "RenderSystem_Direct3D9", *mOgre);
|
||||||
|
|
||||||
#ifdef ENABLE_PLUGIN_GL
|
#ifdef ENABLE_PLUGIN_GL
|
||||||
|
@ -137,7 +108,7 @@ bool GraphicsPage::setupOgre()
|
||||||
|
|
||||||
for (Ogre::RenderSystemList::const_iterator r = renderers.begin(); r != renderers.end(); ++r) {
|
for (Ogre::RenderSystemList::const_iterator r = renderers.begin(); r != renderers.end(); ++r) {
|
||||||
mSelectedRenderSystem = *r;
|
mSelectedRenderSystem = *r;
|
||||||
mRendererComboBox->addItem((*r)->getName().c_str());
|
rendererComboBox->addItem((*r)->getName().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString openGLName = QString("OpenGL Rendering Subsystem");
|
QString openGLName = QString("OpenGL Rendering Subsystem");
|
||||||
|
@ -153,71 +124,85 @@ bool GraphicsPage::setupOgre()
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>Could not select a valid render system</b><br><br> \
|
msgBox.setText(tr("<br><b>Could not select a valid render system</b><br><br> \
|
||||||
Please make sure the plugins.cfg file exists and contains a valid rendering plugin.<br>"));
|
Please make sure the plugins.cfg file exists and contains a valid rendering plugin.<br>"));
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now fill the GUI elements
|
// Now fill the GUI elements
|
||||||
int index = mRendererComboBox->findText(QString::fromStdString(Settings::Manager::getString("render system", "Video")));
|
int index = rendererComboBox->findText(mGraphicsSettings.value(QString("Video/render system")));
|
||||||
|
|
||||||
if ( index != -1) {
|
if ( index != -1) {
|
||||||
mRendererComboBox->setCurrentIndex(index);
|
rendererComboBox->setCurrentIndex(index);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
|
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
|
||||||
mRendererComboBox->setCurrentIndex(mRendererComboBox->findText(direct3DName));
|
rendererComboBox->setCurrentIndex(rendererComboBox->findText(direct3DName));
|
||||||
#else
|
#else
|
||||||
mRendererComboBox->setCurrentIndex(mRendererComboBox->findText(openGLName));
|
rendererComboBox->setCurrentIndex(rendererComboBox->findText(openGLName));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
mAntiAliasingComboBox->clear();
|
antiAliasingComboBox->clear();
|
||||||
mResolutionComboBox->clear();
|
resolutionComboBox->clear();
|
||||||
mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
|
antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
|
||||||
mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem));
|
resolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem));
|
||||||
|
|
||||||
readConfig();
|
// Load the rest of the values
|
||||||
|
loadSettings();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPage::readConfig()
|
void GraphicsPage::loadSettings()
|
||||||
{
|
{
|
||||||
if (Settings::Manager::getBool("vsync", "Video"))
|
if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true"))
|
||||||
mVSyncCheckBox->setCheckState(Qt::Checked);
|
vSyncCheckBox->setCheckState(Qt::Checked);
|
||||||
|
|
||||||
if (Settings::Manager::getBool("fullscreen", "Video"))
|
if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true"))
|
||||||
mFullScreenCheckBox->setCheckState(Qt::Checked);
|
fullScreenCheckBox->setCheckState(Qt::Checked);
|
||||||
|
|
||||||
int aaIndex = mAntiAliasingComboBox->findText(QString::fromStdString(Settings::Manager::getString("antialiasing", "Video")));
|
int aaIndex = antiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing")));
|
||||||
if (aaIndex != -1)
|
if (aaIndex != -1)
|
||||||
mAntiAliasingComboBox->setCurrentIndex(aaIndex);
|
antiAliasingComboBox->setCurrentIndex(aaIndex);
|
||||||
|
|
||||||
QString resolution = QString::number(Settings::Manager::getInt("resolution x", "Video"));
|
QString width = mGraphicsSettings.value(QString("Video/resolution x"));
|
||||||
resolution.append(" x " + QString::number(Settings::Manager::getInt("resolution y", "Video")));
|
QString height = mGraphicsSettings.value(QString("Video/resolution y"));
|
||||||
|
QString resolution = width + QString(" x ") + height;
|
||||||
|
|
||||||
int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith);
|
int resIndex = resolutionComboBox->findText(resolution, Qt::MatchStartsWith);
|
||||||
if (resIndex != -1)
|
|
||||||
mResolutionComboBox->setCurrentIndex(resIndex);
|
if (resIndex != -1) {
|
||||||
|
standardRadioButton->toggle();
|
||||||
|
resolutionComboBox->setCurrentIndex(resIndex);
|
||||||
|
} else {
|
||||||
|
customRadioButton->toggle();
|
||||||
|
customWidthSpinBox->setValue(width.toInt());
|
||||||
|
customHeightSpinBox->setValue(height.toInt());
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPage::writeConfig()
|
void GraphicsPage::saveSettings()
|
||||||
{
|
{
|
||||||
Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState());
|
vSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true"))
|
||||||
Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState());
|
: mGraphicsSettings.setValue(QString("Video/vsync"), QString("false"));
|
||||||
Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString());
|
|
||||||
Settings::Manager::setString("render system", "Video", mRendererComboBox->currentText().toStdString());
|
|
||||||
|
|
||||||
// Get the current resolution, but with the tabs replaced with a single space
|
fullScreenCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("true"))
|
||||||
QString resolution = mResolutionComboBox->currentText().simplified();
|
: mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("false"));
|
||||||
QStringList tokens = resolution.split(" ", QString::SkipEmptyParts);
|
|
||||||
|
|
||||||
int resX = tokens.at(0).toInt();
|
mGraphicsSettings.setValue(QString("Video/antialiasing"), antiAliasingComboBox->currentText());
|
||||||
int resY = tokens.at(2).toInt();
|
mGraphicsSettings.setValue(QString("Video/render system"), rendererComboBox->currentText());
|
||||||
Settings::Manager::setInt("resolution x", "Video", resX);
|
|
||||||
Settings::Manager::setInt("resolution y", "Video", resY);
|
|
||||||
|
if (standardRadioButton->isChecked()) {
|
||||||
|
QRegExp resolutionRe(QString("(\\d+) x (\\d+).*"));
|
||||||
|
|
||||||
|
if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) {
|
||||||
|
mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1));
|
||||||
|
mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mGraphicsSettings.setValue(QString("Video/resolution x"), QString::number(customWidthSpinBox->value()));
|
||||||
|
mGraphicsSettings.setValue(QString("Video/resolution y"), QString::number(customHeightSpinBox->value()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
|
QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
|
||||||
|
@ -231,16 +216,14 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy
|
||||||
{
|
{
|
||||||
Ogre::StringVector::iterator opt_it;
|
Ogre::StringVector::iterator opt_it;
|
||||||
uint idx = 0;
|
uint idx = 0;
|
||||||
for (opt_it = i->second.possibleValues.begin ();
|
|
||||||
opt_it != i->second.possibleValues.end (); opt_it++, idx++)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0)
|
for (opt_it = i->second.possibleValues.begin();
|
||||||
{
|
opt_it != i->second.possibleValues.end(); opt_it++, idx++)
|
||||||
|
{
|
||||||
|
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) {
|
||||||
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
|
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort ascending
|
// Sort ascending
|
||||||
|
@ -257,7 +240,7 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy
|
||||||
|
|
||||||
QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer)
|
QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer)
|
||||||
{
|
{
|
||||||
QString key ("Video Mode");
|
QString key("Video Mode");
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
|
||||||
uint row = 0;
|
uint row = 0;
|
||||||
|
@ -274,24 +257,26 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer)
|
||||||
for (opt_it = i->second.possibleValues.begin ();
|
for (opt_it = i->second.possibleValues.begin ();
|
||||||
opt_it != i->second.possibleValues.end (); opt_it++, idx++)
|
opt_it != i->second.possibleValues.end (); opt_it++, idx++)
|
||||||
{
|
{
|
||||||
QString qval = QString::fromStdString(*opt_it).simplified();
|
QRegExp resolutionRe(QString("(\\d+) x (\\d+)"));
|
||||||
// remove extra tokens after the resolution (for example bpp, can be there or not depending on rendersystem)
|
QString resolution = QString::fromStdString(*opt_it).simplified();
|
||||||
QStringList tokens = qval.split(" ", QString::SkipEmptyParts);
|
|
||||||
assert (tokens.size() >= 3);
|
|
||||||
QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2);
|
|
||||||
|
|
||||||
QString aspect = getAspect(tokens.at(0).toInt(),tokens.at(2).toInt());
|
if (resolutionRe.exactMatch(resolution)) {
|
||||||
|
|
||||||
if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) {
|
int width = resolutionRe.cap(1).toInt();
|
||||||
resolutionStr.append(tr("\t(Widescreen ") + aspect + ")");
|
int height = resolutionRe.cap(2).toInt();
|
||||||
|
|
||||||
} else if (aspect == QLatin1String("4:3")) {
|
QString aspect = getAspect(width, height);
|
||||||
resolutionStr.append(tr("\t(Standard 4:3)"));
|
|
||||||
|
if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) {
|
||||||
|
resolution.append(tr("\t(Wide ") + aspect + ")");
|
||||||
|
|
||||||
|
} else if (aspect == QLatin1String("4:3")) {
|
||||||
|
resolution.append(tr("\t(Standard 4:3)"));
|
||||||
|
}
|
||||||
|
// do not add duplicate resolutions
|
||||||
|
if (!result.contains(resolution))
|
||||||
|
result.append(resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not add duplicate resolutions
|
|
||||||
if (!result.contains(resolutionStr))
|
|
||||||
result << resolutionStr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,9 +290,36 @@ void GraphicsPage::rendererChanged(const QString &renderer)
|
||||||
{
|
{
|
||||||
mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString());
|
mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString());
|
||||||
|
|
||||||
mAntiAliasingComboBox->clear();
|
antiAliasingComboBox->clear();
|
||||||
mResolutionComboBox->clear();
|
resolutionComboBox->clear();
|
||||||
|
|
||||||
mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
|
antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
|
||||||
mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem));
|
resolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsPage::slotFullScreenChanged(int state)
|
||||||
|
{
|
||||||
|
if (state == Qt::Checked) {
|
||||||
|
standardRadioButton->toggle();
|
||||||
|
customRadioButton->setEnabled(false);
|
||||||
|
customWidthSpinBox->setEnabled(false);
|
||||||
|
customHeightSpinBox->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
customRadioButton->setEnabled(true);
|
||||||
|
customWidthSpinBox->setEnabled(true);
|
||||||
|
customHeightSpinBox->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsPage::slotStandardToggled(bool checked)
|
||||||
|
{
|
||||||
|
if (checked) {
|
||||||
|
resolutionComboBox->setEnabled(true);
|
||||||
|
customWidthSpinBox->setEnabled(false);
|
||||||
|
customHeightSpinBox->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
resolutionComboBox->setEnabled(false);
|
||||||
|
customWidthSpinBox->setEnabled(true);
|
||||||
|
customHeightSpinBox->setEnabled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
#include <OgreRoot.h>
|
#include <OgreRoot.h>
|
||||||
#include <OgreRenderSystem.h>
|
#include <OgreRenderSystem.h>
|
||||||
#include <OgreConfigFile.h>
|
//#include <OgreConfigFile.h>
|
||||||
#include <OgreConfigDialog.h>
|
//#include <OgreConfigDialog.h>
|
||||||
|
|
||||||
// Static plugin headers
|
// Static plugin headers
|
||||||
#ifdef ENABLE_PLUGIN_GL
|
#ifdef ENABLE_PLUGIN_GL
|
||||||
|
@ -16,26 +16,29 @@
|
||||||
# include "OgreD3D9Plugin.h"
|
# include "OgreD3D9Plugin.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class QComboBox;
|
#include "ui_graphicspage.h"
|
||||||
class QCheckBox;
|
|
||||||
class QStackedWidget;
|
class GraphicsSettings;
|
||||||
class QSettings;
|
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files { struct ConfigurationManager; }
|
||||||
|
|
||||||
class GraphicsPage : public QWidget
|
class GraphicsPage : public QWidget, private Ui::GraphicsPage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent = 0);
|
GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSettings, QWidget *parent = 0);
|
||||||
|
|
||||||
|
void saveSettings();
|
||||||
bool setupOgre();
|
bool setupOgre();
|
||||||
void writeConfig();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void rendererChanged(const QString &renderer);
|
void rendererChanged(const QString &renderer);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void slotFullScreenChanged(int state);
|
||||||
|
void slotStandardToggled(bool checked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ogre::Root *mOgre;
|
Ogre::Root *mOgre;
|
||||||
Ogre::RenderSystem *mSelectedRenderSystem;
|
Ogre::RenderSystem *mSelectedRenderSystem;
|
||||||
|
@ -48,22 +51,14 @@ private:
|
||||||
Ogre::D3D9Plugin* mD3D9Plugin;
|
Ogre::D3D9Plugin* mD3D9Plugin;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QComboBox *mRendererComboBox;
|
|
||||||
|
|
||||||
QStackedWidget *mDisplayStackedWidget;
|
|
||||||
|
|
||||||
QComboBox *mAntiAliasingComboBox;
|
|
||||||
QComboBox *mResolutionComboBox;
|
|
||||||
QCheckBox *mVSyncCheckBox;
|
|
||||||
QCheckBox *mFullScreenCheckBox;
|
|
||||||
|
|
||||||
Files::ConfigurationManager &mCfgMgr;
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
|
GraphicsSettings &mGraphicsSettings;
|
||||||
|
|
||||||
QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer);
|
QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer);
|
||||||
QStringList getAvailableResolutions(Ogre::RenderSystem *renderer);
|
QStringList getAvailableResolutions(Ogre::RenderSystem *renderer);
|
||||||
|
|
||||||
void createPages();
|
void loadSettings();
|
||||||
void readConfig();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QTextCodec>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
|
||||||
|
|
||||||
#include "maindialog.hpp"
|
#include "maindialog.hpp"
|
||||||
|
|
||||||
|
@ -30,14 +30,17 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
QDir::setCurrent(dir.absolutePath());
|
QDir::setCurrent(dir.absolutePath());
|
||||||
|
|
||||||
|
// Support non-latin characters
|
||||||
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
MainDialog mainWin;
|
MainDialog mainWin;
|
||||||
|
|
||||||
if (mainWin.setup()) {
|
if (mainWin.setup()) {
|
||||||
|
|
||||||
mainWin.show();
|
mainWin.show();
|
||||||
return app.exec();
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,52 +1,16 @@
|
||||||
|
#include "maindialog.hpp"
|
||||||
|
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
|
||||||
#include "maindialog.hpp"
|
#include "utils/checkablemessagebox.hpp"
|
||||||
|
|
||||||
#include "playpage.hpp"
|
#include "playpage.hpp"
|
||||||
#include "graphicspage.hpp"
|
#include "graphicspage.hpp"
|
||||||
#include "datafilespage.hpp"
|
#include "datafilespage.hpp"
|
||||||
|
|
||||||
MainDialog::MainDialog()
|
MainDialog::MainDialog()
|
||||||
|
: mGameSettings(mCfgMgr)
|
||||||
{
|
{
|
||||||
QWidget *centralWidget = new QWidget(this);
|
|
||||||
setCentralWidget(centralWidget);
|
|
||||||
|
|
||||||
mIconWidget = new QListWidget(centralWidget);
|
|
||||||
mIconWidget->setObjectName("IconWidget");
|
|
||||||
mIconWidget->setViewMode(QListView::IconMode);
|
|
||||||
mIconWidget->setWrapping(false);
|
|
||||||
mIconWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Just to be sure
|
|
||||||
mIconWidget->setIconSize(QSize(48, 48));
|
|
||||||
mIconWidget->setMovement(QListView::Static);
|
|
||||||
|
|
||||||
mIconWidget->setMinimumWidth(400);
|
|
||||||
mIconWidget->setFixedHeight(80);
|
|
||||||
mIconWidget->setSpacing(4);
|
|
||||||
mIconWidget->setCurrentRow(0);
|
|
||||||
mIconWidget->setFlow(QListView::LeftToRight);
|
|
||||||
|
|
||||||
QGroupBox *groupBox = new QGroupBox(centralWidget);
|
|
||||||
QVBoxLayout *groupLayout = new QVBoxLayout(groupBox);
|
|
||||||
|
|
||||||
mPagesWidget = new QStackedWidget(groupBox);
|
|
||||||
groupLayout->addWidget(mPagesWidget);
|
|
||||||
|
|
||||||
QPushButton *playButton = new QPushButton(tr("Play"));
|
|
||||||
|
|
||||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(centralWidget);
|
|
||||||
buttonBox->setStandardButtons(QDialogButtonBox::Close);
|
|
||||||
buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole);
|
|
||||||
|
|
||||||
QVBoxLayout *dialogLayout = new QVBoxLayout(centralWidget);
|
|
||||||
dialogLayout->addWidget(mIconWidget);
|
|
||||||
dialogLayout->addWidget(groupBox);
|
|
||||||
dialogLayout->addWidget(buttonBox);
|
|
||||||
|
|
||||||
setWindowTitle(tr("OpenMW Launcher"));
|
|
||||||
setWindowIcon(QIcon(":/images/openmw.png"));
|
|
||||||
// Remove what's this? button
|
|
||||||
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
||||||
setMinimumSize(QSize(575, 575));
|
|
||||||
|
|
||||||
// Install the stylesheet font
|
// Install the stylesheet font
|
||||||
QFile file;
|
QFile file;
|
||||||
QFontDatabase fontDatabase;
|
QFontDatabase fontDatabase;
|
||||||
|
@ -56,64 +20,67 @@ MainDialog::MainDialog()
|
||||||
// Check if the font is installed
|
// Check if the font is installed
|
||||||
if (!fonts.contains("EB Garamond")) {
|
if (!fonts.contains("EB Garamond")) {
|
||||||
|
|
||||||
QString font = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/mygui/EBGaramond-Regular.ttf").string());
|
QString font = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
||||||
file.setFileName(font);
|
file.setFileName(font);
|
||||||
|
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
font = QString::fromStdString((mCfgMgr.getLocalPath() / "resources/mygui/EBGaramond-Regular.ttf").string());
|
font = QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
fontDatabase.addApplicationFont(font);
|
fontDatabase.addApplicationFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the stylesheet
|
setupUi(this);
|
||||||
QString config = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/launcher.qss").string());
|
|
||||||
file.setFileName(config);
|
|
||||||
|
|
||||||
if (!file.exists()) {
|
iconWidget->setViewMode(QListView::IconMode);
|
||||||
file.setFileName(QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.qss").string()));
|
iconWidget->setWrapping(false);
|
||||||
}
|
iconWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Just to be sure
|
||||||
|
iconWidget->setIconSize(QSize(48, 48));
|
||||||
|
iconWidget->setMovement(QListView::Static);
|
||||||
|
|
||||||
file.open(QFile::ReadOnly);
|
iconWidget->setSpacing(4);
|
||||||
QString styleSheet = QLatin1String(file.readAll());
|
iconWidget->setCurrentRow(0);
|
||||||
qApp->setStyleSheet(styleSheet);
|
iconWidget->setFlow(QListView::LeftToRight);
|
||||||
file.close();
|
|
||||||
|
QPushButton *playButton = new QPushButton(tr("Play"));
|
||||||
|
buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole);
|
||||||
|
|
||||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
|
||||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(play()));
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(play()));
|
||||||
|
|
||||||
|
// Remove what's this? button
|
||||||
|
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
createIcons();
|
createIcons();
|
||||||
createPages();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::createIcons()
|
void MainDialog::createIcons()
|
||||||
{
|
{
|
||||||
if (!QIcon::hasThemeIcon("document-new")) {
|
if (!QIcon::hasThemeIcon("document-new"))
|
||||||
QIcon::setThemeName("tango");
|
QIcon::setThemeName("tango");
|
||||||
}
|
|
||||||
|
|
||||||
// We create a fallback icon because the default fallback doesn't work
|
// We create a fallback icon because the default fallback doesn't work
|
||||||
QIcon graphicsIcon = QIcon(":/icons/tango/video-display.png");
|
QIcon graphicsIcon = QIcon(":/icons/tango/video-display.png");
|
||||||
|
|
||||||
QListWidgetItem *playButton = new QListWidgetItem(mIconWidget);
|
QListWidgetItem *playButton = new QListWidgetItem(iconWidget);
|
||||||
playButton->setIcon(QIcon(":/images/openmw.png"));
|
playButton->setIcon(QIcon(":/images/openmw.png"));
|
||||||
playButton->setText(tr("Play"));
|
playButton->setText(tr("Play"));
|
||||||
playButton->setTextAlignment(Qt::AlignCenter);
|
playButton->setTextAlignment(Qt::AlignCenter);
|
||||||
playButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
playButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||||
|
|
||||||
QListWidgetItem *graphicsButton = new QListWidgetItem(mIconWidget);
|
QListWidgetItem *graphicsButton = new QListWidgetItem(iconWidget);
|
||||||
graphicsButton->setIcon(QIcon::fromTheme("video-display", graphicsIcon));
|
graphicsButton->setIcon(QIcon::fromTheme("video-display", graphicsIcon));
|
||||||
graphicsButton->setText(tr("Graphics"));
|
graphicsButton->setText(tr("Graphics"));
|
||||||
graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute);
|
graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute);
|
||||||
graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||||
|
|
||||||
QListWidgetItem *dataFilesButton = new QListWidgetItem(mIconWidget);
|
QListWidgetItem *dataFilesButton = new QListWidgetItem(iconWidget);
|
||||||
dataFilesButton->setIcon(QIcon(":/images/openmw-plugin.png"));
|
dataFilesButton->setIcon(QIcon(":/images/openmw-plugin.png"));
|
||||||
dataFilesButton->setText(tr("Data Files"));
|
dataFilesButton->setText(tr("Data Files"));
|
||||||
dataFilesButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
dataFilesButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||||
dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||||
|
|
||||||
connect(mIconWidget,
|
connect(iconWidget,
|
||||||
SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
|
SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
|
||||||
this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*)));
|
this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*)));
|
||||||
|
|
||||||
|
@ -122,77 +89,183 @@ void MainDialog::createIcons()
|
||||||
void MainDialog::createPages()
|
void MainDialog::createPages()
|
||||||
{
|
{
|
||||||
mPlayPage = new PlayPage(this);
|
mPlayPage = new PlayPage(this);
|
||||||
mGraphicsPage = new GraphicsPage(mCfgMgr, this);
|
mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this);
|
||||||
mDataFilesPage = new DataFilesPage(mCfgMgr, this);
|
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||||
|
|
||||||
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
||||||
mPlayPage->mProfilesComboBox->setModel(mDataFilesPage->mProfilesComboBox->model());
|
mPlayPage->setProfilesComboBoxModel(mDataFilesPage->profilesComboBoxModel());
|
||||||
mPlayPage->mProfilesComboBox->setCurrentIndex(mDataFilesPage->mProfilesComboBox->currentIndex());
|
mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->profilesComboBoxIndex());
|
||||||
|
|
||||||
// Add the pages to the stacked widget
|
// Add the pages to the stacked widget
|
||||||
mPagesWidget->addWidget(mPlayPage);
|
pagesWidget->addWidget(mPlayPage);
|
||||||
mPagesWidget->addWidget(mGraphicsPage);
|
pagesWidget->addWidget(mGraphicsPage);
|
||||||
mPagesWidget->addWidget(mDataFilesPage);
|
pagesWidget->addWidget(mDataFilesPage);
|
||||||
|
|
||||||
// Select the first page
|
// Select the first page
|
||||||
mIconWidget->setCurrentItem(mIconWidget->item(0), QItemSelectionModel::Select);
|
iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select);
|
||||||
|
|
||||||
connect(mPlayPage->mPlayButton, SIGNAL(clicked()), this, SLOT(play()));
|
connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play()));
|
||||||
|
|
||||||
connect(mPlayPage->mProfilesComboBox,
|
connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage, SLOT(setProfilesComboBoxIndex(int)));
|
||||||
SIGNAL(currentIndexChanged(int)),
|
connect(mDataFilesPage, SIGNAL(profileChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int)));
|
||||||
mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int)));
|
|
||||||
|
|
||||||
connect(mDataFilesPage->mProfilesComboBox,
|
|
||||||
SIGNAL(currentIndexChanged(int)),
|
|
||||||
mPlayPage->mProfilesComboBox, SLOT(setCurrentIndex(int)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainDialog::showFirstRunDialog()
|
||||||
|
{
|
||||||
|
CheckableMessageBox msgBox(this);
|
||||||
|
msgBox.setWindowTitle(tr("Morrowind installation detected"));
|
||||||
|
|
||||||
|
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion);
|
||||||
|
int size = QApplication::style()->pixelMetric(QStyle::PM_MessageBoxIconSize);
|
||||||
|
msgBox.setIconPixmap(icon.pixmap(size, size));
|
||||||
|
|
||||||
|
|
||||||
|
QAbstractButton *importerButton =
|
||||||
|
msgBox.addButton(tr("Import"), QDialogButtonBox::AcceptRole); // ActionRole doesn't work?!
|
||||||
|
QAbstractButton *skipButton =
|
||||||
|
msgBox.addButton(tr("Skip"), QDialogButtonBox::RejectRole);
|
||||||
|
|
||||||
|
Q_UNUSED(skipButton); // Surpress compiler unused warning
|
||||||
|
|
||||||
|
msgBox.setStandardButtons(QDialogButtonBox::NoButton);
|
||||||
|
|
||||||
|
msgBox.setText(tr("<br><b>An existing Morrowind installation was detected</b><br><br> \
|
||||||
|
Would you like to import settings from Morrowind.ini?<br>"));
|
||||||
|
|
||||||
|
msgBox.setCheckBoxText(tr("Include selected masters and plugins (creates a new profile)"));
|
||||||
|
msgBox.exec();
|
||||||
|
|
||||||
|
|
||||||
|
if (msgBox.clickedButton() == importerButton) {
|
||||||
|
|
||||||
|
QStringList iniPaths;
|
||||||
|
|
||||||
|
foreach (const QString &path, mGameSettings.getDataDirs()) {
|
||||||
|
QDir dir(path);
|
||||||
|
dir.setPath(dir.canonicalPath()); // Resolve symlinks
|
||||||
|
|
||||||
|
if (!dir.cdUp())
|
||||||
|
continue; // Cannot move from Data Files
|
||||||
|
|
||||||
|
if (dir.exists(QString("Morrowind.ini")))
|
||||||
|
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iniPaths.isEmpty()) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error reading Morrowind configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(QObject::tr("<br><b>Could not find Morrowind.ini</b><br><br> \
|
||||||
|
The problem may be due to an incomplete installation of Morrowind.<br> \
|
||||||
|
Reinstalling Morrowind may resolve the problem."));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iniPaths.count() > 1) {
|
||||||
|
// Multiple Morrowind.ini files found
|
||||||
|
bool ok;
|
||||||
|
QString path = QInputDialog::getItem(this, tr("Multiple configurations found"),
|
||||||
|
tr("<br><b>There are multiple Morrowind.ini files found.</b><br><br> \
|
||||||
|
Please select the one you wish to import from:"), iniPaths, 0, false, &ok);
|
||||||
|
if (ok && !path.isEmpty()) {
|
||||||
|
iniPaths.clear();
|
||||||
|
iniPaths.append(path);
|
||||||
|
} else {
|
||||||
|
// Cancel was clicked TODO: should we abort here?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the file if it doesn't already exist, else the importer will fail
|
||||||
|
QString path = QString::fromStdString(mCfgMgr.getUserPath().string()) + QString("openmw.cfg");
|
||||||
|
QFile file(path);
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
if (!file.open(QIODevice::ReadWrite)) {
|
||||||
|
// File cannot be created
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||||
|
Please make sure you have the right permissions \
|
||||||
|
and try again.<br>").arg(file.fileName()));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the arguments to run the importer
|
||||||
|
QStringList arguments;
|
||||||
|
|
||||||
|
if (msgBox.isChecked())
|
||||||
|
arguments.append(QString("-g"));
|
||||||
|
|
||||||
|
arguments.append(iniPaths.first());
|
||||||
|
arguments.append(path);
|
||||||
|
|
||||||
|
if (!startProgram(QString("mwiniimport"), arguments, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Re-read the game settings
|
||||||
|
if (!setupGameSettings())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Add a new profile
|
||||||
|
if (msgBox.isChecked()) {
|
||||||
|
mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), QString("Imported"));
|
||||||
|
|
||||||
|
mLauncherSettings.remove(QString("Profiles/Imported/master"));
|
||||||
|
mLauncherSettings.remove(QString("Profiles/Imported/plugin"));
|
||||||
|
|
||||||
|
QStringList masters = mGameSettings.values(QString("master"));
|
||||||
|
QStringList plugins = mGameSettings.values(QString("plugin"));
|
||||||
|
|
||||||
|
foreach (const QString &master, masters) {
|
||||||
|
mLauncherSettings.setMultiValue(QString("Profiles/Imported/master"), master);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QString &plugin, plugins) {
|
||||||
|
mLauncherSettings.setMultiValue(QString("Profiles/Imported/plugin"), plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool MainDialog::setup()
|
bool MainDialog::setup()
|
||||||
{
|
{
|
||||||
// Create the settings manager and load default settings file
|
if (!setupLauncherSettings())
|
||||||
const std::string localdefault = (mCfgMgr.getLocalPath() / "settings-default.cfg").string();
|
|
||||||
const std::string globaldefault = (mCfgMgr.getGlobalPath() / "settings-default.cfg").string();
|
|
||||||
|
|
||||||
// prefer local
|
|
||||||
if (boost::filesystem::exists(localdefault)) {
|
|
||||||
mSettings.loadDefault(localdefault);
|
|
||||||
} else if (boost::filesystem::exists(globaldefault)) {
|
|
||||||
mSettings.loadDefault(globaldefault);
|
|
||||||
} else {
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setWindowTitle("Error reading OpenMW configuration file");
|
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
||||||
msgBox.setText(tr("<br><b>Could not find %0</b><br><br> \
|
|
||||||
The problem may be due to an incomplete installation of OpenMW.<br> \
|
|
||||||
Reinstalling OpenMW may resolve the problem.").arg(QString::fromStdString(globaldefault)));
|
|
||||||
msgBox.exec();
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!setupGameSettings())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!setupGraphicsSettings())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if we need to show the importer
|
||||||
|
if (mLauncherSettings.value(QString("General/firstrun"), QString("true")) == QLatin1String("true"))
|
||||||
|
{
|
||||||
|
if (!showFirstRunDialog())
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load user settings if they exist, otherwise just load the default settings as user settings
|
// Now create the pages as they need the settings
|
||||||
const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string();
|
createPages();
|
||||||
|
|
||||||
if (boost::filesystem::exists(settingspath))
|
// Call this so we can exit on Ogre errors before mainwindow is shown
|
||||||
mSettings.loadUser(settingspath);
|
if (!mGraphicsPage->setupOgre())
|
||||||
else if (boost::filesystem::exists(localdefault))
|
|
||||||
mSettings.loadUser(localdefault);
|
|
||||||
else if (boost::filesystem::exists(globaldefault))
|
|
||||||
mSettings.loadUser(globaldefault);
|
|
||||||
|
|
||||||
// Setup the Graphics page
|
|
||||||
if (!mGraphicsPage->setupOgre()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the Data Files page
|
|
||||||
if (!mDataFilesPage->setupDataFiles()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,89 +274,410 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous)
|
||||||
if (!current)
|
if (!current)
|
||||||
current = previous;
|
current = previous;
|
||||||
|
|
||||||
mPagesWidget->setCurrentIndex(mIconWidget->row(current));
|
pagesWidget->setCurrentIndex(iconWidget->row(current));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainDialog::setupLauncherSettings()
|
||||||
|
{
|
||||||
|
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||||
|
|
||||||
|
QStringList paths;
|
||||||
|
paths.append(QString("launcher.cfg"));
|
||||||
|
paths.append(userPath + QString("launcher.cfg"));
|
||||||
|
|
||||||
|
foreach (const QString &path, paths) {
|
||||||
|
qDebug() << "Loading config file:" << qPrintable(path);
|
||||||
|
QFile file(path);
|
||||||
|
if (file.exists()) {
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||||
|
Please make sure you have the right permissions \
|
||||||
|
and try again.<br>").arg(file.fileName()));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
|
mLauncherSettings.readFile(stream);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainDialog::setupGameSettings()
|
||||||
|
{
|
||||||
|
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||||
|
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
||||||
|
|
||||||
|
QStringList paths;
|
||||||
|
paths.append(userPath + QString("openmw.cfg"));
|
||||||
|
paths.append(QString("openmw.cfg"));
|
||||||
|
paths.append(globalPath + QString("openmw.cfg"));
|
||||||
|
|
||||||
|
foreach (const QString &path, paths) {
|
||||||
|
qDebug() << "Loading config file:" << qPrintable(path);
|
||||||
|
|
||||||
|
QFile file(path);
|
||||||
|
if (file.exists()) {
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||||
|
Please make sure you have the right permissions \
|
||||||
|
and try again.<br>").arg(file.fileName()));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
|
mGameSettings.readFile(stream);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList dataDirs;
|
||||||
|
|
||||||
|
// Check if the paths actually contain data files
|
||||||
|
foreach (const QString path, mGameSettings.getDataDirs()) {
|
||||||
|
QDir dir(path);
|
||||||
|
QStringList filters;
|
||||||
|
filters << "*.esp" << "*.esm";
|
||||||
|
|
||||||
|
if (!dir.entryList(filters).isEmpty())
|
||||||
|
dataDirs.append(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataDirs.isEmpty())
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error detecting Morrowind installation"));
|
||||||
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Cancel);
|
||||||
|
msgBox.setText(QObject::tr("<br><b>Could not find the Data Files location</b><br><br> \
|
||||||
|
The directory containing the data files was not found.<br><br> \
|
||||||
|
Press \"Browse...\" to specify the location manually.<br>"));
|
||||||
|
|
||||||
|
QAbstractButton *dirSelectButton =
|
||||||
|
msgBox.addButton(QObject::tr("B&rowse..."), QMessageBox::ActionRole);
|
||||||
|
|
||||||
|
msgBox.exec();
|
||||||
|
|
||||||
|
QString selectedFile;
|
||||||
|
if (msgBox.clickedButton() == dirSelectButton) {
|
||||||
|
selectedFile = QFileDialog::getOpenFileName(
|
||||||
|
NULL,
|
||||||
|
QObject::tr("Select master file"),
|
||||||
|
QDir::currentPath(),
|
||||||
|
QString(tr("Morrowind master file (*.esm)")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedFile.isEmpty())
|
||||||
|
return false; // Cancel was clicked;
|
||||||
|
|
||||||
|
QFileInfo info(selectedFile);
|
||||||
|
|
||||||
|
// Add the new dir to the settings file and to the data dir container
|
||||||
|
mGameSettings.setMultiValue(QString("data"), info.absolutePath());
|
||||||
|
mGameSettings.addDataDir(info.absolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainDialog::setupGraphicsSettings()
|
||||||
|
{
|
||||||
|
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||||
|
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
||||||
|
|
||||||
|
QFile localDefault(QString("settings-default.cfg"));
|
||||||
|
QFile globalDefault(globalPath + QString("settings-default.cfg"));
|
||||||
|
|
||||||
|
if (!localDefault.exists() && !globalDefault.exists()) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error reading OpenMW configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(QObject::tr("<br><b>Could not find settings-default.cfg</b><br><br> \
|
||||||
|
The problem may be due to an incomplete installation of OpenMW.<br> \
|
||||||
|
Reinstalling OpenMW may resolve the problem."));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QStringList paths;
|
||||||
|
paths.append(globalPath + QString("settings-default.cfg"));
|
||||||
|
paths.append(QString("settings-default.cfg"));
|
||||||
|
paths.append(userPath + QString("settings.cfg"));
|
||||||
|
|
||||||
|
foreach (const QString &path, paths) {
|
||||||
|
qDebug() << "Loading config file:" << qPrintable(path);
|
||||||
|
QFile file(path);
|
||||||
|
if (file.exists()) {
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||||
|
Please make sure you have the right permissions \
|
||||||
|
and try again.<br>").arg(file.fileName()));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
|
mGraphicsSettings.readFile(stream);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::loadSettings()
|
||||||
|
{
|
||||||
|
int width = mLauncherSettings.value(QString("General/MainWindow/width")).toInt();
|
||||||
|
int height = mLauncherSettings.value(QString("General/MainWindow/height")).toInt();
|
||||||
|
|
||||||
|
int posX = mLauncherSettings.value(QString("General/MainWindow/posx")).toInt();
|
||||||
|
int posY = mLauncherSettings.value(QString("General/MainWindow/posy")).toInt();
|
||||||
|
|
||||||
|
resize(width, height);
|
||||||
|
move(posX, posY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::saveSettings()
|
||||||
|
{
|
||||||
|
QString width = QString::number(this->width());
|
||||||
|
QString height = QString::number(this->height());
|
||||||
|
|
||||||
|
mLauncherSettings.setValue(QString("General/MainWindow/width"), width);
|
||||||
|
mLauncherSettings.setValue(QString("General/MainWindow/height"), height);
|
||||||
|
|
||||||
|
QString posX = QString::number(this->pos().x());
|
||||||
|
QString posY = QString::number(this->pos().y());
|
||||||
|
|
||||||
|
mLauncherSettings.setValue(QString("General/MainWindow/posx"), posX);
|
||||||
|
mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY);
|
||||||
|
|
||||||
|
mLauncherSettings.setValue(QString("General/firstrun"), QString("false"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainDialog::writeSettings()
|
||||||
|
{
|
||||||
|
// Now write all config files
|
||||||
|
saveSettings();
|
||||||
|
mGraphicsPage->saveSettings();
|
||||||
|
mDataFilesPage->saveSettings();
|
||||||
|
|
||||||
|
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||||
|
QDir dir(userPath);
|
||||||
|
|
||||||
|
if (!dir.exists()) {
|
||||||
|
if (!dir.mkpath(userPath)) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error creating OpenMW configuration directory"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(tr("<br><b>Could not create %0</b><br><br> \
|
||||||
|
Please make sure you have the right permissions \
|
||||||
|
and try again.<br>").arg(userPath));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Game settings
|
||||||
|
QFile file(userPath + QString("openmw.cfg"));
|
||||||
|
|
||||||
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
||||||
|
// File cannot be opened or created
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||||
|
Please make sure you have the right permissions \
|
||||||
|
and try again.<br>").arg(file.fileName()));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
|
mGameSettings.writeFile(stream);
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// Graphics settings
|
||||||
|
file.setFileName(userPath + QString("settings.cfg"));
|
||||||
|
|
||||||
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
||||||
|
// File cannot be opened or created
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||||
|
Please make sure you have the right permissions \
|
||||||
|
and try again.<br>").arg(file.fileName()));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.setDevice(&file);
|
||||||
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
|
mGraphicsSettings.writeFile(stream);
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// Launcher settings
|
||||||
|
file.setFileName(userPath + QString("launcher.cfg"));
|
||||||
|
|
||||||
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
||||||
|
// File cannot be opened or created
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error writing Launcher configuration file"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||||
|
Please make sure you have the right permissions \
|
||||||
|
and try again.<br>").arg(file.fileName()));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.setDevice(&file);
|
||||||
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
|
mLauncherSettings.writeFile(stream);
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::closeEvent(QCloseEvent *event)
|
void MainDialog::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
// Now write all config files
|
writeSettings();
|
||||||
mDataFilesPage->writeConfig();
|
|
||||||
mGraphicsPage->writeConfig();
|
|
||||||
|
|
||||||
// Save user settings
|
|
||||||
const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string();
|
|
||||||
mSettings.saveUser(settingspath);
|
|
||||||
|
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::play()
|
void MainDialog::play()
|
||||||
{
|
{
|
||||||
// First do a write of all the configs, just to be sure
|
if (!writeSettings())
|
||||||
mDataFilesPage->writeConfig();
|
qApp->quit();
|
||||||
mGraphicsPage->writeConfig();
|
|
||||||
|
|
||||||
// Save user settings
|
// Launch the game detached
|
||||||
const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string();
|
startProgram(QString("openmw"), true);
|
||||||
mSettings.saveUser(settingspath);
|
qApp->quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainDialog::startProgram(const QString &name, const QStringList &arguments, bool detached)
|
||||||
|
{
|
||||||
|
QString path = name;
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QString game = "./openmw.exe";
|
path.append(QString(".exe"));
|
||||||
QFile file(game);
|
|
||||||
#elif defined(Q_OS_MAC)
|
#elif defined(Q_OS_MAC)
|
||||||
QDir dir(QCoreApplication::applicationDirPath());
|
QDir dir(QCoreApplication::applicationDirPath());
|
||||||
QString game = dir.absoluteFilePath("openmw");
|
path = dir.absoluteFilePath(name);
|
||||||
QFile file(game);
|
|
||||||
game = "\"" + game + "\"";
|
|
||||||
#else
|
#else
|
||||||
QString game = "./openmw";
|
path.prepend(QString("./"));
|
||||||
QFile file(game);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
QFile file(path);
|
||||||
|
|
||||||
QProcess process;
|
QProcess process;
|
||||||
QFileInfo info(file);
|
QFileInfo info(file);
|
||||||
|
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle("Error starting OpenMW");
|
msgBox.setWindowTitle(tr("Error starting executable"));
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>Could not find OpenMW</b><br><br> \
|
msgBox.setText(tr("<br><b>Could not find %1</b><br><br> \
|
||||||
The OpenMW application is not found.<br> \
|
The application is not found.<br> \
|
||||||
Please make sure OpenMW is installed correctly and try again.<br>"));
|
Please make sure OpenMW is installed correctly and try again.<br>").arg(info.fileName()));
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
|
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info.isExecutable()) {
|
if (!info.isExecutable()) {
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle("Error starting OpenMW");
|
msgBox.setWindowTitle(tr("Error starting executable"));
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>Could not start OpenMW</b><br><br> \
|
msgBox.setText(tr("<br><b>Could not start %1</b><br><br> \
|
||||||
The OpenMW application is not executable.<br> \
|
The application is not executable.<br> \
|
||||||
Please make sure you have the right permissions and try again.<br>"));
|
Please make sure you have the right permissions and try again.<br>").arg(info.fileName()));
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
|
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the game
|
// Start the executable
|
||||||
if (!process.startDetached(game)) {
|
if (detached) {
|
||||||
QMessageBox msgBox;
|
if (!process.startDetached(path, arguments)) {
|
||||||
msgBox.setWindowTitle("Error starting OpenMW");
|
QMessageBox msgBox;
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setWindowTitle(tr("Error starting executable"));
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
msgBox.setText(tr("<br><b>Could not start OpenMW</b><br><br> \
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
An error occurred while starting OpenMW.<br><br> \
|
msgBox.setText(tr("<br><b>Could not start %1</b><br><br> \
|
||||||
Press \"Show Details...\" for more information.<br>"));
|
An error occurred while starting %1.<br><br> \
|
||||||
msgBox.setDetailedText(process.errorString());
|
Press \"Show Details...\" for more information.<br>").arg(info.fileName()));
|
||||||
msgBox.exec();
|
msgBox.setDetailedText(process.errorString());
|
||||||
|
msgBox.exec();
|
||||||
|
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qApp->quit();
|
process.start(path, arguments);
|
||||||
}
|
if (!process.waitForFinished()) {
|
||||||
}
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error starting executable"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(tr("<br><b>Could not start %1</b><br><br> \
|
||||||
|
An error occurred while starting %1.<br><br> \
|
||||||
|
Press \"Show Details...\" for more information.<br>").arg(info.fileName()));
|
||||||
|
msgBox.setDetailedText(process.errorString());
|
||||||
|
msgBox.exec();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.exitCode() != 0) {
|
||||||
|
QString error(process.readAllStandardError());
|
||||||
|
error.append(tr("\nArguments:\n"));
|
||||||
|
error.append(arguments.join(" "));
|
||||||
|
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setWindowTitle(tr("Error running executable"));
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setText(tr("<br><b>Executable %1 returned an error</b><br><br> \
|
||||||
|
An error occurred while running %1.<br><br> \
|
||||||
|
Press \"Show Details...\" for more information.<br>").arg(info.fileName()));
|
||||||
|
msgBox.setDetailedText(error);
|
||||||
|
msgBox.exec();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
|
||||||
|
#include "settings/gamesettings.hpp"
|
||||||
|
#include "settings/graphicssettings.hpp"
|
||||||
|
#include "settings/launchersettings.hpp"
|
||||||
|
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
class QListWidget;
|
class QListWidget;
|
||||||
class QListWidgetItem;
|
class QListWidgetItem;
|
||||||
|
@ -17,32 +22,46 @@ class PlayPage;
|
||||||
class GraphicsPage;
|
class GraphicsPage;
|
||||||
class DataFilesPage;
|
class DataFilesPage;
|
||||||
|
|
||||||
class MainDialog : public QMainWindow
|
class MainDialog : public QMainWindow, private Ui::MainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MainDialog();
|
MainDialog();
|
||||||
|
bool setup();
|
||||||
|
bool showFirstRunDialog();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
|
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
|
||||||
void play();
|
void play();
|
||||||
bool setup();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createIcons();
|
void createIcons();
|
||||||
void createPages();
|
void createPages();
|
||||||
void closeEvent(QCloseEvent *event);
|
|
||||||
|
|
||||||
QListWidget *mIconWidget;
|
bool setupLauncherSettings();
|
||||||
QStackedWidget *mPagesWidget;
|
bool setupGameSettings();
|
||||||
|
bool setupGraphicsSettings();
|
||||||
|
|
||||||
|
void loadSettings();
|
||||||
|
void saveSettings();
|
||||||
|
bool writeSettings();
|
||||||
|
|
||||||
|
inline bool startProgram(const QString &name, bool detached = false) { return startProgram(name, QStringList(), detached); }
|
||||||
|
bool startProgram(const QString &name, const QStringList &arguments, bool detached = false);
|
||||||
|
|
||||||
|
void closeEvent(QCloseEvent *event);
|
||||||
|
|
||||||
PlayPage *mPlayPage;
|
PlayPage *mPlayPage;
|
||||||
GraphicsPage *mGraphicsPage;
|
GraphicsPage *mGraphicsPage;
|
||||||
DataFilesPage *mDataFilesPage;
|
DataFilesPage *mDataFilesPage;
|
||||||
|
|
||||||
Files::ConfigurationManager mCfgMgr;
|
Files::ConfigurationManager mCfgMgr;
|
||||||
Settings::Manager mSettings;
|
|
||||||
|
GameSettings mGameSettings;
|
||||||
|
GraphicsSettings mGraphicsSettings;
|
||||||
|
LauncherSettings mLauncherSettings;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,43 +1,39 @@
|
||||||
#include <QtGui>
|
|
||||||
|
|
||||||
#include "playpage.hpp"
|
#include "playpage.hpp"
|
||||||
|
|
||||||
|
#include <QtGui>
|
||||||
|
|
||||||
PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
|
PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
QWidget *playWidget = new QWidget(this);
|
setupUi(this);
|
||||||
playWidget->setObjectName("PlayGroup");
|
|
||||||
playWidget->setFixedSize(QSize(425, 375));
|
|
||||||
|
|
||||||
mPlayButton = new QPushButton(tr("Play"), playWidget);
|
|
||||||
mPlayButton->setObjectName("PlayButton");
|
|
||||||
mPlayButton->setMinimumSize(QSize(200, 50));
|
|
||||||
|
|
||||||
QLabel *profileLabel = new QLabel(tr("Current Profile:"), playWidget);
|
|
||||||
profileLabel->setObjectName("ProfileLabel");
|
|
||||||
|
|
||||||
|
// Hacks to get the stylesheet look properly
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
QPlastiqueStyle *style = new QPlastiqueStyle;
|
QPlastiqueStyle *style = new QPlastiqueStyle;
|
||||||
mProfilesComboBox = new QComboBox(playWidget);
|
profilesComboBox->setStyle(style);
|
||||||
mProfilesComboBox->setObjectName("ProfilesComboBox");
|
#endif
|
||||||
mProfilesComboBox->setStyle(style);
|
profilesComboBox->setView(new QListView());
|
||||||
|
|
||||||
QGridLayout *playLayout = new QGridLayout(playWidget);
|
connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
|
||||||
|
connect(playButton, SIGNAL(clicked()), this, SLOT(slotPlayClicked()));
|
||||||
|
|
||||||
QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
}
|
||||||
QSpacerItem *hSpacer2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
|
||||||
|
|
||||||
QSpacerItem *vSpacer1 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
void PlayPage::setProfilesComboBoxModel(QAbstractItemModel *model)
|
||||||
QSpacerItem *vSpacer2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
{
|
||||||
|
profilesComboBox->setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
playLayout->addWidget(mPlayButton, 1, 1, 1, 1);
|
void PlayPage::setProfilesComboBoxIndex(int index)
|
||||||
playLayout->addWidget(profileLabel, 2, 1, 1, 1);
|
{
|
||||||
playLayout->addWidget(mProfilesComboBox, 3, 1, 1, 1);
|
profilesComboBox->setCurrentIndex(index);
|
||||||
playLayout->addItem(hSpacer1, 2, 0, 1, 1);
|
}
|
||||||
playLayout->addItem(hSpacer2, 2, 2, 1, 1);
|
|
||||||
playLayout->addItem(vSpacer1, 0, 1, 1, 1);
|
|
||||||
playLayout->addItem(vSpacer2, 4, 1, 1, 1);
|
|
||||||
|
|
||||||
QHBoxLayout *pageLayout = new QHBoxLayout(this);
|
void PlayPage::slotCurrentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
emit profileChanged(index);
|
||||||
|
}
|
||||||
|
|
||||||
pageLayout->addWidget(playWidget);
|
void PlayPage::slotPlayClicked()
|
||||||
|
{
|
||||||
}
|
emit playButtonClicked();
|
||||||
|
}
|
||||||
|
|
|
@ -3,19 +3,33 @@
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "ui_playpage.h"
|
||||||
|
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
|
class QAbstractItemModel;
|
||||||
|
|
||||||
class PlayPage : public QWidget
|
class PlayPage : public QWidget, private Ui::PlayPage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlayPage(QWidget *parent = 0);
|
PlayPage(QWidget *parent = 0);
|
||||||
|
void setProfilesComboBoxModel(QAbstractItemModel *model);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void profileChanged(int index);
|
||||||
|
void playButtonClicked();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setProfilesComboBoxIndex(int index);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void slotCurrentIndexChanged(int index);
|
||||||
|
void slotPlayClicked();
|
||||||
|
|
||||||
|
|
||||||
QComboBox *mProfilesComboBox;
|
|
||||||
QPushButton *mPlayButton;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<!DOCTYPE RCC><RCC version="1.0">
|
|
||||||
<qresource prefix="/images">
|
|
||||||
<file alias="clear.png">resources/images/clear.png</file>
|
|
||||||
<file alias="down.png">resources/images/down.png</file>
|
|
||||||
<file alias="openmw.png">resources/images/openmw.png</file>
|
|
||||||
<file alias="openmw-plugin.png">resources/images/openmw-plugin.png</file>
|
|
||||||
<file alias="openmw-header.png">resources/images/openmw-header.png</file>
|
|
||||||
<file alias="playpage-background.png">resources/images/playpage-background.png</file>
|
|
||||||
</qresource>
|
|
||||||
<qresource prefix="icons/tango">
|
|
||||||
<file alias="index.theme">resources/icons/tango/index.theme</file>
|
|
||||||
<file alias="video-display.png">resources/icons/tango/video-display.png</file>
|
|
||||||
<file alias="16x16/document-new.png">resources/icons/tango/document-new.png</file>
|
|
||||||
<file alias="16x16/edit-copy.png">resources/icons/tango/edit-copy.png</file>
|
|
||||||
<file alias="16x16/edit-delete.png">resources/icons/tango/edit-delete.png</file>
|
|
||||||
<file alias="16x16/go-bottom.png">resources/icons/tango/go-bottom.png</file>
|
|
||||||
<file alias="16x16/go-down.png">resources/icons/tango/go-down.png</file>
|
|
||||||
<file alias="16x16/go-top.png">resources/icons/tango/go-top.png</file>
|
|
||||||
<file alias="16x16/go-up.png">resources/icons/tango/go-up.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
Binary file not shown.
Before Width: | Height: | Size: 644 B |
177
apps/launcher/settings/gamesettings.cpp
Normal file
177
apps/launcher/settings/gamesettings.cpp
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
#include "gamesettings.hpp"
|
||||||
|
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QString>
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
|
#include <boost/version.hpp>
|
||||||
|
/**
|
||||||
|
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
||||||
|
*/
|
||||||
|
#if (BOOST_VERSION <= 104600)
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline boost::filesystem::path lexical_cast<boost::filesystem::path, std::string>(const std::string& arg)
|
||||||
|
{
|
||||||
|
return boost::filesystem::path(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
#endif /* (BOOST_VERSION <= 104600) */
|
||||||
|
|
||||||
|
|
||||||
|
GameSettings::GameSettings(Files::ConfigurationManager &cfg)
|
||||||
|
: mCfgMgr(cfg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GameSettings::~GameSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameSettings::validatePaths()
|
||||||
|
{
|
||||||
|
if (mSettings.isEmpty() || !mDataDirs.isEmpty())
|
||||||
|
return; // Don't re-validate paths if they are already parsed
|
||||||
|
|
||||||
|
QStringList paths = mSettings.values(QString("data"));
|
||||||
|
Files::PathContainer dataDirs;
|
||||||
|
|
||||||
|
foreach (const QString &path, paths) {
|
||||||
|
dataDirs.push_back(Files::PathContainer::value_type(path.toStdString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the data dirs to convert the tokenized paths
|
||||||
|
mCfgMgr.processPaths(dataDirs);
|
||||||
|
mDataDirs.clear();
|
||||||
|
|
||||||
|
for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) {
|
||||||
|
QString path = QString::fromStdString(it->string());
|
||||||
|
path.remove(QChar('\"'));
|
||||||
|
|
||||||
|
QDir dir(path);
|
||||||
|
if (dir.exists())
|
||||||
|
mDataDirs.append(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the same for data-local
|
||||||
|
QString local = mSettings.value(QString("data-local"));
|
||||||
|
|
||||||
|
if (local.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
dataDirs.clear();
|
||||||
|
dataDirs.push_back(Files::PathContainer::value_type(local.toStdString()));
|
||||||
|
|
||||||
|
mCfgMgr.processPaths(dataDirs);
|
||||||
|
|
||||||
|
if (!dataDirs.empty()) {
|
||||||
|
QString path = QString::fromStdString(dataDirs.front().string());
|
||||||
|
path.remove(QChar('\"'));
|
||||||
|
|
||||||
|
QDir dir(path);
|
||||||
|
if (dir.exists())
|
||||||
|
mDataLocal = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList GameSettings::values(const QString &key, const QStringList &defaultValues)
|
||||||
|
{
|
||||||
|
if (!mSettings.values(key).isEmpty())
|
||||||
|
return mSettings.values(key);
|
||||||
|
return defaultValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameSettings::readFile(QTextStream &stream)
|
||||||
|
{
|
||||||
|
QMap<QString, QString> cache;
|
||||||
|
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
|
||||||
|
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
QString line = stream.readLine().simplified();
|
||||||
|
|
||||||
|
if (line.isEmpty() || line.startsWith("#"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (keyRe.indexIn(line) != -1) {
|
||||||
|
|
||||||
|
QString key = keyRe.cap(1).simplified();
|
||||||
|
QString value = keyRe.cap(2).simplified();
|
||||||
|
|
||||||
|
// Don't remove existing data entries
|
||||||
|
if (key != QLatin1String("data"))
|
||||||
|
mSettings.remove(key);
|
||||||
|
|
||||||
|
QStringList values = cache.values(key);
|
||||||
|
values.append(mSettings.values(key));
|
||||||
|
|
||||||
|
if (!values.contains(value)) {
|
||||||
|
cache.insertMulti(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSettings.isEmpty()) {
|
||||||
|
mSettings = cache; // This is the first time we read a file
|
||||||
|
validatePaths();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge the changed keys with those which didn't
|
||||||
|
mSettings.unite(cache);
|
||||||
|
validatePaths();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameSettings::writeFile(QTextStream &stream)
|
||||||
|
{
|
||||||
|
// Iterate in reverse order to preserve insertion order
|
||||||
|
QMapIterator<QString, QString> i(mSettings);
|
||||||
|
i.toBack();
|
||||||
|
|
||||||
|
while (i.hasPrevious()) {
|
||||||
|
i.previous();
|
||||||
|
|
||||||
|
if (i.key() == QLatin1String("master") || i.key() == QLatin1String("plugin"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Quote paths with spaces
|
||||||
|
if (i.key() == QLatin1String("data")
|
||||||
|
|| i.key() == QLatin1String("data-local")
|
||||||
|
|| i.key() == QLatin1String("resources"))
|
||||||
|
{
|
||||||
|
if (i.value().contains(QChar(' ')))
|
||||||
|
{
|
||||||
|
QString stripped = i.value();
|
||||||
|
stripped.remove(QChar('\"')); // Remove quotes
|
||||||
|
|
||||||
|
stream << i.key() << "=\"" << stripped << "\"\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << i.key() << "=" << i.value() << "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList masters = mSettings.values(QString("master"));
|
||||||
|
for (int i = masters.count(); i--;) {
|
||||||
|
stream << "master=" << masters.at(i) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList plugins = mSettings.values(QString("plugin"));
|
||||||
|
for (int i = plugins.count(); i--;) {
|
||||||
|
stream << "plugin=" << plugins.at(i) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
61
apps/launcher/settings/gamesettings.hpp
Normal file
61
apps/launcher/settings/gamesettings.hpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#ifndef GAMESETTINGS_HPP
|
||||||
|
#define GAMESETTINGS_HPP
|
||||||
|
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QString>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
namespace Files { typedef std::vector<boost::filesystem::path> PathContainer;
|
||||||
|
struct ConfigurationManager;}
|
||||||
|
|
||||||
|
class GameSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GameSettings(Files::ConfigurationManager &cfg);
|
||||||
|
~GameSettings();
|
||||||
|
|
||||||
|
inline QString value(const QString &key, const QString &defaultValue = QString())
|
||||||
|
{
|
||||||
|
return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void setValue(const QString &key, const QString &value)
|
||||||
|
{
|
||||||
|
mSettings.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setMultiValue(const QString &key, const QString &value)
|
||||||
|
{
|
||||||
|
QStringList values = mSettings.values(key);
|
||||||
|
if (!values.contains(value))
|
||||||
|
mSettings.insertMulti(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void remove(const QString &key)
|
||||||
|
{
|
||||||
|
mSettings.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QStringList getDataDirs() { return mDataDirs; }
|
||||||
|
inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); }
|
||||||
|
inline QString getDataLocal() {return mDataLocal; }
|
||||||
|
|
||||||
|
QStringList values(const QString &key, const QStringList &defaultValues = QStringList());
|
||||||
|
bool readFile(QTextStream &stream);
|
||||||
|
bool writeFile(QTextStream &stream);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
|
|
||||||
|
void validatePaths();
|
||||||
|
QMap<QString, QString> mSettings;
|
||||||
|
|
||||||
|
QStringList mDataDirs;
|
||||||
|
QString mDataLocal;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GAMESETTINGS_HPP
|
44
apps/launcher/settings/graphicssettings.cpp
Normal file
44
apps/launcher/settings/graphicssettings.cpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include "graphicssettings.hpp"
|
||||||
|
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QString>
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
GraphicsSettings::GraphicsSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsSettings::~GraphicsSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsSettings::writeFile(QTextStream &stream)
|
||||||
|
{
|
||||||
|
QString sectionPrefix;
|
||||||
|
QRegExp sectionRe("([^/]+)/(.+)$");
|
||||||
|
QMap<QString, QString> settings = SettingsBase::getSettings();
|
||||||
|
|
||||||
|
QMapIterator<QString, QString> i(settings);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
|
||||||
|
QString prefix;
|
||||||
|
QString key;
|
||||||
|
|
||||||
|
if (sectionRe.exactMatch(i.key())) {
|
||||||
|
prefix = sectionRe.cap(1);
|
||||||
|
key = sectionRe.cap(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sectionPrefix != prefix) {
|
||||||
|
sectionPrefix = prefix;
|
||||||
|
stream << "\n[" << prefix << "]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << key << " = " << i.value() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
16
apps/launcher/settings/graphicssettings.hpp
Normal file
16
apps/launcher/settings/graphicssettings.hpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef GRAPHICSSETTINGS_HPP
|
||||||
|
#define GRAPHICSSETTINGS_HPP
|
||||||
|
|
||||||
|
#include "settingsbase.hpp"
|
||||||
|
|
||||||
|
class GraphicsSettings : public SettingsBase<QMap<QString, QString> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GraphicsSettings();
|
||||||
|
~GraphicsSettings();
|
||||||
|
|
||||||
|
bool writeFile(QTextStream &stream);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GRAPHICSSETTINGS_HPP
|
101
apps/launcher/settings/launchersettings.cpp
Normal file
101
apps/launcher/settings/launchersettings.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
#include "launchersettings.hpp"
|
||||||
|
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QString>
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
LauncherSettings::LauncherSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
LauncherSettings::~LauncherSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList LauncherSettings::values(const QString &key, Qt::MatchFlags flags)
|
||||||
|
{
|
||||||
|
QMap<QString, QString> settings = SettingsBase::getSettings();
|
||||||
|
|
||||||
|
if (flags == Qt::MatchExactly)
|
||||||
|
return settings.values(key);
|
||||||
|
|
||||||
|
QStringList result;
|
||||||
|
|
||||||
|
if (flags == Qt::MatchStartsWith) {
|
||||||
|
QStringList keys = settings.keys();
|
||||||
|
|
||||||
|
foreach (const QString ¤tKey, keys) {
|
||||||
|
if (currentKey.startsWith(key))
|
||||||
|
result.append(settings.value(currentKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList LauncherSettings::subKeys(const QString &key)
|
||||||
|
{
|
||||||
|
QMap<QString, QString> settings = SettingsBase::getSettings();
|
||||||
|
QStringList keys = settings.uniqueKeys();
|
||||||
|
|
||||||
|
QRegExp keyRe("(.+)/");
|
||||||
|
|
||||||
|
QStringList result;
|
||||||
|
|
||||||
|
foreach (const QString ¤tKey, keys) {
|
||||||
|
|
||||||
|
if (keyRe.indexIn(currentKey) != -1) {
|
||||||
|
|
||||||
|
QString prefixedKey = keyRe.cap(1);
|
||||||
|
if(prefixedKey.startsWith(key)) {
|
||||||
|
|
||||||
|
QString subKey = prefixedKey.remove(key);
|
||||||
|
if (!subKey.isEmpty())
|
||||||
|
result.append(subKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.removeDuplicates();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LauncherSettings::writeFile(QTextStream &stream)
|
||||||
|
{
|
||||||
|
QString sectionPrefix;
|
||||||
|
QRegExp sectionRe("([^/]+)/(.+)$");
|
||||||
|
QMap<QString, QString> settings = SettingsBase::getSettings();
|
||||||
|
|
||||||
|
QMapIterator<QString, QString> i(settings);
|
||||||
|
i.toBack();
|
||||||
|
|
||||||
|
while (i.hasPrevious()) {
|
||||||
|
i.previous();
|
||||||
|
|
||||||
|
QString prefix;
|
||||||
|
QString key;
|
||||||
|
|
||||||
|
if (sectionRe.exactMatch(i.key())) {
|
||||||
|
prefix = sectionRe.cap(1);
|
||||||
|
key = sectionRe.cap(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get rid of legacy settings
|
||||||
|
if (key.contains(QChar('\\')))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (key == QLatin1String("CurrentProfile"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sectionPrefix != prefix) {
|
||||||
|
sectionPrefix = prefix;
|
||||||
|
stream << "\n[" << prefix << "]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << key << "=" << i.value() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
19
apps/launcher/settings/launchersettings.hpp
Normal file
19
apps/launcher/settings/launchersettings.hpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef LAUNCHERSETTINGS_HPP
|
||||||
|
#define LAUNCHERSETTINGS_HPP
|
||||||
|
|
||||||
|
#include "settingsbase.hpp"
|
||||||
|
|
||||||
|
class LauncherSettings : public SettingsBase<QMap<QString, QString> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LauncherSettings();
|
||||||
|
~LauncherSettings();
|
||||||
|
|
||||||
|
QStringList subKeys(const QString &key);
|
||||||
|
QStringList values(const QString &key, Qt::MatchFlags flags = Qt::MatchExactly);
|
||||||
|
|
||||||
|
bool writeFile(QTextStream &stream);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LAUNCHERSETTINGS_HPP
|
98
apps/launcher/settings/settingsbase.hpp
Normal file
98
apps/launcher/settings/settingsbase.hpp
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#ifndef SETTINGSBASE_HPP
|
||||||
|
#define SETTINGSBASE_HPP
|
||||||
|
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QString>
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
template <class Map>
|
||||||
|
class SettingsBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
SettingsBase() {}
|
||||||
|
~SettingsBase() {}
|
||||||
|
|
||||||
|
inline QString value(const QString &key, const QString &defaultValue = QString())
|
||||||
|
{
|
||||||
|
return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setValue(const QString &key, const QString &value)
|
||||||
|
{
|
||||||
|
QStringList values = mSettings.values(key);
|
||||||
|
if (!values.contains(value))
|
||||||
|
mSettings.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setMultiValue(const QString &key, const QString &value)
|
||||||
|
{
|
||||||
|
QStringList values = mSettings.values(key);
|
||||||
|
if (!values.contains(value))
|
||||||
|
mSettings.insertMulti(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void remove(const QString &key)
|
||||||
|
{
|
||||||
|
mSettings.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map getSettings() {return mSettings;}
|
||||||
|
|
||||||
|
bool readFile(QTextStream &stream)
|
||||||
|
{
|
||||||
|
mCache.clear();
|
||||||
|
|
||||||
|
QString sectionPrefix;
|
||||||
|
QRegExp sectionRe("^\\[([^]]+)\\]");
|
||||||
|
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
|
||||||
|
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
QString line = stream.readLine().simplified();
|
||||||
|
|
||||||
|
if (line.isEmpty() || line.startsWith("#"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sectionRe.exactMatch(line)) {
|
||||||
|
sectionPrefix = sectionRe.cap(1);
|
||||||
|
sectionPrefix.append("/");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyRe.indexIn(line) != -1) {
|
||||||
|
|
||||||
|
QString key = keyRe.cap(1).simplified();
|
||||||
|
QString value = keyRe.cap(2).simplified();
|
||||||
|
|
||||||
|
if (!sectionPrefix.isEmpty())
|
||||||
|
key.prepend(sectionPrefix);
|
||||||
|
|
||||||
|
mSettings.remove(key);
|
||||||
|
|
||||||
|
QStringList values = mCache.values(key);
|
||||||
|
if (!values.contains(value)) {
|
||||||
|
mCache.insertMulti(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSettings.isEmpty()) {
|
||||||
|
mSettings = mCache; // This is the first time we read a file
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge the changed keys with those which didn't
|
||||||
|
mSettings.unite(mCache);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Map mSettings;
|
||||||
|
Map mCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SETTINGSBASE_HPP
|
269
apps/launcher/utils/checkablemessagebox.cpp
Normal file
269
apps/launcher/utils/checkablemessagebox.cpp
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "checkablemessagebox.hpp"
|
||||||
|
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QButtonGroup>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QSpacerItem>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class Utils::CheckableMessageBox
|
||||||
|
|
||||||
|
\brief A messagebox suitable for questions with a
|
||||||
|
"Do not ask me again" checkbox.
|
||||||
|
|
||||||
|
Emulates the QMessageBox API with
|
||||||
|
static conveniences. The message label can open external URLs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CheckableMessageBoxPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CheckableMessageBoxPrivate(QDialog *q)
|
||||||
|
: clickedButton(0)
|
||||||
|
{
|
||||||
|
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
|
||||||
|
|
||||||
|
pixmapLabel = new QLabel(q);
|
||||||
|
sizePolicy.setHorizontalStretch(0);
|
||||||
|
sizePolicy.setVerticalStretch(0);
|
||||||
|
sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth());
|
||||||
|
pixmapLabel->setSizePolicy(sizePolicy);
|
||||||
|
pixmapLabel->setVisible(false);
|
||||||
|
|
||||||
|
QSpacerItem *pixmapSpacer =
|
||||||
|
new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
|
||||||
|
|
||||||
|
messageLabel = new QLabel(q);
|
||||||
|
messageLabel->setMinimumSize(QSize(300, 0));
|
||||||
|
messageLabel->setWordWrap(true);
|
||||||
|
messageLabel->setOpenExternalLinks(true);
|
||||||
|
messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse);
|
||||||
|
|
||||||
|
QSpacerItem *checkBoxRightSpacer =
|
||||||
|
new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||||
|
QSpacerItem *buttonSpacer =
|
||||||
|
new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||||
|
|
||||||
|
checkBox = new QCheckBox(q);
|
||||||
|
checkBox->setText(CheckableMessageBox::tr("Do not ask again"));
|
||||||
|
|
||||||
|
buttonBox = new QDialogButtonBox(q);
|
||||||
|
buttonBox->setOrientation(Qt::Horizontal);
|
||||||
|
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
||||||
|
|
||||||
|
QVBoxLayout *verticalLayout = new QVBoxLayout();
|
||||||
|
verticalLayout->addWidget(pixmapLabel);
|
||||||
|
verticalLayout->addItem(pixmapSpacer);
|
||||||
|
|
||||||
|
QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
|
||||||
|
horizontalLayout_2->addLayout(verticalLayout);
|
||||||
|
horizontalLayout_2->addWidget(messageLabel);
|
||||||
|
|
||||||
|
QHBoxLayout *horizontalLayout = new QHBoxLayout();
|
||||||
|
horizontalLayout->addWidget(checkBox);
|
||||||
|
horizontalLayout->addItem(checkBoxRightSpacer);
|
||||||
|
|
||||||
|
QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q);
|
||||||
|
verticalLayout_2->addLayout(horizontalLayout_2);
|
||||||
|
verticalLayout_2->addLayout(horizontalLayout);
|
||||||
|
verticalLayout_2->addItem(buttonSpacer);
|
||||||
|
verticalLayout_2->addWidget(buttonBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
QLabel *pixmapLabel;
|
||||||
|
QLabel *messageLabel;
|
||||||
|
QCheckBox *checkBox;
|
||||||
|
QDialogButtonBox *buttonBox;
|
||||||
|
QAbstractButton *clickedButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
CheckableMessageBox::CheckableMessageBox(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
d(new CheckableMessageBoxPrivate(this))
|
||||||
|
{
|
||||||
|
setModal(true);
|
||||||
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
connect(d->buttonBox, SIGNAL(accepted()), SLOT(accept()));
|
||||||
|
connect(d->buttonBox, SIGNAL(rejected()), SLOT(reject()));
|
||||||
|
connect(d->buttonBox, SIGNAL(clicked(QAbstractButton*)),
|
||||||
|
SLOT(slotClicked(QAbstractButton*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckableMessageBox::~CheckableMessageBox()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckableMessageBox::slotClicked(QAbstractButton *b)
|
||||||
|
{
|
||||||
|
d->clickedButton = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAbstractButton *CheckableMessageBox::clickedButton() const
|
||||||
|
{
|
||||||
|
return d->clickedButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialogButtonBox::StandardButton CheckableMessageBox::clickedStandardButton() const
|
||||||
|
{
|
||||||
|
if (d->clickedButton)
|
||||||
|
return d->buttonBox->standardButton(d->clickedButton);
|
||||||
|
return QDialogButtonBox::NoButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CheckableMessageBox::text() const
|
||||||
|
{
|
||||||
|
return d->messageLabel->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckableMessageBox::setText(const QString &t)
|
||||||
|
{
|
||||||
|
d->messageLabel->setText(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap CheckableMessageBox::iconPixmap() const
|
||||||
|
{
|
||||||
|
if (const QPixmap *p = d->pixmapLabel->pixmap())
|
||||||
|
return QPixmap(*p);
|
||||||
|
return QPixmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckableMessageBox::setIconPixmap(const QPixmap &p)
|
||||||
|
{
|
||||||
|
d->pixmapLabel->setPixmap(p);
|
||||||
|
d->pixmapLabel->setVisible(!p.isNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckableMessageBox::isChecked() const
|
||||||
|
{
|
||||||
|
return d->checkBox->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckableMessageBox::setChecked(bool s)
|
||||||
|
{
|
||||||
|
d->checkBox->setChecked(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CheckableMessageBox::checkBoxText() const
|
||||||
|
{
|
||||||
|
return d->checkBox->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckableMessageBox::setCheckBoxText(const QString &t)
|
||||||
|
{
|
||||||
|
d->checkBox->setText(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckableMessageBox::isCheckBoxVisible() const
|
||||||
|
{
|
||||||
|
return d->checkBox->isVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckableMessageBox::setCheckBoxVisible(bool v)
|
||||||
|
{
|
||||||
|
d->checkBox->setVisible(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialogButtonBox::StandardButtons CheckableMessageBox::standardButtons() const
|
||||||
|
{
|
||||||
|
return d->buttonBox->standardButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckableMessageBox::setStandardButtons(QDialogButtonBox::StandardButtons s)
|
||||||
|
{
|
||||||
|
d->buttonBox->setStandardButtons(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton *CheckableMessageBox::button(QDialogButtonBox::StandardButton b) const
|
||||||
|
{
|
||||||
|
return d->buttonBox->button(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton *CheckableMessageBox::addButton(const QString &text, QDialogButtonBox::ButtonRole role)
|
||||||
|
{
|
||||||
|
return d->buttonBox->addButton(text, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialogButtonBox::StandardButton CheckableMessageBox::defaultButton() const
|
||||||
|
{
|
||||||
|
foreach (QAbstractButton *b, d->buttonBox->buttons())
|
||||||
|
if (QPushButton *pb = qobject_cast<QPushButton *>(b))
|
||||||
|
if (pb->isDefault())
|
||||||
|
return d->buttonBox->standardButton(pb);
|
||||||
|
return QDialogButtonBox::NoButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckableMessageBox::setDefaultButton(QDialogButtonBox::StandardButton s)
|
||||||
|
{
|
||||||
|
if (QPushButton *b = d->buttonBox->button(s)) {
|
||||||
|
b->setDefault(true);
|
||||||
|
b->setFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialogButtonBox::StandardButton
|
||||||
|
CheckableMessageBox::question(QWidget *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &question,
|
||||||
|
const QString &checkBoxText,
|
||||||
|
bool *checkBoxSetting,
|
||||||
|
QDialogButtonBox::StandardButtons buttons,
|
||||||
|
QDialogButtonBox::StandardButton defaultButton)
|
||||||
|
{
|
||||||
|
CheckableMessageBox mb(parent);
|
||||||
|
mb.setWindowTitle(title);
|
||||||
|
mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question));
|
||||||
|
mb.setText(question);
|
||||||
|
mb.setCheckBoxText(checkBoxText);
|
||||||
|
mb.setChecked(*checkBoxSetting);
|
||||||
|
mb.setStandardButtons(buttons);
|
||||||
|
mb.setDefaultButton(defaultButton);
|
||||||
|
mb.exec();
|
||||||
|
*checkBoxSetting = mb.isChecked();
|
||||||
|
return mb.clickedStandardButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton CheckableMessageBox::dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton db)
|
||||||
|
{
|
||||||
|
return static_cast<QMessageBox::StandardButton>(int(db));
|
||||||
|
}
|
100
apps/launcher/utils/checkablemessagebox.hpp
Normal file
100
apps/launcher/utils/checkablemessagebox.hpp
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CHECKABLEMESSAGEBOX_HPP
|
||||||
|
#define CHECKABLEMESSAGEBOX_HPP
|
||||||
|
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class CheckableMessageBoxPrivate;
|
||||||
|
|
||||||
|
class CheckableMessageBox : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString text READ text WRITE setText)
|
||||||
|
Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
|
||||||
|
Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked)
|
||||||
|
Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText)
|
||||||
|
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
|
||||||
|
Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CheckableMessageBox(QWidget *parent);
|
||||||
|
virtual ~CheckableMessageBox();
|
||||||
|
|
||||||
|
static QDialogButtonBox::StandardButton
|
||||||
|
question(QWidget *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &question,
|
||||||
|
const QString &checkBoxText,
|
||||||
|
bool *checkBoxSetting,
|
||||||
|
QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No,
|
||||||
|
QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No);
|
||||||
|
|
||||||
|
QString text() const;
|
||||||
|
void setText(const QString &);
|
||||||
|
|
||||||
|
bool isChecked() const;
|
||||||
|
void setChecked(bool s);
|
||||||
|
|
||||||
|
QString checkBoxText() const;
|
||||||
|
void setCheckBoxText(const QString &);
|
||||||
|
|
||||||
|
bool isCheckBoxVisible() const;
|
||||||
|
void setCheckBoxVisible(bool);
|
||||||
|
|
||||||
|
QDialogButtonBox::StandardButtons standardButtons() const;
|
||||||
|
void setStandardButtons(QDialogButtonBox::StandardButtons s);
|
||||||
|
QPushButton *button(QDialogButtonBox::StandardButton b) const;
|
||||||
|
QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role);
|
||||||
|
|
||||||
|
QDialogButtonBox::StandardButton defaultButton() const;
|
||||||
|
void setDefaultButton(QDialogButtonBox::StandardButton s);
|
||||||
|
|
||||||
|
// See static QMessageBox::standardPixmap()
|
||||||
|
QPixmap iconPixmap() const;
|
||||||
|
void setIconPixmap (const QPixmap &p);
|
||||||
|
|
||||||
|
// Query the result
|
||||||
|
QAbstractButton *clickedButton() const;
|
||||||
|
QDialogButtonBox::StandardButton clickedStandardButton() const;
|
||||||
|
|
||||||
|
// Conversion convenience
|
||||||
|
static QMessageBox::StandardButton dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void slotClicked(QAbstractButton *b);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CheckableMessageBoxPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHECKABLEMESSAGEBOX_HPP
|
|
@ -1,52 +0,0 @@
|
||||||
#include <QRegExpValidator>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
#include "profilescombobox.hpp"
|
|
||||||
|
|
||||||
ProfilesComboBox::ProfilesComboBox(QWidget *parent) :
|
|
||||||
QComboBox(parent)
|
|
||||||
{
|
|
||||||
mValidator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
|
|
||||||
|
|
||||||
setEditable(true);
|
|
||||||
setValidator(mValidator);
|
|
||||||
setCompleter(0);
|
|
||||||
|
|
||||||
connect(this, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(slotIndexChanged(int)));
|
|
||||||
connect(lineEdit(), SIGNAL(returnPressed()), this,
|
|
||||||
SLOT(slotReturnPressed()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfilesComboBox::setEditEnabled(bool editable)
|
|
||||||
{
|
|
||||||
if (!editable)
|
|
||||||
return setEditable(false);
|
|
||||||
|
|
||||||
// Reset the completer and validator
|
|
||||||
setEditable(true);
|
|
||||||
setValidator(mValidator);
|
|
||||||
setCompleter(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfilesComboBox::slotReturnPressed()
|
|
||||||
{
|
|
||||||
QString current = currentText();
|
|
||||||
QString previous = itemText(currentIndex());
|
|
||||||
|
|
||||||
if (findText(current) != -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
setItemText(currentIndex(), current);
|
|
||||||
emit(profileRenamed(previous, current));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfilesComboBox::slotIndexChanged(int index)
|
|
||||||
{
|
|
||||||
if (index == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
emit(profileChanged(mOldProfile, currentText()));
|
|
||||||
mOldProfile = itemText(index);
|
|
||||||
}
|
|
|
@ -1,14 +1,14 @@
|
||||||
|
#include "textinputdialog.hpp"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QApplication>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QDebug>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QValidator>
|
#include <QValidator>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
#include <components/fileorderlist/utils/lineedit.hpp>
|
#include <components/fileorderlist/utils/lineedit.hpp>
|
||||||
|
|
||||||
#include "textinputdialog.hpp"
|
|
||||||
|
|
||||||
TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWidget *parent) :
|
TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWidget *parent) :
|
||||||
QDialog(parent)
|
QDialog(parent)
|
||||||
{
|
{
|
||||||
|
@ -17,9 +17,19 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid
|
||||||
mButtonBox->addButton(QDialogButtonBox::Ok);
|
mButtonBox->addButton(QDialogButtonBox::Ok);
|
||||||
mButtonBox->addButton(QDialogButtonBox::Cancel);
|
mButtonBox->addButton(QDialogButtonBox::Cancel);
|
||||||
|
|
||||||
setMaximumHeight(height());
|
// Line edit
|
||||||
setOkButtonEnabled(false);
|
QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
|
||||||
setModal(true);
|
mLineEdit = new LineEdit(this);
|
||||||
|
mLineEdit->setValidator(validator);
|
||||||
|
mLineEdit->setCompleter(0);
|
||||||
|
|
||||||
|
QLabel *label = new QLabel(this);
|
||||||
|
label->setText(text);
|
||||||
|
|
||||||
|
QVBoxLayout *dialogLayout = new QVBoxLayout(this);
|
||||||
|
dialogLayout->addWidget(label);
|
||||||
|
dialogLayout->addWidget(mLineEdit);
|
||||||
|
dialogLayout->addWidget(mButtonBox);
|
||||||
|
|
||||||
// Messageboxes on mac have no title
|
// Messageboxes on mac have no title
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
|
@ -28,22 +38,12 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid
|
||||||
Q_UNUSED(title);
|
Q_UNUSED(title);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QLabel *label = new QLabel(this);
|
setOkButtonEnabled(false);
|
||||||
label->setText(text);
|
setModal(true);
|
||||||
|
|
||||||
// Line edit
|
|
||||||
QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
|
|
||||||
mLineEdit = new LineEdit(this);
|
|
||||||
mLineEdit->setValidator(validator);
|
|
||||||
mLineEdit->setCompleter(0);
|
|
||||||
|
|
||||||
QVBoxLayout *dialogLayout = new QVBoxLayout(this);
|
|
||||||
dialogLayout->addWidget(label);
|
|
||||||
dialogLayout->addWidget(mLineEdit);
|
|
||||||
dialogLayout->addWidget(mButtonBox);
|
|
||||||
|
|
||||||
connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextInputDialog::exec()
|
int TextInputDialog::exec()
|
||||||
|
@ -55,7 +55,17 @@ int TextInputDialog::exec()
|
||||||
|
|
||||||
void TextInputDialog::setOkButtonEnabled(bool enabled)
|
void TextInputDialog::setOkButtonEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
|
|
||||||
QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok);
|
QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok);
|
||||||
okButton->setEnabled(enabled);
|
okButton->setEnabled(enabled);
|
||||||
|
|
||||||
|
QPalette *palette = new QPalette();
|
||||||
|
palette->setColor(QPalette::Text,Qt::red);
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
mLineEdit->setPalette(QApplication::palette());
|
||||||
|
} else {
|
||||||
|
// Existing profile name, make the text red
|
||||||
|
mLineEdit->setPalette(*palette);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
set (OPENCS_SRC main.cpp)
|
set (OPENCS_SRC main.cpp)
|
||||||
|
|
||||||
opencs_units (. editor)
|
opencs_units (. editor)
|
||||||
|
@ -41,7 +40,7 @@ opencs_units_noqt (model/tools
|
||||||
|
|
||||||
|
|
||||||
opencs_units (view/doc
|
opencs_units (view/doc
|
||||||
viewmanager view operations operation subview startup opendialog
|
viewmanager view operations operation subview startup filedialog
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,6 +75,10 @@ set (OPENCS_US
|
||||||
)
|
)
|
||||||
|
|
||||||
set (OPENCS_RES ../../files/opencs/resources.qrc
|
set (OPENCS_RES ../../files/opencs/resources.qrc
|
||||||
|
../../files/launcher/launcher.qrc
|
||||||
|
)
|
||||||
|
|
||||||
|
set (OPENCS_UI ../../files/ui/datafilespage.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR})
|
source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR})
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
|
|
||||||
#include "editor.hpp"
|
#include "editor.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <QtGui/QApplication>
|
#include <QtGui/QApplication>
|
||||||
|
|
||||||
#include "model/doc/document.hpp"
|
#include "model/doc/document.hpp"
|
||||||
#include "model/world/data.hpp"
|
#include "model/world/data.hpp"
|
||||||
|
|
||||||
CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0)
|
CS::Editor::Editor() : mViewManager (mDocumentManager)
|
||||||
{
|
{
|
||||||
connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ()));
|
connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ()));
|
||||||
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
||||||
|
@ -16,47 +14,106 @@ CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0)
|
||||||
connect (&mStartup, SIGNAL (createDocument()), this, SLOT (createDocument ()));
|
connect (&mStartup, SIGNAL (createDocument()), this, SLOT (createDocument ()));
|
||||||
connect (&mStartup, SIGNAL (loadDocument()), this, SLOT (loadDocument ()));
|
connect (&mStartup, SIGNAL (loadDocument()), this, SLOT (loadDocument ()));
|
||||||
|
|
||||||
connect (&mOpenDialog, SIGNAL(accepted()), this, SLOT(openFiles()));
|
connect (&mFileDialog, SIGNAL(openFiles()), this, SLOT(openFiles()));
|
||||||
|
connect (&mFileDialog, SIGNAL(createNewFile()), this, SLOT(createNewFile()));
|
||||||
|
|
||||||
|
setupDataFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CS::Editor::setupDataFiles()
|
||||||
|
{
|
||||||
|
boost::program_options::variables_map variables;
|
||||||
|
boost::program_options::options_description desc;
|
||||||
|
|
||||||
|
desc.add_options()
|
||||||
|
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
|
||||||
|
("data-local", boost::program_options::value<std::string>()->default_value(""))
|
||||||
|
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
|
||||||
|
("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
|
||||||
|
|
||||||
|
boost::program_options::notify(variables);
|
||||||
|
|
||||||
|
mCfgMgr.readConfiguration(variables, desc);
|
||||||
|
|
||||||
|
Files::PathContainer mDataDirs, mDataLocal;
|
||||||
|
if (!variables["data"].empty()) {
|
||||||
|
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string local = variables["data-local"].as<std::string>();
|
||||||
|
if (!local.empty()) {
|
||||||
|
mDataLocal.push_back(Files::PathContainer::value_type(local));
|
||||||
|
}
|
||||||
|
|
||||||
|
mCfgMgr.processPaths(mDataDirs);
|
||||||
|
mCfgMgr.processPaths(mDataLocal);
|
||||||
|
|
||||||
|
// Set the charset for reading the esm/esp files
|
||||||
|
QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
|
||||||
|
mFileDialog.setEncoding(encoding);
|
||||||
|
|
||||||
|
Files::PathContainer dataDirs;
|
||||||
|
dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end());
|
||||||
|
dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end());
|
||||||
|
|
||||||
|
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
||||||
|
{
|
||||||
|
QString path = QString::fromStdString(iter->string());
|
||||||
|
mFileDialog.addFiles(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::createDocument()
|
void CS::Editor::createDocument()
|
||||||
{
|
{
|
||||||
mStartup.hide();
|
mStartup.hide();
|
||||||
|
|
||||||
/// \todo open the ESX picker instead
|
mFileDialog.newFile();
|
||||||
|
|
||||||
std::ostringstream stream;
|
|
||||||
|
|
||||||
stream << "NewDocument" << (++mNewDocumentIndex);
|
|
||||||
|
|
||||||
std::vector<boost::filesystem::path> files;
|
|
||||||
files.push_back (stream.str());
|
|
||||||
|
|
||||||
CSMDoc::Document *document = mDocumentManager.addDocument (files, true);
|
|
||||||
|
|
||||||
mViewManager.addView (document);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::loadDocument()
|
void CS::Editor::loadDocument()
|
||||||
{
|
{
|
||||||
mStartup.hide();
|
mStartup.hide();
|
||||||
mOpenDialog.show();
|
|
||||||
mOpenDialog.raise();
|
mFileDialog.openFile();
|
||||||
mOpenDialog.activateWindow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::openFiles()
|
void CS::Editor::openFiles()
|
||||||
{
|
{
|
||||||
std::vector<boost::filesystem::path> paths;
|
std::vector<boost::filesystem::path> files;
|
||||||
mOpenDialog.getFileList(paths);
|
QStringList paths = mFileDialog.checkedItemsPaths();
|
||||||
CSMDoc::Document *document = mDocumentManager.addDocument(paths, false);
|
|
||||||
|
foreach (const QString &path, paths) {
|
||||||
|
files.push_back(path.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMDoc::Document *document = mDocumentManager.addDocument(files, false);
|
||||||
|
|
||||||
mViewManager.addView (document);
|
mViewManager.addView (document);
|
||||||
|
mFileDialog.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CS::Editor::createNewFile()
|
||||||
|
{
|
||||||
|
std::vector<boost::filesystem::path> files;
|
||||||
|
QStringList paths = mFileDialog.checkedItemsPaths();
|
||||||
|
|
||||||
|
foreach (const QString &path, paths) {
|
||||||
|
files.push_back(path.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
files.push_back(mFileDialog.fileName().toStdString());
|
||||||
|
|
||||||
|
CSMDoc::Document *document = mDocumentManager.addDocument (files, true);
|
||||||
|
|
||||||
|
mViewManager.addView (document);
|
||||||
|
mFileDialog.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CS::Editor::run()
|
int CS::Editor::run()
|
||||||
{
|
{
|
||||||
mStartup.show();
|
mStartup.show();
|
||||||
|
|
||||||
|
QApplication::setQuitOnLastWindowClosed (true);
|
||||||
|
|
||||||
return QApplication::exec();
|
return QApplication::exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
#include "model/doc/documentmanager.hpp"
|
#include "model/doc/documentmanager.hpp"
|
||||||
|
|
||||||
#include "view/doc/viewmanager.hpp"
|
#include "view/doc/viewmanager.hpp"
|
||||||
#include "view/doc/startup.hpp"
|
#include "view/doc/startup.hpp"
|
||||||
#include "view/doc/opendialog.hpp"
|
#include "view/doc/filedialog.hpp"
|
||||||
|
|
||||||
namespace CS
|
namespace CS
|
||||||
{
|
{
|
||||||
|
@ -15,12 +17,14 @@ namespace CS
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
int mNewDocumentIndex; ///< \todo remove when the proper new document dialogue is implemented.
|
|
||||||
|
|
||||||
CSMDoc::DocumentManager mDocumentManager;
|
CSMDoc::DocumentManager mDocumentManager;
|
||||||
CSVDoc::ViewManager mViewManager;
|
CSVDoc::ViewManager mViewManager;
|
||||||
CSVDoc::StartupDialogue mStartup;
|
CSVDoc::StartupDialogue mStartup;
|
||||||
OpenDialog mOpenDialog;
|
FileDialog mFileDialog;
|
||||||
|
|
||||||
|
Files::ConfigurationManager mCfgMgr;
|
||||||
|
|
||||||
|
void setupDataFiles();
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Editor (const Editor&);
|
Editor (const Editor&);
|
||||||
|
@ -39,7 +43,8 @@ namespace CS
|
||||||
|
|
||||||
void loadDocument();
|
void loadDocument();
|
||||||
void openFiles();
|
void openFiles();
|
||||||
|
void createNewFile();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <QDebug>
|
||||||
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
|
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
|
||||||
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
|
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
|
||||||
{
|
{
|
||||||
|
@ -18,9 +18,6 @@ void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_i
|
||||||
|
|
||||||
if (lastAsModified)
|
if (lastAsModified)
|
||||||
getData().loadFile (*end2, false);
|
getData().loadFile (*end2, false);
|
||||||
|
|
||||||
addOptionalGmsts();
|
|
||||||
addOptionalGlobals();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::addOptionalGmsts()
|
void CSMDoc::Document::addOptionalGmsts()
|
||||||
|
@ -116,8 +113,7 @@ void CSMDoc::Document::addOptionalGmsts()
|
||||||
{
|
{
|
||||||
ESM::GameSetting gmst;
|
ESM::GameSetting gmst;
|
||||||
gmst.mId = sFloats[i];
|
gmst.mId = sFloats[i];
|
||||||
gmst.mF = 0;
|
gmst.mValue.setType (ESM::VT_Float);
|
||||||
gmst.mType = ESM::VT_Float;
|
|
||||||
addOptionalGmst (gmst);
|
addOptionalGmst (gmst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +121,7 @@ void CSMDoc::Document::addOptionalGmsts()
|
||||||
{
|
{
|
||||||
ESM::GameSetting gmst;
|
ESM::GameSetting gmst;
|
||||||
gmst.mId = sIntegers[i];
|
gmst.mId = sIntegers[i];
|
||||||
gmst.mI = 0;
|
gmst.mValue.setType (ESM::VT_Int);
|
||||||
gmst.mType = ESM::VT_Long;
|
|
||||||
addOptionalGmst (gmst);
|
addOptionalGmst (gmst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,8 +129,8 @@ void CSMDoc::Document::addOptionalGmsts()
|
||||||
{
|
{
|
||||||
ESM::GameSetting gmst;
|
ESM::GameSetting gmst;
|
||||||
gmst.mId = sStrings[i];
|
gmst.mId = sStrings[i];
|
||||||
gmst.mStr = "<no text>";
|
gmst.mValue.setType (ESM::VT_String);
|
||||||
gmst.mType = ESM::VT_String;
|
gmst.mValue.setString ("<no text>");
|
||||||
addOptionalGmst (gmst);
|
addOptionalGmst (gmst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,8 +149,7 @@ void CSMDoc::Document::addOptionalGlobals()
|
||||||
{
|
{
|
||||||
ESM::Global global;
|
ESM::Global global;
|
||||||
global.mId = sGlobals[i];
|
global.mId = sGlobals[i];
|
||||||
global.mType = ESM::VT_Int;
|
global.mValue.setType (ESM::VT_Long);
|
||||||
global.mValue = 0;
|
|
||||||
addOptionalGlobal (global);
|
addOptionalGlobal (global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,11 +186,18 @@ void CSMDoc::Document::createBase()
|
||||||
for (int i=0; sGlobals[i]; ++i)
|
for (int i=0; sGlobals[i]; ++i)
|
||||||
{
|
{
|
||||||
ESM::Global record;
|
ESM::Global record;
|
||||||
|
|
||||||
record.mId = sGlobals[i];
|
record.mId = sGlobals[i];
|
||||||
record.mValue = i==0 ? 1 : 0;
|
|
||||||
record.mType = ESM::VT_Float;
|
record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Int);
|
||||||
|
|
||||||
|
if (i==0)
|
||||||
|
record.mValue.setInteger (1);
|
||||||
|
|
||||||
getData().getGlobals().add (record);
|
getData().getGlobals().add (record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \todo add GMSTs
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, bool new_)
|
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, bool new_)
|
||||||
|
@ -211,7 +212,9 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
|
||||||
|
|
||||||
mName = files.back().filename().string();
|
mName = files.back().filename().string();
|
||||||
|
|
||||||
if (files.size()>1 || !new_)
|
if (new_ && files.size()==1)
|
||||||
|
createBase();
|
||||||
|
else if (files.size()>1)
|
||||||
{
|
{
|
||||||
std::vector<boost::filesystem::path>::const_iterator end = files.end();
|
std::vector<boost::filesystem::path>::const_iterator end = files.end();
|
||||||
|
|
||||||
|
@ -221,8 +224,8 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
|
||||||
load (files.begin(), end, !new_);
|
load (files.begin(), end, !new_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_ && files.size()==1)
|
addOptionalGmsts();
|
||||||
createBase();
|
addOptionalGlobals();
|
||||||
|
|
||||||
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
|
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
|
||||||
|
|
||||||
|
@ -234,6 +237,9 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
|
||||||
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
|
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMDoc::Document::~Document()
|
||||||
|
{}
|
||||||
|
|
||||||
QUndoStack& CSMDoc::Document::getUndoStack()
|
QUndoStack& CSMDoc::Document::getUndoStack()
|
||||||
{
|
{
|
||||||
return mUndoStack;
|
return mUndoStack;
|
||||||
|
@ -287,11 +293,13 @@ void CSMDoc::Document::abortOperation (int type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSMDoc::Document::modificationStateChanged (bool clean)
|
void CSMDoc::Document::modificationStateChanged (bool clean)
|
||||||
{
|
{
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSMDoc::Document::operationDone (int type)
|
void CSMDoc::Document::operationDone (int type)
|
||||||
{
|
{
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
|
@ -305,9 +313,12 @@ void CSMDoc::Document::saving()
|
||||||
|
|
||||||
if (mSaveCount>15)
|
if (mSaveCount>15)
|
||||||
{
|
{
|
||||||
|
//clear the stack before resetting the save state
|
||||||
|
//to avoid emitting incorrect states
|
||||||
|
mUndoStack.setClean();
|
||||||
|
|
||||||
mSaveCount = 0;
|
mSaveCount = 0;
|
||||||
mSaveTimer.stop();
|
mSaveTimer.stop();
|
||||||
mUndoStack.setClean();
|
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ namespace CSMDoc
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Document (const std::vector<boost::filesystem::path>& files, bool new_);
|
Document (const std::vector<boost::filesystem::path>& files, bool new_);
|
||||||
|
~Document();
|
||||||
|
|
||||||
QUndoStack& getUndoStack();
|
QUndoStack& getUndoStack();
|
||||||
|
|
||||||
|
@ -105,4 +106,4 @@ namespace CSMDoc
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace CSMWorld
|
||||||
Display_Integer,
|
Display_Integer,
|
||||||
Display_Float,
|
Display_Float,
|
||||||
Display_Var,
|
Display_Var,
|
||||||
Display_VarType
|
Display_GmstVarType,
|
||||||
|
Display_GlobalVarType
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string mTitle;
|
std::string mTitle;
|
||||||
|
|
|
@ -12,13 +12,13 @@ namespace CSMWorld
|
||||||
|
|
||||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
{
|
{
|
||||||
return record.get().mValue;
|
return record.get().mValue.getFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
{
|
{
|
||||||
ESXRecordT record2 = record.get();
|
ESXRecordT record2 = record.get();
|
||||||
record2.mValue = data.toFloat();
|
record2.mValue.setFloat (data.toFloat());
|
||||||
record.setModified (record2);
|
record.setModified (record2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,17 +96,17 @@ namespace CSMWorld
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
struct VarTypeColumn : public Column<ESXRecordT>
|
struct VarTypeColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
VarTypeColumn() : Column<ESXRecordT> ("Type", ColumnBase::Display_VarType) {}
|
VarTypeColumn (ColumnBase::Display display) : Column<ESXRecordT> ("Type", display) {}
|
||||||
|
|
||||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
{
|
{
|
||||||
return static_cast<int> (record.get().mType);
|
return static_cast<int> (record.get().mValue.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
{
|
{
|
||||||
ESXRecordT record2 = record.get();
|
ESXRecordT record2 = record.get();
|
||||||
record2.mType = static_cast<ESM::VarType> (data.toInt());
|
record2.mValue.setType (static_cast<ESM::VarType> (data.toInt()));
|
||||||
record.setModified (record2);
|
record.setModified (record2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,11 +123,21 @@ namespace CSMWorld
|
||||||
|
|
||||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
{
|
{
|
||||||
switch (record.get().mType)
|
switch (record.get().mValue.getType())
|
||||||
{
|
{
|
||||||
case ESM::VT_String: return record.get().mStr.c_str(); break;
|
case ESM::VT_String:
|
||||||
case ESM::VT_Int: return record.get().mI; break;
|
|
||||||
case ESM::VT_Float: return record.get().mF; break;
|
return record.get().mValue.getString().c_str(); break;
|
||||||
|
|
||||||
|
case ESM::VT_Int:
|
||||||
|
case ESM::VT_Short:
|
||||||
|
case ESM::VT_Long:
|
||||||
|
|
||||||
|
return record.get().mValue.getInteger(); break;
|
||||||
|
|
||||||
|
case ESM::VT_Float:
|
||||||
|
|
||||||
|
return record.get().mValue.getFloat(); break;
|
||||||
|
|
||||||
default: return QVariant();
|
default: return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -137,11 +147,24 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
ESXRecordT record2 = record.get();
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
switch (record2.mType)
|
switch (record2.mValue.getType())
|
||||||
{
|
{
|
||||||
case ESM::VT_String: record2.mStr = data.toString().toUtf8().constData(); break;
|
case ESM::VT_String:
|
||||||
case ESM::VT_Int: record2.mI = data.toInt(); break;
|
|
||||||
case ESM::VT_Float: record2.mF = data.toFloat(); break;
|
record2.mValue.setString (data.toString().toUtf8().constData());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESM::VT_Int:
|
||||||
|
case ESM::VT_Short:
|
||||||
|
case ESM::VT_Long:
|
||||||
|
|
||||||
|
record2.mValue.setInteger (data.toInt());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESM::VT_Float:
|
||||||
|
|
||||||
|
record2.mValue.setFloat (data.toFloat());
|
||||||
|
break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/defs.hpp>
|
||||||
#include <components/esm/loadglob.hpp>
|
#include <components/esm/loadglob.hpp>
|
||||||
|
|
||||||
#include "idtable.hpp"
|
#include "idtable.hpp"
|
||||||
|
@ -26,12 +27,13 @@ CSMWorld::Data::Data()
|
||||||
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
||||||
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
|
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
|
||||||
mGlobals.addColumn (new FixedRecordTypeColumn<ESM::Global> (UniversalId::Type_Global));
|
mGlobals.addColumn (new FixedRecordTypeColumn<ESM::Global> (UniversalId::Type_Global));
|
||||||
mGlobals.addColumn (new FloatValueColumn<ESM::Global>);
|
mGlobals.addColumn (new VarTypeColumn<ESM::Global> (ColumnBase::Display_GlobalVarType));
|
||||||
|
mGlobals.addColumn (new VarValueColumn<ESM::Global>);
|
||||||
|
|
||||||
mGmsts.addColumn (new StringIdColumn<ESM::GameSetting>);
|
mGmsts.addColumn (new StringIdColumn<ESM::GameSetting>);
|
||||||
mGmsts.addColumn (new RecordStateColumn<ESM::GameSetting>);
|
mGmsts.addColumn (new RecordStateColumn<ESM::GameSetting>);
|
||||||
mGmsts.addColumn (new FixedRecordTypeColumn<ESM::GameSetting> (UniversalId::Type_Gmst));
|
mGmsts.addColumn (new FixedRecordTypeColumn<ESM::GameSetting> (UniversalId::Type_Gmst));
|
||||||
mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting>);
|
mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting> (ColumnBase::Display_GmstVarType));
|
||||||
mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>);
|
mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>);
|
||||||
|
|
||||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
||||||
|
|
272
apps/opencs/view/doc/filedialog.cpp
Normal file
272
apps/opencs/view/doc/filedialog.cpp
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
#include "filedialog.hpp"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QRegExpValidator>
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QSpacerItem>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
#include <components/fileorderlist/model/datafilesmodel.hpp>
|
||||||
|
#include <components/fileorderlist/model/pluginsproxymodel.hpp>
|
||||||
|
#include <components/fileorderlist/model/esm/esmfile.hpp>
|
||||||
|
|
||||||
|
#include <components/fileorderlist/utils/lineedit.hpp>
|
||||||
|
|
||||||
|
FileDialog::FileDialog(QWidget *parent) :
|
||||||
|
QDialog(parent)
|
||||||
|
{
|
||||||
|
setupUi(this);
|
||||||
|
|
||||||
|
// Models
|
||||||
|
mDataFilesModel = new DataFilesModel(this);
|
||||||
|
|
||||||
|
mMastersProxyModel = new QSortFilterProxyModel();
|
||||||
|
mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm"));
|
||||||
|
mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
mMastersProxyModel->setSourceModel(mDataFilesModel);
|
||||||
|
|
||||||
|
mPluginsProxyModel = new PluginsProxyModel();
|
||||||
|
mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp"));
|
||||||
|
mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
mPluginsProxyModel->setSourceModel(mDataFilesModel);
|
||||||
|
|
||||||
|
mFilterProxyModel = new QSortFilterProxyModel();
|
||||||
|
mFilterProxyModel->setDynamicSortFilter(true);
|
||||||
|
mFilterProxyModel->setSourceModel(mPluginsProxyModel);
|
||||||
|
|
||||||
|
QCheckBox checkBox;
|
||||||
|
unsigned int height = checkBox.sizeHint().height() + 4;
|
||||||
|
|
||||||
|
mastersTable->setModel(mMastersProxyModel);
|
||||||
|
mastersTable->setObjectName("MastersTable");
|
||||||
|
mastersTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
mastersTable->setSortingEnabled(false);
|
||||||
|
mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
mastersTable->setAlternatingRowColors(true);
|
||||||
|
mastersTable->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
|
||||||
|
// Set the row height to the size of the checkboxes
|
||||||
|
mastersTable->verticalHeader()->setDefaultSectionSize(height);
|
||||||
|
mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
||||||
|
mastersTable->verticalHeader()->hide();
|
||||||
|
|
||||||
|
pluginsTable->setModel(mFilterProxyModel);
|
||||||
|
pluginsTable->setObjectName("PluginsTable");
|
||||||
|
pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
pluginsTable->setSortingEnabled(false);
|
||||||
|
pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
pluginsTable->setAlternatingRowColors(true);
|
||||||
|
pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
|
||||||
|
pluginsTable->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
|
||||||
|
pluginsTable->verticalHeader()->setDefaultSectionSize(height);
|
||||||
|
pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
||||||
|
|
||||||
|
// Hide the profile elements
|
||||||
|
profileLabel->hide();
|
||||||
|
profilesComboBox->hide();
|
||||||
|
newProfileButton->hide();
|
||||||
|
deleteProfileButton->hide();
|
||||||
|
|
||||||
|
// Add some extra widgets
|
||||||
|
QHBoxLayout *nameLayout = new QHBoxLayout();
|
||||||
|
QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||||
|
|
||||||
|
mNameLabel = new QLabel(tr("File Name:"), this);
|
||||||
|
|
||||||
|
QRegExpValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9\\s]*$"));
|
||||||
|
mNameLineEdit = new LineEdit(this);
|
||||||
|
mNameLineEdit->setValidator(validator);
|
||||||
|
|
||||||
|
nameLayout->addSpacerItem(spacer);
|
||||||
|
nameLayout->addWidget(mNameLabel);
|
||||||
|
nameLayout->addWidget(mNameLineEdit);
|
||||||
|
|
||||||
|
mButtonBox = new QDialogButtonBox(this);
|
||||||
|
|
||||||
|
mCreateButton = new QPushButton(tr("Create"), this);
|
||||||
|
mCreateButton->setEnabled(false);
|
||||||
|
|
||||||
|
verticalLayout->addLayout(nameLayout);
|
||||||
|
verticalLayout->addWidget(mButtonBox);
|
||||||
|
|
||||||
|
// Set sizes
|
||||||
|
QList<int> sizeList;
|
||||||
|
sizeList << 175;
|
||||||
|
sizeList << 200;
|
||||||
|
|
||||||
|
splitter->setSizes(sizeList);
|
||||||
|
|
||||||
|
resize(600, 400);
|
||||||
|
|
||||||
|
connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews()));
|
||||||
|
connect(mDataFilesModel, SIGNAL(checkedItemsChanged(QStringList)), this, SLOT(updateOpenButton(QStringList)));
|
||||||
|
connect(mNameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateCreateButton(QString)));
|
||||||
|
|
||||||
|
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
|
||||||
|
|
||||||
|
connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
||||||
|
connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
||||||
|
|
||||||
|
connect(mCreateButton, SIGNAL(clicked()), this, SLOT(createButtonClicked()));
|
||||||
|
|
||||||
|
connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
|
connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::updateViews()
|
||||||
|
{
|
||||||
|
// Ensure the columns are hidden because sort() re-enables them
|
||||||
|
mastersTable->setColumnHidden(1, true);
|
||||||
|
mastersTable->setColumnHidden(3, true);
|
||||||
|
mastersTable->setColumnHidden(4, true);
|
||||||
|
mastersTable->setColumnHidden(5, true);
|
||||||
|
mastersTable->setColumnHidden(6, true);
|
||||||
|
mastersTable->setColumnHidden(7, true);
|
||||||
|
mastersTable->setColumnHidden(8, true);
|
||||||
|
mastersTable->resizeColumnsToContents();
|
||||||
|
|
||||||
|
pluginsTable->setColumnHidden(1, true);
|
||||||
|
pluginsTable->setColumnHidden(3, true);
|
||||||
|
pluginsTable->setColumnHidden(4, true);
|
||||||
|
pluginsTable->setColumnHidden(5, true);
|
||||||
|
pluginsTable->setColumnHidden(6, true);
|
||||||
|
pluginsTable->setColumnHidden(7, true);
|
||||||
|
pluginsTable->setColumnHidden(8, true);
|
||||||
|
pluginsTable->resizeColumnsToContents();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::updateOpenButton(const QStringList &items)
|
||||||
|
{
|
||||||
|
QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open);
|
||||||
|
|
||||||
|
if (!openButton)
|
||||||
|
return;
|
||||||
|
|
||||||
|
openButton->setEnabled(!items.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::updateCreateButton(const QString &name)
|
||||||
|
{
|
||||||
|
if (!mCreateButton->isVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCreateButton->setEnabled(!name.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::filterChanged(const QString &filter)
|
||||||
|
{
|
||||||
|
QRegExp filterRe(filter, Qt::CaseInsensitive, QRegExp::FixedString);
|
||||||
|
mFilterProxyModel->setFilterRegExp(filterRe);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::addFiles(const QString &path)
|
||||||
|
{
|
||||||
|
mDataFilesModel->addFiles(path);
|
||||||
|
mDataFilesModel->sort(3); // Sort by date accessed
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::setEncoding(const QString &encoding)
|
||||||
|
{
|
||||||
|
mDataFilesModel->setEncoding(encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::setCheckState(QModelIndex index)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QObject *object = QObject::sender();
|
||||||
|
|
||||||
|
// Not a signal-slot call
|
||||||
|
if (!object)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
if (object->objectName() == QLatin1String("PluginsTable")) {
|
||||||
|
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
|
||||||
|
mFilterProxyModel->mapToSource(index));
|
||||||
|
|
||||||
|
if (sourceIndex.isValid()) {
|
||||||
|
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
||||||
|
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
|
||||||
|
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object->objectName() == QLatin1String("MastersTable")) {
|
||||||
|
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
|
||||||
|
|
||||||
|
if (sourceIndex.isValid()) {
|
||||||
|
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
||||||
|
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
|
||||||
|
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList FileDialog::checkedItemsPaths()
|
||||||
|
{
|
||||||
|
return mDataFilesModel->checkedItemsPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileDialog::fileName()
|
||||||
|
{
|
||||||
|
return mNameLineEdit->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::openFile()
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("Open"));
|
||||||
|
|
||||||
|
mNameLabel->hide();
|
||||||
|
mNameLineEdit->hide();
|
||||||
|
mCreateButton->hide();
|
||||||
|
|
||||||
|
mButtonBox->removeButton(mCreateButton);
|
||||||
|
mButtonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Open);
|
||||||
|
QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open);
|
||||||
|
openButton->setEnabled(false);
|
||||||
|
|
||||||
|
show();
|
||||||
|
raise();
|
||||||
|
activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::newFile()
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("New"));
|
||||||
|
|
||||||
|
mNameLabel->show();
|
||||||
|
mNameLineEdit->clear();
|
||||||
|
mNameLineEdit->show();
|
||||||
|
mCreateButton->show();
|
||||||
|
|
||||||
|
mButtonBox->setStandardButtons(QDialogButtonBox::Cancel);
|
||||||
|
mButtonBox->addButton(mCreateButton, QDialogButtonBox::ActionRole);
|
||||||
|
|
||||||
|
show();
|
||||||
|
raise();
|
||||||
|
activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::accept()
|
||||||
|
{
|
||||||
|
emit openFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::createButtonClicked()
|
||||||
|
{
|
||||||
|
emit createNewFile();
|
||||||
|
}
|
66
apps/opencs/view/doc/filedialog.hpp
Normal file
66
apps/opencs/view/doc/filedialog.hpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef FILEDIALOG_HPP
|
||||||
|
#define FILEDIALOG_HPP
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QModelIndex>
|
||||||
|
|
||||||
|
#include "ui_datafilespage.h"
|
||||||
|
|
||||||
|
class QDialogButtonBox;
|
||||||
|
class QSortFilterProxyModel;
|
||||||
|
class QAbstractItemModel;
|
||||||
|
class QPushButton;
|
||||||
|
class QStringList;
|
||||||
|
class QString;
|
||||||
|
class QMenu;
|
||||||
|
|
||||||
|
class DataFilesModel;
|
||||||
|
class PluginsProxyModel;
|
||||||
|
|
||||||
|
class FileDialog : public QDialog, private Ui::DataFilesPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FileDialog(QWidget *parent = 0);
|
||||||
|
void addFiles(const QString &path);
|
||||||
|
void setEncoding(const QString &encoding);
|
||||||
|
|
||||||
|
void openFile();
|
||||||
|
void newFile();
|
||||||
|
void accepted();
|
||||||
|
|
||||||
|
QStringList checkedItemsPaths();
|
||||||
|
QString fileName();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void openFiles();
|
||||||
|
void createNewFile();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void accept();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateViews();
|
||||||
|
void updateOpenButton(const QStringList &items);
|
||||||
|
void updateCreateButton(const QString &name);
|
||||||
|
void setCheckState(QModelIndex index);
|
||||||
|
|
||||||
|
void filterChanged(const QString &filter);
|
||||||
|
|
||||||
|
void createButtonClicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLabel *mNameLabel;
|
||||||
|
LineEdit *mNameLineEdit;
|
||||||
|
|
||||||
|
QPushButton *mCreateButton;
|
||||||
|
QDialogButtonBox *mButtonBox;
|
||||||
|
|
||||||
|
DataFilesModel *mDataFilesModel;
|
||||||
|
|
||||||
|
PluginsProxyModel *mPluginsProxyModel;
|
||||||
|
QSortFilterProxyModel *mMastersProxyModel;
|
||||||
|
QSortFilterProxyModel *mFilterProxyModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILEDIALOG_HPP
|
|
@ -56,7 +56,7 @@ void CSVDoc::Operations::quitOperation (int type)
|
||||||
|
|
||||||
mLayout->removeItem ((*iter)->getLayout());
|
mLayout->removeItem ((*iter)->getLayout());
|
||||||
|
|
||||||
delete *iter;
|
(*iter)->deleteLater();
|
||||||
mOperations.erase (iter);
|
mOperations.erase (iter);
|
||||||
|
|
||||||
if (oldCount > 1)
|
if (oldCount > 1)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QMdiArea>
|
#include <QMdiArea>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
|
#include <QtGui/QApplication>
|
||||||
|
|
||||||
#include "../../model/doc/document.hpp"
|
#include "../../model/doc/document.hpp"
|
||||||
|
|
||||||
|
@ -39,6 +40,16 @@ void CSVDoc::View::setupFileMenu()
|
||||||
mSave = new QAction (tr ("&Save"), this);
|
mSave = new QAction (tr ("&Save"), this);
|
||||||
connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
|
connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
|
||||||
file->addAction (mSave);
|
file->addAction (mSave);
|
||||||
|
|
||||||
|
QAction *close = new QAction (tr ("&Close"), this);
|
||||||
|
connect (close, SIGNAL (triggered()), this, SLOT (close()));
|
||||||
|
file->addAction(close);
|
||||||
|
|
||||||
|
QAction *exit = new QAction (tr ("&Exit"), this);
|
||||||
|
connect (exit, SIGNAL (triggered()), this, SLOT (exit()));
|
||||||
|
connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *)));
|
||||||
|
|
||||||
|
file->addAction(exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::setupEditMenu()
|
void CSVDoc::View::setupEditMenu()
|
||||||
|
@ -117,15 +128,15 @@ void CSVDoc::View::updateActions()
|
||||||
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
|
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent)
|
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
|
||||||
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews), QMainWindow (viewParent)
|
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
|
||||||
|
mViewTotal (totalViews)
|
||||||
{
|
{
|
||||||
setDockOptions (QMainWindow::AllowNestedDocks);
|
|
||||||
|
|
||||||
resize (300, 300); /// \todo get default size from settings and set reasonable minimal size
|
resize (300, 300); /// \todo get default size from settings and set reasonable minimal size
|
||||||
|
|
||||||
mSubViewWindow = new QMainWindow();
|
mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks);
|
||||||
setCentralWidget (mSubViewWindow);
|
|
||||||
|
setCentralWidget (&mSubViewWindow);
|
||||||
|
|
||||||
mOperations = new Operations;
|
mOperations = new Operations;
|
||||||
addDockWidget (Qt::BottomDockWidgetArea, mOperations);
|
addDockWidget (Qt::BottomDockWidgetArea, mOperations);
|
||||||
|
@ -200,7 +211,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
|
||||||
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
|
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
|
||||||
|
|
||||||
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
|
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
|
||||||
mSubViewWindow->addDockWidget (Qt::TopDockWidgetArea, view);
|
mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
|
||||||
|
|
||||||
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
|
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
|
||||||
SLOT (addSubView (const CSMWorld::UniversalId&)));
|
SLOT (addSubView (const CSMWorld::UniversalId&)));
|
||||||
|
@ -239,7 +250,12 @@ void CSVDoc::View::abortOperation (int type)
|
||||||
updateActions();
|
updateActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
QDockWidget *CSVDoc::View::getOperations() const
|
CSVDoc::Operations *CSVDoc::View::getOperations() const
|
||||||
{
|
{
|
||||||
return mOperations;
|
return mOperations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::exit()
|
||||||
|
{
|
||||||
|
emit exitApplicationRequest (this);
|
||||||
|
}
|
||||||
|
|
|
@ -41,7 +41,8 @@ namespace CSVDoc
|
||||||
std::vector<QAction *> mEditingActions;
|
std::vector<QAction *> mEditingActions;
|
||||||
Operations *mOperations;
|
Operations *mOperations;
|
||||||
SubViewFactoryManager mSubViewFactory;
|
SubViewFactoryManager mSubViewFactory;
|
||||||
QMainWindow* mSubViewWindow;
|
QMainWindow mSubViewWindow;
|
||||||
|
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
View (const View&);
|
View (const View&);
|
||||||
|
@ -65,9 +66,12 @@ namespace CSVDoc
|
||||||
|
|
||||||
void updateActions();
|
void updateActions();
|
||||||
|
|
||||||
|
void exitApplication();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent);
|
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
|
||||||
|
|
||||||
///< The ownership of \a document is not transferred to *this.
|
///< The ownership of \a document is not transferred to *this.
|
||||||
|
|
||||||
virtual ~View();
|
virtual ~View();
|
||||||
|
@ -82,7 +86,7 @@ namespace CSVDoc
|
||||||
|
|
||||||
void updateProgress (int current, int max, int type, int threads);
|
void updateProgress (int current, int max, int type, int threads);
|
||||||
|
|
||||||
QDockWidget *getOperations() const;
|
Operations *getOperations() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
@ -90,23 +94,28 @@ namespace CSVDoc
|
||||||
|
|
||||||
void loadDocumentRequest();
|
void loadDocumentRequest();
|
||||||
|
|
||||||
|
void exitApplicationRequest (CSVDoc::View *view);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void addSubView (const CSMWorld::UniversalId& id);
|
void addSubView (const CSMWorld::UniversalId& id);
|
||||||
|
|
||||||
|
void abortOperation (int type);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void newView();
|
void newView();
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
|
void exit();
|
||||||
|
|
||||||
void verify();
|
void verify();
|
||||||
|
|
||||||
void addGlobalsSubView();
|
void addGlobalsSubView();
|
||||||
|
|
||||||
void addGmstsSubView();
|
void addGmstsSubView();
|
||||||
|
|
||||||
void abortOperation (int type);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
|
|
||||||
#include "view.hpp"
|
#include "view.hpp"
|
||||||
|
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QtGui/QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
void CSVDoc::ViewManager::updateIndices()
|
void CSVDoc::ViewManager::updateIndices()
|
||||||
{
|
{
|
||||||
std::map<CSMDoc::Document *, std::pair<int, int> > documents;
|
std::map<CSMDoc::Document *, std::pair<int, int> > documents;
|
||||||
|
@ -31,12 +36,15 @@ void CSVDoc::ViewManager::updateIndices()
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
||||||
: mDocumentManager (documentManager)
|
: mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
|
||||||
{
|
{
|
||||||
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
|
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
|
||||||
|
|
||||||
mDelegateFactories->add (CSMWorld::ColumnBase::Display_VarType,
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType,
|
||||||
new CSVWorld::VarTypeDelegateFactory (ESM::VT_None, ESM::VT_String, ESM::VT_Int, ESM::VT_Float));
|
new CSVWorld::VarTypeDelegateFactory (ESM::VT_None, ESM::VT_String, ESM::VT_Int, ESM::VT_Float));
|
||||||
|
|
||||||
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
|
||||||
|
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVDoc::ViewManager::~ViewManager()
|
CSVDoc::ViewManager::~ViewManager()
|
||||||
|
@ -59,9 +67,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
|
||||||
this, SLOT (progress (int, int, int, int, CSMDoc::Document *)));
|
this, SLOT (progress (int, int, int, int, CSMDoc::Document *)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QMainWindow *mainWindow = new QMainWindow;
|
View *view = new View (*this, document, countViews (document)+1);
|
||||||
|
|
||||||
View *view = new View (*this, document, countViews (document)+1, mainWindow);
|
|
||||||
|
|
||||||
mViews.push_back (view);
|
mViews.push_back (view);
|
||||||
|
|
||||||
|
@ -90,23 +97,143 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
|
||||||
{
|
{
|
||||||
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
|
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
|
||||||
|
|
||||||
|
bool continueWithClose = true;
|
||||||
|
|
||||||
if (iter!=mViews.end())
|
if (iter!=mViews.end())
|
||||||
{
|
{
|
||||||
bool last = countViews (view->getDocument())<=1;
|
bool last = countViews (view->getDocument())<=1;
|
||||||
|
|
||||||
/// \todo check if save is in progress -> warn user about possible data loss
|
|
||||||
/// \todo check if document has not been saved -> return false and start close dialogue
|
|
||||||
|
|
||||||
mViews.erase (iter);
|
|
||||||
view->deleteLater();
|
|
||||||
|
|
||||||
if (last)
|
if (last)
|
||||||
mDocumentManager.removeDocument (view->getDocument());
|
continueWithClose = notifySaveOnClose (view);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
(*iter)->deleteLater();
|
||||||
|
mViews.erase (iter);
|
||||||
|
|
||||||
updateIndices();
|
updateIndices();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return continueWithClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVDoc::ViewManager::notifySaveOnClose (CSVDoc::View *view)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
CSMDoc::Document *document = view->getDocument();
|
||||||
|
|
||||||
|
//notify user of saving in progress
|
||||||
|
if ( (document->getState() & CSMDoc::State_Saving) )
|
||||||
|
result = showSaveInProgressMessageBox (view);
|
||||||
|
|
||||||
|
//notify user of unsaved changes and process response
|
||||||
|
else if ( document->getState() & CSMDoc::State_Modified)
|
||||||
|
result = showModifiedDocumentMessageBox (view);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
|
||||||
|
{
|
||||||
|
QMessageBox messageBox;
|
||||||
|
CSMDoc::Document *document = view->getDocument();
|
||||||
|
|
||||||
|
messageBox.setText ("The document has been modified.");
|
||||||
|
messageBox.setInformativeText ("Do you want to save your changes?");
|
||||||
|
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
||||||
|
messageBox.setDefaultButton (QMessageBox::Save);
|
||||||
|
|
||||||
|
bool retVal = true;
|
||||||
|
|
||||||
|
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
|
||||||
|
|
||||||
|
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
|
||||||
|
mUserWarned = true;
|
||||||
|
int response = messageBox.exec();
|
||||||
|
mUserWarned = false;
|
||||||
|
|
||||||
|
switch (response)
|
||||||
|
{
|
||||||
|
case QMessageBox::Save:
|
||||||
|
|
||||||
|
document->save();
|
||||||
|
mExitOnSaveStateChange = true;
|
||||||
|
retVal = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMessageBox::Discard:
|
||||||
|
|
||||||
|
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMessageBox::Cancel:
|
||||||
|
|
||||||
|
//disconnect to prevent unintended view closures
|
||||||
|
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
retVal = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVDoc::ViewManager::showSaveInProgressMessageBox (CSVDoc::View *view)
|
||||||
|
{
|
||||||
|
QMessageBox messageBox;
|
||||||
|
CSMDoc::Document *document = view->getDocument();
|
||||||
|
|
||||||
|
messageBox.setText ("The document is currently being saved.");
|
||||||
|
messageBox.setInformativeText("Do you want to close now and abort saving, or wait until saving has completed?");
|
||||||
|
|
||||||
|
QPushButton* waitButton = messageBox.addButton (tr("Wait"), QMessageBox::YesRole);
|
||||||
|
QPushButton* closeButton = messageBox.addButton (tr("Close Now"), QMessageBox::RejectRole);
|
||||||
|
QPushButton* cancelButton = messageBox.addButton (tr("Cancel"), QMessageBox::NoRole);
|
||||||
|
|
||||||
|
messageBox.setDefaultButton (waitButton);
|
||||||
|
|
||||||
|
bool retVal = true;
|
||||||
|
|
||||||
|
//Connections shut down message box if operation ends before user makes a decision.
|
||||||
|
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
|
||||||
|
|
||||||
|
//set / clear the user warned flag to indicate whether or not the message box is currently active.
|
||||||
|
mUserWarned = true;
|
||||||
|
messageBox.exec();
|
||||||
|
mUserWarned = false;
|
||||||
|
|
||||||
|
//if closed by the warning handler, defaults to the RejectRole button (closeButton)
|
||||||
|
if (messageBox.clickedButton() == waitButton)
|
||||||
|
{
|
||||||
|
//save the View iterator for shutdown after the save operation ends
|
||||||
|
mExitOnSaveStateChange = true;
|
||||||
|
retVal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (messageBox.clickedButton() == closeButton)
|
||||||
|
{
|
||||||
|
//disconnect to avoid segmentation fault
|
||||||
|
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
|
||||||
|
view->abortOperation(CSMDoc::State_Saving);
|
||||||
|
mExitOnSaveStateChange = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (messageBox.clickedButton() == cancelButton)
|
||||||
|
{
|
||||||
|
//abort shutdown, allow save to complete
|
||||||
|
//disconnection to prevent unintended view closures
|
||||||
|
mExitOnSaveStateChange = false;
|
||||||
|
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
retVal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document)
|
void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document)
|
||||||
|
@ -122,3 +249,25 @@ void CSVDoc::ViewManager::progress (int current, int max, int type, int threads,
|
||||||
if ((*iter)->getDocument()==document)
|
if ((*iter)->getDocument()==document)
|
||||||
(*iter)->updateProgress (current, max, type, threads);
|
(*iter)->updateProgress (current, max, type, threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::ViewManager::onExitWarningHandler (int state, CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
if ( !(state & CSMDoc::State_Saving) )
|
||||||
|
{
|
||||||
|
//if the user is being warned (message box is active), shut down the message box,
|
||||||
|
//as there is no save operation currently running
|
||||||
|
if ( mUserWarned )
|
||||||
|
emit closeMessageBox();
|
||||||
|
|
||||||
|
//otherwise, the user has closed the message box before the save operation ended.
|
||||||
|
//exit the application
|
||||||
|
else if (mExitOnSaveStateChange)
|
||||||
|
QApplication::instance()->exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view)
|
||||||
|
{
|
||||||
|
if (notifySaveOnClose (view))
|
||||||
|
QApplication::instance()->exit();
|
||||||
|
}
|
||||||
|
|
|
@ -27,12 +27,17 @@ namespace CSVDoc
|
||||||
CSMDoc::DocumentManager& mDocumentManager;
|
CSMDoc::DocumentManager& mDocumentManager;
|
||||||
std::vector<View *> mViews;
|
std::vector<View *> mViews;
|
||||||
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
|
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
|
||||||
|
bool mExitOnSaveStateChange;
|
||||||
|
bool mUserWarned;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
ViewManager (const ViewManager&);
|
ViewManager (const ViewManager&);
|
||||||
ViewManager& operator= (const ViewManager&);
|
ViewManager& operator= (const ViewManager&);
|
||||||
|
|
||||||
void updateIndices();
|
void updateIndices();
|
||||||
|
bool notifySaveOnClose (View *view = 0);
|
||||||
|
bool showModifiedDocumentMessageBox (View *view);
|
||||||
|
bool showSaveInProgressMessageBox (View *view);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -54,13 +59,21 @@ namespace CSVDoc
|
||||||
|
|
||||||
void loadDocumentRequest();
|
void loadDocumentRequest();
|
||||||
|
|
||||||
|
void closeMessageBox();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void exitApplication (CSVDoc::View *view);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void documentStateChanged (int state, CSMDoc::Document *document);
|
void documentStateChanged (int state, CSMDoc::Document *document);
|
||||||
|
|
||||||
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void onExitWarningHandler(int state, CSMDoc::Document* document);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -85,7 +85,7 @@ void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type)
|
||||||
{
|
{
|
||||||
{ ESM::VT_None, "empty" },
|
{ ESM::VT_None, "empty" },
|
||||||
{ ESM::VT_Short, "short" },
|
{ ESM::VT_Short, "short" },
|
||||||
{ ESM::VT_Int, "long" },
|
{ ESM::VT_Int, "integer" },
|
||||||
{ ESM::VT_Long, "long" },
|
{ ESM::VT_Long, "long" },
|
||||||
{ ESM::VT_Float, "float" },
|
{ ESM::VT_Float, "float" },
|
||||||
{ ESM::VT_String, "string" },
|
{ ESM::VT_String, "string" },
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef CSV_WORLD_VARTYPEDELEGATE_H
|
#ifndef CSV_WORLD_VARTYPEDELEGATE_H
|
||||||
#define CSV_WORLD_VARTYPEDELEGATE_H
|
#define CSV_WORLD_VARTYPEDELEGATE_H
|
||||||
|
|
||||||
|
#include <components/esm/variant.hpp>
|
||||||
|
|
||||||
#include "enumdelegate.hpp"
|
#include "enumdelegate.hpp"
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWorld
|
||||||
|
|
|
@ -16,7 +16,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
renderingmanager debugging sky player animation npcanimation creatureanimation activatoranimation
|
renderingmanager debugging sky player animation npcanimation creatureanimation activatoranimation
|
||||||
actors objects renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
|
actors objects renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
|
||||||
compositors characterpreview externalrendering globalmap videoplayer
|
compositors characterpreview externalrendering globalmap videoplayer ripplesimulation refraction
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
@ -26,11 +26,11 @@ add_openmw_dir (mwinput
|
||||||
add_openmw_dir (mwgui
|
add_openmw_dir (mwgui
|
||||||
text_input widgets race class birth review windowmanagerimp console dialogue
|
text_input widgets race class birth review windowmanagerimp console dialogue
|
||||||
dialogue_history window_base stats_window messagebox journalwindow charactercreation
|
dialogue_history window_base stats_window messagebox journalwindow charactercreation
|
||||||
map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list
|
map_window window_pinnable_base tooltips scrollwindow bookwindow list
|
||||||
formatting inventorywindow container hud countdialog tradewindow settingswindow
|
formatting inventorywindow container hud countdialog tradewindow settingswindow
|
||||||
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
|
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
|
||||||
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
|
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
|
||||||
enchantingdialog trainingwindow travelwindow imagebutton exposedwindow
|
enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwdialogue
|
add_openmw_dir (mwdialogue
|
||||||
|
|
|
@ -9,16 +9,15 @@
|
||||||
#include <components/bsa/bsa_archive.hpp>
|
#include <components/bsa/bsa_archive.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/translation/translation.hpp>
|
#include <components/translation/translation.hpp>
|
||||||
#include <components/nif/nif_file.hpp>
|
#include <components/nif/niffile.hpp>
|
||||||
#include <components/nifoverrides/nifoverrides.hpp>
|
#include <components/nifoverrides/nifoverrides.hpp>
|
||||||
|
|
||||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
#include <components/nifbullet/bulletnifloader.hpp>
|
||||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
#include <components/nifogre/ogrenifloader.hpp>
|
||||||
|
|
||||||
#include "mwinput/inputmanagerimp.hpp"
|
#include "mwinput/inputmanagerimp.hpp"
|
||||||
|
|
||||||
#include "mwgui/windowmanagerimp.hpp"
|
#include "mwgui/windowmanagerimp.hpp"
|
||||||
#include "mwgui/cursorreplace.hpp"
|
|
||||||
|
|
||||||
#include "mwscript/scriptmanagerimp.hpp"
|
#include "mwscript/scriptmanagerimp.hpp"
|
||||||
#include "mwscript/extensions.hpp"
|
#include "mwscript/extensions.hpp"
|
||||||
|
@ -63,6 +62,13 @@ void OMW::Engine::setAnimationVerbose(bool animverbose)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OMW::Engine::frameStarted (const Ogre::FrameEvent& evt)
|
||||||
|
{
|
||||||
|
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
MWBase::Environment::get().getWorld()->frameStarted(evt.timeSinceLastFrame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -143,16 +149,22 @@ OMW::Engine::~Engine()
|
||||||
delete mOgre;
|
delete mOgre;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all BSA files in data directory.
|
// Load BSA files
|
||||||
|
|
||||||
void OMW::Engine::loadBSA()
|
void OMW::Engine::loadBSA()
|
||||||
{
|
{
|
||||||
const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa");
|
for (std::vector<std::string>::const_iterator archive = mArchives.begin(); archive != mArchives.end(); ++archive)
|
||||||
|
|
||||||
for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
std::cout << "Adding " << iter->second.string() << std::endl;
|
if (mFileCollections.doesExist(*archive))
|
||||||
Bsa::addBSA(iter->second.string());
|
{
|
||||||
|
const std::string archivePath = mFileCollections.getPath(*archive).string();
|
||||||
|
std::cout << "Adding BSA archive " << archivePath << std::endl;
|
||||||
|
Bsa::addBSA(archivePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Archive " << *archive << " not found" << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Files::PathContainer& dataDirs = mFileCollections.getPaths();
|
const Files::PathContainer& dataDirs = mFileCollections.getPaths();
|
||||||
|
@ -193,6 +205,11 @@ void OMW::Engine::setDataDirs (const Files::PathContainer& dataDirs)
|
||||||
mFileCollections = Files::Collections (dataDirs, !mFSStrict);
|
mFileCollections = Files::Collections (dataDirs, !mFSStrict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add BSA archive
|
||||||
|
void OMW::Engine::addArchive (const std::string& archive) {
|
||||||
|
mArchives.push_back(archive);
|
||||||
|
}
|
||||||
|
|
||||||
// Set resource dir
|
// Set resource dir
|
||||||
void OMW::Engine::setResourceDir (const boost::filesystem::path& parResDir)
|
void OMW::Engine::setResourceDir (const boost::filesystem::path& parResDir)
|
||||||
{
|
{
|
||||||
|
@ -317,7 +334,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
|
|
||||||
addResourcesDirectory(mResDir / "mygui");
|
addResourcesDirectory(mResDir / "mygui");
|
||||||
addResourcesDirectory(mResDir / "water");
|
addResourcesDirectory(mResDir / "water");
|
||||||
addResourcesDirectory(mResDir / "gbuffer");
|
|
||||||
addResourcesDirectory(mResDir / "shadows");
|
addResourcesDirectory(mResDir / "shadows");
|
||||||
addZipResource(mResDir / "mygui" / "Obliviontt.zip");
|
addZipResource(mResDir / "mygui" / "Obliviontt.zip");
|
||||||
|
|
||||||
|
@ -333,9 +349,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
|
|
||||||
loadBSA();
|
loadBSA();
|
||||||
|
|
||||||
// cursor replacer (converts the cursor from the bsa so they can be used by mygui)
|
|
||||||
MWGui::CursorReplace replacer;
|
|
||||||
|
|
||||||
// Create the world
|
// Create the world
|
||||||
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
|
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
|
||||||
mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoder, mFallbackMap,
|
mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoder, mFallbackMap,
|
||||||
|
@ -440,15 +453,13 @@ void OMW::Engine::go()
|
||||||
if (!mStartupScript.empty())
|
if (!mStartupScript.empty())
|
||||||
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
|
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
|
||||||
|
|
||||||
std::cout << "\nPress Q/ESC or close window to exit.\n";
|
|
||||||
|
|
||||||
// Start the main rendering loop
|
// Start the main rendering loop
|
||||||
mOgre->start();
|
mOgre->start();
|
||||||
|
|
||||||
// Save user settings
|
// Save user settings
|
||||||
settings.saveUser(settingspath);
|
settings.saveUser(settingspath);
|
||||||
|
|
||||||
std::cout << "Quitting peacefully.\n";
|
std::cout << "Quitting peacefully." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OMW::Engine::activate()
|
void OMW::Engine::activate()
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace OMW
|
||||||
ToUTF8::FromType mEncoding;
|
ToUTF8::FromType mEncoding;
|
||||||
ToUTF8::Utf8Encoder* mEncoder;
|
ToUTF8::Utf8Encoder* mEncoder;
|
||||||
Files::PathContainer mDataDirs;
|
Files::PathContainer mDataDirs;
|
||||||
|
std::vector<std::string> mArchives;
|
||||||
boost::filesystem::path mResDir;
|
boost::filesystem::path mResDir;
|
||||||
OEngine::Render::OgreRenderer *mOgre;
|
OEngine::Render::OgreRenderer *mOgre;
|
||||||
std::string mCellName;
|
std::string mCellName;
|
||||||
|
@ -99,12 +100,13 @@ namespace OMW
|
||||||
/// add a .zip resource
|
/// add a .zip resource
|
||||||
void addZipResource (const boost::filesystem::path& path);
|
void addZipResource (const boost::filesystem::path& path);
|
||||||
|
|
||||||
/// Load all BSA files in data directory.
|
/// Load BSA files
|
||||||
void loadBSA();
|
void loadBSA();
|
||||||
|
|
||||||
void executeLocalScripts();
|
void executeLocalScripts();
|
||||||
|
|
||||||
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);
|
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);
|
||||||
|
virtual bool frameStarted (const Ogre::FrameEvent& evt);
|
||||||
|
|
||||||
/// Load settings from various files, returns the path to the user settings file
|
/// Load settings from various files, returns the path to the user settings file
|
||||||
std::string loadSettings (Settings::Manager & settings);
|
std::string loadSettings (Settings::Manager & settings);
|
||||||
|
@ -125,6 +127,9 @@ namespace OMW
|
||||||
/// Set data dirs
|
/// Set data dirs
|
||||||
void setDataDirs(const Files::PathContainer& dataDirs);
|
void setDataDirs(const Files::PathContainer& dataDirs);
|
||||||
|
|
||||||
|
/// Add BSA archive
|
||||||
|
void addArchive(const std::string& archive);
|
||||||
|
|
||||||
/// Set resource dir
|
/// Set resource dir
|
||||||
void setResourceDir(const boost::filesystem::path& parResDir);
|
void setResourceDir(const boost::filesystem::path& parResDir);
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
("data-local", bpo::value<std::string>()->default_value(""),
|
("data-local", bpo::value<std::string>()->default_value(""),
|
||||||
"set local data directory (highest priority)")
|
"set local data directory (highest priority)")
|
||||||
|
|
||||||
|
("fallback-archive", bpo::value<StringsVector>()->default_value(StringsVector(), "fallback-archive")
|
||||||
|
->multitoken(), "set fallback BSA archives (later archives have higher priority)")
|
||||||
|
|
||||||
("resources", bpo::value<std::string>()->default_value("resources"),
|
("resources", bpo::value<std::string>()->default_value("resources"),
|
||||||
"set resources directory")
|
"set resources directory")
|
||||||
|
|
||||||
|
@ -201,6 +204,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
|
|
||||||
engine.setDataDirs(dataDirs);
|
engine.setDataDirs(dataDirs);
|
||||||
|
|
||||||
|
// fallback archives
|
||||||
|
StringsVector archives = variables["fallback-archive"].as<StringsVector>();
|
||||||
|
for (StringsVector::const_iterator it = archives.begin(); it != archives.end(); it++)
|
||||||
|
{
|
||||||
|
engine.addArchive(*it);
|
||||||
|
}
|
||||||
|
|
||||||
engine.setResourceDir(variables["resources"].as<std::string>());
|
engine.setResourceDir(variables["resources"].as<std::string>());
|
||||||
|
|
||||||
// master and plugin
|
// master and plugin
|
||||||
|
|
|
@ -237,6 +237,8 @@ namespace MWBase
|
||||||
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
|
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
|
||||||
virtual void startTraining(MWWorld::Ptr actor) = 0;
|
virtual void startTraining(MWWorld::Ptr actor) = 0;
|
||||||
|
|
||||||
|
virtual void changePointer (const std::string& name) = 0;
|
||||||
|
|
||||||
virtual const Translation::Storage& getTranslationDataStorage() const = 0;
|
virtual const Translation::Storage& getTranslationDataStorage() const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,6 +296,7 @@ namespace MWBase
|
||||||
virtual bool toggleVanityMode(bool enable, bool force) = 0;
|
virtual bool toggleVanityMode(bool enable, bool force) = 0;
|
||||||
virtual void allowVanityMode(bool allow) = 0;
|
virtual void allowVanityMode(bool allow) = 0;
|
||||||
virtual void togglePlayerLooking(bool enable) = 0;
|
virtual void togglePlayerLooking(bool enable) = 0;
|
||||||
|
virtual void changeVanityModeScale(float factor) = 0;
|
||||||
|
|
||||||
virtual void renderPlayer() = 0;
|
virtual void renderPlayer() = 0;
|
||||||
|
|
||||||
|
@ -314,6 +315,7 @@ namespace MWBase
|
||||||
/// \todo this does not belong here
|
/// \todo this does not belong here
|
||||||
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
|
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
|
||||||
virtual void stopVideo() = 0;
|
virtual void stopVideo() = 0;
|
||||||
|
virtual void frameStarted (float dt) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Apparatus::getModel(const MWWorld::Ptr &ptr) const
|
std::string Apparatus::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Armor::getModel(const MWWorld::Ptr &ptr) const
|
std::string Armor::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Book::getModel(const MWWorld::Ptr &ptr) const
|
std::string Book::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Clothing::getModel(const MWWorld::Ptr &ptr) const
|
std::string Clothing::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -132,7 +132,7 @@ namespace MWClass
|
||||||
const MWWorld::Ptr& actor) const
|
const MWWorld::Ptr& actor) const
|
||||||
{
|
{
|
||||||
if (MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead())
|
if (MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead())
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionOpen(ptr));
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionOpen(ptr, true));
|
||||||
else
|
else
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Ingredient::getModel(const MWWorld::Ptr &ptr) const
|
std::string Ingredient::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace MWClass
|
||||||
const std::string &model = ref->mBase->mModel;
|
const std::string &model = ref->mBase->mModel;
|
||||||
|
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,ref->mBase->mData.mFlags & ESM::Light::Carry);
|
||||||
|
|
||||||
if (!ref->mBase->mSound.empty())
|
if (!ref->mBase->mSound.empty())
|
||||||
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0, MWBase::SoundManager::Play_Loop);
|
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0, MWBase::SoundManager::Play_Loop);
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Lockpick::getModel(const MWWorld::Ptr &ptr) const
|
std::string Lockpick::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Miscellaneous::getModel(const MWWorld::Ptr &ptr) const
|
std::string Miscellaneous::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -183,13 +183,10 @@ namespace MWClass
|
||||||
std::string bodyRaceID = headID.substr(0, end);
|
std::string bodyRaceID = headID.substr(0, end);
|
||||||
|
|
||||||
std::string model = "meshes\\base_anim.nif";
|
std::string model = "meshes\\base_anim.nif";
|
||||||
if (bodyRaceID == "b_n_khajiit_m_" ||
|
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
||||||
bodyRaceID == "b_n_khajiit_f_" ||
|
if(race->mData.mFlags & ESM::Race::Beast)
|
||||||
bodyRaceID == "b_n_argonian_m_" ||
|
|
||||||
bodyRaceID == "b_n_argonian_f_")
|
|
||||||
{
|
|
||||||
model = "meshes\\base_animkna.nif";
|
model = "meshes\\base_animkna.nif";
|
||||||
}
|
|
||||||
return model;
|
return model;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -220,7 +217,9 @@ namespace MWClass
|
||||||
const MWWorld::Ptr& actor) const
|
const MWWorld::Ptr& actor) const
|
||||||
{
|
{
|
||||||
if (MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead())
|
if (MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead())
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionOpen(ptr));
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionOpen(ptr, true));
|
||||||
|
else if (MWWorld::Class::get(actor).getStance(actor, MWWorld::Class::Sneak))
|
||||||
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionOpen(ptr)); // stealing
|
||||||
else
|
else
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
|
||||||
}
|
}
|
||||||
|
@ -365,11 +364,10 @@ namespace MWClass
|
||||||
fSwimRunAthleticsMult->getFloat();
|
fSwimRunAthleticsMult->getFloat();
|
||||||
moveSpeed = swimSpeed;
|
moveSpeed = swimSpeed;
|
||||||
}
|
}
|
||||||
else if(Npc::getStance(ptr, Run, false))
|
else if(Npc::getStance(ptr, Run, false) && !Npc::getStance(ptr, Sneak, false))
|
||||||
moveSpeed = runSpeed;
|
moveSpeed = runSpeed;
|
||||||
else
|
else
|
||||||
moveSpeed = walkSpeed;
|
moveSpeed = walkSpeed;
|
||||||
|
|
||||||
if(getMovementSettings(ptr).mLeftRight != 0 && getMovementSettings(ptr).mForwardBackward == 0)
|
if(getMovementSettings(ptr).mLeftRight != 0 && getMovementSettings(ptr).mForwardBackward == 0)
|
||||||
moveSpeed *= 0.75f;
|
moveSpeed *= 0.75f;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
#include "../mwrender/renderinginterface.hpp"
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -36,7 +38,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Potion::getModel(const MWWorld::Ptr &ptr) const
|
std::string Potion::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
@ -138,6 +140,23 @@ namespace MWClass
|
||||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects);
|
info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects);
|
||||||
|
|
||||||
|
// hide effects the player doesnt know about
|
||||||
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer();
|
||||||
|
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player);
|
||||||
|
int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase();
|
||||||
|
int i=0;
|
||||||
|
for (MWGui::Widgets::SpellEffectList::iterator it = info.effects.begin(); it != info.effects.end(); ++it)
|
||||||
|
{
|
||||||
|
/// \todo this code is duplicated from mwclass/ingredient, put it in a helper function
|
||||||
|
it->mKnown = ( (i == 0 && alchemySkill >= 15)
|
||||||
|
|| (i == 1 && alchemySkill >= 30)
|
||||||
|
|| (i == 2 && alchemySkill >= 45)
|
||||||
|
|| (i == 3 && alchemySkill >= 60));
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
info.isPotion = true;
|
info.isPotion = true;
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Probe::getModel(const MWWorld::Ptr &ptr) const
|
std::string Probe::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Repair::getModel(const MWWorld::Ptr &ptr) const
|
std::string Repair::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if(!model.empty())
|
if(!model.empty())
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Weapon::getModel(const MWWorld::Ptr &ptr) const
|
std::string Weapon::getModel(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "dialoguemanagerimp.hpp"
|
#include "dialoguemanagerimp.hpp"
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <cstdlib>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
@ -251,8 +252,12 @@ namespace MWDialogue
|
||||||
|
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||||
|
|
||||||
if (const ESM::DialInfo *info = filter.search (dialogue, true))
|
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, true, true);
|
||||||
|
|
||||||
|
if (!infos.empty())
|
||||||
{
|
{
|
||||||
|
const ESM::DialInfo* info = infos[std::rand() % infos.size()];
|
||||||
|
|
||||||
parseText (info->mResponse);
|
parseText (info->mResponse);
|
||||||
|
|
||||||
if (dialogue.mType==ESM::Dialogue::Persuasion)
|
if (dialogue.mType==ESM::Dialogue::Persuasion)
|
||||||
|
|
|
@ -559,8 +559,21 @@ MWDialogue::Filter::Filter (const MWWorld::Ptr& actor, int choice, bool talkedTo
|
||||||
: mActor (actor), mChoice (choice), mTalkedToPlayer (talkedToPlayer)
|
: mActor (actor), mChoice (choice), mTalkedToPlayer (talkedToPlayer)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const ESM::DialInfo *MWDialogue::Filter::search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const
|
const ESM::DialInfo* MWDialogue::Filter::search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const
|
||||||
{
|
{
|
||||||
|
std::vector<const ESM::DialInfo *> suitableInfos = list (dialogue, fallbackToInfoRefusal, false);
|
||||||
|
|
||||||
|
if (suitableInfos.empty())
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return suitableInfos[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const ESM::DialInfo *> MWDialogue::Filter::list (const ESM::Dialogue& dialogue,
|
||||||
|
bool fallbackToInfoRefusal, bool searchAll) const
|
||||||
|
{
|
||||||
|
std::vector<const ESM::DialInfo *> infos;
|
||||||
|
|
||||||
bool infoRefusal = false;
|
bool infoRefusal = false;
|
||||||
|
|
||||||
// Iterate over topic responses to find a matching one
|
// Iterate over topic responses to find a matching one
|
||||||
|
@ -569,14 +582,17 @@ const ESM::DialInfo *MWDialogue::Filter::search (const ESM::Dialogue& dialogue,
|
||||||
{
|
{
|
||||||
if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter))
|
if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter))
|
||||||
{
|
{
|
||||||
if (testDisposition (*iter))
|
if (testDisposition (*iter)) {
|
||||||
return &*iter;
|
infos.push_back(&*iter);
|
||||||
|
if (!searchAll)
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
infoRefusal = true;
|
infoRefusal = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (infoRefusal && fallbackToInfoRefusal)
|
if (infos.empty() && infoRefusal && fallbackToInfoRefusal)
|
||||||
{
|
{
|
||||||
// No response is valid because of low NPC disposition,
|
// No response is valid because of low NPC disposition,
|
||||||
// search a response in the topic "Info Refusal"
|
// search a response in the topic "Info Refusal"
|
||||||
|
@ -588,11 +604,14 @@ const ESM::DialInfo *MWDialogue::Filter::search (const ESM::Dialogue& dialogue,
|
||||||
|
|
||||||
for (std::vector<ESM::DialInfo>::const_iterator iter = infoRefusalDialogue.mInfo.begin();
|
for (std::vector<ESM::DialInfo>::const_iterator iter = infoRefusalDialogue.mInfo.begin();
|
||||||
iter!=infoRefusalDialogue.mInfo.end(); ++iter)
|
iter!=infoRefusalDialogue.mInfo.end(); ++iter)
|
||||||
if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter) && testDisposition(*iter))
|
if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter) && testDisposition(*iter)) {
|
||||||
return &*iter;
|
infos.push_back(&*iter);
|
||||||
|
if (!searchAll)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return infos;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWDialogue::Filter::responseAvailable (const ESM::Dialogue& dialogue) const
|
bool MWDialogue::Filter::responseAvailable (const ESM::Dialogue& dialogue) const
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef GAME_MWDIALOGUE_FILTER_H
|
#ifndef GAME_MWDIALOGUE_FILTER_H
|
||||||
#define GAME_MWDIALOGUE_FILTER_H
|
#define GAME_MWDIALOGUE_FILTER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -51,7 +53,10 @@ namespace MWDialogue
|
||||||
|
|
||||||
Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer);
|
Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer);
|
||||||
|
|
||||||
const ESM::DialInfo *search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const;
|
std::vector<const ESM::DialInfo *> list (const ESM::Dialogue& dialogue,
|
||||||
|
bool fallbackToInfoRefusal, bool searchAll) const;
|
||||||
|
|
||||||
|
const ESM::DialInfo* search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const;
|
||||||
///< Get a matching response for the requested dialogue.
|
///< Get a matching response for the requested dialogue.
|
||||||
/// Redirect to "Info Refusal" topic if a response fulfills all conditions but disposition.
|
/// Redirect to "Info Refusal" topic if a response fulfills all conditions but disposition.
|
||||||
|
|
||||||
|
|
|
@ -31,14 +31,13 @@ namespace
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool selectCompareImp (const ESM::DialInfo::SelectStruct& select, T value1)
|
bool selectCompareImp (const ESM::DialInfo::SelectStruct& select, T value1)
|
||||||
{
|
{
|
||||||
if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int ||
|
if (select.mValue.getType()==ESM::VT_Int)
|
||||||
select.mType==ESM::VT_Long)
|
|
||||||
{
|
{
|
||||||
return selectCompareImp (select.mSelectRule[4], value1, select.mI);
|
return selectCompareImp (select.mSelectRule[4], value1, select.mValue.getInteger());
|
||||||
}
|
}
|
||||||
else if (select.mType==ESM::VT_Float)
|
else if (select.mValue.getType()==ESM::VT_Float)
|
||||||
{
|
{
|
||||||
return selectCompareImp (select.mSelectRule[4], value1, select.mF);
|
return selectCompareImp (select.mSelectRule[4], value1, select.mValue.getFloat());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::runtime_error (
|
throw std::runtime_error (
|
||||||
|
|
|
@ -237,7 +237,7 @@ namespace MWGui
|
||||||
Widgets::SpellEffectList _list = Widgets::MWEffectList::effectListFromESM(&list);
|
Widgets::SpellEffectList _list = Widgets::MWEffectList::effectListFromESM(&list);
|
||||||
effectsWidget->setEffectList(_list);
|
effectsWidget->setEffectList(_list);
|
||||||
|
|
||||||
std::vector<MyGUI::WidgetPtr> effectItems;
|
std::vector<MyGUI::Widget*> effectItems;
|
||||||
effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0);
|
effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0);
|
||||||
effectsWidget->setCoord(coord);
|
effectsWidget->setCoord(coord);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,11 +40,11 @@ BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager)
|
||||||
mBirthList->eventListMouseItemActivate += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
mBirthList->eventListMouseItemActivate += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
||||||
mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
||||||
|
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::Button* backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
|
okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
|
||||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
|
||||||
|
@ -55,7 +55,7 @@ BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager)
|
||||||
|
|
||||||
void BirthDialog::setNextButtonShow(bool shown)
|
void BirthDialog::setNextButtonShow(bool shown)
|
||||||
{
|
{
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
|
|
||||||
if (shown)
|
if (shown)
|
||||||
|
@ -82,7 +82,7 @@ void BirthDialog::setBirthId(const std::string &birthId)
|
||||||
if (boost::iequals(*mBirthList->getItemDataAt<std::string>(i), birthId))
|
if (boost::iequals(*mBirthList->getItemDataAt<std::string>(i), birthId))
|
||||||
{
|
{
|
||||||
mBirthList->setIndexSelected(i);
|
mBirthList->setIndexSelected(i);
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index)
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
|
|
||||||
const std::string *birthId = mBirthList->getItemDataAt<std::string>(_index);
|
const std::string *birthId = mBirthList->getItemDataAt<std::string>(_index);
|
||||||
|
@ -159,7 +159,7 @@ void BirthDialog::updateBirths()
|
||||||
|
|
||||||
void BirthDialog::updateSpells()
|
void BirthDialog::updateSpells()
|
||||||
{
|
{
|
||||||
for (std::vector<MyGUI::WidgetPtr>::iterator it = mSpellItems.begin(); it != mSpellItems.end(); ++it)
|
for (std::vector<MyGUI::Widget*>::iterator it = mSpellItems.begin(); it != mSpellItems.end(); ++it)
|
||||||
{
|
{
|
||||||
MyGUI::Gui::getInstance().destroyWidget(*it);
|
MyGUI::Gui::getInstance().destroyWidget(*it);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,9 @@ namespace MWGui
|
||||||
void updateSpells();
|
void updateSpells();
|
||||||
|
|
||||||
MyGUI::ListBox* mBirthList;
|
MyGUI::ListBox* mBirthList;
|
||||||
MyGUI::WidgetPtr mSpellArea;
|
MyGUI::Widget* mSpellArea;
|
||||||
MyGUI::ImageBox* mBirthImage;
|
MyGUI::ImageBox* mBirthImage;
|
||||||
std::vector<MyGUI::WidgetPtr> mSpellItems;
|
std::vector<MyGUI::Widget*> mSpellItems;
|
||||||
|
|
||||||
std::string mCurrentBirthId;
|
std::string mCurrentBirthId;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "dialogue.hpp"
|
#include "dialogue.hpp"
|
||||||
#include "mode.hpp"
|
#include "mode.hpp"
|
||||||
#include "inventorywindow.hpp"
|
#include "inventorywindow.hpp"
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
@ -17,94 +17,24 @@ namespace
|
||||||
{
|
{
|
||||||
struct Step
|
struct Step
|
||||||
{
|
{
|
||||||
const char* mText;
|
const std::string mText;
|
||||||
const char* mButtons[3];
|
const std::string mButtons[3];
|
||||||
const char* mSound;
|
const std::string mSound;
|
||||||
ESM::Class::Specialization mSpecializations[3]; // The specialization for each answer
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static boost::array<Step, 10> sGenerateClassSteps = { {
|
const ESM::Class::Specialization mSpecializations[3]={ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}; // The specialization for each answer
|
||||||
// Question 1
|
|
||||||
{"On a clear day you chance upon a strange animal, its legs trapped in a hunter's clawsnare. Judging from the bleeding, it will not survive long.",
|
Step sGenerateClassSteps(int number) {
|
||||||
{"Draw your dagger, mercifully endings its life with a single thrust.",
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
"Use herbs from your pack to put it to sleep.",
|
number++;
|
||||||
"Do not interfere in the natural evolution of events, but rather take the opportunity to learn more about a strange animal that you have never seen before."},
|
Step step = {world->getFallback("Question_"+boost::lexical_cast<std::string>(number)+"_Question"),
|
||||||
"vo\\misc\\chargen qa1.wav",
|
{world->getFallback("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerOne"),
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
world->getFallback("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerTwo"),
|
||||||
},
|
world->getFallback("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerThree")},
|
||||||
// Question 2
|
"vo\\misc\\chargen qa"+boost::lexical_cast<std::string>(number)+".wav"
|
||||||
{"One Summer afternoon your father gives you a choice of chores.",
|
};
|
||||||
{"Work in the forge with him casting iron for a new plow.",
|
return step;
|
||||||
"Gather herbs for your mother who is preparing dinner.",
|
}
|
||||||
"Go catch fish at the stream using a net and line."},
|
|
||||||
"vo\\misc\\chargen qa2.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
},
|
|
||||||
// Question 3
|
|
||||||
{"Your cousin has given you a very embarrassing nickname and, even worse, likes to call you it in front of your friends. You asked him to stop, but he finds it very amusing to watch you blush.",
|
|
||||||
{"Beat up your cousin, then tell him that if he ever calls you that nickname again, you will bloody him worse than this time.",
|
|
||||||
"Make up a story that makes your nickname a badge of honor instead of something humiliating.",
|
|
||||||
"Make up an even more embarrassing nickname for him and use it constantly until he learns his lesson."},
|
|
||||||
"vo\\misc\\chargen qa3.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
},
|
|
||||||
// Question 4
|
|
||||||
{"There is a lot of heated discussion at the local tavern over a grouped of people called 'Telepaths'. They have been hired by certain City-State kings. Rumor has it these Telepaths read a person's mind and tell their lord whether a follower is telling the truth or not.",
|
|
||||||
{"This is a terrible practice. A person's thoughts are his own and no one, not even a king, has the right to make such an invasion into another human's mind.",
|
|
||||||
"Loyal followers to the king have nothing to fear from a Telepath. It is important to have a method of finding assassins and spies before it is too late.",
|
|
||||||
"In these times, it is a necessary evil. Although you do not necessarily like the idea, a Telepath could have certain advantages during a time of war or in finding someone innocent of a crime."},
|
|
||||||
"vo\\misc\\chargen qa4.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
},
|
|
||||||
// Question 5
|
|
||||||
{"Your mother sends you to the market with a list of goods to buy. After you finish you find that by mistake a shopkeeper has given you too much money back in exchange for one of the items.",
|
|
||||||
{"Return to the store and give the shopkeeper his hard-earned money, explaining to him the mistake?",
|
|
||||||
"Decide to put the extra money to good use and purchase items that would help your family?",
|
|
||||||
"Pocket the extra money, knowing that shopkeepers in general tend to overcharge customers anyway?"},
|
|
||||||
"vo\\misc\\chargen qa5.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
},
|
|
||||||
// Question 6
|
|
||||||
{"While in the market place you witness a thief cut a purse from a noble. Even as he does so, the noble notices and calls for the city guards. In his haste to get away, the thief drops the purse near you. Surprisingly no one seems to notice the bag of coins at your feet.",
|
|
||||||
{"Pick up the bag and signal to the guard, knowing that the only honorable thing to do is return the money to its rightful owner.",
|
|
||||||
"Leave the bag there, knowing that it is better not to get involved.",
|
|
||||||
"Pick up the bag and pocket it, knowing that the extra windfall will help your family in times of trouble."},
|
|
||||||
"vo\\misc\\chargen qa6.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
},
|
|
||||||
// Question 7
|
|
||||||
{"Your father sends you on a task which you loathe, cleaning the stables. On the way there, pitchfork in hand, you run into your friend from the homestead near your own. He offers to do it for you, in return for a future favor of his choosing.",
|
|
||||||
{"Decline his offer, knowing that your father expects you to do the work, and it is better not to be in debt.",
|
|
||||||
"Ask him to help you, knowing that two people can do the job faster than one, and agree to help him with one task of his choosing in the future.",
|
|
||||||
"Accept his offer, reasoning that as long as the stables are cleaned, it matters not who does the cleaning."},
|
|
||||||
"vo\\misc\\chargen qa7.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
},
|
|
||||||
// Question 8
|
|
||||||
{"Your mother asks you to help fix the stove. While you are working, a very hot pipe slips its mooring and falls towards her.",
|
|
||||||
{"Position yourself between the pipe and your mother.",
|
|
||||||
"Grab the hot pipe and try to push it away.",
|
|
||||||
"Push your mother out of the way."},
|
|
||||||
"vo\\misc\\chargen qa8.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
},
|
|
||||||
// Question 9
|
|
||||||
{"While in town the baker gives you a sweetroll. Delighted, you take it into an alley to enjoy only to be intercepted by a gang of three other kids your age. The leader demands the sweetroll, or else he and his friends will beat you and take it.",
|
|
||||||
{"Drop the sweetroll and step on it, then get ready for the fight.",
|
|
||||||
"Give him the sweetroll now without argument, knowing that later this afternoon you will have all your friends with you and can come and take whatever he owes you.",
|
|
||||||
"Act like you're going to give him the sweetroll, but at the last minute throw it in the air, hoping that they'll pay attention to it long enough for you to get a shot in on the leader."},
|
|
||||||
"vo\\misc\\chargen qa9.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
},
|
|
||||||
// Question 10
|
|
||||||
{"Entering town you find that you are witness to a very well-dressed man running from a crowd. He screams to you for help. The crowd behind him seem very angry.",
|
|
||||||
{"Rush to the town's aid immediately, despite your lack of knowledge of the circumstances.",
|
|
||||||
"Stand aside and allow the man and the mob to pass, realizing it is probably best not to get involved.",
|
|
||||||
"Rush to the man's aid immediately, despite your lack of knowledge of the circumstances."},
|
|
||||||
"vo\\misc\\chargen qa10.wav",
|
|
||||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
|
||||||
}
|
|
||||||
} };
|
|
||||||
|
|
||||||
struct ClassPoint
|
struct ClassPoint
|
||||||
{
|
{
|
||||||
|
@ -206,7 +136,9 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mRaceDialog->setRaceId(mPlayerRaceId);
|
mRaceDialog->setRaceId(mPlayerRaceId);
|
||||||
mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
|
mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
|
||||||
mRaceDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack);
|
mRaceDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack);
|
||||||
mRaceDialog->setVisible(true);;
|
mRaceDialog->setVisible(true);
|
||||||
|
if (mCreationStage < CSE_NameChosen)
|
||||||
|
mCreationStage = CSE_NameChosen;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_Class:
|
case GM_Class:
|
||||||
|
@ -215,6 +147,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mClassChoiceDialog = new ClassChoiceDialog(*mWM);
|
mClassChoiceDialog = new ClassChoiceDialog(*mWM);
|
||||||
mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice);
|
mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice);
|
||||||
mClassChoiceDialog->setVisible(true);
|
mClassChoiceDialog->setVisible(true);
|
||||||
|
if (mCreationStage < CSE_RaceChosen)
|
||||||
|
mCreationStage = CSE_RaceChosen;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_ClassPick:
|
case GM_ClassPick:
|
||||||
|
@ -226,6 +160,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone);
|
mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone);
|
||||||
mPickClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack);
|
mPickClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack);
|
||||||
mPickClassDialog->setVisible(true);
|
mPickClassDialog->setVisible(true);
|
||||||
|
if (mCreationStage < CSE_RaceChosen)
|
||||||
|
mCreationStage = CSE_RaceChosen;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_Birth:
|
case GM_Birth:
|
||||||
|
@ -237,6 +173,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
|
mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
|
||||||
mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
|
mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
|
||||||
mBirthSignDialog->setVisible(true);
|
mBirthSignDialog->setVisible(true);
|
||||||
|
if (mCreationStage < CSE_ClassChosen)
|
||||||
|
mCreationStage = CSE_ClassChosen;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_ClassCreate:
|
case GM_ClassCreate:
|
||||||
|
@ -247,6 +185,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
||||||
mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
||||||
mCreateClassDialog->setVisible(true);
|
mCreateClassDialog->setVisible(true);
|
||||||
|
if (mCreationStage < CSE_RaceChosen)
|
||||||
|
mCreationStage = CSE_RaceChosen;
|
||||||
break;
|
break;
|
||||||
case GM_ClassGenerate:
|
case GM_ClassGenerate:
|
||||||
mGenerateClassStep = 0;
|
mGenerateClassStep = 0;
|
||||||
|
@ -255,6 +195,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mGenerateClassSpecializations[1] = 0;
|
mGenerateClassSpecializations[1] = 0;
|
||||||
mGenerateClassSpecializations[2] = 0;
|
mGenerateClassSpecializations[2] = 0;
|
||||||
showClassQuestionDialog();
|
showClassQuestionDialog();
|
||||||
|
if (mCreationStage < CSE_RaceChosen)
|
||||||
|
mCreationStage = CSE_RaceChosen;
|
||||||
break;
|
break;
|
||||||
case GM_Review:
|
case GM_Review:
|
||||||
mWM->removeDialog(mReviewDialog);
|
mWM->removeDialog(mReviewDialog);
|
||||||
|
@ -292,6 +234,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
|
mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
|
||||||
mReviewDialog->eventActivateDialog += MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog);
|
mReviewDialog->eventActivateDialog += MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog);
|
||||||
mReviewDialog->setVisible(true);
|
mReviewDialog->setVisible(true);
|
||||||
|
if (mCreationStage < CSE_BirthSignChosen)
|
||||||
|
mCreationStage = CSE_BirthSignChosen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -624,7 +568,7 @@ void CharacterCreation::onClassQuestionChosen(int _index)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESM::Class::Specialization specialization = sGenerateClassSteps[mGenerateClassStep].mSpecializations[_index];
|
ESM::Class::Specialization specialization = mSpecializations[_index];
|
||||||
if (specialization == ESM::Class::Stealth)
|
if (specialization == ESM::Class::Stealth)
|
||||||
++mGenerateClassSpecializations[0];
|
++mGenerateClassSpecializations[0];
|
||||||
else if (specialization == ESM::Class::Combat)
|
else if (specialization == ESM::Class::Combat)
|
||||||
|
@ -637,7 +581,7 @@ void CharacterCreation::onClassQuestionChosen(int _index)
|
||||||
|
|
||||||
void CharacterCreation::showClassQuestionDialog()
|
void CharacterCreation::showClassQuestionDialog()
|
||||||
{
|
{
|
||||||
if (mGenerateClassStep == sGenerateClassSteps.size())
|
if (mGenerateClassStep == 10)
|
||||||
{
|
{
|
||||||
static boost::array<ClassPoint, 23> classes = { {
|
static boost::array<ClassPoint, 23> classes = { {
|
||||||
{"Acrobat", {6, 2, 2}},
|
{"Acrobat", {6, 2, 2}},
|
||||||
|
@ -704,7 +648,7 @@ void CharacterCreation::showClassQuestionDialog()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mGenerateClassStep > sGenerateClassSteps.size())
|
if (mGenerateClassStep > 10)
|
||||||
{
|
{
|
||||||
mWM->popGuiMode();
|
mWM->popGuiMode();
|
||||||
mWM->pushGuiMode(GM_Class);
|
mWM->pushGuiMode(GM_Class);
|
||||||
|
@ -717,15 +661,15 @@ void CharacterCreation::showClassQuestionDialog()
|
||||||
mGenerateClassQuestionDialog = new InfoBoxDialog(*mWM);
|
mGenerateClassQuestionDialog = new InfoBoxDialog(*mWM);
|
||||||
|
|
||||||
InfoBoxDialog::ButtonList buttons;
|
InfoBoxDialog::ButtonList buttons;
|
||||||
mGenerateClassQuestionDialog->setText(sGenerateClassSteps[mGenerateClassStep].mText);
|
mGenerateClassQuestionDialog->setText(sGenerateClassSteps(mGenerateClassStep).mText);
|
||||||
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[0]);
|
buttons.push_back(sGenerateClassSteps(mGenerateClassStep).mButtons[0]);
|
||||||
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[1]);
|
buttons.push_back(sGenerateClassSteps(mGenerateClassStep).mButtons[1]);
|
||||||
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[2]);
|
buttons.push_back(sGenerateClassSteps(mGenerateClassStep).mButtons[2]);
|
||||||
mGenerateClassQuestionDialog->setButtons(buttons);
|
mGenerateClassQuestionDialog->setButtons(buttons);
|
||||||
mGenerateClassQuestionDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
|
mGenerateClassQuestionDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
|
||||||
mGenerateClassQuestionDialog->setVisible(true);
|
mGenerateClassQuestionDialog->setVisible(true);
|
||||||
|
|
||||||
MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps[mGenerateClassStep].mSound);
|
MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps(mGenerateClassStep).mSound);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterCreation::onGenerateClassBack()
|
void CharacterCreation::onGenerateClassBack()
|
||||||
|
|
|
@ -31,11 +31,11 @@ GenerateClassResultDialog::GenerateClassResultDialog(MWBase::WindowManager& parW
|
||||||
getWidget(mClassImage, "ClassImage");
|
getWidget(mClassImage, "ClassImage");
|
||||||
getWidget(mClassName, "ClassName");
|
getWidget(mClassName, "ClassName");
|
||||||
|
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::Button* backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
|
okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
|
||||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
|
||||||
|
@ -97,11 +97,11 @@ PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager)
|
||||||
|
|
||||||
getWidget(mClassImage, "ClassImage");
|
getWidget(mClassImage, "ClassImage");
|
||||||
|
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::Button* backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager)
|
||||||
|
|
||||||
void PickClassDialog::setNextButtonShow(bool shown)
|
void PickClassDialog::setNextButtonShow(bool shown)
|
||||||
{
|
{
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
|
|
||||||
if (shown)
|
if (shown)
|
||||||
|
@ -138,7 +138,7 @@ void PickClassDialog::setClassId(const std::string &classId)
|
||||||
if (boost::iequals(*mClassList->getItemDataAt<std::string>(i), classId))
|
if (boost::iequals(*mClassList->getItemDataAt<std::string>(i), classId))
|
||||||
{
|
{
|
||||||
mClassList->setIndexSelected(i);
|
mClassList->setIndexSelected(i);
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index)
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
|
|
||||||
const std::string *classId = mClassList->getItemDataAt<std::string>(_index);
|
const std::string *classId = mClassList->getItemDataAt<std::string>(_index);
|
||||||
|
@ -256,7 +256,7 @@ void InfoBoxDialog::fitToText(MyGUI::TextBox* widget)
|
||||||
widget->setSize(size);
|
widget->setSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoBoxDialog::layoutVertically(MyGUI::WidgetPtr widget, int margin)
|
void InfoBoxDialog::layoutVertically(MyGUI::Widget* widget, int margin)
|
||||||
{
|
{
|
||||||
size_t count = widget->getChildCount();
|
size_t count = widget->getChildCount();
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
@ -264,7 +264,7 @@ void InfoBoxDialog::layoutVertically(MyGUI::WidgetPtr widget, int margin)
|
||||||
int width = 0;
|
int width = 0;
|
||||||
for (unsigned i = 0; i < count; ++i)
|
for (unsigned i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
MyGUI::WidgetPtr child = widget->getChildAt(i);
|
MyGUI::Widget* child = widget->getChildAt(i);
|
||||||
if (!child->getVisible())
|
if (!child->getVisible())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ std::string InfoBoxDialog::getText() const
|
||||||
|
|
||||||
void InfoBoxDialog::setButtons(ButtonList &buttons)
|
void InfoBoxDialog::setButtons(ButtonList &buttons)
|
||||||
{
|
{
|
||||||
for (std::vector<MyGUI::ButtonPtr>::iterator it = this->mButtons.begin(); it != this->mButtons.end(); ++it)
|
for (std::vector<MyGUI::Button*>::iterator it = this->mButtons.begin(); it != this->mButtons.end(); ++it)
|
||||||
{
|
{
|
||||||
MyGUI::Gui::getInstance().destroyWidget(*it);
|
MyGUI::Gui::getInstance().destroyWidget(*it);
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ void InfoBoxDialog::setButtons(ButtonList &buttons)
|
||||||
mCurrentButton = -1;
|
mCurrentButton = -1;
|
||||||
|
|
||||||
// TODO: The buttons should be generated from a template in the layout file, ie. cloning an existing widget
|
// TODO: The buttons should be generated from a template in the layout file, ie. cloning an existing widget
|
||||||
MyGUI::ButtonPtr button;
|
MyGUI::Button* button;
|
||||||
MyGUI::IntCoord coord = MyGUI::IntCoord(0, 0, mButtonBar->getWidth(), 10);
|
MyGUI::IntCoord coord = MyGUI::IntCoord(0, 0, mButtonBar->getWidth(), 10);
|
||||||
ButtonList::const_iterator end = buttons.end();
|
ButtonList::const_iterator end = buttons.end();
|
||||||
for (ButtonList::const_iterator it = buttons.begin(); it != end; ++it)
|
for (ButtonList::const_iterator it = buttons.begin(); it != end; ++it)
|
||||||
|
@ -342,11 +342,11 @@ int InfoBoxDialog::getChosenButton() const
|
||||||
return mCurrentButton;
|
return mCurrentButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoBoxDialog::onButtonClicked(MyGUI::WidgetPtr _sender)
|
void InfoBoxDialog::onButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
std::vector<MyGUI::ButtonPtr>::const_iterator end = mButtons.end();
|
std::vector<MyGUI::Button*>::const_iterator end = mButtons.end();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (std::vector<MyGUI::ButtonPtr>::const_iterator it = mButtons.begin(); it != end; ++it)
|
for (std::vector<MyGUI::Button*>::const_iterator it = mButtons.begin(); it != end; ++it)
|
||||||
{
|
{
|
||||||
if (*it == _sender)
|
if (*it == _sender)
|
||||||
{
|
{
|
||||||
|
@ -376,10 +376,10 @@ ClassChoiceDialog::ClassChoiceDialog(MWBase::WindowManager& parWindowManager)
|
||||||
|
|
||||||
CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager)
|
CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager)
|
||||||
: WindowModal("openmw_chargen_create_class.layout", parWindowManager)
|
: WindowModal("openmw_chargen_create_class.layout", parWindowManager)
|
||||||
, mSpecDialog(nullptr)
|
, mSpecDialog(NULL)
|
||||||
, mAttribDialog(nullptr)
|
, mAttribDialog(NULL)
|
||||||
, mSkillDialog(nullptr)
|
, mSkillDialog(NULL)
|
||||||
, mDescDialog(nullptr)
|
, mDescDialog(NULL)
|
||||||
{
|
{
|
||||||
// Centre dialog
|
// Centre dialog
|
||||||
center();
|
center();
|
||||||
|
@ -420,15 +420,15 @@ CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager)
|
||||||
// Make sure the edit box has focus
|
// Make sure the edit box has focus
|
||||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(mEditName);
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(mEditName);
|
||||||
|
|
||||||
MyGUI::ButtonPtr descriptionButton;
|
MyGUI::Button* descriptionButton;
|
||||||
getWidget(descriptionButton, "DescriptionButton");
|
getWidget(descriptionButton, "DescriptionButton");
|
||||||
descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked);
|
descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::Button* backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onOkClicked);
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMinorSkills() const
|
||||||
|
|
||||||
void CreateClassDialog::setNextButtonShow(bool shown)
|
void CreateClassDialog::setNextButtonShow(bool shown)
|
||||||
{
|
{
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
|
|
||||||
if (shown)
|
if (shown)
|
||||||
|
@ -544,7 +544,7 @@ void CreateClassDialog::onDialogCancel()
|
||||||
mDescDialog = 0;
|
mDescDialog = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender)
|
void CreateClassDialog::onSpecializationClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
delete mSpecDialog;
|
delete mSpecDialog;
|
||||||
mSpecDialog = new SelectSpecializationDialog(mWindowManager);
|
mSpecDialog = new SelectSpecializationDialog(mWindowManager);
|
||||||
|
@ -694,7 +694,7 @@ SelectSpecializationDialog::SelectSpecializationDialog(MWBase::WindowManager& pa
|
||||||
ToolTips::createSpecializationToolTip(mSpecialization1, magic, ESM::Class::Magic);
|
ToolTips::createSpecializationToolTip(mSpecialization1, magic, ESM::Class::Magic);
|
||||||
ToolTips::createSpecializationToolTip(mSpecialization2, stealth, ESM::Class::Stealth);
|
ToolTips::createSpecializationToolTip(mSpecialization2, stealth, ESM::Class::Stealth);
|
||||||
|
|
||||||
MyGUI::ButtonPtr cancelButton;
|
MyGUI::Button* cancelButton;
|
||||||
getWidget(cancelButton, "CancelButton");
|
getWidget(cancelButton, "CancelButton");
|
||||||
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
||||||
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
|
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
|
||||||
|
@ -706,7 +706,7 @@ SelectSpecializationDialog::~SelectSpecializationDialog()
|
||||||
|
|
||||||
// widget controls
|
// widget controls
|
||||||
|
|
||||||
void SelectSpecializationDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender)
|
void SelectSpecializationDialog::onSpecializationClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
if (_sender == mSpecialization0)
|
if (_sender == mSpecialization0)
|
||||||
mSpecializationId = ESM::Class::Combat;
|
mSpecializationId = ESM::Class::Combat;
|
||||||
|
@ -747,7 +747,7 @@ SelectAttributeDialog::SelectAttributeDialog(MWBase::WindowManager& parWindowMan
|
||||||
ToolTips::createAttributeToolTip(attribute, attribute->getAttributeId());
|
ToolTips::createAttributeToolTip(attribute, attribute->getAttributeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::ButtonPtr cancelButton;
|
MyGUI::Button* cancelButton;
|
||||||
getWidget(cancelButton, "CancelButton");
|
getWidget(cancelButton, "CancelButton");
|
||||||
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
||||||
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
|
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
|
||||||
|
@ -840,7 +840,7 @@ SelectSkillDialog::SelectSkillDialog(MWBase::WindowManager& parWindowManager)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::ButtonPtr cancelButton;
|
MyGUI::Button* cancelButton;
|
||||||
getWidget(cancelButton, "CancelButton");
|
getWidget(cancelButton, "CancelButton");
|
||||||
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
||||||
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
|
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
|
||||||
|
@ -873,7 +873,7 @@ DescriptionDialog::DescriptionDialog(MWBase::WindowManager& parWindowManager)
|
||||||
|
|
||||||
getWidget(mTextEdit, "TextEdit");
|
getWidget(mTextEdit, "TextEdit");
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::Button* okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked);
|
||||||
okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", ""));
|
okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", ""));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef MWGUI_CLASS_H
|
#ifndef MWGUI_CLASS_H
|
||||||
#define MWGUI_CLASS_H
|
#define MWGUI_CLASS_H
|
||||||
|
|
||||||
#include <MyGUI.h>
|
|
||||||
#include "widgets.hpp"
|
#include "widgets.hpp"
|
||||||
#include "window_base.hpp"
|
#include "window_base.hpp"
|
||||||
|
|
||||||
|
@ -35,17 +35,17 @@ namespace MWGui
|
||||||
EventHandle_Int eventButtonSelected;
|
EventHandle_Int eventButtonSelected;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onButtonClicked(MyGUI::WidgetPtr _sender);
|
void onButtonClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void fitToText(MyGUI::TextBox* widget);
|
void fitToText(MyGUI::TextBox* widget);
|
||||||
void layoutVertically(MyGUI::WidgetPtr widget, int margin);
|
void layoutVertically(MyGUI::Widget* widget, int margin);
|
||||||
int mCurrentButton;
|
int mCurrentButton;
|
||||||
MyGUI::WidgetPtr mTextBox;
|
MyGUI::Widget* mTextBox;
|
||||||
MyGUI::TextBox* mText;
|
MyGUI::TextBox* mText;
|
||||||
MyGUI::WidgetPtr mButtonBar;
|
MyGUI::Widget* mButtonBar;
|
||||||
std::vector<MyGUI::ButtonPtr> mButtons;
|
std::vector<MyGUI::Button*> mButtons;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lets the player choose between 3 ways of creating a class
|
// Lets the player choose between 3 ways of creating a class
|
||||||
|
@ -235,7 +235,7 @@ namespace MWGui
|
||||||
void onOkClicked(MyGUI::Widget* _sender);
|
void onOkClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::EditPtr mTextEdit;
|
MyGUI::EditBox* mTextEdit;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CreateClassDialog : public WindowModal
|
class CreateClassDialog : public WindowModal
|
||||||
|
@ -265,7 +265,7 @@ namespace MWGui
|
||||||
void onOkClicked(MyGUI::Widget* _sender);
|
void onOkClicked(MyGUI::Widget* _sender);
|
||||||
void onBackClicked(MyGUI::Widget* _sender);
|
void onBackClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
void onSpecializationClicked(MyGUI::WidgetPtr _sender);
|
void onSpecializationClicked(MyGUI::Widget* _sender);
|
||||||
void onSpecializationSelected();
|
void onSpecializationSelected();
|
||||||
void onAttributeClicked(Widgets::MWAttributePtr _sender);
|
void onAttributeClicked(Widgets::MWAttributePtr _sender);
|
||||||
void onAttributeSelected();
|
void onAttributeSelected();
|
||||||
|
@ -280,7 +280,7 @@ namespace MWGui
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::EditPtr mEditName;
|
MyGUI::EditBox* mEditName;
|
||||||
MyGUI::TextBox* mSpecializationName;
|
MyGUI::TextBox* mSpecializationName;
|
||||||
Widgets::MWAttributePtr mFavoriteAttribute0, mFavoriteAttribute1;
|
Widgets::MWAttributePtr mFavoriteAttribute0, mFavoriteAttribute1;
|
||||||
Widgets::MWSkillPtr mMajorSkill[5];
|
Widgets::MWSkillPtr mMajorSkill[5];
|
||||||
|
|
|
@ -216,7 +216,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::keyPress(MyGUI::WidgetPtr _sender,
|
void Console::keyPress(MyGUI::Widget* _sender,
|
||||||
MyGUI::KeyCode key,
|
MyGUI::KeyCode key,
|
||||||
MyGUI::Char _char)
|
MyGUI::Char _char)
|
||||||
{
|
{
|
||||||
|
@ -266,7 +266,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::acceptCommand(MyGUI::EditPtr _sender)
|
void Console::acceptCommand(MyGUI::EditBox* _sender)
|
||||||
{
|
{
|
||||||
const std::string &cm = command->getCaption();
|
const std::string &cm = command->getCaption();
|
||||||
if(cm.empty()) return;
|
if(cm.empty()) return;
|
||||||
|
|
|
@ -55,8 +55,8 @@ namespace MWGui
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MyGUI::EditPtr command;
|
MyGUI::EditBox* command;
|
||||||
MyGUI::EditPtr history;
|
MyGUI::EditBox* history;
|
||||||
|
|
||||||
typedef std::list<std::string> StringList;
|
typedef std::list<std::string> StringList;
|
||||||
|
|
||||||
|
@ -95,11 +95,11 @@ namespace MWGui
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void keyPress(MyGUI::WidgetPtr _sender,
|
void keyPress(MyGUI::Widget* _sender,
|
||||||
MyGUI::KeyCode key,
|
MyGUI::KeyCode key,
|
||||||
MyGUI::Char _char);
|
MyGUI::Char _char);
|
||||||
|
|
||||||
void acceptCommand(MyGUI::EditPtr _sender);
|
void acceptCommand(MyGUI::EditBox* _sender);
|
||||||
|
|
||||||
std::string complete( std::string input, std::vector<std::string> &matches );
|
std::string complete( std::string input, std::vector<std::string> &matches );
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "../mwworld/manualref.hpp"
|
#include "../mwworld/manualref.hpp"
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
@ -70,9 +71,11 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) :
|
ContainerBase::ContainerBase(DragAndDrop* dragAndDrop)
|
||||||
mDragAndDrop(dragAndDrop),
|
: mDragAndDrop(dragAndDrop)
|
||||||
mFilter(ContainerBase::Filter_All)
|
, mFilter(ContainerBase::Filter_All)
|
||||||
|
, mDisplayEquippedItems(true)
|
||||||
|
, mHighlightEquippedItems(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +316,6 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount);
|
object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount);
|
||||||
}
|
}
|
||||||
std::cout << "container weight " << curWeight << "/" << capacity << std::endl;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -430,7 +432,7 @@ void ContainerBase::drawItems()
|
||||||
equippedItems.erase(found);
|
equippedItems.erase(found);
|
||||||
}
|
}
|
||||||
// and add the items that are left (= have the correct category)
|
// and add the items that are left (= have the correct category)
|
||||||
if (!ignoreEquippedItems())
|
if (mDisplayEquippedItems && mHighlightEquippedItems)
|
||||||
{
|
{
|
||||||
for (std::vector<MWWorld::Ptr>::const_iterator it=equippedItems.begin();
|
for (std::vector<MWWorld::Ptr>::const_iterator it=equippedItems.begin();
|
||||||
it != equippedItems.end(); ++it)
|
it != equippedItems.end(); ++it)
|
||||||
|
@ -445,7 +447,8 @@ void ContainerBase::drawItems()
|
||||||
std::vector<MWWorld::Ptr> regularItems;
|
std::vector<MWWorld::Ptr> regularItems;
|
||||||
for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter)
|
for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end()
|
if ( (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end()
|
||||||
|
|| (!mHighlightEquippedItems && mDisplayEquippedItems))
|
||||||
&& std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end()
|
&& std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end()
|
||||||
&& std::find(mBoughtItems.begin(), mBoughtItems.end(), *iter) == mBoughtItems.end())
|
&& std::find(mBoughtItems.begin(), mBoughtItems.end(), *iter) == mBoughtItems.end())
|
||||||
regularItems.push_back(*iter);
|
regularItems.push_back(*iter);
|
||||||
|
@ -587,6 +590,27 @@ void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<MWWorld::Ptr> ContainerBase::getEquippedItems()
|
||||||
|
{
|
||||||
|
if (mPtr.getTypeName() != typeid(ESM::NPC).name())
|
||||||
|
return std::vector<MWWorld::Ptr>();
|
||||||
|
|
||||||
|
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||||
|
|
||||||
|
std::vector<MWWorld::Ptr> items;
|
||||||
|
|
||||||
|
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
||||||
|
{
|
||||||
|
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
|
||||||
|
if (it != invStore.end())
|
||||||
|
{
|
||||||
|
items.push_back(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
MWWorld::ContainerStore& ContainerBase::getContainerStore()
|
MWWorld::ContainerStore& ContainerBase::getContainerStore()
|
||||||
{
|
{
|
||||||
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||||
|
@ -599,6 +623,7 @@ ContainerWindow::ContainerWindow(MWBase::WindowManager& parWindowManager,DragAnd
|
||||||
: ContainerBase(dragAndDrop)
|
: ContainerBase(dragAndDrop)
|
||||||
, WindowBase("openmw_container_window.layout", parWindowManager)
|
, WindowBase("openmw_container_window.layout", parWindowManager)
|
||||||
{
|
{
|
||||||
|
getWidget(mDisposeCorpseButton, "DisposeCorpseButton");
|
||||||
getWidget(mTakeButton, "TakeButton");
|
getWidget(mTakeButton, "TakeButton");
|
||||||
getWidget(mCloseButton, "CloseButton");
|
getWidget(mCloseButton, "CloseButton");
|
||||||
|
|
||||||
|
@ -608,6 +633,7 @@ ContainerWindow::ContainerWindow(MWBase::WindowManager& parWindowManager,DragAnd
|
||||||
getWidget(itemView, "ItemView");
|
getWidget(itemView, "ItemView");
|
||||||
setWidgets(containerWidget, itemView);
|
setWidgets(containerWidget, itemView);
|
||||||
|
|
||||||
|
mDisposeCorpseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onDisposeCorpseButtonClicked);
|
||||||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
|
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
|
||||||
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
|
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
|
||||||
|
|
||||||
|
@ -625,8 +651,18 @@ void ContainerWindow::onWindowResize(MyGUI::Window* window)
|
||||||
drawItems();
|
drawItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::open(MWWorld::Ptr container)
|
void ContainerWindow::open(MWWorld::Ptr container, bool loot)
|
||||||
{
|
{
|
||||||
|
mDisplayEquippedItems = true;
|
||||||
|
mHighlightEquippedItems = false;
|
||||||
|
if (container.getTypeName() == typeid(ESM::NPC).name() && !loot)
|
||||||
|
{
|
||||||
|
// we are stealing stuff
|
||||||
|
mDisplayEquippedItems = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDisposeCorpseButton->setVisible(loot);
|
||||||
|
|
||||||
openContainer(container);
|
openContainer(container);
|
||||||
setTitle(MWWorld::Class::get(container).getName(container));
|
setTitle(MWWorld::Class::get(container).getName(container));
|
||||||
drawItems();
|
drawItems();
|
||||||
|
@ -671,6 +707,22 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender)
|
||||||
|
{
|
||||||
|
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
|
||||||
|
{
|
||||||
|
onTakeAllButtonClicked(mTakeButton);
|
||||||
|
|
||||||
|
/// \todo I don't think this is the correct flag to check
|
||||||
|
if (MWWorld::Class::get(mPtr).isEssential(mPtr))
|
||||||
|
mWindowManager.messageBox("#{sDisposeCorpseFail}");
|
||||||
|
else
|
||||||
|
MWBase::Environment::get().getWorld()->deleteObject(mPtr);
|
||||||
|
|
||||||
|
mPtr = MWWorld::Ptr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ContainerWindow::onReferenceUnavailable()
|
void ContainerWindow::onReferenceUnavailable()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||||
|
|
|
@ -82,6 +82,9 @@ namespace MWGui
|
||||||
void drawItems();
|
void drawItems();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool mDisplayEquippedItems;
|
||||||
|
bool mHighlightEquippedItems;
|
||||||
|
|
||||||
MyGUI::ScrollView* mItemView;
|
MyGUI::ScrollView* mItemView;
|
||||||
MyGUI::Widget* mContainerWidget;
|
MyGUI::Widget* mContainerWidget;
|
||||||
|
|
||||||
|
@ -111,14 +114,13 @@ namespace MWGui
|
||||||
|
|
||||||
virtual bool isTradeWindow() { return false; }
|
virtual bool isTradeWindow() { return false; }
|
||||||
virtual bool isInventory() { return false; }
|
virtual bool isInventory() { return false; }
|
||||||
virtual std::vector<MWWorld::Ptr> getEquippedItems() { return std::vector<MWWorld::Ptr>(); }
|
virtual std::vector<MWWorld::Ptr> getEquippedItems();
|
||||||
virtual void _unequipItem(MWWorld::Ptr item) { ; }
|
virtual void _unequipItem(MWWorld::Ptr item) { ; }
|
||||||
|
|
||||||
virtual bool isTrading() { return false; }
|
virtual bool isTrading() { return false; }
|
||||||
|
|
||||||
virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; }
|
virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; }
|
||||||
|
|
||||||
virtual bool ignoreEquippedItems() { return false; }
|
|
||||||
virtual std::vector<MWWorld::Ptr> itemsToIgnore() { return std::vector<MWWorld::Ptr>(); }
|
virtual std::vector<MWWorld::Ptr> itemsToIgnore() { return std::vector<MWWorld::Ptr>(); }
|
||||||
|
|
||||||
virtual void notifyContentChanged() { ; }
|
virtual void notifyContentChanged() { ; }
|
||||||
|
@ -131,15 +133,17 @@ namespace MWGui
|
||||||
|
|
||||||
virtual ~ContainerWindow();
|
virtual ~ContainerWindow();
|
||||||
|
|
||||||
void open(MWWorld::Ptr container);
|
void open(MWWorld::Ptr container, bool loot=false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
MyGUI::Button* mDisposeCorpseButton;
|
||||||
MyGUI::Button* mTakeButton;
|
MyGUI::Button* mTakeButton;
|
||||||
MyGUI::Button* mCloseButton;
|
MyGUI::Button* mCloseButton;
|
||||||
|
|
||||||
void onWindowResize(MyGUI::Window* window);
|
void onWindowResize(MyGUI::Window* window);
|
||||||
void onCloseButtonClicked(MyGUI::Widget* _sender);
|
void onCloseButtonClicked(MyGUI::Widget* _sender);
|
||||||
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
|
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
|
||||||
|
void onDisposeCorpseButtonClicked(MyGUI::Widget* sender);
|
||||||
|
|
||||||
virtual void onReferenceUnavailable();
|
virtual void onReferenceUnavailable();
|
||||||
};
|
};
|
||||||
|
|
131
apps/openmw/mwgui/cursor.cpp
Normal file
131
apps/openmw/mwgui/cursor.cpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#include "cursor.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_PointerManager.h>
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
#include <MyGUI_RenderManager.h>
|
||||||
|
#include <MyGUI_RotatingSkin.h>
|
||||||
|
#include <MyGUI_Gui.h>
|
||||||
|
|
||||||
|
#include <OgreMath.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
ResourceImageSetPointerFix::ResourceImageSetPointerFix()
|
||||||
|
: mImageSet(NULL)
|
||||||
|
, mRotation(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceImageSetPointerFix::~ResourceImageSetPointerFix()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceImageSetPointerFix::deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version)
|
||||||
|
{
|
||||||
|
Base::deserialization(_node, _version);
|
||||||
|
|
||||||
|
MyGUI::xml::ElementEnumerator info = _node->getElementEnumerator();
|
||||||
|
while (info.next("Property"))
|
||||||
|
{
|
||||||
|
const std::string& key = info->findAttribute("key");
|
||||||
|
const std::string& value = info->findAttribute("value");
|
||||||
|
|
||||||
|
if (key == "Point")
|
||||||
|
mPoint = MyGUI::IntPoint::parse(value);
|
||||||
|
else if (key == "Size")
|
||||||
|
mSize = MyGUI::IntSize::parse(value);
|
||||||
|
else if (key == "Rotation")
|
||||||
|
mRotation = MyGUI::utility::parseInt(value);
|
||||||
|
else if (key == "Resource")
|
||||||
|
mImageSet = MyGUI::ResourceManager::getInstance().getByName(value)->castType<MyGUI::ResourceImageSet>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResourceImageSetPointerFix::getRotation()
|
||||||
|
{
|
||||||
|
return mRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceImageSetPointerFix::setImage(MyGUI::ImageBox* _image)
|
||||||
|
{
|
||||||
|
if (mImageSet != NULL)
|
||||||
|
_image->setItemResourceInfo(mImageSet->getIndexInfo(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceImageSetPointerFix::setPosition(MyGUI::ImageBox* _image, const MyGUI::IntPoint& _point)
|
||||||
|
{
|
||||||
|
_image->setCoord(_point.left - mPoint.left, _point.top - mPoint.top, mSize.width, mSize.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::ResourceImageSetPtr ResourceImageSetPointerFix:: getImageSet()
|
||||||
|
{
|
||||||
|
return mImageSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::IntPoint ResourceImageSetPointerFix::getHotSpot()
|
||||||
|
{
|
||||||
|
return mPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::IntSize ResourceImageSetPointerFix::getSize()
|
||||||
|
{
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Cursor::Cursor()
|
||||||
|
{
|
||||||
|
// hide mygui's pointer since we're rendering it ourselves (because mygui's pointer doesn't support rotation)
|
||||||
|
MyGUI::PointerManager::getInstance().setVisible(false);
|
||||||
|
|
||||||
|
MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &Cursor::onCursorChange);
|
||||||
|
|
||||||
|
mWidget = MyGUI::Gui::getInstance().createWidget<MyGUI::ImageBox>("RotatingSkin",0,0,0,0,MyGUI::Align::Default,"Pointer","");
|
||||||
|
|
||||||
|
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor::~Cursor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::onCursorChange(const std::string &name)
|
||||||
|
{
|
||||||
|
ResourceImageSetPointerFix* imgSetPtr = dynamic_cast<ResourceImageSetPointerFix*>(
|
||||||
|
MyGUI::PointerManager::getInstance().getByName(name));
|
||||||
|
assert(imgSetPtr != NULL);
|
||||||
|
|
||||||
|
MyGUI::ResourceImageSet* imgSet = imgSetPtr->getImageSet();
|
||||||
|
|
||||||
|
std::string texture = imgSet->getIndexInfo(0,0).texture;
|
||||||
|
|
||||||
|
mSize = imgSetPtr->getSize();
|
||||||
|
mHotSpot = imgSetPtr->getHotSpot();
|
||||||
|
|
||||||
|
int rotation = imgSetPtr->getRotation();
|
||||||
|
|
||||||
|
mWidget->setImageTexture(texture);
|
||||||
|
MyGUI::ISubWidget* main = mWidget->getSubWidgetMain();
|
||||||
|
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
|
||||||
|
rotatingSubskin->setCenter(MyGUI::IntPoint(mSize.width/2,mSize.height/2));
|
||||||
|
rotatingSubskin->setAngle(Ogre::Degree(rotation).valueRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::update()
|
||||||
|
{
|
||||||
|
MyGUI::IntPoint position = MyGUI::InputManager::getInstance().getMousePosition();
|
||||||
|
|
||||||
|
mWidget->setPosition(position - mHotSpot);
|
||||||
|
mWidget->setSize(mSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::setVisible(bool visible)
|
||||||
|
{
|
||||||
|
mWidget->setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
62
apps/openmw/mwgui/cursor.hpp
Normal file
62
apps/openmw/mwgui/cursor.hpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#ifndef MWGUI_CURSOR_H
|
||||||
|
#define MWGUI_CURSOR_H
|
||||||
|
|
||||||
|
#include <MyGUI_IPointer.h>
|
||||||
|
#include <MyGUI_ResourceImageSet.h>
|
||||||
|
#include <MyGUI_RTTI.h>
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
|
||||||
|
/// \brief Allows us to get the members of
|
||||||
|
/// ResourceImageSetPointer that we need.
|
||||||
|
/// \example MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
|
||||||
|
/// MyGUI::ResourceManager::getInstance().load("core.xml");
|
||||||
|
class ResourceImageSetPointerFix :
|
||||||
|
public MyGUI::IPointer
|
||||||
|
{
|
||||||
|
MYGUI_RTTI_DERIVED( ResourceImageSetPointerFix )
|
||||||
|
|
||||||
|
public:
|
||||||
|
ResourceImageSetPointerFix();
|
||||||
|
virtual ~ResourceImageSetPointerFix();
|
||||||
|
|
||||||
|
virtual void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version);
|
||||||
|
|
||||||
|
virtual void setImage(MyGUI::ImageBox* _image);
|
||||||
|
virtual void setPosition(MyGUI::ImageBox* _image, const MyGUI::IntPoint& _point);
|
||||||
|
|
||||||
|
//and now for the whole point of this class, allow us to get
|
||||||
|
//the hot spot, the image and the size of the cursor.
|
||||||
|
virtual MyGUI::ResourceImageSetPtr getImageSet();
|
||||||
|
virtual MyGUI::IntPoint getHotSpot();
|
||||||
|
virtual MyGUI::IntSize getSize();
|
||||||
|
virtual int getRotation();
|
||||||
|
|
||||||
|
private:
|
||||||
|
MyGUI::IntPoint mPoint;
|
||||||
|
MyGUI::IntSize mSize;
|
||||||
|
MyGUI::ResourceImageSetPtr mImageSet;
|
||||||
|
int mRotation; // rotation in degrees
|
||||||
|
};
|
||||||
|
|
||||||
|
class Cursor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Cursor();
|
||||||
|
~Cursor();
|
||||||
|
void update ();
|
||||||
|
|
||||||
|
void setVisible (bool visible);
|
||||||
|
|
||||||
|
void onCursorChange (const std::string& name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MyGUI::ImageBox* mWidget;
|
||||||
|
|
||||||
|
MyGUI::IntSize mSize;
|
||||||
|
MyGUI::IntPoint mHotSpot;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,16 +0,0 @@
|
||||||
#include "cursorreplace.hpp"
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <openengine/ogre/imagerotate.hpp>
|
|
||||||
|
|
||||||
#include <OgreResourceGroupManager.h>
|
|
||||||
#include <OgreRoot.h>
|
|
||||||
|
|
||||||
using namespace MWGui;
|
|
||||||
|
|
||||||
CursorReplace::CursorReplace()
|
|
||||||
{
|
|
||||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_vresize.png", 90);
|
|
||||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize1.png", -45);
|
|
||||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize2.png", 45);
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef GAME_CURSORREPLACE_H
|
|
||||||
#define GAME_CURSORREPLACE_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace MWGui
|
|
||||||
{
|
|
||||||
/// \brief MyGUI does not support rotating cursors, so we have to do it manually
|
|
||||||
class CursorReplace
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CursorReplace();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -151,7 +151,7 @@ DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager)
|
||||||
getWidget(mTopicsList, "TopicsList");
|
getWidget(mTopicsList, "TopicsList");
|
||||||
mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
||||||
|
|
||||||
MyGUI::ButtonPtr byeButton;
|
MyGUI::Button* byeButton;
|
||||||
getWidget(byeButton, "ByeButton");
|
getWidget(byeButton, "ByeButton");
|
||||||
byeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
byeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager)
|
||||||
void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
|
void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
MyGUI::ISubWidgetText* t = mHistory->getClient()->getSubWidgetText();
|
MyGUI::ISubWidgetText* t = mHistory->getClient()->getSubWidgetText();
|
||||||
if(t == nullptr)
|
if(t == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const MyGUI::IntPoint& lastPressed = MyGUI::InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
|
const MyGUI::IntPoint& lastPressed = MyGUI::InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
|
||||||
|
@ -223,50 +223,60 @@ void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
||||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onSelectTopic(std::string topic)
|
void DialogueWindow::onSelectTopic(const std::string& topic, int id)
|
||||||
{
|
{
|
||||||
if (!mEnabled) return;
|
if (!mEnabled) return;
|
||||||
|
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
int separatorPos = mTopicsList->getItemCount();
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
for (unsigned int i=0; i<mTopicsList->getItemCount(); ++i)
|
||||||
|
{
|
||||||
|
if (mTopicsList->getItemNameAt(i) == "")
|
||||||
|
separatorPos = i;
|
||||||
|
}
|
||||||
|
|
||||||
if (topic == gmst.find("sBarter")->getString())
|
if (id > separatorPos)
|
||||||
{
|
|
||||||
/// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)?
|
|
||||||
mWindowManager.pushGuiMode(GM_Barter);
|
|
||||||
mWindowManager.getTradeWindow()->startTrade(mPtr);
|
|
||||||
}
|
|
||||||
if (topic == gmst.find("sPersuasion")->getString())
|
|
||||||
{
|
|
||||||
mPersuasionDialog.setVisible(true);
|
|
||||||
}
|
|
||||||
else if (topic == gmst.find("sSpells")->getString())
|
|
||||||
{
|
|
||||||
mWindowManager.pushGuiMode(GM_SpellBuying);
|
|
||||||
mWindowManager.getSpellBuyingWindow()->startSpellBuying(mPtr);
|
|
||||||
}
|
|
||||||
else if (topic == gmst.find("sTravel")->getString())
|
|
||||||
{
|
|
||||||
mWindowManager.pushGuiMode(GM_Travel);
|
|
||||||
mWindowManager.getTravelWindow()->startTravel(mPtr);
|
|
||||||
}
|
|
||||||
else if (topic == gmst.find("sSpellMakingMenuTitle")->getString())
|
|
||||||
{
|
|
||||||
mWindowManager.pushGuiMode(GM_SpellCreation);
|
|
||||||
mWindowManager.startSpellMaking (mPtr);
|
|
||||||
}
|
|
||||||
else if (topic == gmst.find("sEnchanting")->getString())
|
|
||||||
{
|
|
||||||
mWindowManager.pushGuiMode(GM_Enchanting);
|
|
||||||
mWindowManager.startEnchanting (mPtr);
|
|
||||||
}
|
|
||||||
else if (topic == gmst.find("sServiceTrainingTitle")->getString())
|
|
||||||
{
|
|
||||||
mWindowManager.pushGuiMode(GM_Training);
|
|
||||||
mWindowManager.startTraining (mPtr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic));
|
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
|
if (topic == gmst.find("sBarter")->getString())
|
||||||
|
{
|
||||||
|
/// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)?
|
||||||
|
mWindowManager.pushGuiMode(GM_Barter);
|
||||||
|
mWindowManager.getTradeWindow()->startTrade(mPtr);
|
||||||
|
}
|
||||||
|
if (topic == gmst.find("sPersuasion")->getString())
|
||||||
|
{
|
||||||
|
mPersuasionDialog.setVisible(true);
|
||||||
|
}
|
||||||
|
else if (topic == gmst.find("sSpells")->getString())
|
||||||
|
{
|
||||||
|
mWindowManager.pushGuiMode(GM_SpellBuying);
|
||||||
|
mWindowManager.getSpellBuyingWindow()->startSpellBuying(mPtr);
|
||||||
|
}
|
||||||
|
else if (topic == gmst.find("sTravel")->getString())
|
||||||
|
{
|
||||||
|
mWindowManager.pushGuiMode(GM_Travel);
|
||||||
|
mWindowManager.getTravelWindow()->startTravel(mPtr);
|
||||||
|
}
|
||||||
|
else if (topic == gmst.find("sSpellMakingMenuTitle")->getString())
|
||||||
|
{
|
||||||
|
mWindowManager.pushGuiMode(GM_SpellCreation);
|
||||||
|
mWindowManager.startSpellMaking (mPtr);
|
||||||
|
}
|
||||||
|
else if (topic == gmst.find("sEnchanting")->getString())
|
||||||
|
{
|
||||||
|
mWindowManager.pushGuiMode(GM_Enchanting);
|
||||||
|
mWindowManager.startEnchanting (mPtr);
|
||||||
|
}
|
||||||
|
else if (topic == gmst.find("sServiceTrainingTitle")->getString())
|
||||||
|
{
|
||||||
|
mWindowManager.pushGuiMode(GM_Training);
|
||||||
|
mWindowManager.startTraining (mPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
|
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
|
||||||
|
@ -381,7 +391,7 @@ std::string DialogueWindow::parseText(const std::string& text)
|
||||||
std::vector<MWDialogue::HyperTextToken> hypertext = MWDialogue::ParseHyperText(text);
|
std::vector<MWDialogue::HyperTextToken> hypertext = MWDialogue::ParseHyperText(text);
|
||||||
|
|
||||||
size_t historySize = 0;
|
size_t historySize = 0;
|
||||||
if(mHistory->getClient()->getSubWidgetText() != nullptr)
|
if(mHistory->getClient()->getSubWidgetText() != NULL)
|
||||||
{
|
{
|
||||||
historySize = mHistory->getOnlyText().size();
|
historySize = mHistory->getOnlyText().size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace MWGui
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onSelectTopic(std::string topic);
|
void onSelectTopic(const std::string& topic, int id);
|
||||||
void onByeClicked(MyGUI::Widget* _sender);
|
void onByeClicked(MyGUI::Widget* _sender);
|
||||||
void onHistoryClicked(MyGUI::Widget* _sender);
|
void onHistoryClicked(MyGUI::Widget* _sender);
|
||||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||||
|
@ -113,7 +113,7 @@ namespace MWGui
|
||||||
DialogueHistory* mHistory;
|
DialogueHistory* mHistory;
|
||||||
Widgets::MWList* mTopicsList;
|
Widgets::MWList* mTopicsList;
|
||||||
MyGUI::ProgressPtr mDispositionBar;
|
MyGUI::ProgressPtr mDispositionBar;
|
||||||
MyGUI::EditPtr mDispositionText;
|
MyGUI::EditBox* mDispositionText;
|
||||||
|
|
||||||
PersuasionDialog mPersuasionDialog;
|
PersuasionDialog mPersuasionDialog;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include "exposedwindow.hpp"
|
#include "exposedwindow.hpp"
|
||||||
|
|
||||||
#include "MyGUI_Window.h"
|
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
MyGUI::VectorWidgetPtr ExposedWindow::getSkinWidgetsByName (const std::string &name)
|
MyGUI::VectorWidgetPtr ExposedWindow::getSkinWidgetsByName (const std::string &name)
|
||||||
|
@ -16,7 +14,7 @@ namespace MWGui
|
||||||
if (widgets.empty())
|
if (widgets.empty())
|
||||||
{
|
{
|
||||||
MYGUI_ASSERT( ! _throw, "widget name '" << _name << "' not found in skin of layout '" << getName() << "'");
|
MYGUI_ASSERT( ! _throw, "widget name '" << _name << "' not found in skin of layout '" << getName() << "'");
|
||||||
return nullptr;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef MWGUI_EXPOSEDWINDOW_H
|
#ifndef MWGUI_EXPOSEDWINDOW_H
|
||||||
#define MWGUI_EXPOSEDWINDOW_H
|
#define MWGUI_EXPOSEDWINDOW_H
|
||||||
|
|
||||||
#include "MyGUI_Window.h"
|
#include <MyGUI_Window.h>
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <MyGUI.h>
|
#include <MyGUI_Widget.h>
|
||||||
|
#include <MyGUI_RenderManager.h>
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
#include "inventorywindow.hpp"
|
#include "inventorywindow.hpp"
|
||||||
#include "container.hpp"
|
#include "container.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
|
#include "spellicons.hpp"
|
||||||
|
|
||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
|
|
||||||
|
@ -32,7 +34,6 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
|
||||||
, mWeapStatus(NULL)
|
, mWeapStatus(NULL)
|
||||||
, mSpellStatus(NULL)
|
, mSpellStatus(NULL)
|
||||||
, mEffectBox(NULL)
|
, mEffectBox(NULL)
|
||||||
, mEffect1(NULL)
|
|
||||||
, mMinimap(NULL)
|
, mMinimap(NULL)
|
||||||
, mCompass(NULL)
|
, mCompass(NULL)
|
||||||
, mCrosshair(NULL)
|
, mCrosshair(NULL)
|
||||||
|
@ -86,9 +87,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
|
||||||
mSpellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
|
mSpellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
|
||||||
|
|
||||||
getWidget(mEffectBox, "EffectBox");
|
getWidget(mEffectBox, "EffectBox");
|
||||||
getWidget(mEffect1, "Effect1");
|
|
||||||
mEffectBoxBaseRight = viewSize.width - mEffectBox->getRight();
|
mEffectBoxBaseRight = viewSize.width - mEffectBox->getRight();
|
||||||
mEffectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
|
|
||||||
|
|
||||||
getWidget(mMinimapBox, "MiniMapBox");
|
getWidget(mMinimapBox, "MiniMapBox");
|
||||||
mMinimapBoxBaseRight = viewSize.width - mMinimapBox->getRight();
|
mMinimapBoxBaseRight = viewSize.width - mMinimapBox->getRight();
|
||||||
|
@ -107,13 +106,18 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
|
||||||
getWidget(mTriangleCounter, "TriangleCounter");
|
getWidget(mTriangleCounter, "TriangleCounter");
|
||||||
getWidget(mBatchCounter, "BatchCounter");
|
getWidget(mBatchCounter, "BatchCounter");
|
||||||
|
|
||||||
setEffect("icons\\s\\tx_s_chameleon.dds");
|
|
||||||
|
|
||||||
LocalMapBase::init(mMinimap, mCompass, this);
|
LocalMapBase::init(mMinimap, mCompass, this);
|
||||||
|
|
||||||
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
|
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
|
||||||
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
|
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
|
||||||
mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus);
|
mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus);
|
||||||
|
|
||||||
|
mSpellIcons = new SpellIcons();
|
||||||
|
}
|
||||||
|
|
||||||
|
HUD::~HUD()
|
||||||
|
{
|
||||||
|
delete mSpellIcons;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HUD::setFpsLevel(int level)
|
void HUD::setFpsLevel(int level)
|
||||||
|
@ -156,11 +160,6 @@ void HUD::setBatchCount(unsigned int count)
|
||||||
mBatchCounter->setCaption(boost::lexical_cast<std::string>(count));
|
mBatchCounter->setCaption(boost::lexical_cast<std::string>(count));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HUD::setEffect(const char *img)
|
|
||||||
{
|
|
||||||
mEffect1->setImageTexture(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
||||||
{
|
{
|
||||||
static const char *ids[] =
|
static const char *ids[] =
|
||||||
|
@ -222,7 +221,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
||||||
else
|
else
|
||||||
world->dropObjectOnGround(world->getPlayer().getPlayer(), object);
|
world->dropObjectOnGround(world->getPlayer().getPlayer(), object);
|
||||||
|
|
||||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
||||||
|
|
||||||
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
|
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
|
||||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||||
|
@ -273,21 +272,21 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
|
||||||
bool canDrop = world->canPlaceObject(mouseX, mouseY);
|
bool canDrop = world->canPlaceObject(mouseX, mouseY);
|
||||||
|
|
||||||
if (!canDrop)
|
if (!canDrop)
|
||||||
MyGUI::PointerManager::getInstance().setPointer("drop_ground");
|
MWBase::Environment::get().getWindowManager()->changePointer("drop_ground");
|
||||||
else
|
else
|
||||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
||||||
mWorldMouseOver = true;
|
mWorldMouseOver = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new)
|
void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new)
|
||||||
{
|
{
|
||||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
||||||
mWorldMouseOver = false;
|
mWorldMouseOver = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,3 +541,8 @@ void HUD::updatePositions()
|
||||||
mMapVisible = mMinimapBox->getVisible ();
|
mMapVisible = mMinimapBox->getVisible ();
|
||||||
mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop());
|
mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HUD::update()
|
||||||
|
{
|
||||||
|
mSpellIcons->updateWidgets(mEffectBox, true);
|
||||||
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
class DragAndDrop;
|
class DragAndDrop;
|
||||||
|
class SpellIcons;
|
||||||
|
|
||||||
class HUD : public OEngine::GUI::Layout, public LocalMapBase
|
class HUD : public OEngine::GUI::Layout, public LocalMapBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop);
|
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop);
|
||||||
void setEffect(const char *img);
|
virtual ~HUD();
|
||||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||||
void setFPS(float fps);
|
void setFPS(float fps);
|
||||||
void setTriangleCount(unsigned int count);
|
void setTriangleCount(unsigned int count);
|
||||||
|
@ -43,6 +44,10 @@ namespace MWGui
|
||||||
|
|
||||||
bool getWorldMouseOver() { return mWorldMouseOver; }
|
bool getWorldMouseOver() { return mWorldMouseOver; }
|
||||||
|
|
||||||
|
MyGUI::Widget* getEffectBox() { return mEffectBox; }
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::ProgressPtr mHealth, mMagicka, mStamina;
|
MyGUI::ProgressPtr mHealth, mMagicka, mStamina;
|
||||||
MyGUI::Widget* mHealthFrame;
|
MyGUI::Widget* mHealthFrame;
|
||||||
|
@ -51,7 +56,6 @@ namespace MWGui
|
||||||
MyGUI::ProgressPtr mWeapStatus, mSpellStatus;
|
MyGUI::ProgressPtr mWeapStatus, mSpellStatus;
|
||||||
MyGUI::Widget *mEffectBox, *mMinimapBox;
|
MyGUI::Widget *mEffectBox, *mMinimapBox;
|
||||||
MyGUI::Button* mMinimapButton;
|
MyGUI::Button* mMinimapButton;
|
||||||
MyGUI::ImageBox* mEffect1;
|
|
||||||
MyGUI::ScrollView* mMinimap;
|
MyGUI::ScrollView* mMinimap;
|
||||||
MyGUI::ImageBox* mCompass;
|
MyGUI::ImageBox* mCompass;
|
||||||
MyGUI::ImageBox* mCrosshair;
|
MyGUI::ImageBox* mCrosshair;
|
||||||
|
@ -60,7 +64,7 @@ namespace MWGui
|
||||||
|
|
||||||
MyGUI::Widget* mDummy;
|
MyGUI::Widget* mDummy;
|
||||||
|
|
||||||
MyGUI::WidgetPtr mFpsBox;
|
MyGUI::Widget* mFpsBox;
|
||||||
MyGUI::TextBox* mFpsCounter;
|
MyGUI::TextBox* mFpsCounter;
|
||||||
MyGUI::TextBox* mTriangleCounter;
|
MyGUI::TextBox* mTriangleCounter;
|
||||||
MyGUI::TextBox* mBatchCounter;
|
MyGUI::TextBox* mBatchCounter;
|
||||||
|
@ -85,6 +89,8 @@ namespace MWGui
|
||||||
|
|
||||||
bool mWorldMouseOver;
|
bool mWorldMouseOver;
|
||||||
|
|
||||||
|
SpellIcons* mSpellIcons;
|
||||||
|
|
||||||
void onWorldClicked(MyGUI::Widget* _sender);
|
void onWorldClicked(MyGUI::Widget* _sender);
|
||||||
void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y);
|
void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y);
|
||||||
void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new);
|
void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef MWGUI_IMAGEBUTTON_H
|
#ifndef MWGUI_IMAGEBUTTON_H
|
||||||
#define MWGUI_IMAGEBUTTON_H
|
#define MWGUI_IMAGEBUTTON_H
|
||||||
|
|
||||||
#include "MyGUI_ImageBox.h"
|
#include <MyGUI_ImageBox.h>
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
|
@ -160,11 +160,8 @@ namespace MWGui
|
||||||
// the "Take" button should not be visible.
|
// the "Take" button should not be visible.
|
||||||
// NOTE: the take button is "reset" when the window opens, so we can safely do the following
|
// NOTE: the take button is "reset" when the window opens, so we can safely do the following
|
||||||
// without screwing up future book windows
|
// without screwing up future book windows
|
||||||
if (mDragAndDrop->mDraggedFrom == this)
|
mWindowManager.getBookWindow()->setTakeButtonShow(false);
|
||||||
{
|
mWindowManager.getScrollWindow()->setTakeButtonShow(false);
|
||||||
mWindowManager.getBookWindow()->setTakeButtonShow(false);
|
|
||||||
mWindowManager.getScrollWindow()->setTakeButtonShow(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
mDragAndDrop->mIsOnDragAndDrop = false;
|
mDragAndDrop->mIsOnDragAndDrop = false;
|
||||||
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
|
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
|
||||||
|
@ -214,24 +211,6 @@ namespace MWGui
|
||||||
return MWWorld::Ptr();
|
return MWWorld::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MWWorld::Ptr> InventoryWindow::getEquippedItems()
|
|
||||||
{
|
|
||||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
|
||||||
|
|
||||||
std::vector<MWWorld::Ptr> items;
|
|
||||||
|
|
||||||
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
|
||||||
{
|
|
||||||
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
|
|
||||||
if (it != invStore.end())
|
|
||||||
{
|
|
||||||
items.push_back(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InventoryWindow::_unequipItem(MWWorld::Ptr item)
|
void InventoryWindow::_unequipItem(MWWorld::Ptr item)
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||||
|
|
|
@ -64,7 +64,6 @@ namespace MWGui
|
||||||
|
|
||||||
virtual bool isTrading() { return mTrading; }
|
virtual bool isTrading() { return mTrading; }
|
||||||
virtual bool isInventory() { return true; }
|
virtual bool isInventory() { return true; }
|
||||||
virtual std::vector<MWWorld::Ptr> getEquippedItems();
|
|
||||||
virtual void _unequipItem(MWWorld::Ptr item);
|
virtual void _unequipItem(MWWorld::Ptr item);
|
||||||
|
|
||||||
virtual void onReferenceUnavailable() { ; }
|
virtual void onReferenceUnavailable() { ; }
|
||||||
|
|
|
@ -29,8 +29,8 @@ namespace MWGui
|
||||||
void notifyNextPage(MyGUI::Widget* _sender);
|
void notifyNextPage(MyGUI::Widget* _sender);
|
||||||
void notifyPrevPage(MyGUI::Widget* _sender);
|
void notifyPrevPage(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
MyGUI::EditPtr mLeftTextWidget;
|
MyGUI::EditBox* mLeftTextWidget;
|
||||||
MyGUI::EditPtr mRightTextWidget;
|
MyGUI::EditBox* mRightTextWidget;
|
||||||
MWGui::ImageButton* mPrevBtn;
|
MWGui::ImageButton* mPrevBtn;
|
||||||
MWGui::ImageButton* mNextBtn;
|
MWGui::ImageButton* mNextBtn;
|
||||||
std::vector<std::string> mLeftPages;
|
std::vector<std::string> mLeftPages;
|
||||||
|
|
|
@ -23,6 +23,8 @@ namespace MWGui
|
||||||
getWidget(mOkButton, "OkButton");
|
getWidget(mOkButton, "OkButton");
|
||||||
getWidget(mClassImage, "ClassImage");
|
getWidget(mClassImage, "ClassImage");
|
||||||
getWidget(mLevelText, "LevelText");
|
getWidget(mLevelText, "LevelText");
|
||||||
|
getWidget(mLevelDescription, "LevelDescription");
|
||||||
|
getWidget(mCoinBox, "Coins");
|
||||||
|
|
||||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onOkButtonClicked);
|
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onOkButtonClicked);
|
||||||
|
|
||||||
|
@ -80,11 +82,13 @@ namespace MWGui
|
||||||
|
|
||||||
void LevelupDialog::resetCoins ()
|
void LevelupDialog::resetCoins ()
|
||||||
{
|
{
|
||||||
int curX = mMainWidget->getWidth()/2 - (16 + 2) * 1.5;
|
int curX = 0;
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
{
|
{
|
||||||
MyGUI::ImageBox* image = mCoins[i];
|
MyGUI::ImageBox* image = mCoins[i];
|
||||||
image->setCoord(MyGUI::IntCoord(curX,250,16,16));
|
image->detachFromWidget();
|
||||||
|
image->attachToWidget(mCoinBox);
|
||||||
|
image->setCoord(MyGUI::IntCoord(curX,0,16,16));
|
||||||
curX += 24+2;
|
curX += 24+2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +99,9 @@ namespace MWGui
|
||||||
for (unsigned int i=0; i<mSpentAttributes.size(); ++i)
|
for (unsigned int i=0; i<mSpentAttributes.size(); ++i)
|
||||||
{
|
{
|
||||||
MyGUI::ImageBox* image = mCoins[i];
|
MyGUI::ImageBox* image = mCoins[i];
|
||||||
|
image->detachFromWidget();
|
||||||
|
image->attachToWidget(mMainWidget);
|
||||||
|
|
||||||
int attribute = mSpentAttributes[i];
|
int attribute = mSpentAttributes[i];
|
||||||
|
|
||||||
int xdiff = mAttributeMultipliers[attribute]->getCaption() == "" ? 0 : 30;
|
int xdiff = mAttributeMultipliers[attribute]->getCaption() == "" ? 0 : 30;
|
||||||
|
@ -113,8 +120,6 @@ namespace MWGui
|
||||||
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
|
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
|
||||||
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
|
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
|
||||||
|
|
||||||
center();
|
|
||||||
|
|
||||||
mSpentAttributes.clear();
|
mSpentAttributes.clear();
|
||||||
resetCoins();
|
resetCoins();
|
||||||
|
|
||||||
|
@ -128,16 +133,25 @@ namespace MWGui
|
||||||
|
|
||||||
mClassImage->setImageTexture ("textures\\levelup\\" + cls->mId + ".dds");
|
mClassImage->setImageTexture ("textures\\levelup\\" + cls->mId + ".dds");
|
||||||
|
|
||||||
/// \todo replace this with INI-imported texts
|
|
||||||
int level = creatureStats.getLevel ()+1;
|
int level = creatureStats.getLevel ()+1;
|
||||||
mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + boost::lexical_cast<std::string>(level));
|
mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + boost::lexical_cast<std::string>(level));
|
||||||
|
|
||||||
|
std::string levelupdescription;
|
||||||
|
if(level>20)
|
||||||
|
levelupdescription=world->getFallback("Level_Up_Default");
|
||||||
|
else
|
||||||
|
levelupdescription=world->getFallback("Level_Up_Level"+boost::lexical_cast<std::string>(level));
|
||||||
|
|
||||||
|
mLevelDescription->setCaption (levelupdescription);
|
||||||
|
|
||||||
for (int i=0; i<8; ++i)
|
for (int i=0; i<8; ++i)
|
||||||
{
|
{
|
||||||
MyGUI::TextBox* text = mAttributeMultipliers[i];
|
MyGUI::TextBox* text = mAttributeMultipliers[i];
|
||||||
int mult = pcStats.getLevelupAttributeMultiplier (i);
|
int mult = pcStats.getLevelupAttributeMultiplier (i);
|
||||||
text->setCaption(mult <= 1 ? "" : "x" + boost::lexical_cast<std::string>(mult));
|
text->setCaption(mult <= 1 ? "" : "x" + boost::lexical_cast<std::string>(mult));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
center();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender)
|
void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender)
|
||||||
|
|
|
@ -17,6 +17,9 @@ namespace MWGui
|
||||||
MyGUI::Button* mOkButton;
|
MyGUI::Button* mOkButton;
|
||||||
MyGUI::ImageBox* mClassImage;
|
MyGUI::ImageBox* mClassImage;
|
||||||
MyGUI::TextBox* mLevelText;
|
MyGUI::TextBox* mLevelText;
|
||||||
|
MyGUI::EditBox* mLevelDescription;
|
||||||
|
|
||||||
|
MyGUI::Widget* mCoinBox;
|
||||||
|
|
||||||
std::vector<MyGUI::Button*> mAttributes;
|
std::vector<MyGUI::Button*> mAttributes;
|
||||||
std::vector<MyGUI::TextBox*> mAttributeValues;
|
std::vector<MyGUI::TextBox*> mAttributeValues;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "list.hpp"
|
#include "list.hpp"
|
||||||
|
|
||||||
#include <MyGUI.h>
|
#include <MyGUI_Gui.h>
|
||||||
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_ImageBox.h>
|
||||||
|
#include <MyGUI_ScrollBar.h>
|
||||||
|
|
||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
using namespace MWGui::Widgets;
|
using namespace MWGui::Widgets;
|
||||||
|
@ -20,7 +23,7 @@ void MWList::initialiseOverride()
|
||||||
if (mClient == 0)
|
if (mClient == 0)
|
||||||
mClient = this;
|
mClient = this;
|
||||||
|
|
||||||
mScrollView = mClient->createWidgetReal<MyGUI::ScrollView>(
|
mScrollView = mClient->createWidgetReal<MWGui::Widgets::MWScrollView>(
|
||||||
"MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0),
|
"MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0),
|
||||||
MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView");
|
MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView");
|
||||||
}
|
}
|
||||||
|
@ -45,6 +48,7 @@ void MWList::redraw(bool scrollbarShown)
|
||||||
const int _scrollBarWidth = 24; // fetch this from skin?
|
const int _scrollBarWidth = 24; // fetch this from skin?
|
||||||
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
|
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
|
||||||
const int spacing = 3;
|
const int spacing = 3;
|
||||||
|
size_t scrollbarPosition = mScrollView->getScrollPosition();
|
||||||
|
|
||||||
while (mScrollView->getChildCount())
|
while (mScrollView->getChildCount())
|
||||||
{
|
{
|
||||||
|
@ -52,6 +56,7 @@ void MWList::redraw(bool scrollbarShown)
|
||||||
}
|
}
|
||||||
|
|
||||||
mItemHeight = 0;
|
mItemHeight = 0;
|
||||||
|
int i=0;
|
||||||
for (std::vector<std::string>::const_iterator it=mItems.begin();
|
for (std::vector<std::string>::const_iterator it=mItems.begin();
|
||||||
it!=mItems.end(); ++it)
|
it!=mItems.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -68,6 +73,7 @@ void MWList::redraw(bool scrollbarShown)
|
||||||
|
|
||||||
int height = button->getTextSize().height;
|
int height = button->getTextSize().height;
|
||||||
button->setSize(MyGUI::IntSize(button->getSize().width, height));
|
button->setSize(MyGUI::IntSize(button->getSize().width, height));
|
||||||
|
button->setUserData(i);
|
||||||
|
|
||||||
mItemHeight += height + spacing;
|
mItemHeight += height + spacing;
|
||||||
}
|
}
|
||||||
|
@ -80,11 +86,17 @@ void MWList::redraw(bool scrollbarShown)
|
||||||
|
|
||||||
mItemHeight += 18 + spacing;
|
mItemHeight += 18 + spacing;
|
||||||
}
|
}
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
mScrollView->setCanvasSize(mClient->getSize().width + (_scrollBarWidth-scrollBarWidth), std::max(mItemHeight, mClient->getSize().height));
|
mScrollView->setCanvasSize(mClient->getSize().width + (_scrollBarWidth-scrollBarWidth), std::max(mItemHeight, mClient->getSize().height));
|
||||||
|
|
||||||
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
|
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
|
||||||
redraw(true);
|
redraw(true);
|
||||||
|
|
||||||
|
size_t scrollbarRange = mScrollView->getScrollRange();
|
||||||
|
if(scrollbarPosition > scrollbarRange)
|
||||||
|
scrollbarPosition = scrollbarRange;
|
||||||
|
mScrollView->setScrollPosition(scrollbarPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWList::hasItem(const std::string& name)
|
bool MWList::hasItem(const std::string& name)
|
||||||
|
@ -126,8 +138,8 @@ void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel)
|
||||||
void MWList::onItemSelected(MyGUI::Widget* _sender)
|
void MWList::onItemSelected(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
std::string name = static_cast<MyGUI::Button*>(_sender)->getCaption();
|
std::string name = static_cast<MyGUI::Button*>(_sender)->getCaption();
|
||||||
|
int id = *_sender->getUserData<int>();
|
||||||
eventItemSelected(name);
|
eventItemSelected(name, id);
|
||||||
eventWidgetSelected(_sender);
|
eventWidgetSelected(_sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,3 +147,17 @@ MyGUI::Widget* MWList::getItemWidget(const std::string& name)
|
||||||
{
|
{
|
||||||
return mScrollView->findWidget (getName() + "_item_" + name);
|
return mScrollView->findWidget (getName() + "_item_" + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t MWScrollView::getScrollPosition()
|
||||||
|
{
|
||||||
|
return getVScroll()->getScrollPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MWScrollView::setScrollPosition(size_t position)
|
||||||
|
{
|
||||||
|
getVScroll()->setScrollPosition(position);
|
||||||
|
}
|
||||||
|
size_t MWScrollView::getScrollRange()
|
||||||
|
{
|
||||||
|
return getVScroll()->getScrollRange();
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
#ifndef MWGUI_LIST_HPP
|
#ifndef MWGUI_LIST_HPP
|
||||||
#define MWGUI_LIST_HPP
|
#define MWGUI_LIST_HPP
|
||||||
|
|
||||||
#include <MyGUI.h>
|
#include <MyGUI_Widget.h>
|
||||||
|
#include <MyGUI_ScrollView.h>
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
namespace Widgets
|
namespace Widgets
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* \brief a custom ScrollView which has access to scrollbar properties
|
||||||
|
*/
|
||||||
|
class MWScrollView : public MyGUI::ScrollView
|
||||||
|
{
|
||||||
|
MYGUI_RTTI_DERIVED(MWScrollView)
|
||||||
|
public:
|
||||||
|
size_t getScrollPosition();
|
||||||
|
void setScrollPosition(size_t);
|
||||||
|
size_t getScrollRange();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief a very simple list widget that supports word-wrapping entries
|
* \brief a very simple list widget that supports word-wrapping entries
|
||||||
* \note if the width or height of the list changes, you must call adjustSize() method
|
* \note if the width or height of the list changes, you must call adjustSize() method
|
||||||
|
@ -17,14 +30,14 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
MWList();
|
MWList();
|
||||||
|
|
||||||
typedef MyGUI::delegates::CMultiDelegate1<std::string> EventHandle_String;
|
typedef MyGUI::delegates::CMultiDelegate2<const std::string&, int> EventHandle_StringInt;
|
||||||
typedef MyGUI::delegates::CMultiDelegate1<MyGUI::Widget*> EventHandle_Widget;
|
typedef MyGUI::delegates::CMultiDelegate1<MyGUI::Widget*> EventHandle_Widget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event: Item selected with the mouse.
|
* Event: Item selected with the mouse.
|
||||||
* signature: void method(std::string itemName)
|
* signature: void method(std::string itemName)
|
||||||
*/
|
*/
|
||||||
EventHandle_String eventItemSelected;
|
EventHandle_StringInt eventItemSelected;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event: Item selected with the mouse.
|
* Event: Item selected with the mouse.
|
||||||
|
@ -58,7 +71,7 @@ namespace MWGui
|
||||||
void onItemSelected(MyGUI::Widget* _sender);
|
void onItemSelected(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::ScrollView* mScrollView;
|
MWGui::Widgets::MWScrollView* mScrollView;
|
||||||
MyGUI::Widget* mClient;
|
MyGUI::Widget* mClient;
|
||||||
|
|
||||||
std::vector<std::string> mItems;
|
std::vector<std::string> mItems;
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace MWGui
|
||||||
float progress = (float(mCurrentCellLoading)+refProgress) / float(mTotalCellsLoading);
|
float progress = (float(mCurrentCellLoading)+refProgress) / float(mTotalCellsLoading);
|
||||||
assert(progress <= 1 && progress >= 0);
|
assert(progress <= 1 && progress >= 0);
|
||||||
|
|
||||||
mLoadingText->setCaption(stage + "... ");
|
mLoadingText->setCaption(stage);
|
||||||
mProgressBar->setProgressPosition (static_cast<size_t>(progress * 1000));
|
mProgressBar->setProgressPosition (static_cast<size_t>(progress * 1000));
|
||||||
|
|
||||||
static float loadingScreenFps = 30.f;
|
static float loadingScreenFps = 30.f;
|
||||||
|
|
|
@ -19,6 +19,8 @@ namespace MWGui
|
||||||
|
|
||||||
void onResChange(int w, int h);
|
void onResChange(int w, int h);
|
||||||
|
|
||||||
|
void updateWindow(Ogre::RenderWindow* rw) { mWindow = rw; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mFirstLoad;
|
bool mFirstLoad;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <OgreTextureManager.h>
|
#include <OgreTextureManager.h>
|
||||||
#include <OgreSceneNode.h>
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
|
#include <MyGUI_Gui.h>
|
||||||
|
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -13,6 +15,8 @@
|
||||||
|
|
||||||
#include "../mwrender/globalmap.hpp"
|
#include "../mwrender/globalmap.hpp"
|
||||||
|
|
||||||
|
#include "widgets.hpp"
|
||||||
|
|
||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
|
|
||||||
LocalMapBase::LocalMapBase()
|
LocalMapBase::LocalMapBase()
|
||||||
|
@ -96,6 +100,7 @@ void LocalMapBase::applyFogOfWar()
|
||||||
: "");
|
: "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
notifyMapChanged ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||||
|
@ -425,3 +430,17 @@ void MapWindow::notifyPlayerUpdate ()
|
||||||
{
|
{
|
||||||
globalMapUpdatePlayer ();
|
globalMapUpdatePlayer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapWindow::notifyMapChanged ()
|
||||||
|
{
|
||||||
|
// workaround to prevent the map from drawing on top of the button
|
||||||
|
MyGUI::IntCoord oldCoord = mButton->getCoord ();
|
||||||
|
MyGUI::Gui::getInstance().destroyWidget (mButton);
|
||||||
|
mButton = mMainWidget->createWidget<MWGui::Widgets::AutoSizedButton>("MW_Button",
|
||||||
|
oldCoord, MyGUI::Align::Bottom | MyGUI::Align::Right);
|
||||||
|
mButton->setProperty ("ExpandDirection", "Left");
|
||||||
|
|
||||||
|
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
|
||||||
|
mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" :
|
||||||
|
"#{sWorld}");
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue