├── docs ├── requirements.txt ├── images │ ├── main.png │ └── settings.png ├── app │ ├── theme.rst │ ├── installation.rst │ ├── introduction.rst │ ├── contributing.rst │ ├── credits.rst │ └── usage │ │ ├── initialisation.rst │ │ └── settings.rst ├── index.rst └── licenses │ ├── MIT License (Jed).txt │ ├── MIT License (Marked).txt │ ├── MIT License (Jed Gettext Parser).txt │ ├── Boost Software License v1.0.txt │ ├── notice.rst │ ├── texts.rst │ ├── BSD License (Polymer).txt │ └── BSD License (Chromium Embedded Framework).txt ├── src ├── gui │ ├── html │ │ ├── polymer-settings.html │ │ ├── js │ │ │ ├── handlePromiseError.js │ │ │ ├── query.js │ │ │ ├── dialog.js │ │ │ ├── updateExists.js │ │ │ ├── translator.js │ │ │ └── state.js │ │ └── elements │ │ │ ├── loot-menu.html │ │ │ ├── loot-custom-icons.html │ │ │ ├── loot-dropdown-menu.html │ │ │ └── loot-message-dialog.html │ ├── LOOT.exe.manifest │ ├── resource.rc │ ├── resource.h │ ├── state │ │ ├── logging.h │ │ ├── game_detection_error.h │ │ ├── loot_paths.h │ │ ├── loot_state.h │ │ ├── game_settings.h │ │ ├── loot_settings.h │ │ └── loot_paths.cpp │ ├── helpers.h │ ├── version.h │ ├── version.cpp.in │ ├── cef │ │ ├── query │ │ │ ├── types │ │ │ │ ├── editor_opened_query.h │ │ │ │ ├── redate_plugins_query.h │ │ │ │ ├── cancel_find_query.h │ │ │ │ ├── open_readme_query.h │ │ │ │ ├── open_log_location_query.h │ │ │ │ ├── get_init_errors_query.h │ │ │ │ ├── discard_unapplied_changes_query.h │ │ │ │ ├── get_version_query.h │ │ │ │ ├── change_game_query.h │ │ │ │ ├── copy_content_query.h │ │ │ │ ├── apply_sort_query.h │ │ │ │ ├── save_filter_state_query.h │ │ │ │ ├── get_installed_games_query.h │ │ │ │ ├── clear_plugin_metadata_query.h │ │ │ │ ├── get_game_types_query.h │ │ │ │ ├── get_settings_query.h │ │ │ │ ├── update_masterlist_query.h │ │ │ │ ├── cancel_sort_query.h │ │ │ │ ├── close_settings_query.h │ │ │ │ ├── get_languages_query.h │ │ │ │ ├── copy_metadata_query.h │ │ │ │ ├── get_game_data_query.h │ │ │ │ ├── copy_load_order_query.h │ │ │ │ ├── clear_all_metadata_query.h │ │ │ │ ├── clipboard_query.h │ │ │ │ ├── get_conflicting_plugins_query.h │ │ │ │ ├── sort_plugins_query.h │ │ │ │ └── editor_closed_query.h │ │ │ ├── query_handler.h │ │ │ ├── query.h │ │ │ └── derived_plugin_metadata.h │ │ ├── loot_scheme_handler_factory.h │ │ ├── window_delegate.h │ │ ├── loot_app.h │ │ ├── loot_scheme_handler_factory.cpp │ │ ├── loot_handler.h │ │ └── window_delegate.cpp │ └── helpers.cpp └── tests │ ├── gui │ ├── html │ │ ├── js │ │ │ ├── mock_dom.js │ │ │ ├── test_query.js │ │ │ ├── mock_github.js │ │ │ └── test_updateExists.js │ │ └── elements │ │ │ ├── test_loot-menu.html │ │ │ ├── test_loot-plugin-item.html │ │ │ ├── test_loot-custom-icons.html │ │ │ ├── test_loot-plugin-editor.html │ │ │ ├── test_loot-message-dialog.html │ │ │ ├── test_loot-dropdown-menu.html │ │ │ ├── test_editable-table.html │ │ │ ├── test_loot-search-toolbar.html │ │ │ └── test_loot-plugin-card.html │ ├── main.cpp │ └── state │ │ ├── loot_state_test.h │ │ └── loot_paths_test.h │ └── printers.h ├── scripts ├── travis │ └── loot.bintray.json ├── appveyor │ ├── update_masterlist_branches.ps1 │ └── build_installer.ps1 ├── potomo.js ├── get_roboto_files.js ├── create_ico.js ├── git │ └── pre-commit ├── cmake │ └── configure_cef.cmake ├── helpers.js ├── set_version_number.js └── build_ui.js ├── .clang-format ├── .eslintrc.yml ├── .gitattributes ├── .gitignore ├── karma.conf.js ├── package.json ├── bower.json ├── resources └── ui │ └── css │ └── dark-theme.css ├── .travis.yml └── appveyor.yml /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==1.4.9 2 | sphinx_rtd_theme 3 | -------------------------------------------------------------------------------- /docs/images/main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TarekJor/loot/dev/docs/images/main.png -------------------------------------------------------------------------------- /docs/images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TarekJor/loot/dev/docs/images/settings.png -------------------------------------------------------------------------------- /src/gui/html/polymer-settings.html: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /scripts/travis/loot.bintray.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": { 3 | "name": "loot", 4 | "repo": "loot", 5 | "subject": "wrinklyninja" 6 | }, 7 | "version": { 8 | "name": "REPLACE_THIS_VERSION" 9 | }, 10 | "files": [{ 11 | "includePattern": "build/(loot_.+\\.tar.xz)", 12 | "uploadPattern": "$1" 13 | }], 14 | "publish": true 15 | } 16 | -------------------------------------------------------------------------------- /docs/app/theme.rst: -------------------------------------------------------------------------------- 1 | ****** 2 | Themes 3 | ****** 4 | 5 | LOOT's user interface has CSS theming support. A dark theme is provided with LOOT: to use it, rename ``dark-theme.css`` in the ``resources/ui/css`` folder to ``theme.css``. A working knowledge of CSS is required to create new themes, though the provided dark theme CSS file is commented to provide some assistance. 6 | -------------------------------------------------------------------------------- /src/gui/LOOT.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | True/PM 6 | 7 | 8 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Google 4 | 5 | AccessModifierOffset: -2 6 | AllowAllParametersOfDeclarationOnNextLine: false 7 | AllowShortIfStatementsOnASingleLine: false 8 | BinPackArguments: false 9 | BinPackParameters: false 10 | BreakConstructorInitializers: AfterColon 11 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 12 | FixNamespaceComments: false 13 | SpaceAfterTemplateKeyword: false 14 | Standard: Cpp11 15 | ... 16 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | #### 2 | LOOT 3 | #### 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: Application Documentation 8 | 9 | app/introduction 10 | app/installation 11 | app/usage/initialisation 12 | app/usage/main 13 | app/usage/editor 14 | app/usage/settings 15 | app/theme 16 | app/contributing 17 | app/credits 18 | app/changelog 19 | 20 | .. toctree:: 21 | :caption: Copyright Licenses 22 | 23 | licenses/notice.rst 24 | licenses/texts.rst 25 | -------------------------------------------------------------------------------- /src/gui/resource.rc: -------------------------------------------------------------------------------- 1 | #include "gui/resource.h" 2 | 1 VERSIONINFO 3 | FILEVERSION 0, 12, 1, 0 4 | PRODUCTVERSION 0, 12, 1, 0 5 | FILEOS VOS__WINDOWS32 6 | FILETYPE VFT_APP 7 | BEGIN 8 | BLOCK "StringFileInfo" 9 | BEGIN 10 | BLOCK "040904b0" 11 | BEGIN 12 | VALUE "FileVersion", "0.12.1" 13 | VALUE "LegalCopyright", "Copyright (C) 2013-2017 WrinklyNinja" 14 | VALUE "ProductVersion", "0.12.1" 15 | END 16 | END 17 | BLOCK "VarFileInfo" 18 | BEGIN 19 | VALUE "Translation", 0x409, 1200 20 | END 21 | END 22 | MAINICON ICON "../build/icon/icon.ico" 23 | -------------------------------------------------------------------------------- /src/tests/gui/html/js/mock_dom.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Mock the DOM interactions */ 4 | window.loot = window.loot || {}; 5 | 6 | loot.DOM = { 7 | elementShownStates: new Map(), 8 | elementEnabledStates: new Map(), 9 | state: undefined, 10 | 11 | show(elementId, showElement = true) { 12 | this.elementShownStates.set(elementId, showElement); 13 | }, 14 | 15 | enable(elementId, enableElement = true) { 16 | this.elementEnabledStates.set(elementId, enableElement); 17 | }, 18 | 19 | setUIState(state) { 20 | this.state = state; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | parserOptions: 2 | ecmaVersion: 7 3 | sourceType: script 4 | 5 | env: 6 | es6: true 7 | mocha: true 8 | amd: true 9 | node: true 10 | browser: true 11 | 12 | globals: 13 | loot: false 14 | should: false 15 | 16 | extends: 17 | - "eslint:recommended" 18 | - "airbnb-base" 19 | - "prettier" 20 | 21 | rules: 22 | prettier/prettier: error 23 | no-param-reassign: 24 | - error 25 | - props: false 26 | no-underscore-dangle: off 27 | curly: [error, all] 28 | no-confusing-arrow: error 29 | 30 | plugins: 31 | - html 32 | - prettier 33 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_loot-menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_loot-menu.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Note 16 | Warning 17 | Error 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/gui/html/js/handlePromiseError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function exportModule(root, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | // AMD. Register as an anonymous module. 6 | define([], factory); 7 | } else { 8 | // Browser globals 9 | root.loot = root.loot || {}; 10 | root.loot.handlePromiseError = factory(root.loot); 11 | } 12 | })(this, loot => error => { 13 | /* Error.stack seems to be Chromium-specific. */ 14 | console.error(error.stack); // eslint-disable-line no-console 15 | loot.Dialog.closeProgress(); 16 | loot.Dialog.showMessage(loot.l10n.translate('Error'), error.message); 17 | }); 18 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_loot-plugin-item.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_loot-plugin-item.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Skyrim.esm 18 | 19 | -------------------------------------------------------------------------------- /scripts/appveyor/update_masterlist_branches.ps1: -------------------------------------------------------------------------------- 1 | function Get-BranchName() { 2 | $numbers = $env:APPVEYOR_REPO_TAG_NAME.Split('.') 3 | 4 | if ($numbers[0] -eq 0) { 5 | $numbers = $numbers[0..($numbers.length - 2)] 6 | } else { 7 | $numbers = @($numbers[0]) 8 | } 9 | 10 | return "v" + ($numbers -join '.') 11 | } 12 | 13 | if ($env:APPVEYOR_REPO_TAG -eq 'true') { 14 | npm install -g lomad 15 | $branchName = Get-BranchName 16 | 17 | Write-Output "`nUpdating masterlists' default branch to $branchName..." 18 | lomad -t $env:github_auth_token -a -d $branchName 19 | 20 | if ($lastexitcode -eq 0) { 21 | Write-Output "Masterlists' default branches have been updated." 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_loot-custom-icons.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_loot-custom-icons.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /scripts/potomo.js: -------------------------------------------------------------------------------- 1 | /* Convert .po files to .mo files. */ 2 | /* eslint-disable no-console */ 3 | 4 | 'use strict'; 5 | 6 | const fs = require('fs'); 7 | const path = require('path'); 8 | const helpers = require('./helpers'); 9 | 10 | const [, , rootPath = '.'] = process.argv; 11 | 12 | const l10nPath = path.join(rootPath, 'resources', 'l10n'); 13 | fs.readdirSync(l10nPath).forEach(file => { 14 | if (fs.statSync(path.join(l10nPath, file)).isDirectory()) { 15 | try { 16 | const poPath = path.join(l10nPath, file, 'LC_MESSAGES', 'loot.po'); 17 | const moPath = path.join(l10nPath, file, 'LC_MESSAGES', 'loot.mo'); 18 | 19 | fs.accessSync(poPath, fs.R_OK); 20 | 21 | helpers.safeExecFileSync('msgfmt', [poPath, '-o', moPath]); 22 | } catch (error) { 23 | console.error(error); 24 | } 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # Temporary files # 30 | ##################3 31 | *~ 32 | 33 | # OS generated files # 34 | ###################### 35 | .DS_Store 36 | .DS_Store? 37 | ._* 38 | .Spotlight-V100 39 | .Trashes 40 | Icon? 41 | ehthumbs.db 42 | Thumbs.db 43 | 44 | # Other # 45 | ######### 46 | 47 | .vscode/ 48 | *.user 49 | *.suo 50 | *.sdf 51 | *.opensdf 52 | build 53 | *.mo 54 | bower_components 55 | node_modules 56 | *.pb.h 57 | *.pb.cc 58 | -------------------------------------------------------------------------------- /src/tests/gui/html/js/test_query.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('query()', () => { 4 | it('should throw if no arguments are passed', () => { 5 | (() => { 6 | loot.query(); 7 | }).should.throw(); 8 | }); 9 | 10 | it('should return a promise', () => { 11 | loot.query('test').should.be.a('promise'); // eslint-disable-line new-cap 12 | }); 13 | 14 | it('should succeed if a request name is passed', () => 15 | loot 16 | .query('discardUnappliedChanges') 17 | .then(result => result.should.be.empty)); 18 | 19 | it('should succeed if a request name and arguments are passed', () => 20 | loot 21 | .query('copyContent', { messages: {} }) 22 | .then(result => result.should.be.empty)); 23 | 24 | it('should fail with an Error object when an error occurs', () => 25 | loot.query('copyContent').catch(error => error.should.be.an('error'))); 26 | }); 27 | -------------------------------------------------------------------------------- /scripts/get_roboto_files.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs-extra'); 4 | const path = require('path'); 5 | const request = require('request'); 6 | const decompress = require('decompress'); 7 | 8 | function getRobotoFiles(url, destinationPath) { 9 | const extractPath = path.dirname(destinationPath); 10 | const downloadPath = path.join(extractPath, 'roboto-hinted.zip'); 11 | 12 | return new Promise((resolve, reject) => { 13 | request(url) 14 | .pipe(fs.createWriteStream(downloadPath)) 15 | .on('close', err => { 16 | if (err) { 17 | reject(err); 18 | } 19 | resolve(); 20 | }); 21 | }) 22 | .then(() => decompress(downloadPath, extractPath)) 23 | .then(() => { 24 | fs.renameSync(path.join(extractPath, 'roboto-hinted'), destinationPath); 25 | fs.removeSync(downloadPath); 26 | }); 27 | } 28 | 29 | module.exports.getRobotoFiles = getRobotoFiles; 30 | -------------------------------------------------------------------------------- /scripts/create_ico.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const helpers = require('./helpers'); 4 | const fs = require('fs-extra'); 5 | const path = require('path'); 6 | 7 | const svgPath = path.join('resources', 'icon.svg'); 8 | const buildDirectory = path.join('build', 'icon'); 9 | const outputPath = path.join(buildDirectory, 'icon.ico'); 10 | 11 | const svgSize = 192; 12 | const svgDPI = 90; 13 | 14 | const sizes = [16, 20, 24, 30, 32, 36, 40, 48, 60, 64, 72, 80, 96, 128, 256]; 15 | 16 | fs.mkdirsSync(buildDirectory); 17 | 18 | const convertArgs = []; 19 | sizes.forEach(size => { 20 | const pngFile = path.join(buildDirectory, `icon-${size}.png`); 21 | convertArgs.push(pngFile); 22 | 23 | helpers.safeExecFileSync('convert', [ 24 | '-density', 25 | size / svgSize * svgDPI, 26 | '-background', 27 | 'none', 28 | svgPath, 29 | pngFile 30 | ]); 31 | }); 32 | 33 | convertArgs.push(outputPath); 34 | helpers.safeExecFileSync('convert', convertArgs); 35 | -------------------------------------------------------------------------------- /docs/app/installation.rst: -------------------------------------------------------------------------------- 1 | ***************************** 2 | Installation & Uninstallation 3 | ***************************** 4 | 5 | **LOOT requires Windows 7 or later.** 6 | 7 | LOOT can be installed either using its automated installer or manually. If you are using the installer, just run it and follow the wizard steps. If installing manually, extract the downloaded archive to a location of your choice, then download and install the `MSVC 2015 x86 redistributable`_ if you don't already have it installed. 8 | 9 | If LOOT was installed using the installer, then use the uninstaller linked to in the Start Menu to uninstall LOOT. If LOOT was installed manually: 10 | 11 | 1. Delete the files you extracted from the location you chose. 12 | 2. Delete the ``LOOT`` folder in your local application data folder, which can be accessed by entering ``%LOCALAPPDATA%`` into Windows' File Explorer. 13 | 14 | .. _MSVC 2015 x86 redistributable: https://download.microsoft.com/download/6/A/A/6AA4EDFF-645B-48C5-81CC-ED5963AEAD48/vc_redist.x86.exe 15 | -------------------------------------------------------------------------------- /src/gui/resource.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef __LOOT_GUI_RESOURCE__ 26 | #define __LOOT_GUI_RESOURCE__ 27 | 28 | #ifdef _WIN32 29 | #include 30 | 31 | #define MAINICON 101 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /scripts/git/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a Git pre-commit hook. Install it to `.git/hooks`. 3 | # 4 | # Run xgettext to write a new resources/l10n/template.pot, then add it to the 5 | # commit if more than one line in it has changed, otherwise discard any changes 6 | # to it. 7 | 8 | xgettext --keyword="translate:1,1t" --keyword="translate:1,2,3t" --keyword="translateFormatted:1" --add-location=full --from-code=utf-8 --package-name=LOOT --package-version=0.12.1 --copyright-holder="WrinklyNinja" --msgid-bugs-address="https://github.com/loot/loot/issues" -o resources/l10n/template.pot src/gui/html/js/*.* src/gui/*.cpp src/gui/cef/query/*.h src/gui/*/*.cpp 9 | 10 | sed -i 's|charset=CHARSET|charset=UTF-8|' resources/l10n/template.pot 11 | 12 | LINES_ADDED=$(git diff --numstat resources/l10n/template.pot | cut -f 1) 13 | LINES_REMOVED=$(git diff --numstat resources/l10n/template.pot | cut -f 2) 14 | 15 | if [ "$LINES_ADDED" = "$LINES_REMOVED" -a "$LINES_ADDED" = "1" ]; then 16 | git checkout -- resources/l10n/template.pot 17 | else 18 | git add resources/l10n/template.pot 19 | fi 20 | -------------------------------------------------------------------------------- /scripts/cmake/configure_cef.cmake: -------------------------------------------------------------------------------- 1 | # Set CEF_PATH to the path to the root of the CEF folder that contains the 2 | # files to be edited. 3 | 4 | # Remove the "add_subdirectory(cefclient)" and "add_subdirectory(cefsimple)" 5 | # lines from CEF's CMakeLists.txt. 6 | set(CEF_CMAKELISTS_PATH "CMakeLists.txt") 7 | file(READ ${CEF_CMAKELISTS_PATH} CEF_CMAKELISTS) 8 | 9 | string(REPLACE "add_subdirectory(cefclient)" "" CEF_CMAKELISTS ${CEF_CMAKELISTS}) 10 | string(REPLACE "add_subdirectory(cefsimple)" "" CEF_CMAKELISTS ${CEF_CMAKELISTS}) 11 | string(REGEX REPLACE "add_subdirectory\\(tests/.+\\)" "" CEF_CMAKELISTS ${CEF_CMAKELISTS}) 12 | 13 | file(WRITE ${CEF_CMAKELISTS_PATH} ${CEF_CMAKELISTS}) 14 | 15 | message("MSVC_STATIC_RUNTIME: ${MSVC_STATIC_RUNTIME}") 16 | 17 | if (NOT MSVC_STATIC_RUNTIME) 18 | # Replace the "/MT" and "/MTd" linker flags with "/MD" and "/MDd". 19 | set(CEF_VARIABLES_PATH "cmake/cef_variables.cmake") 20 | file(READ ${CEF_VARIABLES_PATH} CEF_VARIABLES) 21 | 22 | string(REPLACE "/MT" "/MD" CEF_VARIABLES ${CEF_VARIABLES}) 23 | 24 | file(WRITE ${CEF_VARIABLES_PATH} ${CEF_VARIABLES}) 25 | endif () 26 | -------------------------------------------------------------------------------- /docs/licenses/MIT License (Jed).txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /docs/licenses/MIT License (Marked).txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /docs/licenses/MIT License (Jed Gettext Parser).txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Oliver Hamlet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/gui/html/elements/loot-menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 16 | 40 | 41 | -------------------------------------------------------------------------------- /scripts/appveyor/build_installer.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = "Stop" 2 | 3 | function DownloadLanguageFile($languageFile, $innoPath) { 4 | $url = 'https://raw.github.com/jrsoftware/issrc/master/Files/Languages/Unofficial/' + $languageFile 5 | $installPath = $innoPath + '\Languages\' + $languageFile 6 | 7 | (New-Object System.Net.WebClient).DownloadFile($url, $installPath) 8 | } 9 | 10 | $innoInstallPath = 'C:\Program Files (x86)\Inno Setup 5' 11 | 12 | # Install the Inno Download Plugin 13 | $url = 'https://bitbucket.org/mitrich_k/inno-download-plugin/downloads/idpsetup-1.5.1.exe' 14 | (New-Object System.Net.WebClient).DownloadFile($url, (pwd).path + '/idpsetup-1.5.1.exe') 15 | 16 | Start-Process ./idpsetup-1.5.1.exe /verysilent -Wait 17 | if (!$?) { 18 | throw 'Failed to install the Inno Download Plugin' 19 | } 20 | 21 | # Also install the unofficial Korean and Simplified Chinese translation 22 | # files for Inno Setup. 23 | DownloadLanguageFile '\Korean.isl' $innoInstallPath 24 | DownloadLanguageFile '\ChineseSimplified.isl' $innoInstallPath 25 | 26 | $env:PATH += ';' + $innoInstallPath 27 | 28 | iscc scripts\installer.iss 29 | if ($LastExitCode -ne 0) { 30 | throw 'Failed to build the LOOT installer' 31 | } 32 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_loot-plugin-editor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_loot-plugin-editor.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

Skyrim.esm

18 | 1.9 19 | ABCDEF01 20 |
21 | 22 | 37 | 38 | -------------------------------------------------------------------------------- /src/gui/state/logging.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2012-2016 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | #ifndef LOOT_GUI_STATE_LOGGING 25 | #define LOOT_GUI_STATE_LOGGING 26 | 27 | #include 28 | 29 | namespace loot { 30 | static const char* LOGGER_NAME = "loot_logger"; 31 | 32 | inline std::shared_ptr getLogger() { 33 | return spdlog::get(LOGGER_NAME); 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/gui/helpers.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | #ifndef LOOT_GUI_HELPERS 25 | #define LOOT_GUI_HELPERS 26 | 27 | #include 28 | 29 | namespace loot { 30 | void OpenInDefaultApplication(const boost::filesystem::path& file); 31 | 32 | #ifdef _WIN32 33 | std::wstring ToWinWide(const std::string& str); 34 | 35 | std::string FromWinWide(const std::wstring& wstr); 36 | #endif 37 | } 38 | #endif 39 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | 'use strict'; 4 | 5 | const helpers = require('./scripts/helpers'); 6 | const path = require('path'); 7 | 8 | process.env.CHROME_BIN = path.join( 9 | helpers.getAppReleasePaths('.')[0].path, 10 | 'LOOT' 11 | ); 12 | console.log( 13 | `Running tests using browser executable at ${process.env.CHROME_BIN}` 14 | ); 15 | 16 | module.exports = config => { 17 | config.set({ 18 | basePath: '', 19 | frameworks: ['mocha', 'chai'], 20 | files: [ 21 | 'bower_components/Jed/jed.js', 22 | 'bower_components/jed-gettext-parser/jedGettextParser.js', 23 | 'bower_components/lodash/dist/lodash.core.min.js', 24 | 'src/tests/gui/html/js/mock_*.js', 25 | 'src/gui/html/js/filters.js', 26 | 'src/gui/html/js/plugin.js', 27 | 'src/gui/html/js/game.js', 28 | 'src/gui/html/js/query.js', 29 | 'src/gui/html/js/state.js', 30 | 'src/gui/html/js/translator.js', 31 | 'src/gui/html/js/updateExists.js', 32 | 'src/tests/gui/html/js/*.js' 33 | ], 34 | exclude: [], 35 | preprocessors: {}, 36 | reporters: ['progress'], 37 | port: 9876, 38 | colors: true, 39 | logLevel: config.LOG_INFO, 40 | autoWatch: false, 41 | browsers: ['Chrome'], 42 | singleRun: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "loot", 3 | "author": "Oliver Hamlet ", 4 | "version": "0.9.1", 5 | "license": "GPL-3.0", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/loot/loot.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/loot/loot/issues" 12 | }, 13 | "homepage": "https://github.com/loot/loot", 14 | "private": true, 15 | "dependencies": { 16 | "decompress": "^4.0.0", 17 | "decompress-unzip": "^4.0.1", 18 | "fs-extra": "^3.0.1", 19 | "github-api": "^3.0.0", 20 | "polymer-analyzer": "^2.1.0", 21 | "replace": "^0.3.0", 22 | "request": "^2.79.0" 23 | }, 24 | "devDependencies": { 25 | "bower": "^1.7.1", 26 | "chai": "^3.5.0", 27 | "eslint": "^4.11.0", 28 | "eslint-config-airbnb-base": "^12.1.0", 29 | "eslint-config-prettier": "^2.8.0", 30 | "eslint-plugin-html": "^4.0.1", 31 | "eslint-plugin-import": "^2.8.0", 32 | "eslint-plugin-prettier": "^2.3.1", 33 | "karma": "^1.3.0", 34 | "karma-chai": "^0.1.0", 35 | "karma-chrome-launcher": "^2.0.0", 36 | "karma-mocha": "^1.3.0", 37 | "mkdirp": "^0.5.1", 38 | "mocha": "^3.0.1", 39 | "prettier": "^1.8.2" 40 | }, 41 | "scripts": { 42 | "test": "karma start" 43 | }, 44 | "prettier": { 45 | "singleQuote": true 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/gui/version.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2017 WrinklyNinja 7 | 8 | This file is part of the LOOT metadata validator. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_VERSION 26 | #define LOOT_GUI_VERSION 27 | 28 | #include 29 | 30 | namespace loot { 31 | namespace gui { 32 | class Version { 33 | public: 34 | static const unsigned int major; 35 | static const unsigned int minor; 36 | static const unsigned int patch; 37 | static const std::string revision; 38 | 39 | static std::string string(); 40 | }; 41 | } 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_loot-message-dialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_loot-message-dialog.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Show Message Box 15 | Show Message Dialog 16 | 17 | 34 | 35 | -------------------------------------------------------------------------------- /src/gui/state/game_detection_error.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2012-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_GAME_DETECTION_ERROR 26 | #define LOOT_GUI_GAME_DETECTION_ERROR 27 | 28 | #include 29 | 30 | namespace loot { 31 | /** 32 | * @brief An exception class thrown if an error occurs when detecting installed 33 | * games. 34 | */ 35 | class GameDetectionError : public std::runtime_error { 36 | public: 37 | using std::runtime_error::runtime_error; 38 | }; 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/gui/version.cpp.in: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2017 WrinklyNinja 7 | 8 | This file is part of the LOOT metadata validator. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #include "gui/version.h" 26 | 27 | namespace loot { 28 | namespace gui { 29 | const unsigned int Version::major = 0; 30 | const unsigned int Version::minor = 12; 31 | const unsigned int Version::patch = 1; 32 | const std::string Version::revision = "@GIT_COMMIT_STRING@"; 33 | 34 | std::string Version::string() { 35 | return std::to_string(major) + '.' + std::to_string(minor) + '.' + std::to_string(patch); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /docs/app/introduction.rst: -------------------------------------------------------------------------------- 1 | ************ 2 | Introduction 3 | ************ 4 | 5 | LOOT is a plugin load order optimiser for TES IV: Oblivion, TES V: Skyrim, TES V: Skyrim Special Edition, Fallout 3, Fallout: New Vegas and Fallout 4. It is designed to assist mod users in avoiding detrimental conflicts, by automatically calculating a load order that satisfies all plugin dependencies and maximises each plugin's impact on the user's game. 6 | 7 | LOOT also provides some load order error checking, including checks for requirements, incompatibilities and cyclic dependencies. In addition, it provides a large number of plugin-specific usage notes, bug warnings and Bash Tag suggestions for Wrye Bash. 8 | 9 | While LOOT is able to calculate correct load order positions for the vast majority of plugins using only their content, it cannot do so for all plugins. As such, LOOT provides a mechanism for supplying additional plugin metadata so that it may sort them correctly. An online *masterlist* is provided to supply metadata for many plugins that need it, while users can make their own metadata additions, which are saved in their *userlist*. 10 | 11 | LOOT is intended to make using mods easier, and mod users should still possess a working knowledge of mod load ordering. See `Introduction To Load Orders`_ for an overview. 12 | 13 | .. _Introduction To Load Orders: https://loot.github.io/docs/help/Introduction-To-Load-Orders 14 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/editor_opened_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_EDITOR_OPENED_QUERY 26 | #define LOOT_GUI_QUERY_EDITOR_OPENED_QUERY 27 | 28 | #include "gui/cef/query/query.h" 29 | #include "gui/state/loot_state.h" 30 | 31 | namespace loot { 32 | class EditorOpenedQuery : public Query { 33 | public: 34 | EditorOpenedQuery(LootState& state) : state_(state) {} 35 | 36 | std::string executeLogic() { 37 | state_.incrementUnappliedChangeCounter(); 38 | return ""; 39 | } 40 | 41 | private: 42 | LootState& state_; 43 | }; 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/redate_plugins_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_REDATE_PLUGINS_QUERY 26 | #define LOOT_GUI_QUERY_REDATE_PLUGINS_QUERY 27 | 28 | #include "gui/cef/query/query.h" 29 | #include "gui/state/loot_state.h" 30 | 31 | namespace loot { 32 | class RedatePluginsQuery : public Query { 33 | public: 34 | RedatePluginsQuery(LootState& state) : state_(state) {} 35 | 36 | std::string executeLogic() { 37 | state_.getCurrentGame().RedatePlugins(); 38 | return ""; 39 | } 40 | 41 | private: 42 | LootState& state_; 43 | }; 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/cancel_find_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_CANCEL_FIND_QUERY 26 | #define LOOT_GUI_QUERY_CANCEL_FIND_QUERY 27 | 28 | #include 29 | 30 | #include "gui/cef/query/query.h" 31 | 32 | namespace loot { 33 | class CancelFindQuery : public Query { 34 | public: 35 | CancelFindQuery(CefRefPtr browser) : browser_(browser) {} 36 | 37 | std::string executeLogic() { 38 | browser_->GetHost()->StopFinding(true); 39 | return ""; 40 | } 41 | 42 | private: 43 | const CefRefPtr browser_; 44 | }; 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /docs/licenses/Boost Software License v1.0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/open_readme_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_OPEN_README_QUERY 26 | #define LOOT_GUI_QUERY_OPEN_README_QUERY 27 | 28 | #include "gui/cef/query/query.h" 29 | #include "gui/helpers.h" 30 | #include "gui/state/loot_paths.h" 31 | 32 | namespace loot { 33 | class OpenReadmeQuery : public Query { 34 | public: 35 | std::string executeLogic() { 36 | auto logger = getLogger(); 37 | if (logger) { 38 | logger->info("Opening LOOT's readme."); 39 | } 40 | OpenInDefaultApplication(LootPaths::getReadmePath()); 41 | 42 | return ""; 43 | } 44 | }; 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/gui/html/js/query.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function exportModule(root, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | // AMD. Register as an anonymous module. 6 | define(['bower_components/lodash/dist/lodash.core.min'], factory); 7 | } else { 8 | // Browser globals 9 | root.loot = root.loot || {}; 10 | root.loot.query = factory(root._); 11 | } 12 | })(this, _ => (requestName, payload) => { 13 | if (!requestName) { 14 | throw new Error('No request name passed'); 15 | } 16 | const request = { 17 | name: requestName 18 | }; 19 | if (payload) { 20 | if (Array.isArray(payload)) { 21 | request.pluginNames = payload; 22 | } else if (_.isString(payload)) { 23 | request.targetName = payload; 24 | } else if (payload.name) { 25 | request.filter = payload; 26 | } else if (payload.messages) { 27 | request.content = payload; 28 | } else if ( 29 | Object.prototype.hasOwnProperty.call(payload, 'enableDebugLogging') 30 | ) { 31 | request.settings = payload; 32 | } else if (payload.metadata) { 33 | request.editorState = payload; 34 | } 35 | } 36 | 37 | return new Promise((resolve, reject) => { 38 | window.cefQuery({ 39 | request: JSON.stringify(request), 40 | persistent: false, 41 | onSuccess: resolve, 42 | onFailure: (errorCode, errorMessage) => { 43 | reject(new Error(errorMessage)); 44 | } 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/open_log_location_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_OPEN_LOG_LOCATION_QUERY 26 | #define LOOT_GUI_QUERY_OPEN_LOG_LOCATION_QUERY 27 | 28 | #include "gui/cef/query/query.h" 29 | #include "gui/helpers.h" 30 | #include "gui/state/loot_paths.h" 31 | 32 | namespace loot { 33 | class OpenLogLocationQuery : public Query { 34 | public: 35 | std::string executeLogic() { 36 | auto logger = getLogger(); 37 | if (logger) { 38 | logger->info("Opening LOOT's local appdata folder."); 39 | } 40 | OpenInDefaultApplication(LootPaths::getLogPath().parent_path()); 41 | 42 | return ""; 43 | } 44 | }; 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_loot-dropdown-menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_loot-dropdown-menu.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | A dropdown: 16 | 17 | Note 18 | Warning 19 | Error 20 | 21 | 22 | 23 | 1 24 | 2 25 | 3 26 | 27 |
28 | 29 |
30 | 31 | 1 32 | 2 33 | 3 34 | 35 | 36 | 37 | 1 38 | 2 39 | 3 40 | 41 |
42 | 43 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/get_init_errors_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_GET_INIT_ERRORS_QUERY 26 | #define LOOT_GUI_QUERY_GET_INIT_ERRORS_QUERY 27 | 28 | #undef min 29 | 30 | #include 31 | 32 | #include "gui/cef/query/query.h" 33 | #include "gui/state/loot_state.h" 34 | 35 | namespace loot { 36 | class GetInitErrorsQuery : public Query { 37 | public: 38 | GetInitErrorsQuery(LootState& state) : state_(state) {} 39 | 40 | std::string executeLogic() { 41 | nlohmann::json json; 42 | json["errors"] = state_.getInitErrors(); 43 | 44 | return json.dump(); 45 | } 46 | 47 | private: 48 | LootState& state_; 49 | }; 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/discard_unapplied_changes_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_DISCARD_UNAPPLIED_CHANGES_QUERY 26 | #define LOOT_GUI_QUERY_DISCARD_UNAPPLIED_CHANGES_QUERY 27 | 28 | #include "gui/cef/query/query.h" 29 | #include "gui/state/loot_state.h" 30 | 31 | namespace loot { 32 | class DiscardUnappliedChangesQuery : public Query { 33 | public: 34 | DiscardUnappliedChangesQuery(LootState& state) : state_(state) {} 35 | 36 | std::string executeLogic() { 37 | while (state_.hasUnappliedChanges()) 38 | state_.decrementUnappliedChangeCounter(); 39 | 40 | return ""; 41 | } 42 | 43 | private: 44 | LootState& state_; 45 | }; 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/get_version_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_GET_VERSION_QUERY 26 | #define LOOT_GUI_QUERY_GET_VERSION_QUERY 27 | 28 | #undef min 29 | 30 | #include 31 | 32 | #include "gui/cef/query/query.h" 33 | #include "gui/version.h" 34 | 35 | namespace loot { 36 | class GetVersionQuery : public Query { 37 | public: 38 | std::string executeLogic() { 39 | auto logger = getLogger(); 40 | if (logger) { 41 | logger->info("Getting LOOT's version."); 42 | } 43 | 44 | nlohmann::json json = { 45 | { "release", gui::Version::string() }, 46 | { "build", gui::Version::revision }, 47 | }; 48 | 49 | return json.dump(); 50 | } 51 | }; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /docs/licenses/notice.rst: -------------------------------------------------------------------------------- 1 | **************** 2 | Copyright Notice 3 | **************** 4 | 5 | LOOT and its API are distributed under the GNU General Public License v3.0. The documentation is distributed under the GNU Free Documentation License v1.3. The full texts of both licenses are included in :doc:`../licenses/texts`. 6 | 7 | While the GPL license allows anyone to make derivative works of LOOT, the LOOT Team encourages those thinking of doing so to first discuss their reasoning for such an endeavour with the Team. It may be that what the derivative work would do differently is already planned for a future version of LOOT or would be happily integrated into LOOT, thus avoiding any extra effort by others. 8 | 9 | LOOT has been specifically designed to prevent it being locked into the LOOT Team's official masterlist repositories. Nevertheless, the LOOT Team appeals to the community to avoid the distribution of unofficial masterlists, as this would only hamper the effort to create one set of stores for load order information. Any issues with a masterlist are best brought to the attention of the LOOT Team so that they may be remedied. 10 | 11 | GNU Free Documentation License Version 1.3 Notice: 12 | 13 | Copyright (C) 2012—2017 WrinklyNinja 14 | 15 | Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. 16 | 17 | A copy of the license is included in :doc:`../licenses/texts`. 18 | -------------------------------------------------------------------------------- /src/tests/gui/html/js/mock_github.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable class-methods-use-this */ 2 | 3 | 'use strict'; 4 | 5 | /* Mock the GitHub library methods used. */ 6 | class Repo { 7 | getRelease(/* latest */) { 8 | return Promise.resolve({ 9 | data: { 10 | tag_name: '0.9.2' 11 | } 12 | }); 13 | } 14 | 15 | listTags() { 16 | return Promise.resolve({ 17 | data: [ 18 | { 19 | name: '0.9.2', 20 | commit: { 21 | sha: '6b58f92a5d41f5d7f149a1263dac78687a065ff5' 22 | } 23 | }, 24 | { 25 | name: '0.9.1', 26 | commit: { 27 | sha: 'dc24e10a4774903ede4e94165e7d6fa806466e4a' 28 | } 29 | }, 30 | { 31 | name: '0.9.0', 32 | commit: { 33 | sha: '44a0d8505d5402dd24cf0fda9540da9557866c80' 34 | } 35 | } 36 | ] 37 | }); 38 | } 39 | 40 | getCommit(/* sha */) { 41 | return Promise.resolve({ 42 | data: { 43 | committer: { 44 | date: '2011-04-14T16:00:49Z' 45 | } 46 | } 47 | }); 48 | } 49 | 50 | getSingleCommit(ref) { 51 | return Promise.resolve({ 52 | data: { 53 | commit: { 54 | committer: { 55 | date: 56 | ref === 'deadbeef' 57 | ? '2011-04-14T16:00:00Z' 58 | : '2011-04-14T16:00:49Z' 59 | } 60 | } 61 | } 62 | }); 63 | } 64 | } 65 | 66 | class GitHub { 67 | getRepo(/* owner, repo */) { 68 | return new Repo(); 69 | } 70 | } 71 | 72 | window.GitHub = GitHub; 73 | -------------------------------------------------------------------------------- /src/gui/html/elements/loot-custom-icons.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/licenses/texts.rst: -------------------------------------------------------------------------------- 1 | *********************** 2 | Copyright License Texts 3 | *********************** 4 | 5 | .. contents:: 6 | 7 | `Boost`_ 8 | ======== 9 | 10 | .. _Boost: http://www.boost.org/ 11 | 12 | .. include:: Boost Software License v1.0.txt 13 | :literal: 14 | 15 | `Chromium Embedded Framework`_ 16 | ============================== 17 | 18 | .. _Chromium Embedded Framework: https://bitbucket.org/chromiumembedded/cef 19 | 20 | .. include:: BSD License (Chromium Embedded Framework).txt 21 | :literal: 22 | 23 | `Jed`_ 24 | ====== 25 | 26 | .. _Jed: https://github.com/SlexAxton/Jed 27 | 28 | .. include:: MIT License (Jed).txt 29 | :literal: 30 | 31 | `Jed Gettext Parser`_ 32 | ===================== 33 | 34 | .. _Jed Gettext Parser: https://github.com/WrinklyNinja/jed-gettext-parser 35 | 36 | .. include:: MIT License (Jed Gettext Parser).txt 37 | :literal: 38 | 39 | LOOT, `LOOT API`_, `Libespm`_ & `Libloadorder`_ 40 | =============================================== 41 | 42 | .. _LOOT API: https://github.com/loot/loot-api 43 | .. _libespm: https://github.com/WrinklyNinja/libespm 44 | .. _libloadorder: https://github.com/WrinklyNinja/libloadorder 45 | 46 | .. include:: GNU GPL v3.txt 47 | :literal: 48 | 49 | LOOT Documentation 50 | ================== 51 | 52 | .. include:: GNU FDL v1.3.txt 53 | :literal: 54 | 55 | `Marked`_ 56 | ========= 57 | 58 | .. _Marked: https://github.com/chjj/marked 59 | 60 | .. include:: MIT License (Marked).txt 61 | :literal: 62 | 63 | `Polymer`_ 64 | ========== 65 | 66 | .. _Polymer: https://www.polymer-project.org/ 67 | 68 | .. include:: BSD License (Polymer).txt 69 | :literal: 70 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/change_game_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_CHANGE_GAME_QUERY 26 | #define LOOT_GUI_QUERY_CHANGE_GAME_QUERY 27 | 28 | #include "gui/cef/query/types/get_game_data_query.h" 29 | 30 | namespace loot { 31 | class ChangeGameQuery : public GetGameDataQuery { 32 | public: 33 | ChangeGameQuery(LootState& state, 34 | CefRefPtr frame, 35 | const std::string& gameFolder) : 36 | GetGameDataQuery(state, frame), 37 | state_(state), 38 | gameFolder_(gameFolder) {} 39 | 40 | std::string executeLogic() { 41 | state_.changeGame(gameFolder_); 42 | 43 | return GetGameDataQuery::executeLogic(); 44 | } 45 | 46 | private: 47 | LootState& state_; 48 | const std::string gameFolder_; 49 | }; 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /docs/app/contributing.rst: -------------------------------------------------------------------------------- 1 | ********************** 2 | Contributing & Support 3 | ********************** 4 | 5 | LOOT is very much a community project, and contributions from its users are very welcome, whether they be metadata, translations, code or anything else. The best way to contribute is to `make changes yourself`_ at GitHub! It's the fastest way to get changes you want applied, and you'll get your name automatically immortalised in our `credits`_. 6 | 7 | If you encounter an issue with LOOT, check the `Frequently Asked Questions`_ page in case a solution is available there. 8 | Otherwise, general discussion and support takes place in LOOT's official forum thread, which is linked to on `LOOT's homepage`_. 9 | 10 | If you want to submit metadata, the easiest way to do so is to add the metadata to your own LOOT install, then use the Copy Metadata feature to easily get it in a form that you can then edit into a masterlist on GitHub or post in the official forum threads. 11 | 12 | Information on dirty plugins is very welcome, but for such information to be useful we require at least the filename and the CRC of the dirty plugin. The CRC may be calculated using Wrye Bash or 7-Zip, with other sources being unverified as correct. In the case of 7-Zip, the "CRC checksum for data" is the one required. Any other information, such as the ITM record and deleted reference counts, is very welcome. 13 | 14 | .. _make changes yourself: https://loot.github.io/docs/contributing/How-To-Contribute 15 | .. _credits: https://loot.github.io/credits/ 16 | .. _Frequently Asked Questions: https://loot.github.io/docs/help/LOOT-FAQs 17 | .. _LOOT's homepage: https://loot.github.io/ 18 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/copy_content_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_COPY_CONTENT_QUERY 26 | #define LOOT_GUI_QUERY_COPY_CONTENT_QUERY 27 | 28 | #undef min 29 | 30 | #include 31 | 32 | #include "gui/cef/query/types/clipboard_query.h" 33 | 34 | namespace loot { 35 | class CopyContentQuery : public ClipboardQuery { 36 | public: 37 | CopyContentQuery(const nlohmann::json& content) : content_(content) {} 38 | 39 | std::string executeLogic() { 40 | const std::string text = 41 | "[spoiler][code]" + getContentAsText() + "[/code][/spoiler]"; 42 | 43 | copyToClipboard(text); 44 | return ""; 45 | } 46 | 47 | private: 48 | std::string getContentAsText() const { 49 | return content_.dump(4); 50 | } 51 | 52 | const nlohmann::json content_; 53 | }; 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/gui/cef/loot_scheme_handler_factory.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_LOOT_SCHEME_HANDLER_FACTORY 26 | #define LOOT_GUI_LOOT_SCHEME_HANDLER_FACTORY 27 | 28 | #include 29 | #include 30 | 31 | namespace loot { 32 | class LootSchemeHandlerFactory : public CefSchemeHandlerFactory { 33 | public: 34 | virtual CefRefPtr Create( 35 | CefRefPtr browser, 36 | CefRefPtr frame, 37 | const CefString& scheme_name, 38 | CefRefPtr request) OVERRIDE; 39 | 40 | private: 41 | std::string GetPath(const CefString& url) const; 42 | std::string GetMimeType(const std::string& file) const; 43 | CefResponse::HeaderMap GetHeaders() const; 44 | 45 | IMPLEMENT_REFCOUNTING(LootSchemeHandlerFactory); 46 | }; 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /docs/licenses/BSD License (Polymer).txt: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 The Polymer Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/apply_sort_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_APPLY_SORT_QUERY 26 | #define LOOT_GUI_QUERY_APPLY_SORT_QUERY 27 | 28 | #include "gui/cef/query/query.h" 29 | 30 | namespace loot { 31 | class ApplySortQuery : public Query { 32 | public: 33 | ApplySortQuery(LootState& state, const std::vector& plugins) : 34 | state_(state), 35 | plugins_(plugins) {} 36 | 37 | std::string executeLogic() { 38 | auto logger = state_.getLogger(); 39 | if (logger) { 40 | logger->trace("User has accepted sorted load order, applying it."); 41 | } 42 | state_.decrementUnappliedChangeCounter(); 43 | state_.getCurrentGame().SetLoadOrder(plugins_); 44 | 45 | return ""; 46 | } 47 | 48 | private: 49 | LootState& state_; 50 | const std::vector plugins_; 51 | }; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/tests/gui/main.cpp: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #include 26 | 27 | #include "tests/gui/state/game_settings_test.h" 28 | #include "tests/gui/state/game_test.h" 29 | #include "tests/gui/state/loot_paths_test.h" 30 | #include "tests/gui/state/loot_settings_test.h" 31 | #include "tests/gui/state/loot_state_test.h" 32 | 33 | int main(int argc, char **argv) { 34 | // Set the locale to get encoding conversions working correctly. 35 | std::locale::global(boost::locale::generator().generate("")); 36 | boost::filesystem::path::imbue(std::locale()); 37 | loot::InitialiseLocale(""); 38 | 39 | // Disable logging or else stdout will get overrun. 40 | loot::SetLoggingCallback([&](loot::LogLevel level, const char *message) {}); 41 | 42 | ::testing::InitGoogleTest(&argc, argv); 43 | return RUN_ALL_TESTS(); 44 | } 45 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LOOT", 3 | "private": true, 4 | "ignore": [ 5 | "**/.*", 6 | "node_modules", 7 | "bower_components" 8 | ], 9 | "dependencies": { 10 | "polymer": "Polymer/polymer#2.0.1", 11 | "app-layout": "PolymerElements/app-layout#2.0.0", 12 | "iron-icons": "PolymerElements/iron-icons#2.0.1", 13 | "iron-list": "PolymerElements/iron-list#2.0.8", 14 | "iron-pages": "PolymerElements/iron-pages#2.0.0", 15 | "neon-animation": "PolymerElements/neon-animation#2.0.1", 16 | "paper-autocomplete": "ellipticaljs/paper-autocomplete#3.0.0", 17 | "paper-button": "PolymerElements/paper-button#2.0.0", 18 | "paper-checkbox": "PolymerElements/paper-checkbox#2.0.0", 19 | "paper-dialog": "PolymerElements/paper-dialog#2.0.0", 20 | "paper-dialog-scrollable": "PolymerElements/paper-dialog-scrollable#2.1.0", 21 | "paper-dropdown-menu": "PolymerElements/paper-dropdown-menu#2.0.0", 22 | "paper-icon-button": "PolymerElements/paper-icon-button#2.0.0", 23 | "paper-input": "PolymerElements/paper-input#2.0.1", 24 | "paper-item": "PolymerElements/paper-item#2.0.0", 25 | "paper-listbox": "PolymerElements/paper-listbox#2.0.0", 26 | "paper-menu-button": "PolymerElements/paper-menu-button#2.0.0", 27 | "paper-progress": "PolymerElements/paper-progress#2.0.1", 28 | "paper-tabs": "PolymerElements/paper-tabs#2.0.0", 29 | "paper-toast": "PolymerElements/paper-toast#2.0.0", 30 | "paper-toggle-button": "PolymerElements/paper-toggle-button#2.0.0", 31 | "paper-tooltip": "PolymerElements/paper-tooltip#2.0.0", 32 | "webcomponentsjs": "1.0.5", 33 | "Jed": "SlexAxton/Jed#1.1.1", 34 | "jed-gettext-parser": "1.0.0", 35 | "marked": "0.3.6", 36 | "lodash": "4.17.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/save_filter_state_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_SAVE_FILTER_STATE_QUERY 26 | #define LOOT_GUI_QUERY_SAVE_FILTER_STATE_QUERY 27 | 28 | #include "gui/cef/query/query.h" 29 | #include "gui/state/loot_state.h" 30 | 31 | namespace loot { 32 | class SaveFilterStateQuery : public Query { 33 | public: 34 | SaveFilterStateQuery(LootState& state, 35 | const std::string& filterId, 36 | bool enabled) : 37 | state_(state), 38 | filterId_(filterId), 39 | enabled_(enabled) {} 40 | 41 | std::string executeLogic() { 42 | auto logger = state_.getLogger(); 43 | if (logger) { 44 | logger->trace("Saving filter states."); 45 | } 46 | state_.storeFilterState(filterId_, enabled_); 47 | return ""; 48 | } 49 | 50 | private: 51 | LootState& state_; 52 | std::string filterId_; 53 | bool enabled_; 54 | }; 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/get_installed_games_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_GET_INSTALLED_GAMES_QUERY 26 | #define LOOT_GUI_QUERY_GET_INSTALLED_GAMES_QUERY 27 | 28 | #undef min 29 | 30 | #include 31 | 32 | #include "gui/cef/query/query.h" 33 | #include "gui/state/loot_state.h" 34 | 35 | namespace loot { 36 | class GetInstalledGamesQuery : public Query { 37 | public: 38 | GetInstalledGamesQuery(LootState& state) : state_(state) {} 39 | 40 | std::string executeLogic() { 41 | auto logger = state_.getLogger(); 42 | if (logger) { 43 | logger->info("Getting LOOT's detected games."); 44 | } 45 | return getInstalledGamesAsJson(); 46 | } 47 | 48 | private: 49 | std::string getInstalledGamesAsJson() const { 50 | nlohmann::json json; 51 | json["installedGames"] = state_.getInstalledGames(); 52 | 53 | return json.dump(); 54 | } 55 | 56 | LootState& state_; 57 | }; 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /docs/licenses/BSD License (Chromium Embedded Framework).txt: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008-2013 Marshall A. Greenblatt. Portions Copyright (c) 2 | // 2006-2009 Google Inc. All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the name Chromium Embedded 15 | // Framework nor the names of its contributors may be used to endorse 16 | // or promote products derived from this software without specific prior 17 | // written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /scripts/helpers.js: -------------------------------------------------------------------------------- 1 | // Helper functions shared across scripts. 2 | 3 | 'use strict'; 4 | 5 | const childProcess = require('child_process'); 6 | const path = require('path'); 7 | const fs = require('fs'); 8 | const os = require('os'); 9 | 10 | function fileExists(filePath) { 11 | try { 12 | // Query the entry 13 | const stats = fs.lstatSync(filePath); 14 | 15 | // Is it a directory? 16 | if (stats.isFile()) { 17 | return true; 18 | } 19 | } catch (e) { 20 | /* Don't do anything, it's not an error. */ 21 | } 22 | 23 | return false; 24 | } 25 | 26 | function getBinaryParentPaths(rootPath) { 27 | const paths = [ 28 | { 29 | path: path.join(rootPath, 'build'), 30 | label: null 31 | }, 32 | { 33 | path: path.join(rootPath, 'build', '32'), 34 | label: '32-bit' 35 | }, 36 | { 37 | path: path.join(rootPath, 'build', '64'), 38 | label: '64-bit' 39 | } 40 | ]; 41 | 42 | if (os.platform() === 'win32') { 43 | paths.forEach(parentPath => { 44 | parentPath.path = path.join(parentPath.path, 'Release'); 45 | }); 46 | } 47 | 48 | return paths; 49 | } 50 | 51 | function getAppReleasePaths(rootPath) { 52 | let file = 'LOOT'; 53 | if (os.platform() === 'win32') { 54 | file += '.exe'; 55 | } 56 | 57 | return getBinaryParentPaths(rootPath).filter(parentPath => 58 | fileExists(path.join(parentPath.path, file)) 59 | ); 60 | } 61 | 62 | function safeExecFileSync(file, args, options) { 63 | try { 64 | return childProcess.execFileSync(file, args, options); 65 | } catch (error) { 66 | throw new Error(error.message); 67 | } 68 | } 69 | 70 | module.exports.fileExists = fileExists; 71 | module.exports.getAppReleasePaths = getAppReleasePaths; 72 | module.exports.safeExecFileSync = safeExecFileSync; 73 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/clear_plugin_metadata_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_CLEAR_PLUGIN_METADATA_QUERY 26 | #define LOOT_GUI_QUERY_CLEAR_PLUGIN_METADATA_QUERY 27 | 28 | #include "gui/cef/query/types/metadata_query.h" 29 | #include "gui/state/game.h" 30 | 31 | namespace loot { 32 | class ClearPluginMetadataQuery : public MetadataQuery { 33 | public: 34 | ClearPluginMetadataQuery(LootState& state, const std::string& pluginName) : 35 | MetadataQuery(state), 36 | game_(state.getCurrentGame()), 37 | pluginName_(pluginName) {} 38 | 39 | std::string executeLogic() { 40 | auto logger = getLogger(); 41 | if (logger) { 42 | logger->debug("Clearing user metadata for plugin {}", pluginName_); 43 | } 44 | 45 | game_.ClearUserMetadata(pluginName_); 46 | game_.SaveUserMetadata(); 47 | 48 | return generateJsonResponse(pluginName_); 49 | } 50 | 51 | private: 52 | gui::Game& game_; 53 | const std::string pluginName_; 54 | }; 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/gui/html/js/dialog.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function exportModule(root, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | // AMD. Register as an anonymous module. 6 | define([], factory); 7 | } else { 8 | // Browser globals 9 | root.loot = root.loot || {}; 10 | root.loot.Dialog = factory(); 11 | } 12 | })( 13 | this, 14 | () => 15 | class { 16 | static showProgress(text) { 17 | const progressDialog = document.getElementById('progressDialog'); 18 | progressDialog.getElementsByTagName('p')[0].textContent = text; 19 | if (!progressDialog.opened) { 20 | progressDialog.open(); 21 | } else { 22 | progressDialog.refit(); 23 | } 24 | } 25 | 26 | static closeProgress() { 27 | const progressDialog = document.getElementById('progressDialog'); 28 | if (progressDialog.opened) { 29 | progressDialog.refit(); 30 | progressDialog.close(); 31 | } 32 | } 33 | 34 | static showMessage(title, text) { 35 | const dialog = document.createElement('loot-message-dialog'); 36 | document.body.appendChild(dialog); 37 | dialog.setDismissable(false); 38 | dialog.showModal(title, text); 39 | } 40 | 41 | static askQuestion(title, text, confirmText, closeCallback) { 42 | const dialog = document.createElement('loot-message-dialog'); 43 | document.body.appendChild(dialog); 44 | dialog.setConfirmText(confirmText); 45 | dialog.showModal(title, text, closeCallback); 46 | } 47 | 48 | static showNotification(text) { 49 | const toast = document.getElementById('toast'); 50 | if (toast.opened) { 51 | toast.hide(); 52 | } 53 | toast.show(text); 54 | } 55 | } 56 | ); 57 | -------------------------------------------------------------------------------- /docs/app/credits.rst: -------------------------------------------------------------------------------- 1 | ******* 2 | Credits 3 | ******* 4 | 5 | LOOT is developed on `GitHub`_, and a full list of GitHub contributors may be found `here`_. 6 | 7 | LOOT's masterlists were largely converted from `BOSS`_'s masterlists, and so credit is due to the very large number of sources and people who have contributed to them. 8 | 9 | In addition, the following are credited with application-related support: 10 | 11 | * Original icon: jonwd7 12 | * Translations: 13 | 14 | * Brazilian Portuguese: Kassane 15 | * Chinese: bluesky404 16 | * Danish: Freso 17 | * Finnish: 3ventic 18 | * French: Kaos 19 | * German: lpradel 20 | * Korean: SteamB23 21 | * Polish: Łukasz Niemczyk 22 | * Russian: Tokc.D.K. 23 | * Spanish: Sharlikran 24 | * Swedish: Mikael Hiort af Ornäs 25 | 26 | * Beta testing: Too many to list, thank you all! 27 | 28 | LOOT is written in C/C++, HTML5, CSS3 and JavaScript, and uses the `Boost`_, `Jed`_, `Jed Gettext Parser`_, `libespm`_, `libgit2`_, `libloadorder`_, `Marked`_, `pseudosem`_, `Polymer`_ and `yaml-cpp`_ libraries, and the `Chromium Embedded Framework`_. 29 | 30 | .. _GitHub: https://github.com/loot/ 31 | .. _here: https://loot.github.io/credits/ 32 | .. _BOSS: https://boss-developers.github.io/ 33 | .. _Boost: http://www.boost.org/ 34 | .. _Jed: https://github.com/SlexAxton/Jed 35 | .. _Jed Gettext Parser: https://github.com/WrinklyNinja/jed-gettext-parser 36 | .. _libespm: https://github.com/WrinklyNinja/libespm 37 | .. _libgit2: https://github.com/libgit2/libgit2 38 | .. _libloadorder: https://github.com/WrinklyNinja/libloadorder 39 | .. _Marked: https://github.com/chjj/marked 40 | .. _pseudosem: https://github.com/WrinklyNinja/pseudosem 41 | .. _Polymer: https://www.polymer-project.org/ 42 | .. _yaml-cpp: https://github.com/loot/yaml-cpp 43 | .. _Chromium Embedded Framework: https://bitbucket.org/chromiumembedded/cef 44 | -------------------------------------------------------------------------------- /src/gui/state/loot_paths.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_STATE_LOOT_PATHS 26 | #define LOOT_GUI_STATE_LOOT_PATHS 27 | 28 | #include 29 | 30 | namespace loot { 31 | class LootPaths { 32 | public: 33 | static boost::filesystem::path getReadmePath(); 34 | static boost::filesystem::path getResourcesPath(); 35 | static boost::filesystem::path getL10nPath(); 36 | static boost::filesystem::path getLootDataPath(); 37 | static boost::filesystem::path getSettingsPath(); 38 | static boost::filesystem::path getLogPath(); 39 | 40 | // Sets the app path to the current path, and the data path to the given 41 | // path or (if it is an empty string), local app data path / "LOOT". 42 | static void initialise(const std::string& lootDataPath); 43 | 44 | private: 45 | // Get the local application data path. 46 | static boost::filesystem::path getLocalAppDataPath(); 47 | 48 | static boost::filesystem::path lootAppPath_; 49 | static boost::filesystem::path lootDataPath_; 50 | }; 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_editable-table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_editable-table.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
FilenameDisplay NameCondition
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
TypeContentConditionLanguage
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
Add/RemoveBash TagCondition
41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
CRCITM CountDeleted ReferencesDeleted NavmeshesCleaning Utility
51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
URLName
61 |
62 | 63 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/get_game_types_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_GET_GAME_TYPES_QUERY 26 | #define LOOT_GUI_QUERY_GET_GAME_TYPES_QUERY 27 | 28 | #undef min 29 | 30 | #include 31 | 32 | #include "gui/cef/query/query.h" 33 | #include "gui/state/game_settings.h" 34 | 35 | namespace loot { 36 | class GetGameTypesQuery : public Query { 37 | public: 38 | std::string executeLogic() { 39 | auto logger = getLogger(); 40 | if (logger) { 41 | logger->info("Getting LOOT's supported game types."); 42 | } 43 | return getGameTypesAsJson(); 44 | } 45 | 46 | private: 47 | static std::string getGameTypesAsJson() { 48 | nlohmann::json json; 49 | 50 | json["gameTypes"] = { 51 | GameSettings(GameType::tes4).FolderName(), 52 | GameSettings(GameType::tes5).FolderName(), 53 | GameSettings(GameType::tes5se).FolderName(), 54 | GameSettings(GameType::fo3).FolderName(), 55 | GameSettings(GameType::fonv).FolderName(), 56 | GameSettings(GameType::fo4).FolderName(), 57 | }; 58 | 59 | return json.dump(); 60 | } 61 | }; 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/gui/cef/query/query_handler.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_HANDLER 26 | #define LOOT_GUI_QUERY_HANDLER 27 | 28 | #include 29 | 30 | #include "gui/cef/query/query.h" 31 | #include "gui/state/loot_state.h" 32 | 33 | namespace loot { 34 | class QueryHandler : public CefMessageRouterBrowserSide::Handler { 35 | public: 36 | QueryHandler(LootState& lootState); 37 | 38 | // Called due to cefQuery execution in binding.html. 39 | virtual bool OnQuery(CefRefPtr browser, 40 | CefRefPtr frame, 41 | int64 query_id, 42 | const CefString& request, 43 | bool persistent, 44 | CefRefPtr callback) OVERRIDE; 45 | 46 | private: 47 | CefRefPtr createQuery(CefRefPtr browser, 48 | CefRefPtr frame, 49 | const std::string& request); 50 | 51 | LootState& lootState_; 52 | }; 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /resources/ui/css/dark-theme.css: -------------------------------------------------------------------------------- 1 | /* Dark theme CSS overrides. */ 2 | 3 | /* CSS Custom Variables */ 4 | :root { 5 | /* --primary-color is used for the main toolbar background, floating input 6 | labels and dialog buttons. */ 7 | --primary-color: var(--paper-blue-600); 8 | 9 | /* --light-primary-color is used for the editor toolbar background. */ 10 | --light-primary-color: var(--paper-grey-900); 11 | 12 | /* --accent-color is used for underlines and ripples */ 13 | --accent-color: var(--paper-blue-600); 14 | 15 | /* --dark-accent-color is used for links, the Apply sorting button, and the 16 | Save editor icon button. */ 17 | --dark-accent-color: var(--paper-blue-500); 18 | 19 | /* --primary-background-color is use for sidebar, dialog and card backgrounds. */ 20 | --primary-background-color: var(--paper-grey-800); 21 | --primary-text-color: var(--dark-theme-text-color); 22 | --secondary-text-color: var(--dark-theme-secondary-color); 23 | --disabled-text-color: var(--dark-theme-disabled-color); 24 | --divider-color: var(--dark-theme-divider-color); 25 | 26 | /* --app-toolbar-background can be used to override the --primary-color defined 27 | above for the main toolbar. */ 28 | --app-toolbar-background: var(--paper-grey-900); 29 | 30 | /* --secondary-background-color is used for the progress bar background and 31 | the background behind cards. */ 32 | --secondary-background-color: #303030; 33 | --paper-progress-container-color: var(--secondary-background-color); 34 | 35 | /* --loot-plugin-item-index-border-color is used to control the colour of the 36 | border around load order indices in the sidebar. */ 37 | --loot-plugin-item-index-border-color: var(--paper-color-300); 38 | } 39 | 40 | #main { 41 | background: var(--secondary-background-color); 42 | } 43 | 44 | li.error > p, 45 | li.warn > p { 46 | color: black; 47 | } 48 | 49 | .version { 50 | color: #78909C; 51 | } 52 | 53 | .crc { 54 | color: #8D6E63; 55 | } 56 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/get_settings_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_GET_SETTINGS_QUERY 26 | #define LOOT_GUI_QUERY_GET_SETTINGS_QUERY 27 | 28 | #undef min 29 | 30 | #include 31 | 32 | #include "gui/cef/query/query.h" 33 | #include "gui/state/loot_settings.h" 34 | 35 | namespace loot { 36 | class GetSettingsQuery : public Query { 37 | public: 38 | GetSettingsQuery(LootSettings& settings) : settings_(settings) {} 39 | 40 | std::string executeLogic() { 41 | auto logger = getLogger(); 42 | if (logger) { 43 | logger->info("Getting LOOT's settings."); 44 | } 45 | 46 | nlohmann::json json = { 47 | { "game", settings_.getGame() }, 48 | { "lastVersion", settings_.getLastVersion() }, 49 | { "language", settings_.getLanguage() }, 50 | { "enableDebugLogging", settings_.isDebugLoggingEnabled() }, 51 | { "updateMasterlist", settings_.updateMasterlist() }, 52 | { "games", settings_.getGameSettings() }, 53 | { "filters", settings_.getFilters() }, 54 | }; 55 | 56 | return json.dump(); 57 | } 58 | 59 | private: 60 | const LootSettings& settings_; 61 | }; 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/update_masterlist_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_UPDATE_MASTERLIST_QUERY 26 | #define LOOT_GUI_QUERY_UPDATE_MASTERLIST_QUERY 27 | 28 | #include "gui/cef/query/types/metadata_query.h" 29 | #include "gui/state/game.h" 30 | 31 | namespace loot { 32 | class UpdateMasterlistQuery : public MetadataQuery { 33 | public: 34 | UpdateMasterlistQuery(LootState& state) : 35 | MetadataQuery(state), 36 | game_(state.getCurrentGame()) {} 37 | 38 | std::string executeLogic() { 39 | auto logger = getLogger(); 40 | if (logger) { 41 | logger->debug("Updating and parsing masterlist."); 42 | } 43 | 44 | if (!updateMasterlist()) 45 | return "null"; 46 | 47 | auto plugins = game_.GetPlugins(); 48 | return generateJsonResponse(plugins.cbegin(), plugins.cend()); 49 | } 50 | 51 | private: 52 | bool updateMasterlist() { 53 | try { 54 | return game_.UpdateMasterlist(); 55 | } catch (std::exception&) { 56 | try { 57 | game_.LoadMetadata(); 58 | } catch (...) { 59 | } 60 | throw; 61 | } 62 | } 63 | 64 | gui::Game& game_; 65 | }; 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/gui/cef/window_delegate.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_WINDOW_DELEGATE 26 | #define LOOT_GUI_WINDOW_DELEGATE 27 | #define NOMINMAX 28 | 29 | #include 30 | #include 31 | 32 | #include "gui/state/loot_state.h" 33 | 34 | namespace loot { 35 | class WindowDelegate : public CefWindowDelegate { 36 | public: 37 | explicit WindowDelegate(CefRefPtr browser_view, 38 | LootState& lootState); 39 | 40 | void OnWindowCreated(CefRefPtr window) OVERRIDE; 41 | 42 | void OnWindowDestroyed(CefRefPtr window) OVERRIDE; 43 | 44 | bool CanClose(CefRefPtr window) OVERRIDE; 45 | 46 | private: 47 | void SetWindowPosition(LootSettings::WindowPosition position); 48 | 49 | CefRect ConstrainWindowPosition(CefRect rect); 50 | 51 | void SetWindowIcon(CefRefPtr window); 52 | 53 | CefRefPtr browser_view_; 54 | LootState& lootState_; 55 | 56 | IMPLEMENT_REFCOUNTING(WindowDelegate); 57 | DISALLOW_COPY_AND_ASSIGN(WindowDelegate); 58 | }; 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /docs/app/usage/initialisation.rst: -------------------------------------------------------------------------------- 1 | ************** 2 | Initialisation 3 | ************** 4 | 5 | When LOOT is run, it will attempt to detect which of the supported games are installed. If a :ref:`default game ` has been set, LOOT will run for it, otherwise it will run for the same game as it last ran for. If the relevant game cannot be detected, or if there is no record of the last game LOOT ran for, it will run for the first detected game. 6 | 7 | LOOT's initialisation can be customised using command line parameters: 8 | 9 | ``--game=``: 10 | Set the game to run for. If the supplied game folder name is valid, the default and last game values are ignored. The default folder names are ``Oblivion``, ``Skyrim``, ``Fallout3``, ``FalloutNV`` and ``Fallout4``. 11 | 12 | ``--loot-data-path=``: 13 | Set the path to use for LOOT's application data storage. If this is an empty string or not specified, defaults to ``%LOCALAPPDATA%\LOOT`` on Windows and (in order of decreasing preference) ``$XDG_CONFIG_HOME/LOOT``, ``$HOME/.config/LOOT`` or the current path on Linux. 14 | 15 | ``--game-appdata-path=``: 16 | Set the path to use for the all games' local application data storage. If this is an empty string or not specified, defaults to ``%LOCALAPPDATA%\``. Specifying this is unnecessary and generally wrong on Windows, but useful on Linux when running for a single game. 17 | 18 | If LOOT cannot detect any supported game installs, it will immediately open the :doc:`Settings dialog `. There you can edit LOOT’s settings to provide a path to a supported game, after which you can select it from the game menu. 19 | 20 | Once a game has been set, LOOT will scan its plugins and load the game’s masterlist, if one is present. The plugins and any metadata they have are then listed in their current load order. 21 | 22 | If LOOT detects that it is the first time you have run that version of LOOT, it will display a "First-Time Tips" dialog, which provides some information about the user interface that may not be immediately obvious. 23 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/cancel_sort_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_CANCEL_SORT_QUERY 26 | #define LOOT_GUI_QUERY_CANCEL_SORT_QUERY 27 | 28 | #include "gui/cef/query/json.h" 29 | #include "gui/cef/query/types/metadata_query.h" 30 | #include "gui/state/loot_state.h" 31 | 32 | namespace loot { 33 | class CancelSortQuery : public MetadataQuery { 34 | public: 35 | CancelSortQuery(LootState& state) : MetadataQuery(state), state_(state) {} 36 | 37 | std::string executeLogic() { 38 | state_.decrementUnappliedChangeCounter(); 39 | state_.getCurrentGame().DecrementLoadOrderSortCount(); 40 | 41 | nlohmann::json json = { 42 | { "plugins", nlohmann::json::array() }, 43 | { "generalMessages", getGeneralMessages() }, 44 | }; 45 | 46 | std::vector loadOrder = state_.getCurrentGame().GetLoadOrder(); 47 | for (const auto& plugin : loadOrder) { 48 | auto pluginObject = state_.getCurrentGame().GetPlugin(plugin); 49 | auto loadOrderIndex = state_.getCurrentGame().GetActiveLoadOrderIndex( 50 | pluginObject, loadOrder); 51 | 52 | json["plugins"].push_back({ 53 | { "name", plugin }, 54 | { "loadOrderIndex", loadOrderIndex }, 55 | }); 56 | } 57 | 58 | return json.dump(); 59 | } 60 | 61 | private: 62 | LootState& state_; 63 | }; 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/close_settings_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_CLOSE_SETTINGS_QUERY 26 | #define LOOT_GUI_QUERY_CLOSE_SETTINGS_QUERY 27 | 28 | #include "gui/cef/query/json.h" 29 | #include "gui/cef/query/types/get_installed_games_query.h" 30 | #include "gui/state/loot_state.h" 31 | 32 | namespace loot { 33 | class CloseSettingsQuery : public GetInstalledGamesQuery { 34 | public: 35 | CloseSettingsQuery(LootState& state, nlohmann::json settings) : 36 | GetInstalledGamesQuery(state), 37 | state_(state), 38 | settings_(settings) {} 39 | 40 | std::string executeLogic() { 41 | auto logger = state_.getLogger(); 42 | if (logger) { 43 | logger->trace("Settings dialog closed and changes accepted, updating " 44 | "settings object."); 45 | } 46 | 47 | state_.setDefaultGame(settings_.value("game", "")); 48 | state_.setLanguage(settings_.value("language", "")); 49 | state_.enableDebugLogging(settings_.value("enableDebugLogging", false)); 50 | state_.updateMasterlist(settings_.value("updateMasterlist", false)); 51 | state_.storeGameSettings(settings_.value("games", std::vector())); 52 | 53 | return GetInstalledGamesQuery::executeLogic(); 54 | } 55 | 56 | private: 57 | LootState& state_; 58 | nlohmann::json settings_; 59 | }; 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/tests/gui/html/js/test_updateExists.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('updateExists()', () => { 4 | it('should reject if no arguments are passed', () => 5 | loot.updateExists().catch(error => error.should.be.an('error'))); 6 | 7 | it('should reject if one argument is passed', () => 8 | loot.updateExists('1.0.0').catch(error => error.should.be.an('error'))); 9 | 10 | it('should reject if passed a version number has less than three parts', () => 11 | loot 12 | .updateExists('1.0', 'deadbeef') 13 | .catch(error => error.should.be.an('error'))); 14 | 15 | it('should reject if passed a version number has more than three parts', () => 16 | loot 17 | .updateExists('1.0.0.0', 'deadbeef') 18 | .catch(error => error.should.be.an('error'))); 19 | 20 | it('should reject if the version number given contains non-digit, non-period characters', () => 21 | loot 22 | .updateExists('1.0a.0', 'deadbeef') 23 | .catch(error => error.should.be.an('error'))); 24 | 25 | it('should resolve to true if the given version is less than the latest version', () => 26 | loot 27 | .updateExists('0.9.1', 'deadbeef') 28 | .then(result => result.should.be.true)); 29 | 30 | it('should resolve to false if the given version is greater than the latest version', () => 31 | loot 32 | .updateExists('0.10.0', 'deadbeef') 33 | .then(result => result.should.be.false)); 34 | 35 | it('should resolve to true if the given version equals the latest version but the short build SHAs are unequal and the latest version commit is newer', () => 36 | loot 37 | .updateExists('0.9.2', 'deadbeef') 38 | .then(result => result.should.be.true)); 39 | 40 | it('should resolve to false if the given version equals the latest version but the short build SHAs are unequal and the build commits dates are equal', () => 41 | loot 42 | .updateExists('0.9.2', 'feedbac') 43 | .then(result => result.should.be.false)); 44 | 45 | it('should resolve to false if the given version equals the latest version and the short build SHAs are equal', () => 46 | loot 47 | .updateExists('0.9.2', '6b58f92') 48 | .then(result => result.should.be.false)); 49 | }); 50 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/get_languages_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_GET_LANGUAGES_QUERY 26 | #define LOOT_GUI_QUERY_GET_LANGUAGES_QUERY 27 | 28 | #undef min 29 | 30 | #include 31 | 32 | #include "gui/cef/query/query.h" 33 | 34 | namespace loot { 35 | class GetLanguagesQuery : public Query { 36 | public: 37 | std::string executeLogic() { 38 | auto logger = getLogger(); 39 | if (logger) { 40 | logger->info("Getting LOOT's supported languages."); 41 | } 42 | return getLanguagesAsJson(); 43 | } 44 | 45 | private: 46 | static std::string getLanguagesAsJson() { 47 | nlohmann::json json; 48 | 49 | json["languages"] = nlohmann::json::array(); 50 | for (const auto& language : getLanguages()) { 51 | json["languages"].push_back({ 52 | { "locale", language.first }, 53 | { "name", language.second } 54 | }); 55 | } 56 | 57 | return json.dump(); 58 | } 59 | 60 | static std::map getLanguages() { 61 | return std::map({ 62 | {"da", "Dansk"}, 63 | {"de", "Deutsch"}, 64 | {"en", "English"}, 65 | {"es", "Español"}, 66 | {"fi", "suomi"}, 67 | {"fr", "Français"}, 68 | {"ko", "한국어"}, 69 | {"pl", "Polski"}, 70 | {"pt_BR", "Português do Brasil"}, 71 | {"ru", "Русский"}, 72 | {"sv", "Svenska"}, 73 | {"zh_CN", "简体中文"}, 74 | {"ja", "日本語"}, 75 | }); 76 | } 77 | }; 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/copy_metadata_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_COPY_METADATA_QUERY 26 | #define LOOT_GUI_QUERY_COPY_METADATA_QUERY 27 | 28 | #include "gui/cef/query/json.h" 29 | #include "gui/cef/query/types/clipboard_query.h" 30 | 31 | namespace loot { 32 | class CopyMetadataQuery : public ClipboardQuery { 33 | public: 34 | CopyMetadataQuery(LootState& state, const std::string& pluginName) : 35 | state_(state), 36 | pluginName_(pluginName) {} 37 | 38 | std::string executeLogic() { 39 | auto logger = getLogger(); 40 | if (logger) { 41 | logger->debug("Copying metadata for plugin {}", pluginName_); 42 | } 43 | 44 | // Get metadata from masterlist and userlist. 45 | PluginMetadata metadata = 46 | state_.getCurrentGame().GetMasterlistMetadata(pluginName_); 47 | metadata.MergeMetadata( 48 | state_.getCurrentGame().GetUserMetadata(pluginName_)); 49 | 50 | // Generate text representation. 51 | std::string text = 52 | "[spoiler][code]" + asText(metadata) + "[/code][/spoiler]"; 53 | 54 | copyToClipboard(text); 55 | 56 | if (logger) { 57 | logger->debug("Exported userlist metadata text for \"{}\": {}", 58 | pluginName_, 59 | text); 60 | } 61 | 62 | return ""; 63 | } 64 | 65 | private: 66 | std::string asText(const PluginMetadata& metadata) { 67 | return to_json_with_language(metadata, state_.getLanguage()).dump(4); 68 | } 69 | 70 | LootState& state_; 71 | std::string pluginName_; 72 | }; 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/gui/cef/query/query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_QUERY 26 | #define LOOT_GUI_QUERY_QUERY 27 | 28 | #include 29 | #include 30 | 31 | #include "gui/state/logging.h" 32 | 33 | namespace loot { 34 | class Query : public CefBaseRefCounted { 35 | public: 36 | void execute(CefRefPtr callback) { 37 | try { 38 | callback->Success(executeLogic()); 39 | } catch (std::exception& e) { 40 | auto logger = getLogger(); 41 | if (logger) { 42 | logger->error("Exception while executing query: {}", e.what()); 43 | } 44 | callback->Failure(-1, 45 | boost::locale::translate( 46 | "Oh no, something went wrong! You can check your " 47 | "LOOTDebugLog.txt (you can get to it through the " 48 | "main menu) for more information.") 49 | .str()); 50 | } 51 | } 52 | 53 | protected: 54 | virtual std::string executeLogic() = 0; 55 | 56 | void sendProgressUpdate(CefRefPtr frame, 57 | const std::string& message) { 58 | auto logger = getLogger(); 59 | if (logger) { 60 | logger->trace("Sending progress update: {}", message); 61 | } 62 | frame->ExecuteJavaScript( 63 | "loot.Dialog.showProgress('" + message + "');", frame->GetURL(), 0); 64 | } 65 | 66 | private: 67 | IMPLEMENT_REFCOUNTING(Query); 68 | }; 69 | } 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/gui/helpers.cpp: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #include "gui/helpers.h" 26 | 27 | #ifdef _WIN32 28 | #ifndef UNICODE 29 | #define UNICODE 30 | #endif 31 | #ifndef _UNICODE 32 | #define _UNICODE 33 | #endif 34 | #include "shlobj.h" 35 | #include "shlwapi.h" 36 | #include "windows.h" 37 | #endif 38 | 39 | namespace loot { 40 | void OpenInDefaultApplication(const boost::filesystem::path& file) { 41 | #ifdef _WIN32 42 | HINSTANCE ret = ShellExecute( 43 | 0, NULL, ToWinWide(file.string()).c_str(), NULL, NULL, SW_SHOWNORMAL); 44 | if ((int)ret <= 32) 45 | throw std::system_error(GetLastError(), 46 | std::system_category(), 47 | "Failed to open file in its default application."); 48 | #else 49 | if (system(("/usr/bin/xdg-open " + file.string()).c_str()) != 0) 50 | throw std::system_error(errno, 51 | std::system_category(), 52 | "Failed to open file in its default application."); 53 | #endif 54 | } 55 | 56 | #ifdef _WIN32 57 | std::wstring ToWinWide(const std::string& str) { 58 | size_t len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), 0, 0); 59 | std::wstring wstr(len, 0); 60 | MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &wstr[0], len); 61 | return wstr; 62 | } 63 | 64 | std::string FromWinWide(const std::wstring& wstr) { 65 | size_t len = WideCharToMultiByte( 66 | CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL); 67 | std::string str(len, 0); 68 | WideCharToMultiByte( 69 | CP_UTF8, 0, wstr.c_str(), wstr.length(), &str[0], len, NULL, NULL); 70 | return str; 71 | } 72 | #endif 73 | } 74 | -------------------------------------------------------------------------------- /scripts/set_version_number.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | /* eslint-disable no-console */ 3 | 4 | 'use strict'; 5 | 6 | const path = require('path'); 7 | const replace = require('replace'); 8 | 9 | function updatePreCommitHookScript(version) { 10 | replace({ 11 | regex: /--package-version=[\d.]+/, 12 | replacement: `--package-version=${version}`, 13 | paths: [path.join('scripts', 'git', 'pre-commit')], 14 | silent: true 15 | }); 16 | } 17 | 18 | function updateInstallerScript(version) { 19 | replace({ 20 | regex: /#define MyAppVersion "[\d.]+"/, 21 | replacement: `#define MyAppVersion "${version}"`, 22 | paths: [path.join('scripts', 'installer.iss')], 23 | silent: true 24 | }); 25 | } 26 | 27 | function updateCppFile(version) { 28 | const file = path.join('src', 'gui', 'version.cpp.in'); 29 | const versionParts = version.split('.'); 30 | 31 | replace({ 32 | regex: /Version::major = \d+;/, 33 | replacement: `Version::major = ${versionParts[0]};`, 34 | paths: [file], 35 | silent: true 36 | }); 37 | 38 | replace({ 39 | regex: /Version::minor = \d+;/, 40 | replacement: `Version::minor = ${versionParts[1]};`, 41 | paths: [file], 42 | silent: true 43 | }); 44 | 45 | replace({ 46 | regex: /Version::patch = \d+;/, 47 | replacement: `Version::patch = ${versionParts[2]};`, 48 | paths: [file], 49 | silent: true 50 | }); 51 | } 52 | 53 | function updateResourceFiles(version) { 54 | const files = [path.join('src', 'gui', 'resource.rc')]; 55 | const commaSeparatedVersion = version.replace(/\./g, ', '); 56 | 57 | replace({ 58 | regex: /VERSION \d+, \d+, \d+/g, 59 | replacement: `VERSION ${commaSeparatedVersion}`, 60 | paths: files, 61 | silent: true 62 | }); 63 | 64 | replace({ 65 | regex: /Version", "\d+\.\d+\.\d+"/g, 66 | replacement: `Version", "${version}"`, 67 | paths: files, 68 | silent: true 69 | }); 70 | } 71 | 72 | function main() { 73 | if (process.argv.length !== 3) { 74 | console.error( 75 | 'Invalid number of arguments given. Only one argument (the new version number) is expected.' 76 | ); 77 | process.exit(1); 78 | } 79 | 80 | const newVersion = process.argv[2]; 81 | 82 | if (newVersion.split('.').length !== 3) { 83 | console.error('The version number must be a three-part semantic version.'); 84 | process.exit(1); 85 | } 86 | 87 | updatePreCommitHookScript(newVersion); 88 | updateInstallerScript(newVersion); 89 | updateCppFile(newVersion); 90 | updateResourceFiles(newVersion); 91 | } 92 | 93 | main(); 94 | -------------------------------------------------------------------------------- /src/gui/state/loot_state.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_STATE_LOOT_STATE 26 | #define LOOT_GUI_STATE_LOOT_STATE 27 | 28 | #include 29 | 30 | #include "gui/state/game.h" 31 | #include "gui/state/loot_settings.h" 32 | 33 | namespace loot { 34 | class LootState : public LootSettings { 35 | public: 36 | LootState(); 37 | 38 | void init(const std::string& cmdLineGame, const std::string& gameAppDataPath); 39 | const std::vector& getInitErrors() const; 40 | 41 | void save(const boost::filesystem::path& file); 42 | 43 | gui::Game& getCurrentGame(); 44 | void changeGame(const std::string& newGameFolder); 45 | 46 | // Get the folder names of the installed games. 47 | std::vector getInstalledGames() const; 48 | 49 | bool hasUnappliedChanges() const; 50 | void incrementUnappliedChangeCounter(); 51 | void decrementUnappliedChangeCounter(); 52 | 53 | void enableDebugLogging(bool enable); 54 | void storeGameSettings(const std::vector& gameSettings); 55 | 56 | std::shared_ptr getLogger() const; 57 | 58 | private: 59 | // Select initial game. 60 | void selectGame(std::string cmdLineGame); 61 | void updateStoredGamePathSetting(const gui::Game& game); 62 | 63 | std::shared_ptr logger_; 64 | std::string gameAppDataPath; 65 | std::list installedGames_; 66 | std::list::iterator currentGame_; 67 | std::vector initErrors_; 68 | 69 | // Used to check if LOOT has unaccepted sorting or metadata changes on quit. 70 | size_t unappliedChangeCounter_; 71 | 72 | // Mutex used to protect access to member variables. 73 | std::mutex mutex_; 74 | }; 75 | } 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/get_game_data_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_GET_GAME_DATA_QUERY 26 | #define LOOT_GUI_QUERY_GET_GAME_DATA_QUERY 27 | 28 | #include 29 | 30 | #include "gui/cef/query/types/metadata_query.h" 31 | #include "gui/state/loot_state.h" 32 | #include "loot/loot_version.h" 33 | 34 | namespace loot { 35 | class GetGameDataQuery : public MetadataQuery { 36 | public: 37 | GetGameDataQuery(LootState& state, CefRefPtr frame) : 38 | MetadataQuery(state), 39 | state_(state), 40 | frame_(frame) {} 41 | 42 | std::string executeLogic() { 43 | sendProgressUpdate(frame_, 44 | boost::locale::translate( 45 | "Parsing, merging and evaluating metadata...")); 46 | 47 | /* If the game's plugins object is empty, this is the first time loading 48 | the game data, so also load the metadata lists. */ 49 | bool isFirstLoad = state_.getCurrentGame().GetPlugins().empty(); 50 | 51 | state_.getCurrentGame().LoadAllInstalledPlugins(true); 52 | 53 | if (isFirstLoad) 54 | state_.getCurrentGame().LoadMetadata(); 55 | 56 | // Sort plugins into their load order. 57 | std::vector> installed; 58 | std::vector loadOrder = state_.getCurrentGame().GetLoadOrder(); 59 | for (const auto& pluginName : loadOrder) { 60 | try { 61 | const auto plugin = state_.getCurrentGame().GetPlugin(pluginName); 62 | installed.push_back(plugin); 63 | } catch (...) { 64 | } 65 | } 66 | 67 | return generateJsonResponse(installed.cbegin(), installed.cend()); 68 | } 69 | 70 | private: 71 | LootState& state_; 72 | CefRefPtr frame_; 73 | }; 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/gui/state/game_settings.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2012-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_STATE_GAME_SETTINGS 26 | #define LOOT_GUI_STATE_GAME_SETTINGS 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #include "loot/enum/game_type.h" 34 | 35 | namespace loot { 36 | class GameSettings { 37 | public: 38 | GameSettings(); 39 | explicit GameSettings(const GameType gameType, 40 | const std::string& lootFolder = ""); 41 | 42 | bool IsRepoBranchOldDefault() const; 43 | 44 | bool operator==( 45 | const GameSettings& rhs) const; // Compares names and folder names. 46 | 47 | GameType Type() const; 48 | std::string Name() const; // Returns the game's name, eg. "TES IV: Oblivion". 49 | std::string FolderName() const; 50 | std::string Master() const; 51 | std::string RegistryKey() const; 52 | std::string RepoURL() const; 53 | std::string RepoBranch() const; 54 | boost::filesystem::path GamePath() const; 55 | 56 | GameSettings& SetName(const std::string& name); 57 | GameSettings& SetMaster(const std::string& masterFile); 58 | GameSettings& SetRegistryKey(const std::string& registry); 59 | GameSettings& SetRepoURL(const std::string& repositoryURL); 60 | GameSettings& SetRepoBranch(const std::string& repositoryBranch); 61 | GameSettings& SetGamePath(const boost::filesystem::path& path); 62 | 63 | private: 64 | static const std::set oldDefaultBranches; 65 | 66 | GameType type_; 67 | std::string name_; 68 | std::string masterFile_; 69 | 70 | std::string registryKey_; 71 | 72 | std::string lootFolderName_; 73 | std::string repositoryURL_; 74 | std::string repositoryBranch_; 75 | 76 | boost::filesystem::path gamePath_; // Path to the game's folder. 77 | }; 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/copy_load_order_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_COPY_LOAD_ORDER_QUERY 26 | #define LOOT_GUI_QUERY_COPY_LOAD_ORDER_QUERY 27 | 28 | #include "gui/cef/query/types/clipboard_query.h" 29 | 30 | namespace loot { 31 | struct Counters { 32 | size_t activeNormal = 0; 33 | size_t activeLightMasters = 0; 34 | }; 35 | 36 | class CopyLoadOrderQuery : public ClipboardQuery { 37 | public: 38 | CopyLoadOrderQuery(LootState& state, 39 | const std::vector& plugins) : 40 | state_(state), 41 | plugins_(plugins) {} 42 | 43 | std::string executeLogic() { 44 | Counters counters; 45 | std::stringstream stream; 46 | for (const auto& pluginName : plugins_) { 47 | writePluginLine(stream, pluginName, counters); 48 | } 49 | 50 | copyToClipboard(stream.str()); 51 | return ""; 52 | } 53 | 54 | private: 55 | void writePluginLine(std::ostream& stream, 56 | const std::string& plugin, 57 | Counters& counters) { 58 | auto isActive = state_.getCurrentGame().IsPluginActive(plugin); 59 | auto isLightMaster = 60 | state_.getCurrentGame().GetPlugin(plugin)->IsLightMaster(); 61 | 62 | if (isActive && isLightMaster) { 63 | stream << "254 FE " << std::setw(3) << std::hex 64 | << counters.activeLightMasters << std::dec << " "; 65 | counters.activeLightMasters += 1; 66 | } else if (isActive) { 67 | stream << std::setw(3) << counters.activeNormal << " " << std::hex 68 | << std::setw(2) << counters.activeNormal << std::dec << " "; 69 | counters.activeNormal += 1; 70 | } else { 71 | stream << " "; 72 | } 73 | 74 | stream << plugin << "\r\n"; 75 | } 76 | 77 | LootState& state_; 78 | const std::vector plugins_; 79 | }; 80 | } 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/gui/cef/loot_app.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_LOOT_APP 26 | #define LOOT_GUI_LOOT_APP 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "gui/state/loot_state.h" 33 | 34 | namespace loot { 35 | class LootApp : public CefApp, 36 | public CefBrowserProcessHandler, 37 | public CefRenderProcessHandler { 38 | public: 39 | void Initialise(const std::string& defaultGame, 40 | const std::string& gameAppDataPath, 41 | const std::string& lootDataPath, 42 | const std::string& url); 43 | 44 | // Override CefApp methods. 45 | virtual void OnBeforeCommandLineProcessing( 46 | const CefString& process_type, 47 | CefRefPtr command_line); 48 | virtual CefRefPtr GetBrowserProcessHandler() 49 | OVERRIDE; 50 | virtual CefRefPtr GetRenderProcessHandler() OVERRIDE; 51 | 52 | // Override CefBrowserProcessHandler methods. 53 | virtual void OnContextInitialized() OVERRIDE; 54 | virtual void OnWebKitInitialized() OVERRIDE; 55 | 56 | // Override CefRenderProcessHandler methods. 57 | virtual bool OnProcessMessageReceived( 58 | CefRefPtr browser, 59 | CefProcessId source_process, 60 | CefRefPtr message) OVERRIDE; 61 | 62 | private: 63 | virtual void OnContextCreated(CefRefPtr browser, 64 | CefRefPtr frame, 65 | CefRefPtr context) OVERRIDE; 66 | 67 | LootState lootState_; 68 | CefRefPtr message_router_; 69 | std::string url_; 70 | 71 | IMPLEMENT_REFCOUNTING(LootApp); 72 | }; 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_loot-search-toolbar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_loot-search-toolbar.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 81 | 82 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/clear_all_metadata_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_CLEAR_ALL_METADATA_QUERY 26 | #define LOOT_GUI_QUERY_CLEAR_ALL_METADATA_QUERY 27 | 28 | #include "gui/cef/query/json.h" 29 | #include "gui/cef/query/types/metadata_query.h" 30 | #include "gui/state/game.h" 31 | 32 | namespace loot { 33 | class ClearAllMetadataQuery : public MetadataQuery { 34 | public: 35 | ClearAllMetadataQuery(LootState& state) : 36 | MetadataQuery(state), 37 | game_(state.getCurrentGame()) {} 38 | 39 | std::string executeLogic() { 40 | auto logger = getLogger(); 41 | if (logger) { 42 | logger->debug("Clearing all user metadata."); 43 | } 44 | 45 | // Record which plugins have userlist entries. 46 | auto userlistPluginNames = getUserlistPluginNames(); 47 | 48 | // Clear the user metadata. 49 | game_.ClearAllUserMetadata(); 50 | game_.SaveUserMetadata(); 51 | 52 | if (logger) { 53 | logger->trace("Rederiving display metadata for {} plugins that had user " 54 | "metadata.", userlistPluginNames.size()); 55 | } 56 | 57 | return getDerivedMetadataJson(userlistPluginNames); 58 | } 59 | 60 | private: 61 | std::vector getUserlistPluginNames() const { 62 | std::vector userlistPluginNames; 63 | for (const auto& plugin : game_.GetPlugins()) { 64 | if (!game_.GetUserMetadata(plugin->GetName()).HasNameOnly()) { 65 | userlistPluginNames.push_back(plugin->GetName()); 66 | } 67 | } 68 | 69 | return userlistPluginNames; 70 | } 71 | 72 | std::string getDerivedMetadataJson( 73 | const std::vector& userlistPluginNames) { 74 | nlohmann::json json; 75 | 76 | json["plugins"] = nlohmann::json::array(); 77 | for (const auto& pluginName : userlistPluginNames) { 78 | json["plugins"].push_back(generateDerivedMetadata(pluginName)); 79 | } 80 | 81 | return json.dump(); 82 | } 83 | 84 | gui::Game& game_; 85 | }; 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/tests/gui/state/loot_state_test.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_TESTS_GUI_STATE_LOOT_STATE_TEST 26 | #define LOOT_TESTS_GUI_STATE_LOOT_STATE_TEST 27 | 28 | #include "gui/state/loot_state.h" 29 | 30 | #include 31 | 32 | namespace loot { 33 | namespace test { 34 | class LootStateTest : public ::testing::Test { 35 | protected: 36 | LootState lootState_; 37 | }; 38 | 39 | TEST_F(LootStateTest, hasUnappliedChangesShouldBeFalseByDefault) { 40 | EXPECT_FALSE(lootState_.hasUnappliedChanges()); 41 | } 42 | 43 | TEST_F(LootStateTest, shouldNotHaveUnappliedChangesIfCounterIsDeccremented) { 44 | lootState_.decrementUnappliedChangeCounter(); 45 | EXPECT_FALSE(lootState_.hasUnappliedChanges()); 46 | } 47 | 48 | TEST_F(LootStateTest, shouldHaveUnappliedChangesIfCounterIsIncremented) { 49 | lootState_.incrementUnappliedChangeCounter(); 50 | EXPECT_TRUE(lootState_.hasUnappliedChanges()); 51 | } 52 | 53 | TEST_F( 54 | LootStateTest, 55 | incrementingTheChangeCounterMoreThanItIsDecrementedShouldLeaveUnappliedChanges) { 56 | lootState_.incrementUnappliedChangeCounter(); 57 | lootState_.incrementUnappliedChangeCounter(); 58 | lootState_.decrementUnappliedChangeCounter(); 59 | EXPECT_TRUE(lootState_.hasUnappliedChanges()); 60 | } 61 | 62 | TEST_F( 63 | LootStateTest, 64 | incrementingTheChangeCounterLessThanItIsDecrementedShouldLeaveNoUnappliedChanges) { 65 | lootState_.incrementUnappliedChangeCounter(); 66 | lootState_.decrementUnappliedChangeCounter(); 67 | lootState_.decrementUnappliedChangeCounter(); 68 | EXPECT_FALSE(lootState_.hasUnappliedChanges()); 69 | } 70 | 71 | TEST_F( 72 | LootStateTest, 73 | incrementingTheChangeCounterThenDecrementingItEquallyShouldLeaveNoUnappliedChanges) { 74 | lootState_.incrementUnappliedChangeCounter(); 75 | lootState_.incrementUnappliedChangeCounter(); 76 | lootState_.decrementUnappliedChangeCounter(); 77 | lootState_.decrementUnappliedChangeCounter(); 78 | EXPECT_FALSE(lootState_.hasUnappliedChanges()); 79 | } 80 | } 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /src/gui/html/elements/loot-dropdown-menu.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 54 | 86 | 87 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/clipboard_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_CLIPBOARD_QUERY 26 | #define LOOT_GUI_QUERY_CLIPBOARD_QUERY 27 | 28 | #include 29 | #include 30 | 31 | #include "gui/cef/query/query.h" 32 | #include "gui/helpers.h" 33 | 34 | namespace loot { 35 | class ClipboardQuery : public Query { 36 | protected: 37 | void copyToClipboard(const std::string& text) { 38 | #ifdef _WIN32 39 | if (!OpenClipboard(NULL)) { 40 | throw std::system_error(GetLastError(), 41 | std::system_category(), 42 | "Failed to open the Windows clipboard."); 43 | } 44 | 45 | if (!EmptyClipboard()) { 46 | throw std::system_error(GetLastError(), 47 | std::system_category(), 48 | "Failed to empty the Windows clipboard."); 49 | } 50 | 51 | // The clipboard takes a Unicode (ie. UTF-16) string that it then owns and 52 | // must not be destroyed by LOOT. Convert the string, then copy it into a 53 | // new block of memory for the clipboard. 54 | std::wstring wtext = ToWinWide(text); 55 | wchar_t* wcstr = new wchar_t[wtext.length() + 1]; 56 | wcscpy(wcstr, wtext.c_str()); 57 | 58 | if (SetClipboardData(CF_UNICODETEXT, wcstr) == NULL) { 59 | throw std::system_error( 60 | GetLastError(), 61 | std::system_category(), 62 | "Failed to copy metadata to the Windows clipboard."); 63 | } 64 | 65 | if (!CloseClipboard()) { 66 | throw std::system_error(GetLastError(), 67 | std::system_category(), 68 | "Failed to close the Windows clipboard."); 69 | } 70 | #else 71 | std::string copyCommand = 72 | "echo '" + text + "' | xclip -selection clipboard"; 73 | int returnCode = system(copyCommand.c_str()); 74 | 75 | if (returnCode != 0) { 76 | throw std::system_error( 77 | returnCode, 78 | std::system_category(), 79 | "Failed to run clipboard copy command: " + copyCommand); 80 | } 81 | #endif 82 | } 83 | }; 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/gui/state/loot_settings.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_STATE_LOOT_SETTINGS 26 | #define LOOT_GUI_STATE_LOOT_SETTINGS 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | #include "gui/state/game_settings.h" 36 | 37 | namespace loot { 38 | class LootSettings { 39 | public: 40 | struct WindowPosition { 41 | WindowPosition(); 42 | 43 | long top; 44 | long bottom; 45 | long left; 46 | long right; 47 | bool maximised; 48 | }; 49 | 50 | LootSettings(); 51 | 52 | void load(const boost::filesystem::path& file); 53 | void save(const boost::filesystem::path& file); 54 | 55 | bool isDebugLoggingEnabled() const; 56 | bool updateMasterlist() const; 57 | bool isWindowPositionStored() const; 58 | std::string getGame() const; 59 | std::string getLastGame() const; 60 | std::string getLastVersion() const; 61 | std::string getLanguage() const; 62 | const WindowPosition& getWindowPosition() const; 63 | const std::vector& getGameSettings() const; 64 | const std::map& getFilters() const; 65 | 66 | void setDefaultGame(const std::string& game); 67 | void setLanguage(const std::string& language); 68 | void enableDebugLogging(bool enable); 69 | void updateMasterlist(bool update); 70 | 71 | void storeLastGame(const std::string& lastGame); 72 | void storeWindowPosition(const WindowPosition& position); 73 | void storeGameSettings(const std::vector& gameSettings); 74 | void storeFilterState(const std::string& filterId, bool enabled); 75 | void updateLastVersion(); 76 | 77 | private: 78 | bool enableDebugLogging_; 79 | bool updateMasterlist_; 80 | std::string game_; 81 | std::string lastGame_; 82 | std::string lastVersion_; 83 | std::string language_; 84 | WindowPosition windowPosition_; 85 | std::vector gameSettings_; 86 | std::map filters_; 87 | 88 | mutable std::recursive_mutex mutex_; 89 | 90 | void appendBaseGames(); 91 | }; 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/tests/gui/html/elements/test_loot-plugin-card.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test_loot-plugin-card.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 36 | 37 | 38 | 39 | 82 | 83 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/get_conflicting_plugins_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_GET_CONFLICTING_PLUGINS_QUERY 26 | #define LOOT_GUI_QUERY_GET_CONFLICTING_PLUGINS_QUERY 27 | 28 | #include "gui/cef/query/json.h" 29 | #include "gui/cef/query/types/metadata_query.h" 30 | #include "gui/state/game.h" 31 | 32 | namespace loot { 33 | class GetConflictingPluginsQuery : public MetadataQuery { 34 | public: 35 | GetConflictingPluginsQuery(LootState& state, const std::string& pluginName) : 36 | MetadataQuery(state), 37 | game_(state.getCurrentGame()), 38 | pluginName_(pluginName) {} 39 | 40 | std::string executeLogic() { 41 | logger_ = getLogger(); 42 | if (logger_) { 43 | logger_->debug("Searching for plugins that conflict with {}", pluginName_); 44 | } 45 | 46 | // Checking for FormID overlap will only work if the plugins have been 47 | // loaded, so check if the plugins have been fully loaded, and if not load 48 | // all plugins. 49 | if (!game_.ArePluginsFullyLoaded()) 50 | game_.LoadAllInstalledPlugins(false); 51 | 52 | return getJsonResponse(); 53 | } 54 | 55 | private: 56 | std::string getJsonResponse() { 57 | nlohmann::json json; 58 | 59 | json["plugins"] = nlohmann::json::array(); 60 | auto plugin = game_.GetPlugin(pluginName_); 61 | for (const auto& otherPlugin : game_.GetPlugins()) { 62 | json["plugins"].push_back({ 63 | { "metadata", generateDerivedMetadata(otherPlugin) }, 64 | { "conflicts", doPluginsConflict(plugin, otherPlugin) }, 65 | }); 66 | } 67 | 68 | return json.dump(); 69 | } 70 | 71 | bool doPluginsConflict( 72 | const std::shared_ptr& plugin, 73 | const std::shared_ptr& otherPlugin) { 74 | if (plugin->DoFormIDsOverlap(*otherPlugin)) { 75 | if (logger_) { 76 | logger_->debug("Found conflicting plugin: {}", otherPlugin->GetName()); 77 | } 78 | return true; 79 | } else { 80 | return false; 81 | } 82 | } 83 | 84 | gui::Game& game_; 85 | const std::string pluginName_; 86 | std::shared_ptr logger_; 87 | }; 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/gui/html/js/updateExists.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function exportModule(root, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | // AMD. Register as an anonymous module. 6 | define(['node_modules/github-api/dist/GitHub.bundle.min.js'], factory); 7 | } else { 8 | // Browser globals 9 | root.loot = root.loot || {}; 10 | root.loot.updateExists = factory(root.GitHub); 11 | } 12 | })(this, GitHub => { 13 | const versionRegex = /^(\d+)\.(\d+)\.(\d+)$/; 14 | 15 | function compare(lhs, rhs) { 16 | if (!versionRegex.test(lhs) || !versionRegex.test(rhs)) { 17 | throw new Error( 18 | `versions to compare are of unexpected format: ${lhs}, ${rhs}` 19 | ); 20 | } 21 | 22 | const lhsNumbers = lhs.split('.'); 23 | const rhsNumbers = rhs.split('.'); 24 | 25 | for (let i = 0; i < lhsNumbers.length; i += 1) { 26 | const lhsNumber = Number(lhsNumbers[i]); 27 | const rhsNumber = Number(rhsNumbers[i]); 28 | 29 | if (lhsNumber < rhsNumber) { 30 | return -1; 31 | } 32 | 33 | if (rhsNumber < lhsNumber) { 34 | return 1; 35 | } 36 | } 37 | 38 | return 0; 39 | } 40 | 41 | return (currentVersion, currentBuild) => { 42 | if (currentVersion === undefined || currentBuild === undefined) { 43 | return Promise.reject( 44 | new Error('Invalid arguments, both version and build must be given') 45 | ); 46 | } 47 | 48 | const repo = new GitHub().getRepo('loot', 'loot'); 49 | 50 | return repo 51 | .getRelease('latest') 52 | .then(response => { 53 | const latestReleaseTagName = response.data.tag_name; 54 | const comparison = compare(currentVersion, latestReleaseTagName); 55 | if (comparison === -1) { 56 | return true; 57 | } else if (comparison === 1) { 58 | return false; 59 | } 60 | 61 | return repo 62 | .listTags() 63 | .then(tagsResponse => 64 | tagsResponse.data.find( 65 | element => element.name === latestReleaseTagName 66 | ) 67 | ) 68 | .then(tag => { 69 | if (tag.commit.sha.startsWith(currentBuild)) { 70 | return false; 71 | } 72 | 73 | return repo 74 | .getCommit(tag.commit.sha) 75 | .then(commitResponse => 76 | Date.parse(commitResponse.data.committer.date) 77 | ) 78 | .then(tagDate => 79 | repo 80 | .getSingleCommit(currentBuild) 81 | .then(commitResponse => 82 | Date.parse(commitResponse.data.commit.committer.date) 83 | ) 84 | .then(buildCommitDate => tagDate > buildCommitDate) 85 | ); 86 | }); 87 | }) 88 | .catch(error => { 89 | if (!error.message) { 90 | console.error(error); // eslint-disable-line no-console 91 | } else { 92 | throw error; 93 | } 94 | }); 95 | }; 96 | }); 97 | -------------------------------------------------------------------------------- /src/gui/html/js/translator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function exportModule(root, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | // AMD. Register as an anonymous module. 6 | define( 7 | [ 8 | 'bower_components/Jed/jed', 9 | 'bower_components/jed-gettext-parser/jedGettextParser' 10 | ], 11 | factory 12 | ); 13 | } else { 14 | // Browser globals 15 | root.loot = root.loot || {}; 16 | root.loot.Translator = factory(root.Jed, root.jedGettextParser); 17 | } 18 | })( 19 | this, 20 | (Jed, jedGettextParser) => 21 | class { 22 | /* Returns a Promise */ 23 | constructor(locale) { 24 | this.locale = locale || 'en'; 25 | this.jed = undefined; 26 | } 27 | 28 | load() { 29 | const defaultTranslationData = { 30 | messages: { 31 | '': { 32 | domain: 'messages', 33 | lang: 'en', 34 | plural_forms: 'nplurals=2; plural=(n != 1);' 35 | } 36 | } 37 | }; 38 | 39 | let translationDataPromise; 40 | if (this.locale === 'en') { 41 | /* Just resolve to an empty data set. */ 42 | translationDataPromise = Promise.resolve(defaultTranslationData); 43 | } else { 44 | translationDataPromise = new Promise((resolve, reject) => { 45 | const url = `http://loot/l10n/${this.locale}/LC_MESSAGES/loot.mo`; 46 | const xhr = new XMLHttpRequest(); 47 | xhr.open('GET', url); 48 | xhr.responseType = 'arraybuffer'; 49 | xhr.addEventListener( 50 | 'readystatechange', 51 | evt => { 52 | if (evt.target.readyState === 4) { 53 | /* Status is 0 for local file URL loading. */ 54 | if (evt.target.status >= 200 && evt.target.status < 400) { 55 | resolve(jedGettextParser.mo.parse(evt.target.response)); 56 | } else { 57 | reject(new Error(evt.target.statusText)); 58 | } 59 | } 60 | }, 61 | false 62 | ); 63 | xhr.send(); 64 | }); 65 | } 66 | 67 | return translationDataPromise 68 | .catch(error => { 69 | console.error(`Error loading translation data: ${error.message}`); // eslint-disable-line no-console 70 | return defaultTranslationData; 71 | }) 72 | .then(result => { 73 | this.jed = new Jed({ 74 | locale_data: result, 75 | domain: 'messages' 76 | }); 77 | }); 78 | } 79 | 80 | translate(text) { 81 | return this.translateFormatted(text); 82 | } 83 | 84 | translateFormatted(text, ...substitutions) { 85 | if (text === undefined) { 86 | return ''; 87 | } 88 | if (this.jed === undefined) { 89 | return text; 90 | } 91 | return this.jed.translate(text).fetch(...substitutions); 92 | } 93 | } 94 | ); 95 | -------------------------------------------------------------------------------- /src/tests/gui/state/loot_paths_test.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_TESTS_GUI_STATE_LOOT_PATHS_TEST 26 | #define LOOT_TESTS_GUI_STATE_LOOT_PATHS_TEST 27 | 28 | #include "gui/state/loot_paths.h" 29 | 30 | #include 31 | 32 | namespace loot { 33 | namespace test { 34 | TEST(LootPaths, getReadmePathShouldUseLootAppPath) { 35 | LootPaths::initialise(""); 36 | 37 | EXPECT_EQ(boost::filesystem::current_path() / "docs" / "index.html", 38 | LootPaths::getReadmePath()); 39 | } 40 | 41 | TEST(LootPaths, getResourcesPathShouldUseLootAppPath) { 42 | LootPaths::initialise(""); 43 | 44 | EXPECT_EQ(boost::filesystem::current_path() / "resources", 45 | LootPaths::getResourcesPath()); 46 | } 47 | 48 | TEST(LootPaths, getL10nPathShouldUseLootAppPath) { 49 | LootPaths::initialise(""); 50 | 51 | EXPECT_EQ(boost::filesystem::current_path() / "resources" / "l10n", 52 | LootPaths::getL10nPath()); 53 | } 54 | 55 | TEST(LootPaths, getSettingsPathShouldUseLootDataPath) { 56 | LootPaths::initialise(""); 57 | 58 | EXPECT_EQ(LootPaths::getLootDataPath() / "settings.toml", 59 | LootPaths::getSettingsPath()); 60 | } 61 | 62 | TEST(LootPaths, getLogPathShouldUseLootDataPath) { 63 | LootPaths::initialise(""); 64 | 65 | EXPECT_EQ(LootPaths::getLootDataPath() / "LOOTDebugLog.txt", 66 | LootPaths::getLogPath()); 67 | } 68 | 69 | TEST(LootPaths, initialiseShouldSetTheAppPathToTheCurrentPath) { 70 | LootPaths::initialise(""); 71 | 72 | EXPECT_EQ(boost::filesystem::current_path(), 73 | LootPaths::getReadmePath().parent_path().parent_path()); 74 | } 75 | 76 | TEST( 77 | LootPaths, 78 | initialiseShouldSetTheDataPathToTheLocalAppDataPathSlashLootIfGivenAnEmptyString) { 79 | LootPaths::initialise(""); 80 | 81 | // Can't actually know what the path should be, but we can check 82 | // its properties. 83 | EXPECT_EQ("LOOT", LootPaths::getLootDataPath().filename()); 84 | EXPECT_FALSE(LootPaths::getLootDataPath().parent_path().empty()); 85 | EXPECT_TRUE( 86 | boost::filesystem::exists(LootPaths::getLootDataPath().parent_path())); 87 | } 88 | 89 | TEST(LootPaths, initialiseShouldSetTheDataPathToGivenStringIfNonEmpty) { 90 | LootPaths::initialise("foo"); 91 | 92 | EXPECT_EQ("foo", LootPaths::getLootDataPath()); 93 | } 94 | } 95 | } 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /docs/app/usage/settings.rst: -------------------------------------------------------------------------------- 1 | **************** 2 | Editing Settings 3 | **************** 4 | 5 | .. image:: ../../images/settings.png 6 | 7 | LOOT's settings may be accessed through the main menu. 8 | 9 | General Settings 10 | ================ 11 | 12 | .. _default-game: 13 | 14 | Default Game 15 | If set to something other than Autodetect, this overrides game autodetection. If the game specified is not detected, LOOT falls back to autodetection. 16 | 17 | Language 18 | Controls the language LOOT uses. Any plugin messages that do not have translations in the selected language will be displayed in English, if available, or in their available language otherwise. 19 | 20 | Enable Debug Logging 21 | If enabled, writes debug output to ``%LOCALAPPDATA%\LOOT\LOOTDebugLog.txt``. Debug logging can have a noticeable impact on performance, so it is off by default. 22 | 23 | .. _update-masterlist: 24 | 25 | Update masterlist before sorting 26 | If checked, LOOT will update its masterlist, should an update be available, before sorting plugins. 27 | 28 | Game Settings 29 | ============= 30 | 31 | LOOT's game-specific settings can be customised in the games table. New game profiles can be added, making it easy to use LOOT across multiple copies of a game, including total conversion mods. LOOT ships with settings for the "Nehrim - At Fate's Edge" total conversion mod as an example. Game profiles can also be deleted, though the active game cannot have its profile deleted, and LOOT will recreate the profiles for the base games it supports (Oblivion, Skyrim, Fallout 3, Fallout: New Vegas, Fallout 4) when it is next run. 32 | 33 | Name 34 | The name of the game, or another identifying text, that is displayed in menus and the LOOT's title bar. 35 | 36 | Base Game Type 37 | Every game LOOT runs for must use the plugin file format and load order system of one of the following games: 38 | 39 | - TES IV: Oblivion 40 | - TES V: Skyrim 41 | - TES V: Skyrim Special Edition 42 | - Fallout 3 43 | - Fallout: New Vegas 44 | - Fallout 4 45 | 46 | LOOT Folder Name 47 | The sub-folder which LOOT uses to store the game's files in. Each game must be given a unique sub-folder. 48 | 49 | Master File 50 | The game's main master file. This is checked for when detecting if the game is installed. 51 | 52 | Masterlist Repository URL 53 | The URL of the repository that LOOT uses to update its local copy of the masterlist. If left empty, masterlist updating will be skipped. 54 | 55 | Masterlist repositories are `Git`_ repositories that are configured to allow unauthenticated read access and contain a masterlist file named ``masterlist.yaml`` in their root directory. The LOOT team maintains a set of official repositories for the games that LOOT supports by default. 56 | 57 | Masterlist Repository Branch 58 | The branch of the masterlist repository that LOOT should get masterlist updates from. 59 | 60 | Install Path 61 | The path to the game's folder, in which the Data folder lies. Either this or a registry key must be supplied. 62 | 63 | Install Path Registry Key 64 | The registry key, in ``HKEY_LOCAL_MACHINE``, that contains the install path of the game. This is used to obtain the install path if LOOT has no previous record of the game's install path, or LOOT's stored install path is invalid. Either this or an install path must be supplied. 65 | 66 | .. _Git: https://git-scm.com/ 67 | -------------------------------------------------------------------------------- /src/gui/cef/loot_scheme_handler_factory.cpp: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #include "gui/cef/loot_scheme_handler_factory.h" 26 | 27 | #include "gui/state/logging.h" 28 | #include "gui/state/loot_paths.h" 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | namespace loot { 39 | /////////////////////////////// 40 | // LootSchemeHandlerFactory 41 | /////////////////////////////// 42 | 43 | CefRefPtr LootSchemeHandlerFactory::Create( 44 | CefRefPtr browser, 45 | CefRefPtr frame, 46 | const CefString& scheme_name, 47 | CefRefPtr request) { 48 | auto logger = getLogger(); 49 | if (logger) { 50 | logger->info("Handling request to URL: {}", request->GetURL().ToString()); 51 | } 52 | const string filePath = GetPath(request->GetURL()); 53 | 54 | if (boost::filesystem::exists(filePath)) { 55 | return new CefStreamResourceHandler( 56 | 200, 57 | "OK", 58 | GetMimeType(filePath), 59 | GetHeaders(), 60 | CefStreamReader::CreateForFile(filePath)); 61 | } 62 | 63 | if (logger) { 64 | logger->trace("File {} not found, sending 404.", filePath); 65 | } 66 | const string error404 = "File not found."; 67 | CefRefPtr stream = 68 | CefStreamReader::CreateForData((void*)error404.c_str(), error404.size()); 69 | return new CefStreamResourceHandler( 70 | 404, "Not Found", "text/plain", GetHeaders(), stream); 71 | } 72 | 73 | std::string LootSchemeHandlerFactory::GetPath(const CefString& url) const { 74 | CefURLParts urlParts; 75 | CefParseURL(url, urlParts); 76 | 77 | return (LootPaths::getResourcesPath() / CefString(&urlParts.path).ToString()) 78 | .string(); 79 | } 80 | 81 | std::string LootSchemeHandlerFactory::GetMimeType( 82 | const std::string& file) const { 83 | if (file.substr(file.length() - 5) == ".html") 84 | return "text/html"; 85 | else if (file.substr(file.length() - 3) == ".js") 86 | return "application/javascript"; 87 | else if (file.substr(file.length() - 4) == ".css") 88 | return "text/css"; 89 | else 90 | return "application/octet-stream"; 91 | } 92 | 93 | CefResponse::HeaderMap LootSchemeHandlerFactory::GetHeaders() const { 94 | CefResponse::HeaderMap headers; 95 | headers.emplace("Access-Control-Allow-Origin", "*"); 96 | 97 | return headers; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: cpp 3 | compiler: gcc 4 | 5 | addons: 6 | apt: 7 | sources: 8 | - ubuntu-toolchain-r-test # ppa:ubuntu-toolchain-r/test 9 | packages: 10 | - libbz2-dev 11 | - libssl-dev 12 | - gcc-5 13 | - g++-5 14 | # GUI dependencies 15 | - libx11-dev 16 | - libgtk2.0-dev 17 | - libnss3-dev 18 | - libgconf2-dev 19 | - libxss-dev 20 | - libasound2-dev 21 | - libxtst-dev 22 | # Scripting dependencies 23 | - imagemagick 24 | 25 | cache: 26 | directories: 27 | - $TRAVIS_BUILD_DIR/node_modules 28 | - $TRAVIS_BUILD_DIR/bower_components 29 | - $HOME/boost_1_65_1/boost 30 | - $HOME/boost_1_65_1/stage/lib 31 | 32 | install: 33 | # Use GCC 5. 34 | - if [ "$CXX" = "g++" ]; then export CXX="g++-5" CC="gcc-5"; fi 35 | - export CXXFLAGS="-fPIC" CFLAGS="-fPIC" 36 | # Install the latest stable Node.js. The default Node.js version is too old 37 | # for some of the JavaScript syntax used. 38 | - npm install -g nvm 39 | - nvm install node 40 | # Install Node.js dependencies 41 | - npm install 42 | # Add local binary path to PATH 43 | - export PATH="./node_modules/.bin:$PATH" 44 | # Install runtime dependencies using Bower 45 | - bower install 46 | - wget https://raw.githubusercontent.com/WrinklyNinja/ci-scripts/1.0.0/install_boost.py 47 | - python install_boost.py --directory ~ --boost-version 1.65.1 filesystem locale system 48 | # Install packages for generating documentation 49 | - pip install --user sphinx sphinx_rtd_theme 50 | # Add sphinx-build to PATH 51 | - export PATH="$HOME/.local/bin:$PATH" 52 | # Get CMake (version available in repositories is too old, needs to be 3.1+) 53 | - wget --no-check-certificate https://cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.tar.gz 54 | - tar -xzf cmake-3.7.2-Linux-x86_64.tar.gz 55 | - export PATH=$PWD/cmake-3.7.2-Linux-x86_64/bin:$PATH 56 | 57 | before_script: 58 | - mkdir build 59 | - node scripts/create_ico.js 60 | # Move into the cloned LOOT repo build path. 61 | - cd build 62 | # Link dynamically to the C++ standard library runtime. 63 | - cmake .. -DBOOST_ROOT=~/boost_1_65_1 64 | 65 | script: 66 | - make all 67 | - ./loot_gui_tests 68 | 69 | after_success: 70 | - cd $TRAVIS_BUILD_DIR 71 | # Get the full repo history before trying to run the archiver. 72 | - git fetch --unshallow 73 | - node scripts/potomo.js 74 | - sphinx-build -b html docs build/docs/html 75 | - node scripts/archive.js 76 | # Need to replace the HEAD branch descriptor in the archive filenames 77 | - for ARCHIVE in build/*.tar.xz; do mv $ARCHIVE $(echo $ARCHIVE | sed "s/HEAD/$TRAVIS_BRANCH/"); done 78 | # Need to replace the Bintray config files' version placeholders. 79 | - VERSION=$(ls build/loot_*.tar.xz | sed 's/build\/loot_//;s/.tar.xz//;') 80 | - sed -i "s/REPLACE_THIS_VERSION/$VERSION/" scripts/travis/loot.bintray.json 81 | 82 | deploy: 83 | - provider: bintray 84 | file: scripts/travis/loot.bintray.json 85 | user: wrinklyninja 86 | key: 87 | secure: "CyJpCbkO4pK+h4ZFDqwS3FZNwTaY7638IT7uzVKhGQV2CD9nMR7mb9bL6DG/Uxs91MuBeCu8RwzXtK5IVmPkH5AbMO95JMsjor+t8lT6AHhjvgmAhOBXJa5qMbFBFbLQErTdudHIcOxgjyjA5vqt5Zf0DlWty7WnE10WoU/O7qg=" 88 | skip_cleanup: true 89 | on: 90 | all_branches: true 91 | 92 | notifications: 93 | irc: 94 | channels: 95 | - "chat.freenode.net#loot" 96 | use_notice: true 97 | skip_join: true 98 | -------------------------------------------------------------------------------- /src/tests/printers.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2013-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_TESTS_PRINTERS 26 | #define LOOT_TESTS_PRINTERS 27 | 28 | #include 29 | 30 | #include 31 | 32 | #include "loot/metadata/file.h" 33 | #include "loot/metadata/location.h" 34 | #include "loot/metadata/message.h" 35 | #include "loot/metadata/plugin_cleaning_data.h" 36 | #include "loot/metadata/plugin_metadata.h" 37 | #include "loot/metadata/tag.h" 38 | 39 | namespace loot { 40 | namespace test { 41 | void PrintTo(const File& value, ::std::ostream* os) { 42 | *os << "File(\"" << value.GetName() << "\", " 43 | << "\"" << value.GetDisplayName() << "\", " 44 | << "\"" << value.GetCondition() << "\"" 45 | << ")"; 46 | } 47 | 48 | void PrintTo(const Location& value, ::std::ostream* os) { 49 | *os << "Location(\"" << value.GetURL() << "\", " 50 | << "\"" << value.GetName() << "\", " 51 | << ")"; 52 | } 53 | 54 | void PrintTo(const Message& value, ::std::ostream* os) { 55 | std::string type; 56 | if (value.GetType() == MessageType::warn) 57 | type = "warn"; 58 | else if (value.GetType() == MessageType::error) 59 | type = "error"; 60 | else 61 | type = "say"; 62 | 63 | *os << "Message(\"" << type << "\", " 64 | << ::testing::PrintToString(value.GetContent()) << ", " 65 | << "\"" << value.GetCondition() << "\"" 66 | << ")"; 67 | } 68 | 69 | void PrintTo(const MessageContent& value, ::std::ostream* os) { 70 | *os << "MessageContent(\"" << value.GetText() << "\", " 71 | << "\"" << Language(value.GetLanguage()).GetName() << "\"" 72 | << ")"; 73 | } 74 | 75 | void PrintTo(const PluginCleaningData& value, ::std::ostream* os) { 76 | *os << "PluginCleaningData(0x" << std::hex << std::uppercase << value.GetCRC() 77 | << std::nouppercase << std::dec << ", " << value.GetITMCount() << ", " 78 | << value.GetDeletedReferenceCount() << ", " 79 | << value.GetDeletedNavmeshCount() << ", " 80 | << "\"" << value.GetCleaningUtility() << "\"" 81 | << ")"; 82 | } 83 | 84 | void PrintTo(const PluginMetadata& value, ::std::ostream* os) { 85 | *os << "PluginMetadata(\"" << value.GetName() << "\")"; 86 | } 87 | 88 | void PrintTo(const Tag& value, ::std::ostream* os) { 89 | *os << "Tag(\"" << value.GetName() << "\", " << value.IsAddition() << ", " 90 | << "\"" << value.GetCondition() << "\"" 91 | << ")"; 92 | } 93 | 94 | void PrintTo(const Plugin& value, ::std::ostream* os) { 95 | *os << "Plugin(\"" << value.GetName() << "\")"; 96 | } 97 | } 98 | } 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/gui/cef/query/derived_plugin_metadata.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_DERIVED_PLUGIN_METADATA 26 | #define LOOT_GUI_QUERY_DERIVED_PLUGIN_METADATA 27 | 28 | #include 29 | #include 30 | 31 | #include "gui/state/loot_state.h" 32 | 33 | namespace loot { 34 | class DerivedPluginMetadata { 35 | public: 36 | DerivedPluginMetadata(LootState& state, 37 | const std::shared_ptr& file, 38 | const PluginMetadata& evaluatedMetadata) { 39 | name = file->GetName(); 40 | version = file->GetVersion(); 41 | isActive = state.getCurrentGame().IsPluginActive(name); 42 | isDirty = !evaluatedMetadata.GetDirtyInfo().empty(); 43 | isEmpty = file->IsEmpty(); 44 | isMaster = file->IsMaster(); 45 | isLightMaster = file->IsLightMaster(); 46 | loadsArchive = file->LoadsArchive(); 47 | 48 | crc = file->GetCRC(); 49 | loadOrderIndex = state.getCurrentGame().GetActiveLoadOrderIndex(file, 50 | state.getCurrentGame().GetLoadOrder()); 51 | 52 | priority = evaluatedMetadata.GetLocalPriority().GetValue(); 53 | globalPriority = evaluatedMetadata.GetGlobalPriority().GetValue(); 54 | if (!evaluatedMetadata.GetCleanInfo().empty()) { 55 | cleanedWith = evaluatedMetadata.GetCleanInfo().begin()->GetCleaningUtility(); 56 | } 57 | messages = evaluatedMetadata.GetSimpleMessages(state.getLanguage()); 58 | tags = evaluatedMetadata.GetTags(); 59 | 60 | language = state.getLanguage(); 61 | } 62 | 63 | void storeUnevaluatedMetadata(PluginMetadata masterlistEntry, PluginMetadata userlistEntry) { 64 | masterlistMetadata = masterlistEntry; 65 | userMetadata = userlistEntry; 66 | } 67 | 68 | void setLoadOrderIndex(short loadOrderIndex) { 69 | this->loadOrderIndex = loadOrderIndex; 70 | } 71 | 72 | static DerivedPluginMetadata none() { 73 | return DerivedPluginMetadata(); 74 | } 75 | private: 76 | std::string name; 77 | std::string version; 78 | bool isActive; 79 | bool isDirty; 80 | bool isEmpty; 81 | bool isMaster; 82 | bool isLightMaster; 83 | bool loadsArchive; 84 | 85 | uint32_t crc; 86 | short loadOrderIndex; 87 | 88 | short priority; 89 | short globalPriority; 90 | std::string cleanedWith; 91 | std::vector messages; 92 | std::set tags; 93 | 94 | PluginMetadata masterlistMetadata; 95 | PluginMetadata userMetadata; 96 | 97 | std::string language; 98 | 99 | DerivedPluginMetadata() {} 100 | 101 | friend void to_json(nlohmann::json& json, const DerivedPluginMetadata& plugin); 102 | }; 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /scripts/build_ui.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | 'use strict'; 4 | 5 | const helpers = require('./helpers'); 6 | const { Analyzer, FSUrlLoader } = require('polymer-analyzer'); 7 | const fs = require('fs-extra'); 8 | const path = require('path'); 9 | const { getRobotoFiles } = require('./get_roboto_files'); 10 | 11 | function handleError(error) { 12 | console.error(error); 13 | process.exit(1); 14 | } 15 | 16 | function getFeatureURLs(filePath, featureTypes) { 17 | const analyzer = new Analyzer({ 18 | urlLoader: new FSUrlLoader(process.cwd()) 19 | }); 20 | return analyzer.analyze([filePath]).then(analysis => { 21 | const featureUrls = {}; 22 | featureTypes.forEach(featureType => { 23 | featureUrls[featureType] = new Set(); 24 | analysis 25 | .getFeatures({ 26 | kind: featureType, 27 | imported: true, 28 | externalPackages: true 29 | }) 30 | .forEach(feature => { 31 | featureUrls[featureType].add(feature.url); 32 | }); 33 | }); 34 | 35 | return featureUrls; 36 | }); 37 | } 38 | 39 | function getRelativePath(filePath) { 40 | if (filePath.startsWith('src/gui/html/')) { 41 | return filePath.substring(13); 42 | } 43 | return filePath; 44 | } 45 | 46 | function normalisePaths(html) { 47 | return html 48 | .replace(/href="(\.\.\/){3}/g, 'href="') 49 | .replace(/src="(\.\.\/){3}/g, 'src="'); 50 | } 51 | 52 | function copyNormalisedFile(sourceFile, destinationFile) { 53 | const html = fs.readFileSync(sourceFile, { encoding: 'utf8' }); 54 | fs.mkdirsSync(path.dirname(destinationFile)); 55 | fs.writeFileSync(destinationFile, normalisePaths(html)); 56 | } 57 | 58 | function copyFiles(pathsPromise, destinationRootPath) { 59 | pathsPromise 60 | .then(paths => { 61 | paths.forEach(filePath => { 62 | const destinationPath = `${destinationRootPath}/${getRelativePath( 63 | filePath 64 | )}`; 65 | if (filePath.includes('bower_components')) { 66 | fs.copySync(filePath, destinationPath); 67 | } else { 68 | copyNormalisedFile(filePath, destinationPath); 69 | } 70 | }); 71 | }) 72 | .catch(handleError); 73 | } 74 | 75 | const url = 76 | 'https://github.com/google/roboto/releases/download/v2.135/roboto-hinted.zip'; 77 | const fontsPath = 'build/fonts'; 78 | 79 | Promise.resolve() 80 | .then(() => { 81 | if (!fs.existsSync(fontsPath)) { 82 | return getRobotoFiles(url, fontsPath); 83 | } 84 | 85 | return ''; 86 | }) 87 | .then(() => { 88 | helpers.getAppReleasePaths('.').forEach(releasePath => { 89 | const index = 'src/gui/html/index.html'; 90 | const destinationRootPath = `${releasePath.path}/resources/ui`; 91 | 92 | const urls = getFeatureURLs(index, ['html-import', 'html-script']); 93 | const htmlImportUrls = urls.then(features => features['html-import']); 94 | const scriptUrls = urls.then(features => features['html-script']); 95 | 96 | copyFiles(htmlImportUrls, destinationRootPath); 97 | copyFiles(scriptUrls, destinationRootPath); 98 | fs.copySync('src/gui/html/css', `${destinationRootPath}/css`); 99 | fs.copySync( 100 | 'resources/ui/css/dark-theme.css', 101 | `${destinationRootPath}/css/dark-theme.css` 102 | ); 103 | fs.copySync(fontsPath, `${destinationRootPath}/fonts`); 104 | copyNormalisedFile(index, `${destinationRootPath}/index.html`); 105 | }); 106 | }) 107 | .catch(handleError); 108 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | os: Visual Studio 2015 2 | 3 | version: "{build}-{branch}" 4 | 5 | configuration: Release 6 | 7 | cache: 8 | - node_modules 9 | - bower_components 10 | 11 | environment: 12 | github_auth_token: 13 | secure: V1GojGQfrAiQtUWtNNXfm3samiH+1yNF5UYhkn8B8mbif20IGTGWNlBS9E4S0SUC 14 | bintray_auth_token: 15 | secure: fBQJmUDK/EgEUWjjbo6bWcitczeFTJZT4OZ3ZZ4FoUT6soBsTWPQJnr8YEVMFhGP 16 | 17 | install: 18 | - ps: Install-Product node LTS 19 | - choco install -y imagemagick.tool 20 | - python -m pip install sphinx sphinx_rtd_theme 21 | - npm install 22 | - .\node_modules\.bin\bower install 23 | - ps: (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/WrinklyNinja/ci-scripts/1.2.0/delete_old_bintray_versions.py', "$env:APPVEYOR_BUILD_FOLDER\delete_old_bintray_versions.py") 24 | 25 | before_build: 26 | - cd %APPVEYOR_BUILD_FOLDER% 27 | - ps: mkdir build 28 | - set PATH=C:\ProgramData\chocolatey\lib\imagemagick.tool\tools;%PATH%;C:\Program Files\Inkscape 29 | - node scripts\create_ico.js 30 | - cd build 31 | - cmake .. -G "Visual Studio 14 2015" -DBOOST_ROOT="C:\Libraries\boost_1_63_0" -DBOOST_LIBRARYDIR="C:\Libraries\boost_1_63_0\lib32-msvc-14.0" -DMSVC_STATIC_RUNTIME=ON 32 | 33 | build: 34 | verbosity: minimal 35 | project: '$(APPVEYOR_BUILD_FOLDER)\build\LOOT.sln' 36 | 37 | test_script: 38 | - cd %APPVEYOR_BUILD_FOLDER% 39 | - npm test 40 | - cd %APPVEYOR_BUILD_FOLDER%\build\%CONFIGURATION% 41 | - .\loot_gui_tests.exe --gtest_output=xml:loot_gui_tests.xml 42 | 43 | after_test: 44 | - cd %APPVEYOR_BUILD_FOLDER% 45 | - C:\Python27\Scripts\sphinx-build -b html docs build\docs\html 46 | - ps: $env:GIT_DESCRIBE = ((git describe --tags --long --abbrev=7) | Out-String) -replace "`n|`r", "" 47 | - ps: $env:PATH = "$env:PATH;C:\cygwin\bin\" 48 | - node scripts\potomo.js 49 | - ps: scripts\appveyor\build_installer.ps1 50 | - node scripts\archive.js 51 | 52 | artifacts: 53 | - path: build\loot_$(GIT_DESCRIBE)_$(APPVEYOR_REPO_BRANCH).7z 54 | name: LOOT 55 | - path: build\LOOT Installer.exe 56 | name: installer 57 | 58 | deploy: 59 | - provider: BinTray 60 | username: wrinklyninja 61 | api_key: 62 | secure: fBQJmUDK/EgEUWjjbo6bWcitczeFTJZT4OZ3ZZ4FoUT6soBsTWPQJnr8YEVMFhGP 63 | subject: wrinklyninja 64 | repo: loot 65 | package: loot 66 | version: $(GIT_DESCRIBE)_$(APPVEYOR_REPO_BRANCH) 67 | publish: true 68 | artifact: LOOT 69 | 70 | - provider: GitHub 71 | tag: $(APPVEYOR_REPO_TAG_NAME) 72 | release: LOOT v$(APPVEYOR_REPO_TAG_NAME) 73 | description: | 74 | Requires Windows 7 or later and the [MSVC 2015 x86 redistributable](https://download.microsoft.com/download/6/A/A/6AA4EDFF-645B-48C5-81CC-ED5963AEAD48/vc_redist.x86.exe), and [7-Zip](http://www.7-zip.org/) to extract the archives. The list of changes can be found [here](https://loot.readthedocs.io/en/$(APPVEYOR_REPO_TAG_NAME)/app/changelog.html). 75 | auth_token: 76 | secure: V1GojGQfrAiQtUWtNNXfm3samiH+1yNF5UYhkn8B8mbif20IGTGWNlBS9E4S0SUC 77 | artifact: LOOT,installer 78 | draft: false 79 | force_update: true 80 | on: 81 | appveyor_repo_tag: true 82 | 83 | on_success: 84 | - ps: python "$env:APPVEYOR_BUILD_FOLDER\delete_old_bintray_versions.py" -o loot -g loot -u wrinklyninja -b loot -p loot -t $env:bintray_auth_token -a $env:github_auth_token -n 30 85 | - ps: scripts\appveyor\update_masterlist_branches.ps1 86 | 87 | on_finish: 88 | - ps: (New-Object System.Net.WebClient).UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", "$($env:APPVEYOR_BUILD_FOLDER)\build\$($env:CONFIGURATION)\loot_gui_tests.xml") 89 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/sort_plugins_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_SORT_PLUGINS_QUERY 26 | #define LOOT_GUI_QUERY_SORT_PLUGINS_QUERY 27 | 28 | 29 | #include 30 | 31 | #include "gui/cef/query/json.h" 32 | #include "gui/cef/query/types/metadata_query.h" 33 | #include "gui/state/loot_state.h" 34 | 35 | namespace loot { 36 | class SortPluginsQuery : public MetadataQuery { 37 | public: 38 | SortPluginsQuery(LootState& state, CefRefPtr frame) : 39 | MetadataQuery(state), 40 | state_(state), 41 | frame_(frame) {} 42 | 43 | std::string executeLogic() { 44 | auto logger = state_.getLogger(); 45 | if (logger) { 46 | logger->info("Beginning sorting operation."); 47 | } 48 | 49 | // Sort plugins into their load order. 50 | sendProgressUpdate(frame_, 51 | boost::locale::translate("Sorting load order...")); 52 | std::vector plugins = state_.getCurrentGame().SortPlugins(); 53 | 54 | if ((state_.getCurrentGame().Type() == GameType::tes5 || 55 | state_.getCurrentGame().Type() == GameType::fo4 || 56 | state_.getCurrentGame().Type() == GameType::tes5se)) 57 | applyUnchangedLoadOrder(plugins); 58 | 59 | std::string json = generateJsonResponse(plugins); 60 | 61 | // plugins will be empty if there was a sorting error. 62 | if (!plugins.empty()) 63 | state_.incrementUnappliedChangeCounter(); 64 | 65 | return json; 66 | } 67 | 68 | private: 69 | void applyUnchangedLoadOrder(const std::vector& plugins) { 70 | if (plugins.empty() || 71 | !equal(begin(plugins), 72 | end(plugins), 73 | begin(state_.getCurrentGame().GetLoadOrder()))) 74 | return; 75 | 76 | // Load order has not been changed, set it without asking for user input 77 | // because there are no changes to accept and some plugins' positions 78 | // may only be inferred and not written to loadorder.txt/plugins.txt. 79 | state_.getCurrentGame().SetLoadOrder(plugins); 80 | } 81 | 82 | std::string generateJsonResponse(const std::vector& plugins) { 83 | nlohmann::json json = { 84 | { "generalMessages", getGeneralMessages() }, 85 | { "plugins", nlohmann::json::array() }, 86 | }; 87 | 88 | for (const auto& pluginName : plugins) { 89 | auto plugin = state_.getCurrentGame().GetPlugin(pluginName); 90 | 91 | auto derivedMetadata = generateDerivedMetadata(plugin); 92 | derivedMetadata.setLoadOrderIndex( 93 | state_.getCurrentGame().GetActiveLoadOrderIndex(plugin, plugins)); 94 | 95 | json["plugins"].push_back(derivedMetadata); 96 | } 97 | 98 | return json.dump(); 99 | } 100 | 101 | LootState& state_; 102 | CefRefPtr frame_; 103 | }; 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /src/gui/state/loot_paths.cpp: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2012-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software : you can redistribute 11 | it and / or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT.If not, see 22 | . 23 | */ 24 | 25 | #include "loot_paths.h" 26 | 27 | #include 28 | 29 | #include 30 | 31 | #include "gui/helpers.h" 32 | #include "loot/api.h" 33 | 34 | #ifdef _WIN32 35 | #ifndef UNICODE 36 | #define UNICODE 37 | #endif 38 | #ifndef _UNICODE 39 | #define _UNICODE 40 | #endif 41 | #include "shlobj.h" 42 | #include "windows.h" 43 | #endif 44 | 45 | namespace loot { 46 | boost::filesystem::path LootPaths::getReadmePath() { 47 | return lootAppPath_ / "docs" / "index.html"; 48 | } 49 | 50 | boost::filesystem::path LootPaths::getResourcesPath() { 51 | return lootAppPath_ / "resources"; 52 | } 53 | 54 | boost::filesystem::path LootPaths::getL10nPath() { 55 | return getResourcesPath() / "l10n"; 56 | } 57 | 58 | boost::filesystem::path LootPaths::getLootDataPath() { return lootDataPath_; } 59 | 60 | boost::filesystem::path LootPaths::getSettingsPath() { 61 | return lootDataPath_ / "settings.toml"; 62 | } 63 | 64 | boost::filesystem::path LootPaths::getLogPath() { 65 | return lootDataPath_ / "LOOTDebugLog.txt"; 66 | } 67 | 68 | void LootPaths::initialise(const std::string& lootDataPath) { 69 | // Set the locale to get UTF-8 conversions working correctly. 70 | std::locale::global(boost::locale::generator().generate("")); 71 | boost::filesystem::path::imbue(std::locale()); 72 | loot::InitialiseLocale(""); 73 | 74 | lootAppPath_ = boost::filesystem::current_path(); 75 | 76 | if (!lootDataPath.empty()) 77 | lootDataPath_ = lootDataPath; 78 | else 79 | lootDataPath_ = getLocalAppDataPath() / "LOOT"; 80 | } 81 | 82 | boost::filesystem::path LootPaths::getLocalAppDataPath() { 83 | #ifdef _WIN32 84 | HWND owner = 0; 85 | PWSTR path; 86 | 87 | if (SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &path) != S_OK) 88 | throw std::system_error(GetLastError(), 89 | std::system_category(), 90 | "Failed to get %LOCALAPPDATA% path."); 91 | 92 | boost::filesystem::path localAppDataPath(FromWinWide(path)); 93 | CoTaskMemFree(path); 94 | 95 | return localAppDataPath; 96 | #else 97 | // Use XDG_CONFIG_HOME environmental variable if it's available. 98 | const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); 99 | 100 | if (xdgConfigHome != nullptr) 101 | return boost::filesystem::path(xdgConfigHome); 102 | 103 | // Otherwise, use the HOME env. var. if it's available. 104 | xdgConfigHome = getenv("HOME"); 105 | 106 | if (xdgConfigHome != nullptr) 107 | return boost::filesystem::path(xdgConfigHome) / ".config"; 108 | 109 | // If somehow both are missing, use the current path. 110 | return boost::filesystem::current_path(); 111 | #endif 112 | } 113 | 114 | boost::filesystem::path LootPaths::lootAppPath_; 115 | boost::filesystem::path LootPaths::lootDataPath_; 116 | } 117 | -------------------------------------------------------------------------------- /src/gui/cef/loot_handler.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_LOOT_HANDLER 26 | #define LOOT_GUI_LOOT_HANDLER 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include "gui/state/loot_state.h" 34 | 35 | namespace loot { 36 | class LootHandler : public CefClient, 37 | public CefDisplayHandler, 38 | public CefLifeSpanHandler, 39 | public CefLoadHandler, 40 | public CefRequestHandler { 41 | public: 42 | LootHandler(LootState& lootState); 43 | 44 | // CefClient methods 45 | //------------------ 46 | virtual CefRefPtr GetDisplayHandler() OVERRIDE; 47 | virtual CefRefPtr GetLifeSpanHandler() OVERRIDE; 48 | virtual CefRefPtr GetLoadHandler() OVERRIDE; 49 | 50 | virtual bool OnProcessMessageReceived( 51 | CefRefPtr browser, 52 | CefProcessId source_process, 53 | CefRefPtr message) OVERRIDE; 54 | 55 | // CefDisplayHandler methods 56 | //-------------------------- 57 | 58 | virtual bool OnConsoleMessage(CefRefPtr< CefBrowser > browser, 59 | const CefString& message, 60 | const CefString& source, 61 | int line) OVERRIDE; 62 | 63 | // CefLifeSpanHandler methods 64 | //--------------------------- 65 | virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE; 66 | virtual bool DoClose(CefRefPtr browser) OVERRIDE; 67 | virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE; 68 | 69 | // CefLoadHandler methods 70 | //----------------------- 71 | virtual void OnLoadError(CefRefPtr browser, 72 | CefRefPtr frame, 73 | ErrorCode errorCode, 74 | const CefString& errorText, 75 | const CefString& failedUrl) OVERRIDE; 76 | 77 | // CefRequestHandler methods 78 | //-------------------------- 79 | 80 | virtual CefRefPtr GetRequestHandler() OVERRIDE; 81 | 82 | virtual bool OnBeforeBrowse(CefRefPtr browser, 83 | CefRefPtr frame, 84 | CefRefPtr request, 85 | bool is_redirect) OVERRIDE; 86 | 87 | virtual CefRequestHandler::ReturnValue OnBeforeResourceLoad( 88 | CefRefPtr browser, 89 | CefRefPtr frame, 90 | CefRefPtr request, 91 | CefRefPtr callback) OVERRIDE; 92 | 93 | private: 94 | typedef std::list> BrowserList; 95 | 96 | // List of existing browser windows. Only accessed on the CEF UI thread. 97 | BrowserList browser_list_; 98 | CefRefPtr browser_side_router_; 99 | 100 | LootState& lootState_; 101 | 102 | // Include the default reference counting implementation. 103 | IMPLEMENT_REFCOUNTING(LootHandler); 104 | }; 105 | } 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /src/gui/html/elements/loot-message-dialog.html: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 46 | 115 | 116 | -------------------------------------------------------------------------------- /src/gui/cef/query/types/editor_closed_query.h: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | 25 | #ifndef LOOT_GUI_QUERY_EDITOR_CLOSED_QUERY 26 | #define LOOT_GUI_QUERY_EDITOR_CLOSED_QUERY 27 | 28 | #include "gui/cef/query/json.h" 29 | #include "gui/cef/query/types/metadata_query.h" 30 | #include "gui/state/loot_state.h" 31 | 32 | namespace loot { 33 | class EditorClosedQuery : public MetadataQuery { 34 | public: 35 | EditorClosedQuery(LootState& state, nlohmann::json editorState) : 36 | MetadataQuery(state), 37 | state_(state), 38 | applyEdits_(editorState.at("applyEdits")) { 39 | try { 40 | metadata_ = editorState.at("metadata"); 41 | } catch (...) { 42 | state_.decrementUnappliedChangeCounter(); 43 | throw; 44 | } 45 | } 46 | 47 | std::string executeLogic() { 48 | if (applyEdits_) { 49 | applyUserEdits(); 50 | } 51 | state_.decrementUnappliedChangeCounter(); 52 | 53 | return generateJsonResponse(metadata_.GetName()); 54 | } 55 | 56 | private: 57 | PluginMetadata getNonUserMetadata() { 58 | auto logger = state_.getLogger(); 59 | if (logger) { 60 | logger->trace("Getting non-user metadata for: {}", metadata_.GetName()); 61 | } 62 | auto masterlistMetadata = 63 | state_.getCurrentGame().GetMasterlistMetadata(metadata_.GetName()); 64 | 65 | try { 66 | auto plugin = state_.getCurrentGame().GetPlugin(metadata_.GetName()); 67 | return MetadataQuery::getNonUserMetadata(plugin, masterlistMetadata); 68 | } catch (...) { 69 | } 70 | 71 | return masterlistMetadata; 72 | } 73 | 74 | PluginMetadata getUserMetadata() { 75 | auto nonUserMetadata = getNonUserMetadata(); 76 | auto userMetadata = metadata_.NewMetadata(nonUserMetadata); 77 | 78 | if (metadata_.GetLocalPriority().GetValue() != 79 | nonUserMetadata.GetLocalPriority().GetValue()) { 80 | userMetadata.SetLocalPriority(metadata_.GetLocalPriority()); 81 | } else { 82 | userMetadata.SetLocalPriority(Priority()); 83 | } 84 | 85 | if (metadata_.GetGlobalPriority().GetValue() != 86 | nonUserMetadata.GetGlobalPriority().GetValue()) { 87 | userMetadata.SetGlobalPriority(metadata_.GetGlobalPriority()); 88 | } else { 89 | userMetadata.SetGlobalPriority(Priority()); 90 | } 91 | 92 | return userMetadata; 93 | } 94 | 95 | void applyUserEdits() { 96 | auto logger = state_.getLogger(); 97 | if (logger) { 98 | logger->trace("Applying user edits for: {}", metadata_.GetName()); 99 | } 100 | 101 | // Determine what metadata in the response is user-added. 102 | auto userMetadata = getUserMetadata(); 103 | 104 | // Now erase any existing userlist entry. 105 | if (logger) { 106 | logger->trace("Erasing the existing userlist entry."); 107 | } 108 | state_.getCurrentGame().ClearUserMetadata(userMetadata.GetName()); 109 | 110 | // Add a new userlist entry if necessary. 111 | if (!userMetadata.HasNameOnly()) { 112 | if (logger) { 113 | logger->trace("Adding new metadata to new userlist entry."); 114 | } 115 | state_.getCurrentGame().AddUserMetadata(userMetadata); 116 | } 117 | 118 | // Save edited userlist. 119 | state_.getCurrentGame().SaveUserMetadata(); 120 | } 121 | 122 | LootState& state_; 123 | const bool applyEdits_; 124 | PluginMetadata metadata_; 125 | }; 126 | } 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /src/gui/cef/window_delegate.cpp: -------------------------------------------------------------------------------- 1 | /* LOOT 2 | 3 | A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and 4 | Fallout: New Vegas. 5 | 6 | Copyright (C) 2014-2017 WrinklyNinja 7 | 8 | This file is part of LOOT. 9 | 10 | LOOT is free software: you can redistribute 11 | it and/or modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation, either version 3 of 13 | the License, or (at your option) any later version. 14 | 15 | LOOT is distributed in the hope that it will 16 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with LOOT. If not, see 22 | . 23 | */ 24 | #include "gui/cef/window_delegate.h" 25 | 26 | #include "gui/resource.h" 27 | #include "gui/state/loot_paths.h" 28 | 29 | namespace loot { 30 | WindowDelegate::WindowDelegate(CefRefPtr browser_view, 31 | LootState& lootState) : 32 | browser_view_(browser_view), 33 | lootState_(lootState) {} 34 | 35 | void WindowDelegate::OnWindowCreated(CefRefPtr window) { 36 | window->SetTitle("LOOT"); 37 | SetWindowIcon(window); 38 | 39 | window->AddChildView(browser_view_); 40 | 41 | bool isMaximised = false; 42 | if (lootState_.isWindowPositionStored()) { 43 | auto windowPosition = lootState_.getWindowPosition(); 44 | isMaximised = windowPosition.maximised; 45 | SetWindowPosition(windowPosition); 46 | } else { 47 | window->CenterWindow(CefSize(1024, 768)); 48 | } 49 | 50 | window->Show(); 51 | 52 | #ifdef _WIN32 53 | // This is necessary because CefWindow::Maximise() doesn't seem to do 54 | // anything on Windows if it's called before window->Show(); 55 | if (isMaximised) { 56 | window->Maximize(); 57 | } 58 | #endif 59 | 60 | // Give keyboard focus to the browser view. 61 | browser_view_->RequestFocus(); 62 | } 63 | 64 | void WindowDelegate::OnWindowDestroyed(CefRefPtr window) { 65 | browser_view_ = nullptr; 66 | } 67 | 68 | bool WindowDelegate::CanClose(CefRefPtr window) { 69 | CefRefPtr browser = browser_view_->GetBrowser(); 70 | if (browser) 71 | return browser->GetHost()->TryCloseBrowser(); 72 | 73 | return true; 74 | } 75 | 76 | void WindowDelegate::SetWindowPosition(LootSettings::WindowPosition position) { 77 | CefRect rect(position.left, 78 | position.top, 79 | abs(position.right - position.left), 80 | abs(position.bottom - position.top)); 81 | browser_view_->GetWindow()->SetBounds(ConstrainWindowPosition(rect)); 82 | 83 | if (position.maximised) 84 | browser_view_->GetWindow()->Maximize(); 85 | } 86 | 87 | CefRect WindowDelegate::ConstrainWindowPosition(CefRect rect) { 88 | CefRect workArea = 89 | CefDisplay::GetDisplayMatchingBounds(rect, true)->GetWorkArea(); 90 | 91 | rect.x = std::max(workArea.x, std::min(workArea.width - rect.width, rect.x)); 92 | rect.y = 93 | std::max(workArea.y, std::min(workArea.height - rect.height, rect.y)); 94 | 95 | return rect; 96 | } 97 | 98 | void WindowDelegate::SetWindowIcon(CefRefPtr window) { 99 | #ifdef _WIN32 100 | // Set the title bar icon. 101 | HWND hWnd = window->GetWindowHandle(); 102 | HANDLE hIcon = LoadImage(GetModuleHandle(NULL), 103 | MAKEINTRESOURCE(MAINICON), 104 | IMAGE_ICON, 105 | 0, 106 | 0, 107 | LR_DEFAULTSIZE); 108 | HANDLE hIconSm = LoadImage(GetModuleHandle(NULL), 109 | MAKEINTRESOURCE(MAINICON), 110 | IMAGE_ICON, 111 | 0, 112 | 0, 113 | LR_DEFAULTSIZE); 114 | SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 115 | SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm); 116 | #endif 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/gui/html/js/state.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function exportModule(root, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | // AMD. Register as an anonymous module. 6 | define([], factory); 7 | } else { 8 | // Browser globals 9 | root.loot = root.loot || {}; 10 | root.loot.State = factory(root.loot.DOM); 11 | root.loot.state = new root.loot.State(); 12 | } 13 | })( 14 | this, 15 | dom => 16 | class State { 17 | static get DEFAULT_STATE() { 18 | return 0; 19 | } 20 | 21 | static get SORTING_STATE() { 22 | return 1; 23 | } 24 | 25 | static get EDITING_STATE() { 26 | return 2; 27 | } 28 | 29 | constructor() { 30 | this.currentState = State.DEFAULT_STATE; 31 | } 32 | 33 | isInDefaultState() { 34 | return this.currentState === State.DEFAULT_STATE; 35 | } 36 | 37 | isInEditingState() { 38 | return this.currentState === State.EDITING_STATE; 39 | } 40 | 41 | isInSortingState() { 42 | return this.currentState === State.SORTING_STATE; 43 | } 44 | 45 | enterSortingState() { 46 | if (this.isInSortingState()) { 47 | return; 48 | } 49 | if (this.isInEditingState()) { 50 | throw new Error('Cannot enter sorting state from editing state'); 51 | } 52 | 53 | /* Hide the masterlist update buttons, and display the accept and 54 | cancel sort buttons. */ 55 | dom.show('updateMasterlistButton', false); 56 | dom.show('sortButton', false); 57 | dom.show('applySortButton'); 58 | dom.show('cancelSortButton'); 59 | 60 | /* Disable changing game. */ 61 | dom.enable('gameMenu', false); 62 | dom.enable('refreshContentButton', false); 63 | 64 | dom.setUIState('sorting'); 65 | 66 | this.currentState = State.SORTING_STATE; 67 | } 68 | 69 | exitSortingState() { 70 | if (this.isInDefaultState()) { 71 | return; 72 | } 73 | if (this.isInEditingState()) { 74 | throw new Error('Cannot exit sorting state from editing state'); 75 | } 76 | 77 | /* Show the masterlist update buttons, and hide the accept and 78 | cancel sort buttons. */ 79 | dom.show('updateMasterlistButton'); 80 | dom.show('sortButton'); 81 | dom.show('applySortButton', false); 82 | dom.show('cancelSortButton', false); 83 | 84 | /* Enable changing game. */ 85 | dom.enable('gameMenu'); 86 | dom.enable('refreshContentButton'); 87 | 88 | dom.setUIState('default'); 89 | 90 | this.currentState = State.DEFAULT_STATE; 91 | } 92 | 93 | enterEditingState() { 94 | if (this.isInEditingState()) { 95 | return; 96 | } 97 | if (this.isInSortingState()) { 98 | throw new Error('Cannot enter editing state from sorting state'); 99 | } 100 | 101 | /* Disable the toolbar elements. */ 102 | dom.enable('wipeUserlistButton', false); 103 | dom.enable('copyContentButton', false); 104 | dom.enable('refreshContentButton', false); 105 | dom.enable('settingsButton', false); 106 | dom.enable('gameMenu', false); 107 | dom.enable('updateMasterlistButton', false); 108 | dom.enable('sortButton', false); 109 | 110 | dom.setUIState('editing'); 111 | 112 | this.currentState = State.EDITING_STATE; 113 | } 114 | 115 | exitEditingState() { 116 | if (this.isInDefaultState()) { 117 | return; 118 | } 119 | if (this.isInSortingState()) { 120 | throw new Error('Cannot exit editing state from sorting state'); 121 | } 122 | 123 | /* Re-enable toolbar elements. */ 124 | dom.enable('wipeUserlistButton'); 125 | dom.enable('copyContentButton'); 126 | dom.enable('refreshContentButton'); 127 | dom.enable('settingsButton'); 128 | dom.enable('gameMenu'); 129 | dom.enable('updateMasterlistButton'); 130 | dom.enable('sortButton'); 131 | 132 | dom.setUIState('default'); 133 | 134 | this.currentState = State.DEFAULT_STATE; 135 | } 136 | } 137 | ); 138 | --------------------------------------------------------------------------------