Compare commits

...
104 Commits
Author SHA1 Message Date
Tannin fe8c3aaea5 some fixes and removed obsolete code 2015-11-23 21:44:47 +01:00
Tannin dda9e11976 added interface for file mapping plugins 2015-11-23 21:43:37 +01:00
Tannin 9945b5e926 added support for fallout 4 savegames 2015-11-23 21:41:25 +01:00
Tannin dbbd0c4eec usvfs log is now written to a persistent file (no log rotation yet though) 2015-11-19 19:10:18 +01:00
Tannin 4ff751fb7e some fixes/disabled code required since hook.dll is gone 2015-11-19 19:09:34 +01:00
Tannin d8d81ee06f fix/workaround for a problem where Qt thinks it's not connected to the net 2015-11-19 19:07:23 +01:00
Tannin a4b69c9ed8 added fallout 4 support 2015-11-19 19:05:50 +01:00
Tannin 053ebc898f build system fix 2015-11-17 20:01:44 +01:00
Tannin 0bd38e3f67 Merge branch 'master' into new_vfs_library
Conflicts:
	src/CMakeLists.txt
2015-11-17 19:12:53 +01:00
Tannin 7f4f4cafea first work on interfacing with usvfs 2015-11-17 18:58:00 +01:00
Tannin 56ba058cd5 updated build scripts 2015-11-16 21:39:52 +01:00
TanninOne f25a51446c Merge pull request #329 from ThosRTanner/master
Update to scons build
2015-10-14 19:52:44 +02:00
Thomas Tanner ec07d3d4d9 Updated scons build a bit to produce helpful-ish git tag for organizer.
Use r"..." strings in template file to make it easier to copy/paste paths from windows clipboard.

Changed organizer.pro to not produce strange messages if you opened it because it couldn't find a .hg directory
2015-10-13 15:24:41 +01:00
Thomas Tanner 939993aefe Bring scons build up to date with cmake build 2015-10-11 21:28:38 +01:00
Thomas Tanner af9a128b4f Merge branch 'TanninOne/master' 2015-10-11 21:26:21 +01:00
Tannin 7d93a9a200 updated about dialog. Now contains a link to the source code 2015-10-10 19:36:12 +02:00
Tannin 90d87a0cf7 fixed progress dialogs appearing on startup
Appears to be a new bug in qt or maybe incompatibility with Windows 10: All Progress dialogs were made visibly automatically a few seconds after application startup. This was "fixed" by creating the dialog dynamically on demand
2015-10-10 19:35:18 +02:00
Tannin 115315df28 build fixes 2015-10-10 19:29:45 +02:00
Thomas Tanner c5876cb6a1 Merge remote-tracking branch 'TanninOne/master' 2015-10-10 13:50:22 +01:00
Thomas Tanner e7b61cb485 Remove the exec of hg which does funny things in your QT project window if you aren't using mercurial 2015-10-10 13:43:01 +01:00
Tannin a0eb00b6b6 more work on build system 2015-10-08 23:56:07 +02:00
TanninOne f2484c3b0e Update readme.md 2015-10-06 20:08:57 +02:00
TanninOne 107adbfffc Update readme.md 2015-10-06 20:03:49 +02:00
TanninOne de98fe64a3 Merge pull request #1 from ThosRTanner/master
Small cleanups
2015-09-26 19:54:31 +02:00
Thomas Tanner 364c385f1a Merge branch 'master' of https://github.com/TanninOne/modorganizer.git
# Conflicts:
#	.gitignore
2015-09-26 12:21:43 +01:00
Thomas Tanner 3c1c50fefc Create an ignore file 2015-09-26 12:12:31 +01:00
Tom Tanner 095967451e Remove some unused files and build esptk as a library 2015-09-26 11:55:17 +01:00
Tom Tanner eb901e0dfc This fixes some resource leaks with archive handling 2015-09-26 11:54:27 +01:00
Tannin 462c549f77 added cmake build system 2015-09-26 11:39:30 +02:00
Tannin 1f8c24ee7a updated readme 2015-09-23 21:57:03 +02:00
Tannin 8865f9d7bc added cmake build script and a few fixes for 64-bit compatibility 2015-09-23 21:47:56 +02:00
Tannin ae82ab7dca Merge 2015-09-06 09:50:35 +02:00
Tannin 999810e1d5 incremented version number 2015-09-06 09:49:01 +02:00
Tom Tanner 4dbf01cd56 Merge 2015-09-05 17:18:58 +01:00
Tom Tanner cd7b409c10 Weren't getting warned if you changed an executable then selected another
This fixes that and also redisplays the newly selected item properly
2015-09-05 17:18:37 +01:00
Tannin ff8377a8ff Added tag release v1.3.11 for changeset c14a9865ea2e 2015-09-05 17:24:47 +02:00
Tannin 4573d111a2 better sorting on the flag-column 2015-09-03 21:35:48 +02:00
Tannin 84ec954073 more intuitive sorting with grouping active 2015-09-03 21:35:04 +02:00
Tannin 63188eb6f3 Merge 2015-09-03 19:34:53 +02:00
Tannin 0a51fdf08e DLC bsas are now auto-enabled for pre-skyrim games 2015-09-03 19:33:33 +02:00
Tannin cb315b4179 bugfix: "add" button in editexecutables dialog didn't work 2015-09-03 19:32:40 +02:00
Tom Tanner d96d904765 Fix not recognising 'add' (1308) 2015-09-02 22:13:24 +01:00
Tannin 9588667404 Added tag release v1.3.10 for changeset 8638428b1ebc 2015-09-01 20:31:32 +02:00
Tannin b008753e1d workaround: after editing in a filtered view, if the edited item disappears as
a result of the edit, no further editor could be opened
2015-09-01 19:49:28 +02:00
Tannin 3c7ab3b668 Merge 2015-08-31 21:26:47 +02:00
Tannin d85019f4b1 auto-discovered executables aren't turned into custom ones if the user presses
"Modify" without doing any changes
2015-08-31 21:25:43 +02:00
Tannin 05edcf8840 code cleanup 2015-08-31 21:24:48 +02:00
Tannin 2a22461f14 bugfix: auto-discovered executables couldn't be customized 2015-08-31 21:24:04 +02:00
Tom Tanner 0c3c822d77 Stop the temp files to delete list growing on each install 2015-08-30 13:36:11 +01:00
Tom Tanner f0ee9c3e4d Merge 2015-08-28 20:04:15 +01:00
Tannin 83edfe0c96 Merge 2015-08-27 20:59:37 +02:00
Tannin 86d833bcc8 bugfix: crash on network connection problem 2015-08-27 20:58:39 +02:00
Tannin 58198a6bfd bugfix: update.bsa sorted incorrectly 2015-08-27 20:58:01 +02:00
Tom Tanner 32339addbf Fix nasty message when starting MO for first time 2015-08-22 22:53:13 +01:00
Tannin dd875c05de removed obsolete code 2015-08-17 20:56:53 +02:00
Tannin 17938b503a Merge 2015-08-17 20:52:12 +02:00
Tannin 269d4f6765 bugfix: wrong app ids used for oblivion and fallout 3
rewrote handling of different game variants: now resides in game plugin and works
2015-08-17 20:50:47 +02:00
Tom Tanner 0fa7f7469f Merge 2015-08-15 16:52:18 +01:00
Tannin ea1c2b46fe Merge 2015-08-15 12:37:19 +02:00
Tannin 89f3c0d65a more verbosity about login/logout to/from nexus 2015-08-15 12:06:26 +02:00
Tom Tanner 821f95b8ab Clean up of fixes for custom executable window 2015-08-13 22:37:33 +01:00
Tom Tanner 716dbcc97d Merge 2015-08-13 21:48:33 +01:00
Tom Tanner 8e7ac4e064 Fix the executable configuration flags going awry from Customise window 2015-08-13 20:07:21 +01:00
Tannin 69a8a40b99 bugfix: categories that reference each other in a cycle could send MO into an endless loop 2015-08-12 21:50:06 +02:00
Tannin 229161565e some fixes after reverting changes in c361167b9b75 2015-08-12 21:48:51 +02:00
Tom Tanner 9c3b390f08 Fix up merge mess 2015-08-11 21:53:00 +01:00
Tom Tanner 5244544424 Merge 2015-08-11 21:35:06 +01:00
Tannin 217ca284fe Merge 2015-08-11 19:31:48 +02:00
Tannin 0aecc3427a small bugfix 2015-08-11 19:23:12 +02:00
Tannin b6627ff5e0 small code cleanup 2015-08-09 17:11:18 +02:00
Tom Tanner b0d86c9e01 Merge 2015-08-09 15:56:39 +01:00
Tannin a7d6eb75c2 reverted most changes of changeset 626da419828a as I don't agree with them 2015-08-09 15:16:57 +02:00
Tannin 6f09cf2205 Merge 2015-08-09 13:51:17 +02:00
Tannin e6abe486a7 added some (currently unused) functionality to dump the list of file mappings
from real to virtual location
2015-08-09 13:04:01 +02:00
Tannin 52fcfaa292 some code cleanup 2015-08-09 12:52:30 +02:00
Tannin 4230313ef5 now displays currently logged in account in title bar 2015-08-09 12:51:19 +02:00
Tannin ff8057d34b - MO now validates session cookie on startup
- It also retrieves account status
- rewrote how MO decides when to log-in/when to give up on logging in
2015-08-09 12:40:57 +02:00
Tom Tanner b098214860 More work on the executables list
Apart from an off by one in the popup list which had crept back in, reworked
the underlying code even more, which now seems to get the list behaving in
a predictable way.
2015-08-05 22:40:49 +01:00
Tannin 8cf429a1dd - bugfix: manual installer now cancels drag&drop when dropping on a subitem
- bugfix: objects dropped on the modlist were treated as mods when they weren't urls
2015-08-05 22:48:34 +02:00
Tom Tanner 9f7bec01d0 Merge 2015-08-02 21:58:02 +01:00
Tannin 643a50ad5a - changed the way flags on executables are stored in memory
- some coding style fixes
2015-08-02 20:09:56 +02:00
Tom Tanner eaaa1b312d Extract multiple copies of file from archive
Had to rewrite the archive handling a bit. First pass, some tidyups required.
2015-08-02 16:25:32 +01:00
Tannin 9c17ecc87e Merge 2015-08-02 14:58:17 +02:00
Tannin 051589c38e bugfix: archive list wasn't saved after enabling/disabling a mod. 2015-07-31 14:18:44 +02:00
Tom Tanner 48fae44566 Fix up selection with exactly/at least/at most one 2015-07-18 20:57:37 +01:00
Tom Tanner e1c8d00979 Reworked executable lists to not use 3 bools in addExecutable
Think it's more readable
2015-07-18 13:34:10 +01:00
Tom Tanner 0503097494 Allow user to select app icon or mo icon for generated shortcuts
Also fixes 'x' for toolbar not disappearing when it should
Issue 701
2015-07-18 10:44:49 +01:00
Tom Tanner 3a39f90870 small patch to show which obsolete files are being removed 2015-07-17 22:12:46 +01:00
Tom Tanner 18ad656586 Merge 2015-07-09 18:58:57 +01:00
Tom Tanner eaafc489fc Reworking the Custom Executables list and the shortcut popup.
Certainly fixes the issue where the 'toolbar' entry doesn't lose the cross.

One of the 'find' methods ignored case but none of the others did, so I've
made it not ignore case either.

Also made the code to get the desktop/startmenu paths use a more up-to-date API
2015-07-09 18:58:34 +01:00
Tannin 7799c348ba defining PSAPI_VERSION to 1 may allow MO 1.3 to run on Vista again. 2015-07-07 20:57:20 +02:00
Tannin 0a1f3efac5 filter names in the filter pane now also show up as tooltips 2015-07-07 20:54:18 +02:00
Tannin 1eea37e4e1 small code beautification 2015-07-07 20:53:38 +02:00
Tannin 9a5965afa7 bugfix: invalidation bsa wasn't created when switching to a profile that needed it
invalidation bsa is now always placed as the first bsa
2015-07-07 20:52:46 +02:00
Tannin 7853ba5f9a Merge 2015-06-30 19:57:59 +02:00
Tannin 90dcc81715 incremented version number 2015-06-30 19:57:46 +02:00
Tannin 1e75fd8dae bugfix: dropping files from overwrite on mod failed whien mod grouping was active 2015-06-29 20:38:16 +02:00
Tannin 61033814fd bugfix: aboutToChangeData and postDataChanged signals were not correctly set up when mod grouping was enabled 2015-06-29 20:28:56 +02:00
Tom Tanner ca591dbd23 and now I find out I don't need to do it at all 2015-06-23 20:27:38 +01:00
Tom Tanner 7602fef6e7 Finish refactoring all the tab code into classes 2015-06-21 18:27:03 +01:00
Tom Tanner 67b1f9dca2 Merge 2015-06-21 07:51:49 +01:00
Tom Tanner 5ae279d8bb More refactoring, slightly easier to use classes 2015-06-21 07:51:05 +01:00
Tom Tanner 81ef3d0a81 Factor out general, nexis, plugins tab code into individual classes
Add some code and page to control what is/isn't significant in overwrite
2015-06-20 15:37:32 +01:00
Tannin dc0e67a8b3 Added tag release v1.3.8 for changeset 04197ab95dcd 2015-06-20 13:55:39 +02:00
73 changed files with 2870 additions and 2248 deletions
+12
View File
@@ -0,0 +1,12 @@
*.user
Thumbs.db
src/moc_*.cpp
src/ui_*.h
src/*.qrc.depends
src/Modorganizer.*
CMakeLists.txt.user
edit
stderr.log
stdout.log
build
.idea
+14
View File
@@ -0,0 +1,14 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(organizer)
SET(DEPENDENCIES_DIR CACHE PATH "")
# hint to find qt in dependencies path
LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake)
FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam)
GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY)
SET(ZLIB_ROOT ${DEPENDENCIES_DIR}/zlib)
ADD_SUBDIRECTORY(src)
-273
View File
@@ -1,273 +0,0 @@
HOW TO BUILD
============
Intro:
------
Building Mod Organizer can be a rather daunting task especially if you're not very comfortable with C++ development under windows.
Please note that if you only want to work on and build a plugin you can save yourself a lot of trouble
Overview:
---------
As of July 2014 MO consists of the following subprojects:
- organizer: The main userinterface. heavy usage of various libraries
- hookdll: core library of the virtual file system
- uibase: interop between plugins and the main application as well as some reusable functionality
- shared: functionality shared between organizer and hookdll. I'm attempting to get rid of this library over time
- nxmhandler: tool to pass handling of nxm links to MO or other applications
- helper: tool for doing operations requiring elevated priviledges if MO doesn't have them
- proxydll: dll used in the "proxy dll" load mechanism
- esptk: small library containing functionality to work with esps/esms
- bsatk: small library containing functionality to work with bsas. Requires zlib to extract files. Requires boost_thread to provide multi-threaded extraction
- archive: small wrapper library around 7zip for dealing with mod archives. Requires 7zip
- NCC: extension to NMM to provide a binary with command line interface for fomod installation. This is c# code and does not build with the rest of the project. Requires the rest of NMM
- bossdummy: dummy dll that looks like the boss.dll. This is used instead of the real boss dlls in NCC to save some disk space
- pythonrunner: library for embedding python code. Requires boost_python, python 2.7 and pyqt5
- loot_cli: this is a command line client of loot. This can be better integrated with MO than the official loot client.
And various plugins:
- bsaExtractor: offers to extract bsas after a mod has been installed
- checkFNIS: Activates each time an application is started from MO and runs fnis if necessary
- diagnoseBasic: Various diagnostic checks on the game
- inieditor: minimalistic file editor for ini files
- installerBain: handles non-scripted bain installers
- installerBundle: handles installation of archives wrapped in archives
- installerFomod: handles installation of xml fomods
- installerManual: handles installations of archives that aren't supported by any other plugin (or if the user chooses to do the installation manually)
- installerNCC: handles installation of any fomod (requires NCC)
- installerQuick: handles very simple one-click installations
- NMMImport: importer from existing nmm installation
- proxyPython: integrates pythonrunner as a plugin into MO
- pyniEdit: more user-friendly ini editor. python code
- previewBase: used for file previews. this plugin covers image formats supported by the qt installation (usually at least jpg, gif, png) and text files
- previewDDS: used to preview dds textures. uses code from the nif file format library
There are a few more plugins that are either broken or samples
- installerBCF: this was intended to use .bcf (bain conversion file) files as installation instructions but currently it is completely function-less
- helloWorldCpp: sample for cpp plugins. This should compile even without fulfilling most dependencies below
- pageTESAlliance: integrates the tes alliance page into MO. This integration is not nearly as tight as that of nexus.
Requirements:
-------------
Visual C++ compiler 2013 (VC 12.0) or up
- Included in visual c++ express 2013
- Do install windows sdk too if only for the cdb debugger which is included in that package
Note: If you're having trouble installing the windows sdk, you may be affected by this bug: http://support.microsoft.com/kb/2717426
Qt Libraries 5.4.x (http://www.qt.io/download-open-source/#section-2)
- i.e. "Qt libraries 5.4.0 for Windows (VS 2013, 722 MB)"
- tested: 5.4.0 for Windows 32-bit (VS 2013, OpenGL, 695 MB)
- Install according to instruction
boost libraries (http://www.boost.org/)
- tested: 1.56
- Build according to their instructions (using vc++): http://www.boost.org/doc/libs/1_57_0/more/getting_started/windows.html
- A few of the boost libraries need to be built (the rest is header-only). The only compiled libs MO needs (at the time of writing) are
boost_thread (for everything that links agains bsatk) and boost_python (for pythonrunner). You can disable the others to save yourself compile time (even on a modern system compiling boost can easily take an hour)
zlib (http://www.zlib.net/)
- Compile static library according to their instructions
- Depending on the version of zlib and how you built you should have a file called zlibstatic.lib or zlibstat.lib in "build" or "x86\ZLibStatRelease".
- Please copy that lib file to "build\zlibstatic.lib" (if it doesn't exist) so MO finds it.
7z sourcecode (http://www.7-zip.org/download.html)
- only for "archive" subproject
- no need to compile, will be linked into project
Python 2.7 (32-bit)
- only for pythonrunner
PyQt5 for Python 2.7 (http://www.riverbankcomputing.co.uk/software/pyqt/download)
- tested: PyQt-gpl-5.4.zip
- only for pythonrunner
SIP (http://www.riverbankcomputing.com/software/sip/download)
- presumably only for pythonrunner as it's needed for PyQT5
Recommended:
------------
Qt Creator
- included in Qt SDK
- With Qt Creator usually the rule is "the newer the better"
- Start Qt Creator and check if things are set up correctly:
1) Go to Tools > Options > Build & Run > Qt Versions
2.1) If the QtSDK 5.4.x you installed earlier is not auto-detected, click "Add" to add it manually
2.2) Navigate to your <your qt5 installation>\bin\qmake.exe
2.3) Restart qt creator
3) Go to Tools > Options > Build & Run > Kits
3.1) If no Kit is auto-detected (or the auto-detected ones have picked up the wrong qt or vc++ installation) click "Add"
3.2) Enter a Name (i.e. "Qt 5.4 MSVC2013 32bit")
3.3) In Compiler select the visual studio compiler installed earlier (may show up as "Microsoft Windows SDK for Windows x). Make sure you select the x86 variant
3.4) CDB should be auto-detected
3.5) Select the qt version set up earlier
4) Apply and close the options
Set up (using Qt Creator):
--------------------------
1. Create a file called "LocalPaths.pri" in your ModOrganizer\source directory
2. Open that file with any text editor and enter (one entry per line)
2a. BOOSTPATH=<path to your boost installation> (i.e. C:\code\boost_1_56_0)
2b. LOOTPATH=C:/Users/Tannin/Documents/Projects/loot_api
2c. PYTHONPATH=D:/Python278
2d. SEVENZIPPATH=D:/Documents/Projects/7zip
2e. ZLIBPATH=D:/Documents/Projects/zlib-1.2.7
3. Using Qt Creator open source/ModOrganizer.pro from your working copy
4. Compile the configuration(s) you want to use (debug and/or release) (Build All). This should compile correctly (though right now it produces a lot of warnings in boost headers).
5. <reserved for future use. Maybe grab a coffee?>
6. return to the "projects" tab and switch to "Run Settings"
7. Determine the folder of the qt binaries in the package you downloaded. This could be "QtSDK\Desktop\Qt\5.4.0\msvc2013\bin" or "Qt5.4.0\bin"
For Release build:
8r. Add a "Run configuration" that points to <your working copy>\output\ModOrganizer.exe
9r. Copy "7z.dll" to <your working copy>\output\dlls
10r. From the qt binaries directory, copy the following files to <your working copy>\output\dlls: Qt5Core.dll, Qt5Declarative.dll, Qt5Gui.dll, Qt5Network.dll, Qt5Script.dll, Qt5Sql.dll, Qt5Webkit.dll, Qt5Xml.dll, Qt5XmlPatterns.dll
For Debug build:
8d. Add a "Run configuration" that points to <your working copy>\outputd\ModOrganizer.exe
9d. Copy "7z.dll" to <your working copy>\outputd\dlls
10d. From the qt binaries copy the following files to <your working copy>\outputd\dlls: Qt5Cored.dll, Qt5Declaratived.dll, Qt5Guid.dll, Qt5Networkd.dll, Qt5Scriptd.dll, Qt5Sqld.dll, Qt5Webkitd.dll, Qt5Xmld.dll, Qt5XmlPatternsd.dll
Now you should be able to compile and run Mod Organizer.
Please note that when you change anything apart from the "organizer" subproject, qt creator may not pick up on the changes
and not recompile the modified subproject. the "organizer" project on the other hand is always re-linked. If anyone knowledgeable enough with qmake
can fix that that would be awesome.
Set up (without Qt Creator):
----------------------------
1. open a command line shell and navigate to <your working copy>\source
2. run "qmake -tp vc" to create a visual c++ solution
3. Open that solution
4. - 98. A miracle happens
99. You can now compile MO using VC
I'm not using this workflow so I can't give more detailed instructions.
Please note that the primary project format of MO remains qmake, if you work with visual studio and make changes to the project (like adding
source files) you have to manually transfer those changes to the .pro file.
-----------------
Troubleshooting (thanks to Ross):
-----------------
1) When I try to build, I am seeing the error "error: LNK1104: cannot open file 'zlibstatic.lib'"
a) Make sure you have the following files
{ZLIBPATH}\build\zconf.h
{ZLIBPATH}\build\zlib.h
{ZLIBPATH}\build\zlibstatic.lib
b) make sure "zlibstat.lib" was renamed to "zlibstatic.lib"
c) currently, there are references to zlibstatic in the following 2 project files:
./bsatk/bsatk.pro
./hookdll/hookdll.pro
Please note if building this, you need to switch OFF -DZLIB_WINAPI ...
2) After building, I try to open {MOPROJECTPATH}\outputd\ModOragnizer.exe and get this error
"The program can't start because QtDeclaratived4.dll is missing from your computer. Try reinstalling the program to fix this problem."
-> When setting up Qt4.8.x, make sure you copied the "d" (debug) versions of the dll files to {MOPROJECTPATH}\outputd\dlls
If you copied the release version or did not copy the dlls at all, you may see this error.
The *.dll files can be found in {QT48xPATH}\bin
Similiar:
http://stackoverflow.com/questions/11196416/cant-start-qt-exe-file-on-windows-7
3) I am getting one or more of the the following compiler warnings...
"{MOPROJECTPATH}\source\bsatk\bsaexception.cpp:32: warning: C4996: 'vsnprintf': This function or variable may be unsafe.
Consider using vsnprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details."
-> Ignore/suppress warning like this and make be ultra-careful using printf-style functions. vsnprintf_s is a visual-c++ only function so using those would make porting (i.e. to mingw) harder
"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\stdio.h:354: see declaration of 'vsnprintf'"
-> see previous
"debug\bsaarchive.obj:-1: warning: LNK4042: object specified more than once; extras ignored"
-> This appears to be an issue when using VC++ 2010 as the compiler. There are some posts on StackOverflow
which suggest fixes when using VC++ as the IDE, but not sure how to apply them to Qt Creator.
http://stackoverflow.com/questions/3729515
http://stackoverflow.com/questions/3695174
-> Also, not sure if this affects VC++ 2012 / VC++ 2013 / GCC via cygwin/mingw.
Not even sure if the project would successfully compile on these.
"{MOPROJECTPATH}\source\organizer\mainwindow.cpp:3995: warning: C4428: universal-character-name encountered in source"
-> very pointless warning.
http://stackoverflow.com/questions/11589571
http://stackoverflow.com/questions/7078013
the best solution I saw was to just disable the warning altogether...
#pragma warning( disable : 4428 )
"warning: LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library"
-> You can always add a #pragma to ignore them :P
http://msdn.microsoft.com/en-us/library/2c8f766e%28v=vs.80%29.aspx
4) I got the following error while building...
"error: LNK1201: error writing to program database
'{MOPROJECTPATH}\{whatever-your-build-directory-name-is}\organizer\debug\ModOrganizer.pdb';
check for insufficient disk space, invalid path, or insufficient privilege"
-> I had this happen after trying to look at something in memory via Process Explorer.
To resolve, I killed and restarted PE. Alternatively, you could probably use the
Unlocker utility. After unlocking, I manually deleted everything in the directory.
Unlocker: http://www.filehippo.com/download_unlocker/ or http://www.emptyloop.com/unlocker/
Warning: With Unlocker v1.9.2, you must select "Advanced" then uncheck everything to
avoid having some Delta toolbar garbage installed...
5) Problem TT has seen:
Complains about 'qtwebkit4' missing. For some reason this seems to insist on
living with modorganiser.exe
6) Debugging the python proxy: I (TT) don't think this is possible unless you have a debug
build of PyQt. However, a debug build of PyQt requires a debug build of python. There doesn't
appear to be a half way house which is build wiht normal python but debug versions of QT libraries.
You can confuse pyqt by copying the debug QT DLLs to appropriate named files in the DLLs
directory, and removing QT from your project run path, which results in the python proxy
initialising succesfully, but causes mod organiser to crash in strange places.
-------------------
Building with scons
-------------------
1) Download scons from www.scons.org and install
2) Download QT4 (and/or QT5) from https://bitbucket.org/dirkbaechle/scons_qt4 and
https://bitbucket.org/dirkbaechle/scons_qt5. Install as per instructions
3) Copy scons_configure_template.py to scons_configure.py. Edit to point to your
boost/python/zlib/7zip/loot directories as appropriate.
4) Create build kits as follows:
Custom Process step:
Command: <python path>\Scripts\scons.bat
Arguments: -u .
Working directory: %{sourcedir}
Clean Custom Process step:
Command: <python path>\Scripts\scons.bat
Arguments: -c -u .
Working directory: %{sourcedir}
For the release build, add 'CONFIG=release' to the arguments.
If you want to do parallel builds, add -j and a number to the arguments.
However you may need to install pywin32 (but it seems to work OK for me).
-j 4 did the entire build in 2m 15s. scons uses -Z7 to store debugging
information in the .obj files which removes the issues with multiple
processes attempting to access one datafile.
Note. If you want to build a sub project separately, it seems to be better
to open the subproject, set that up with the scons kit and build that as a
project.
Please note: the generated (runnable) output files end up in the build directory,
in the '_ModOrganizer' subdirectory (not at the top level). Named like that
so you can see it! The scons build will also populate the directory with
all the necessary DLLs (but see note 6 above about your build tool path if
trying to debug).
+524
View File
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
# Mod Organizer
Mod Organizer (MO) is a tool for managing mod collections of arbitrary size. It is specifically designed for people who like to experiment with mods and thus need an easy and reliable way to install and uninstall them.
## Building
Please refer to [TanninOne/modorganizer-umbrella](https://github.com/TanninOne/modorganizer-umbrella) for build instructions.
## Other Repositories
MO consists of multiple repositories on github. The Umbrella project will download them automatically as required. They should however also be buildable individually.
Here is a complete list:
* https://github.com/TanninOne/modorganizer
* https://github.com/TanninOne/modorganizer-uibase
* https://github.com/TanninOne/modorganizer-hookdll
* https://github.com/TanninOne/modorganizer-bsatk
* https://github.com/TanninOne/modorganizer-esptk
* https://github.com/TanninOne/modorganizer-archive
* https://github.com/TanninOne/modorganizer-nxmhandler
* https://github.com/TanninOne/modorganizer-lootcli
* https://github.com/TanninOne/modorganizer-helper
* https://github.com/TanninOne/modorganizer-tool_nmmimport
* https://github.com/TanninOne/modorganizer-tool_pyniedit
* https://github.com/TanninOne/modorganizer-tool_inieditor
* https://github.com/TanninOne/modorganizer-preview_base
* https://github.com/TanninOne/modorganizer-diagnose_basic
* https://github.com/TanninOne/modorganizer-installer_quick
* https://github.com/TanninOne/modorganizer-installer_manual
* https://github.com/TanninOne/modorganizer-installer_fomod
* https://github.com/TanninOne/modorganizer-installer_bundle
* https://github.com/TanninOne/modorganizer-installer_bain
* https://github.com/TanninOne/modorganizer-game_skyrim
* https://github.com/TanninOne/modorganizer-game_oblivion
* https://github.com/TanninOne/modorganizer-game_fallout3
* https://github.com/TanninOne/modorganizer-game_falloutnv
* https://github.com/TanninOne/modorganizer-game_gamebryo
* https://github.com/TanninOne/modorganizer-game_features
* https://github.com/TanninOne/modorganizer-check_fnis
* https://github.com/TanninOne/modorganizer-plugin_python
* https://github.com/TanninOne/modorganizer-bsa_extractor
+10 -5
View File
@@ -4,7 +4,7 @@
# Path to your boost install - it should have a boost/ subdirectory and a stage/
# subdirectory. The scons script will use stage/lib if there, or the appropriate
# version for your compiler, if you installed the multiple-build version
BOOSTPATH = 'C:\\Apps\\boost_1_55_0'
BOOSTPATH = r"C:\Apps\boost_1_55_0"
# Version of Visual Studio to use, if you wish to use a specific version. If you
# don't specify a version, the latest will be picked.. See the scons manual for
@@ -14,15 +14,20 @@ BOOSTPATH = 'C:\\Apps\\boost_1_55_0'
# Path to your python install
# You don't really need to set this up but you might if (say) you have a 32- and
# 64-bit python install and scons has been installed for the 64 bit version
#PYTHONPATH=C:\Apps\Python
#PYTHONPATH=r"C:\Apps\Python"
# Path to your QT install. This might constrain the version of MSVC you can use.
# This seems to be set by QTCreator
#QTDIR = 'C:\\Apps\\Qt\\4.8.6'
#QTDIR = r"C:\Apps\Qt\4.8.6"
# Path to 7-zip sources
SEVENZIPPATH = 'C:\\Apps\\7-Zip\\7z920'
SEVENZIPPATH = r"C:\Apps\7-Zip\7z920"
# Path to zlib. Please read the README file for more information about how this
# needs to be set up
ZLIBPATH = 'C:\\Apps\\zlib-1.2.8'
ZLIBPATH = r"C:\Apps\zlib-1.2.8"
# Source control programs. Sadly I can't get this information from qt, even
# though you have to set it up in the configuration
GIT = r"C:\Program Files\git\bin\git.exe"
MERCURIAL = r"C:\Program Files\TortoiseHg\hg.exe"
+351
View File
@@ -0,0 +1,351 @@
CMAKE_MINIMUM_REQUIRED (VERSION 2.8)
CMAKE_POLICY(SET CMP0020 NEW)
#CMAKE_POLICY(SET CMP0043 NEW)
SET(PROJ_AUTHOR Tannin)
SET(PROJ_ARCH x86)
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(PROJ_ARCH x64)
ENDIF()
SET(organizer_SRCS
transfersavesdialog.cpp
syncoverwritedialog.cpp
spawn.cpp
singleinstance.cpp
settingsdialog.cpp
settings.cpp
selfupdater.cpp
selectiondialog.cpp
savegameinfowidgetgamebryo.cpp
savegameinfowidget.cpp
savegamegamebryo.cpp
savegame.cpp
queryoverwritedialog.cpp
profilesdialog.cpp
profile.cpp
pluginlistsortproxy.cpp
pluginlist.cpp
overwriteinfodialog.cpp
nxmaccessmanager.cpp
nexusinterface.cpp
motddialog.cpp
modlistsortproxy.cpp
modlist.cpp
modinfodialog.cpp
modinfo.cpp
messagedialog.cpp
mainwindow.cpp
main.cpp
loghighlighter.cpp
logbuffer.cpp
lockeddialog.cpp
loadmechanism.cpp
installationmanager.cpp
helper.cpp
filedialogmemory.cpp
executableslist.cpp
editexecutablesdialog.cpp
downloadmanager.cpp
downloadlistwidgetcompact.cpp
downloadlistwidget.cpp
downloadlistsortproxy.cpp
downloadlist.cpp
directoryrefresher.cpp
credentialsdialog.cpp
categoriesdialog.cpp
categories.cpp
bbcode.cpp
activatemodsdialog.cpp
moapplication.cpp
profileinputdialog.cpp
icondelegate.cpp
gameinfoimpl.cpp
csvbuilder.cpp
savetextasdialog.cpp
qtgroupingproxy.cpp
modlistview.cpp
problemsdialog.cpp
serverinfo.cpp
browserview.cpp
browserdialog.cpp
persistentcookiejar.cpp
noeditdelegate.cpp
previewgenerator.cpp
previewdialog.cpp
aboutdialog.cpp
json.cpp
safewritefile.cpp
modflagicondelegate.cpp
genericicondelegate.cpp
organizerproxy.cpp
viewmarkingscrollbar.cpp
plugincontainer.cpp
organizercore.cpp
usvfsconnector.cpp
shared/inject.cpp
shared/windows_error.cpp
shared/error_report.cpp
shared/directoryentry.cpp
shared/gameinfo.cpp
shared/oblivioninfo.cpp
shared/fallout3info.cpp
shared/fallout4info.cpp
shared/falloutnvinfo.cpp
shared/util.cpp
shared/skyriminfo.cpp
shared/appconfig.cpp
shared/leaktrace.cpp
shared/stackdata.cpp
)
SET(organizer_HDRS
transfersavesdialog.h
syncoverwritedialog.h
spawn.h
singleinstance.h
settingsdialog.h
settings.h
selfupdater.h
selectiondialog.h
savegameinfowidgetgamebryo.h
savegameinfowidget.h
savegamegamebyro.h
savegame.h
queryoverwritedialog.h
profilesdialog.h
profile.h
pluginlistsortproxy.h
pluginlist.h
overwriteinfodialog.h
nxmaccessmanager.h
nexusinterface.h
motddialog.h
modlistsortproxy.h
modlist.h
modinfodialog.h
modinfo.h
messagedialog.h
mainwindow.h
loghighlighter.h
logbuffer.h
lockeddialog.h
loadmechanism.h
installationmanager.h
helper.h
filedialogmemory.h
executableslist.h
editexecutablesdialog.h
downloadmanager.h
downloadlistwidgetcompact.h
downloadlistwidget.h
downloadlistsortproxy.h
downloadlist.h
directoryrefresher.h
credentialsdialog.h
categoriesdialog.h
categories.h
bbcode.h
activatemodsdialog.h
moapplication.h
profileinputdialog.h
icondelegate.h
gameinfoimpl.h
csvbuilder.h
savetextasdialog.h
qtgroupingproxy.h
modlistview.h
problemsdialog.h
serverinfo.h
browserview.h
browserdialog.h
persistentcookiejar.h
noeditdelegate.h
previewgenerator.h
previewdialog.h
aboutdialog.h
json.h
safewritefile.h
modflagicondelegate.h
genericicondelegate.h
organizerproxy.h
viewmarkingscrollbar.h
plugincontainer.h
organizercore.h
iuserinterface.h
usvfsconnector.h
shared/inject.h
shared/windows_error.h
shared/error_report.h
shared/directoryentry.h
shared/gameinfo.h
shared/oblivioninfo.h
shared/fallout3info.h
shared/fallout4info.h
shared/falloutnvinfo.h
shared/util.h
shared/skyriminfo.h
shared/appconfig.h
shared/appconfig.inc
shared/leaktrace.h
shared/stackdata.h
)
SET(organizer_UIS
transfersavesdialog.ui
syncoverwritedialog.ui
simpleinstalldialog.ui
settingsdialog.ui
selectiondialog.ui
savegameinfowidget.ui
queryoverwritedialog.ui
profilesdialog.ui
overwriteinfodialog.ui
motddialog.ui
modinfodialog.ui
messagedialog.ui
mainwindow.ui
lockeddialog.ui
installdialog.ui
finddialog.ui
editexecutablesdialog.ui
downloadlistwidgetcompact.ui
downloadlistwidget.ui
credentialsdialog.ui
categoriesdialog.ui
activatemodsdialog.ui
profileinputdialog.ui
savetextasdialog.ui
problemsdialog.ui
previewdialog.ui
browserdialog.ui
aboutdialog.ui
)
SET(organizer_QRCS
resources.qrc
stylesheet_resource.qrc
)
SET(organizer_RCS
app_icon.rc
version.rc
)
SOURCE_GROUP(Source FILES ${organizer_SRCS})
SOURCE_GROUP(Headers FILES ${organizer_HDRS})
SOURCE_GROUP(UI FILES ${organizer_UIS})
# Qt5
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
FIND_PACKAGE(Qt5Widgets REQUIRED)
FIND_PACKAGE(Qt5Declarative REQUIRED)
FIND_PACKAGE(Qt5Network REQUIRED)
FIND_PACKAGE(Qt5WinExtras REQUIRED)
FIND_PACKAGE(Qt5WebKitWidgets REQUIRED)
QT5_WRAP_UI(organizer_UIHDRS ${organizer_UIS})
QT5_ADD_RESOURCES(organizer_RCCPPS ${organizer_QRCS})
INCLUDE_DIRECTORIES(${Qt5Declarative_INCLUDES})
ADD_DEFINITIONS(-DQT_MESSAGELOGCONTEXT)
# Boost
SET(Boost_USE_STATIC_LIBS ON)
SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE(Boost REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
FIND_PACKAGE(zlib REQUIRED)
# TODO FindZlib doesn't find the static zlib library
# MO projects
SET(default_project_path "${CMAKE_SOURCE_DIR}/..")
GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH)
SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects")
SET(lib_path "${project_path}/../../install/libs")
MESSAGE(STATUS ${lib_path})
MESSAGE(STATUS ${project_path})
INCLUDE_DIRECTORIES(${project_path}/uibase/src
${project_path}/bsatk/src
${project_path}/esptk/src
${project_path}/archive/src
${project_path}/../usvfs/usvfs
${project_path}/game_features/src)
INCLUDE_DIRECTORIES(shared ${ZLIB_INCLUDE_DIRS})
LINK_DIRECTORIES(${lib_path}
${project_path}/../zlib/lib)
ADD_DEFINITIONS(-D_UNICODE -DUNICODE -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
IF("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
SET(usvfs_name usvfs_x64)
ELSE()
SET(usvfs_name usvfs_x86)
ENDIF()
ADD_EXECUTABLE(ModOrganizer WIN32 ${organizer_HDRS} ${organizer_SRCS} ${organizer_UIHDRS} ${organizer_RCS} ${organizer_RCCPPS})
TARGET_LINK_LIBRARIES(ModOrganizer
Qt5::Widgets Qt5::WinExtras Qt5::WebKitWidgets
${Boost_LIBRARIES}
zlibstatic
uibase esptk bsatk
${usvfs_name}
Dbghelp advapi32 Version Shlwapi)
SET_TARGET_PROPERTIES(ModOrganizer PROPERTIES COMPILE_FLAGS /GL)
SET_TARGET_PROPERTIES(ModOrganizer PROPERTIES LINK_FLAGS_RELWITHDEBINFO
"/LTCG /INCREMENTAL:NO /LARGEADDRESSAWARE /OPT:REF /OPT:ICF")
QT5_USE_MODULES(ModOrganizer Widgets Declarative Network WebKitWidgets)
###############
## Installation
SET(qt5bin ${Qt5Core_DIR}/../../../bin)
FIND_PROGRAM(WINDEPLOYQT_COMMAND windeployqt PATHS ${qt5bin} NO_DEFAULT_PATH)
INSTALL(TARGETS ModOrganizer
RUNTIME DESTINATION bin)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/ModOrganizer.pdb
DESTINATION pdb)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dlls.manifest.qt5
DESTINATION bin/dlls
RENAME dlls.manifest)
# use windeployqt.exe to install all required libraries
SET(windeploy_parameters --no-translations --no-plugins --libdir dlls --release-with-debug-info --no-compiler-runtime)
INSTALL(
CODE
"EXECUTE_PROCESS(
COMMAND
${qt5bin}/windeployqt.exe ModOrganizer.exe ${windeploy_parameters}
COMMAND
${qt5bin}/windeployqt.exe uibase.dll ${windeploy_parameters}
WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin
)"
)
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/stylesheets
${CMAKE_CURRENT_SOURCE_DIR}/tutorials
DESTINATION bin)
+2 -2
View File
@@ -3,6 +3,7 @@ TEMPLATE = subdirs
SUBDIRS = bsatk \
shared \
uibase \
esptk \
organizer \
hookdll \
archive \
@@ -11,8 +12,7 @@ SUBDIRS = bsatk \
nxmhandler \
BossDummy \
pythonRunner \
loot_cli \
esptk
loot_cli
pythonRunner.depends = uibase
plugins.depends = pythonRunner uibase
+48 -6
View File
@@ -1,6 +1,43 @@
import ctypes
import os
import subprocess
def resolve_name(source):
# Get the actual name of the file, after reparse points and symlinks are
# taken into account.
GENERIC_READ = 0x80000000
FILE_SHARE_READ = 0x1
OPEN_EXISTING = 0x3
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
handle = ctypes.windll.kernel32.CreateFileA(source,
GENERIC_READ,
FILE_SHARE_READ,
None,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
None)
# get the target
FILE_NAME_NORMALIZED = 0x0
FILE_NAME_OPENED = 0x8
buff = ctypes.create_string_buffer(1024)
res = ctypes.windll.kernel32.GetFinalPathNameByHandleA(handle,
buff,
ctypes.sizeof(buff),
FILE_NAME_NORMALIZED)
target = buff.value
ctypes.windll.kernel32.CloseHandle(handle)
return target
def search_up(path, target):
while True:
if os.path.exists(os.path.join(path, target)):
return True
npath = os.path.dirname(path)
if npath == path:
break
path = npath
return False
Import('qt_env')
env = qt_env.Clone()
@@ -47,16 +84,12 @@ env.AppendUnique(LIBS = [
other_sources = env.AddExtraMoc(env.Glob('*.h'))
for file in env.Glob('*.rc'):
# version.rc is included in app_icon.rc. Not sure why it's a separate file.
if file.name == 'version.rc':
continue
other_sources.append(env.RES(file))
# Note the order of this is important, or you can pick up the wrong report.h...
# Doing appendunique seems to throw the moc code into a tizzy
env['CPPPATH'] += [
'../archive',
# '../boss_modified/boss-api',
'../plugins/gamefeatures',
'.', # Why is this necessary?
'${LOOTPATH}',
@@ -86,10 +119,19 @@ cpp_files = [
]
about_env = env.Clone()
# This is somewhat of a hack until I can work out a way of setting up a build
# with all the repos without using millions of junction points
try:
hgid = subprocess.check_output(['hg', 'id', '-i']).rstrip()
target = resolve_name(Dir('.').srcnode().abspath)
if search_up(target, '.hg'):
hgid = subprocess.check_output([env['MERCURIAL'], 'id', '-i']).rstrip()
elif search_up(target, '.git'):
hgid = subprocess.check_output([env['GIT'], '-C', target, 'describe',
'--tag']).rstrip()
else:
hgid = "Unknown"
except:
hgid = 'Unknown version'
hgid = "Problem determining version"
# FIXME: It'd be much easier to stringify this in the source code
about_env.AppendUnique(CPPDEFINES = [ 'HGID=\\"%s\\"' % hgid ])
+1 -1
View File
@@ -37,7 +37,7 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent)
m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt";
m_LicenseFiles[LICENSE_APACHE2] = "apache-license-2.0.txt";
addLicense("Qt 5.4", LICENSE_LGPL3);
addLicense("Qt", LICENSE_LGPL3);
addLicense("Qt Json", LICENSE_GPL3);
addLicense("Boost Library", LICENSE_BOOST);
addLicense("7-zip", LICENSE_LGPL3);
+1 -1
View File
@@ -90,7 +90,7 @@
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&lt;/p&gt;&lt;p&gt;See the GNU General Public License for more details.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&lt;/p&gt;&lt;p&gt;See the GNU General Public License for more details.&lt;/p&gt;&lt;p&gt;Source code can be found at &lt;a href=&quot;https://github.com/TanninOne/modorganizer&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;GitHub&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
+1 -3
View File
@@ -1,3 +1 @@
#include "version.rc"
IDI_ICON1 ICON DISCARDABLE "mo_icon.ico"
IDI_ICON1 ICON DISCARDABLE "mo_icon.ico"
-113
View File
@@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BainComplexInstallerDialog</class>
<widget class="QDialog" name="BainComplexInstallerDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>398</width>
<height>365</height>
</rect>
</property>
<property name="windowTitle">
<string>BAIN Package Installer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="nameEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>This looks like a Package prepared for Installation through BAIN. You can select options from the list below. If there is a package.txt file, it should contain detailed information about the options.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="optionsList">
<property name="toolTip">
<string>Components of this package.</string>
</property>
<property name="whatsThis">
<string>Components of this package.
If there is a component called &quot;00 Core&quot; it is usually required. Options are ordered by priority as set up by the author.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="packageBtn">
<property name="toolTip">
<string>The package.txt is often part of BAIN packages and contains details about the options available.</string>
</property>
<property name="whatsThis">
<string>The package.txt is often part of BAIN packages and contains details about the options available.</string>
</property>
<property name="text">
<string>Package.txt</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="manualBtn">
<property name="toolTip">
<string>Opens a Dialog that allows custom modifications.</string>
</property>
<property name="whatsThis">
<string>Opens a Dialog that allows custom modifications.</string>
</property>
<property name="text">
<string>Manual</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="okBtn">
<property name="text">
<string>Ok</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelBtn">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+1 -1
View File
@@ -87,7 +87,7 @@ public:
*
* @return unsigned int number of categories
**/
unsigned numCategories() const { return m_Categories.size(); }
size_t numCategories() const { return m_Categories.size(); }
/**
* @brief count all categories that match a specified filter
+5 -3
View File
@@ -76,11 +76,12 @@ void DirectoryRefresher::cleanStructure(DirectoryEntry *structure)
}
}
void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &archives)
void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure, const QString &modName,
int priority, const QString &directory, const QStringList &archives)
{
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
foreach (const QString &archive, archives) {
for (const QString &archive : archives) {
QFileInfo fileInfo(archive);
if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) {
try {
@@ -93,7 +94,8 @@ void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure
}
}
void DirectoryRefresher::addModFilesToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &stealFiles)
void DirectoryRefresher::addModFilesToStructure(DirectoryEntry *directoryStructure, const QString &modName,
int priority, const QString &directory, const QStringList &stealFiles)
{
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
+48 -34
View File
@@ -30,8 +30,10 @@ using namespace MOBase;
using namespace MOShared;
EditExecutablesDialog::EditExecutablesDialog(const ExecutablesList &executablesList, QWidget *parent)
: TutorableDialog("EditExecutables", parent),
ui(new Ui::EditExecutablesDialog), m_CurrentItem(nullptr), m_ExecutablesList(executablesList)
: TutorableDialog("EditExecutables", parent)
, ui(new Ui::EditExecutablesDialog)
, m_CurrentItem(nullptr)
, m_ExecutablesList(executablesList)
{
ui->setupUi(this);
@@ -47,7 +49,7 @@ ExecutablesList EditExecutablesDialog::getExecutablesList() const
{
ExecutablesList newList;
for (int i = 0; i < ui->executablesListBox->count(); ++i) {
newList.addExecutable(ui->executablesListBox->item(i)->data(Qt::UserRole).value<Executable>());
newList.addExecutable(m_ExecutablesList.find(ui->executablesListBox->item(i)->text()));
}
return newList;
}
@@ -60,10 +62,7 @@ void EditExecutablesDialog::refreshExecutablesWidget()
for(; current != end; ++current) {
QListWidgetItem *newItem = new QListWidgetItem(current->m_Title);
QVariant temp;
temp.setValue(*current);
newItem->setData(Qt::UserRole, temp);
newItem->setTextColor(current->m_Custom ? QColor(Qt::black) : QColor(Qt::darkGray));
newItem->setTextColor(current->isCustom() ? QColor(Qt::black) : QColor(Qt::darkGray));
ui->executablesListBox->addItem(newItem);
}
@@ -72,9 +71,9 @@ void EditExecutablesDialog::refreshExecutablesWidget()
}
void EditExecutablesDialog::on_binaryEdit_textChanged(const QString &arg1)
void EditExecutablesDialog::on_binaryEdit_textChanged(const QString &name)
{
QFileInfo fileInfo(arg1);
QFileInfo fileInfo(name);
ui->addButton->setEnabled(fileInfo.exists() && fileInfo.isFile());
}
@@ -87,33 +86,43 @@ void EditExecutablesDialog::resetInput()
ui->appIDOverwriteEdit->clear();
ui->overwriteAppIDBox->setChecked(false);
ui->closeCheckBox->setChecked(false);
ui->useAppIconCheckBox->setChecked(false);
m_CurrentItem = nullptr;
}
void EditExecutablesDialog::saveExecutable()
{
m_ExecutablesList.addExecutable(ui->titleEdit->text(), QDir::fromNativeSeparators(ui->binaryEdit->text()),
ui->argumentsEdit->text(), QDir::fromNativeSeparators(ui->workingDirEdit->text()),
(ui->closeCheckBox->checkState() == Qt::Checked) ? ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE
: ExecutableInfo::CloseMOStyle::DEFAULT_STAY,
ui->overwriteAppIDBox->isChecked() ? ui->appIDOverwriteEdit->text() : "",
true, false);
}
m_ExecutablesList.updateExecutable(ui->titleEdit->text(),
QDir::fromNativeSeparators(ui->binaryEdit->text()),
ui->argumentsEdit->text(),
QDir::fromNativeSeparators(ui->workingDirEdit->text()),
(ui->closeCheckBox->checkState() == Qt::Checked) ?
ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE
: ExecutableInfo::CloseMOStyle::DEFAULT_STAY,
ui->overwriteAppIDBox->isChecked() ?
ui->appIDOverwriteEdit->text() : "",
Executable::UseApplicationIcon | Executable::CustomExecutable,
(ui->useAppIconCheckBox->isChecked() ?
Executable::UseApplicationIcon : Executable::Flags())
| Executable::CustomExecutable);
}
void EditExecutablesDialog::delayedRefresh()
{
int index = ui->executablesListBox->currentIndex().row();
QModelIndex index = ui->executablesListBox->currentIndex();
resetInput();
refreshExecutablesWidget();
ui->executablesListBox->setCurrentRow(index);
on_executablesListBox_clicked(index);
}
void EditExecutablesDialog::on_addButton_clicked()
{
saveExecutable();
if (executableChanged()) {
saveExecutable();
}
resetInput();
refreshExecutablesWidget();
@@ -170,8 +179,6 @@ void EditExecutablesDialog::on_browseDirButton_clicked()
void EditExecutablesDialog::on_removeButton_clicked()
{
// QLineEdit *binaryEdit = findChild<QLineEdit*>("binaryEdit");
if (QMessageBox::question(this, tr("Confirm"), tr("Really remove \"%1\" from executables?").arg(ui->titleEdit->text()),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
m_ExecutablesList.remove(ui->titleEdit->text());
@@ -206,15 +213,19 @@ void EditExecutablesDialog::on_titleEdit_textChanged(const QString &arg1)
bool EditExecutablesDialog::executableChanged()
{
if (m_CurrentItem != nullptr) {
const Executable &selectedExecutable = m_CurrentItem->data(Qt::UserRole).value<Executable>();
Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text()));
return selectedExecutable.m_Arguments != ui->argumentsEdit->text()
|| selectedExecutable.m_SteamAppID != ui->appIDOverwriteEdit->text()
|| selectedExecutable.m_WorkingDirectory != QDir::fromNativeSeparators(ui->workingDirEdit->text())
|| selectedExecutable.m_BinaryInfo.absoluteFilePath() != QDir::fromNativeSeparators(ui->binaryEdit->text())
|| (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE) != ui->closeCheckBox->isChecked();
|| (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE) != ui->closeCheckBox->isChecked()
|| selectedExecutable.usesOwnIcon() != ui->useAppIconCheckBox->isChecked();
} else {
return false;
QFileInfo fileInfo(ui->binaryEdit->text());
return !ui->binaryEdit->text().isEmpty()
&& !ui->titleEdit->text().isEmpty()
&& fileInfo.exists()
&& fileInfo.isFile();
}
}
@@ -252,27 +263,29 @@ void EditExecutablesDialog::on_closeButton_clicked()
void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &current)
{
if (current.isValid()) {
ui->executablesListBox->selectionModel()->clearSelection();
ui->executablesListBox->selectionModel()->select(current, QItemSelectionModel::SelectCurrent);
if (executableChanged()) {
QMessageBox::StandardButton res = QMessageBox::question(this, tr("Save Changes?"),
tr("You made changes to the current executable, do you want to save them?"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (res == QMessageBox::Cancel) {
return;
} else if (res == QMessageBox::Yes) {
// this invalidates the item passed as a a parameter
QMessageBox::Yes | QMessageBox::No);
if (res == QMessageBox::Yes) {
saveExecutable();
//This is necessary if we're adding a new item, but it doesn't look very nice.
//Ideally we'd end up with the correct row displayed
ui->executablesListBox->selectionModel()->clearSelection();
ui->executablesListBox->selectionModel()->select(current, QItemSelectionModel::SelectCurrent);
QTimer::singleShot(50, this, SLOT(delayedRefresh()));
return;
}
}
ui->executablesListBox->selectionModel()->clearSelection();
ui->executablesListBox->selectionModel()->select(current, QItemSelectionModel::SelectCurrent);
m_CurrentItem = ui->executablesListBox->item(current.row());
const Executable &selectedExecutable = m_CurrentItem->data(Qt::UserRole).value<Executable>();
Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text()));
ui->titleEdit->setText(selectedExecutable.m_Title);
ui->binaryEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath()));
@@ -286,12 +299,13 @@ void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &cur
ui->closeCheckBox->setEnabled(true);
ui->closeCheckBox->setToolTip(tr("If checked, MO will be closed once the specified executable is run."));
}
ui->removeButton->setEnabled(selectedExecutable.m_Custom);
ui->removeButton->setEnabled(selectedExecutable.isCustom());
ui->overwriteAppIDBox->setChecked(!selectedExecutable.m_SteamAppID.isEmpty());
if (!selectedExecutable.m_SteamAppID.isEmpty()) {
ui->appIDOverwriteEdit->setText(selectedExecutable.m_SteamAppID);
} else {
ui->appIDOverwriteEdit->clear();
}
ui->useAppIconCheckBox->setChecked(selectedExecutable.usesOwnIcon());
}
}
+25 -14
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>384</width>
<height>362</height>
<height>446</height>
</rect>
</property>
<property name="windowTitle">
@@ -164,21 +164,28 @@ Right now the only case I know of where this needs to be overwritten is for the
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="closeCheckBox">
<property name="toolTip">
<string>If checked, MO will be closed once the specified executable is run.</string>
</property>
<property name="whatsThis">
<string>If checked, MO will be closed once the specified executable is run.</string>
</property>
<property name="text">
<string>Close MO when started</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useAppIconCheckBox">
<property name="text">
<string>Use Application's Icon for shortcuts</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="closeCheckBox">
<property name="toolTip">
<string>If checked, MO will be closed once the specified executable is run.</string>
</property>
<property name="whatsThis">
<string>If checked, MO will be closed once the specified executable is run.</string>
</property>
<property name="text">
<string>Close MO when started</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addButton">
<property name="toolTip">
@@ -240,6 +247,10 @@ Right now the only case I know of where this needs to be overwritten is for the
</layout>
</item>
</layout>
<zorder>executablesListBox</zorder>
<zorder>closeButton</zorder>
<zorder>closeCheckBox</zorder>
<zorder>useAppIconCheckBox</zorder>
</widget>
<resources/>
<connections/>
+37 -74
View File
@@ -30,39 +30,6 @@ using namespace MOBase;
using namespace MOShared;
static QDataStream &operator<<(QDataStream &out, const Executable &obj)
{
out << obj.m_Title
<< obj.m_BinaryInfo.absoluteFilePath()
<< obj.m_Arguments
<< static_cast<std::underlying_type<ExecutableInfo::CloseMOStyle>::type>(obj.m_CloseMO)
<< obj.m_SteamAppID
<< obj.m_WorkingDirectory
<< obj.m_Custom
<< obj.m_Toolbar;
return out;
}
static QDataStream &operator>>(QDataStream &in, Executable &obj)
{
QString binaryTemp;
int closeStyleTemp;
in >> obj.m_Title >> binaryTemp >> obj.m_Arguments >> closeStyleTemp
>> obj.m_SteamAppID >> obj.m_WorkingDirectory >> obj.m_Custom >> obj.m_Toolbar;
obj.m_CloseMO = static_cast<ExecutableInfo::CloseMOStyle>(closeStyleTemp);
obj.m_BinaryInfo.setFile(binaryTemp);
return in;
}
void registerExecutable()
{
qRegisterMetaType<Executable>("Executable");
qRegisterMetaTypeStreamOperators<Executable>("Executable");
}
ExecutablesList::ExecutablesList()
{
}
@@ -102,23 +69,23 @@ void ExecutablesList::getExecutables(std::vector<Executable>::const_iterator &be
const Executable &ExecutablesList::find(const QString &title) const
{
for (std::vector<Executable>::const_iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) {
if (iter->m_Title == title) {
return *iter;
for (Executable const &exe : m_Executables) {
if (exe.m_Title == title) {
return exe;
}
}
throw std::runtime_error("invalid name");
throw std::runtime_error(QString("invalid name %1").arg(title).toLocal8Bit().constData());
}
Executable &ExecutablesList::find(const QString &title)
{
for (Executable &exe : m_Executables) {
if (QString::compare(exe.m_Title, title, Qt::CaseInsensitive) == 0) {
if (exe.m_Title == title) {
return exe;
}
}
throw std::runtime_error("invalid name");
throw std::runtime_error(QString("invalid name %1").arg(title).toLocal8Bit().constData());
}
@@ -162,42 +129,34 @@ void ExecutablesList::addExecutable(const Executable &executable)
}
void ExecutablesList::position(const QString &title, bool toolbar, int pos)
{
auto existingExe = findExe(title);
if (existingExe != m_Executables.end()) {
Executable temp = *existingExe;
temp.m_Toolbar = toolbar;
m_Executables.erase(existingExe);
m_Executables.insert(m_Executables.begin() + pos, temp);
}
}
void ExecutablesList::addExecutable(const QString &title, const QString &executableName, const QString &arguments,
const QString &workingDirectory, ExecutableInfo::CloseMOStyle closeMO, const QString &steamAppID,
bool custom, bool toolbar, int pos)
void ExecutablesList::updateExecutable(const QString &title,
const QString &executableName,
const QString &arguments,
const QString &workingDirectory,
ExecutableInfo::CloseMOStyle closeMO,
const QString &steamAppID,
Executable::Flags mask,
Executable::Flags flags)
{
QFileInfo file(executableName);
auto existingExe = findExe(title);
flags &= mask;
if (existingExe != m_Executables.end()) {
existingExe->m_Title = title;
existingExe->m_Custom = custom;
existingExe->m_CloseMO = closeMO;
existingExe->m_Toolbar = toolbar;
if (custom) {
// for pre-configured executables don't overwrite settings we didn't store
existingExe->m_BinaryInfo = file;
existingExe->m_Flags &= ~mask;
existingExe->m_Flags |= flags;
// for pre-configured executables don't overwrite settings we didn't store
if (flags & Executable::CustomExecutable) {
if (file.exists()) {
// don't overwrite a valid binary with an invalid one
existingExe->m_BinaryInfo = file;
}
existingExe->m_Arguments = arguments;
existingExe->m_WorkingDirectory = workingDirectory;
existingExe->m_SteamAppID = steamAppID;
}
if (pos >= 0) {
Executable temp = *existingExe;
m_Executables.erase(existingExe);
m_Executables.insert(m_Executables.begin() + pos, temp);
}
} else {
Executable newExe;
newExe.m_Title = title;
@@ -206,13 +165,8 @@ void ExecutablesList::addExecutable(const QString &title, const QString &executa
newExe.m_Arguments = arguments;
newExe.m_WorkingDirectory = workingDirectory;
newExe.m_SteamAppID = steamAppID;
newExe.m_Custom = true;
newExe.m_Toolbar = toolbar;
if ((pos < 0) || (pos >= static_cast<int>(m_Executables.size()))) {
m_Executables.push_back(newExe);
} else {
m_Executables.insert(m_Executables.begin() + pos, newExe);
}
newExe.m_Flags = Executable::CustomExecutable | flags;
m_Executables.push_back(newExe);
}
}
@@ -220,7 +174,7 @@ void ExecutablesList::addExecutable(const QString &title, const QString &executa
void ExecutablesList::remove(const QString &title)
{
for (std::vector<Executable>::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) {
if (iter->m_Custom && (iter->m_Title == title)) {
if (iter->isCustom() && (iter->m_Title == title)) {
m_Executables.erase(iter);
break;
}
@@ -241,8 +195,17 @@ void ExecutablesList::addExecutableInternal(const QString &title, const QString
newExe.m_Arguments = arguments;
newExe.m_WorkingDirectory = workingDirectory;
newExe.m_SteamAppID = steamAppID;
newExe.m_Custom = false;
newExe.m_Toolbar = false;
newExe.m_Flags = 0;
m_Executables.push_back(newExe);
}
}
void Executable::showOnToolbar(bool state)
{
if (state) {
m_Flags |= ShowInToolbar;
} else {
m_Flags &= ~ShowInToolbar;
}
}
+59 -30
View File
@@ -39,13 +39,26 @@ struct Executable {
QString m_SteamAppID;
QString m_WorkingDirectory;
bool m_Custom;
bool m_Toolbar;
enum Flag {
CustomExecutable = 0x01,
ShowInToolbar = 0x02,
UseApplicationIcon = 0x04,
AllFlags = 0xff //I know, I know
};
Q_DECLARE_FLAGS(Flags, Flag)
Flags m_Flags;
bool isCustom() const { return m_Flags.testFlag(CustomExecutable); }
bool isShownOnToolbar() const { return m_Flags.testFlag(ShowInToolbar); }
void showOnToolbar(bool state);
bool usesOwnIcon() const { return m_Flags.testFlag(UseApplicationIcon); }
};
Q_DECLARE_METATYPE(Executable)
void registerExecutable();
/*!
@@ -68,13 +81,13 @@ public:
void init(MOBase::IPluginGame *game);
/**
* @brief retrieve an executable by index
* @brief find an executable by its name
*
* @param index index of the executable to look up
* @return reference to the executable
* @exception out_of_range will throw an exception if the index is invalid
* @param title the title of the executable to look up
* @return the executable
* @exception runtime_error will throw an exception if the name is not correct
**/
const Executable &get(int index) const { return m_Executables.at(index); }
const Executable &find(const QString &title) const;
/**
* @brief find an executable by its name
@@ -83,16 +96,7 @@ public:
* @return the executable
* @exception runtime_error will throw an exception if the name is not correct
**/
const Executable &find(const QString &tilte) const;
/**
* @brief find an executable by its name
*
* @param title the title of the executable to look up
* @return the executable
* @exception runtime_error will throw an exception if the name is not correct
**/
Executable &find(const QString &tilte);
Executable &find(const QString &title);
/**
* @brief find an executable by a fileinfo structure
@@ -123,17 +127,33 @@ public:
* @param arguments arguments to pass to the executable
* @param closeMO if true, MO will be closed when the binary is started
**/
void addExecutable(const QString &title, const QString &executableName, const QString &arguments,
const QString &workingDirectory, MOBase::ExecutableInfo::CloseMOStyle closeMO, const QString &steamAppID,
bool custom, bool toolbar, int pos = -1);
void addExecutable(const QString &title,
const QString &executableName,
const QString &arguments,
const QString &workingDirectory,
MOBase::ExecutableInfo::CloseMOStyle closeMO,
const QString &steamAppID,
Executable::Flags flags)
{
updateExecutable(title, executableName, arguments, workingDirectory, closeMO, steamAppID, Executable::AllFlags, flags);
}
/**
* @brief change position of an executable which is expected to exist
* @param title title of the executable
* @param toolbar enable/disable placement on the toolbar
* @param pos new position for the executable
*/
void position(const QString &title, bool toolbar, int pos);
* @brief Update an executable to the list
*
* @param title name displayed in the UI
* @param executableName the actual filename to execute
* @param arguments arguments to pass to the executable
* @param closeMO if true, MO will be closed when the binary is started
**/
void updateExecutable(const QString &title,
const QString &executableName,
const QString &arguments,
const QString &workingDirectory,
MOBase::ExecutableInfo::CloseMOStyle closeMO,
const QString &steamAppID,
Executable::Flags mask,
Executable::Flags flags);
/**
* @brief remove the executable with the specified file name. This needs to be an absolute file path
@@ -159,6 +179,13 @@ public:
**/
void getExecutables(std::vector<Executable>::iterator &begin, std::vector<Executable>::iterator &end);
/**
* @brief get the number of executables (custom or otherwise)
**/
size_t size() const {
return m_Executables.size();
}
private:
std::vector<Executable>::iterator findExe(const QString &title);
@@ -173,4 +200,6 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Executable::Flags)
#endif // EXECUTABLESLIST_H
-200
View File
@@ -1,200 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FomodInstallerDialog</class>
<widget class="QDialog" name="FomodInstallerDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>662</width>
<height>501</height>
</rect>
</property>
<property name="windowTitle">
<string>FOMOD Installation Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="nameEdit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="horizontalSpacing">
<number>15</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Author</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="authorLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Version</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="versionLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Website</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="websiteLabel">
<property name="text">
<string>&lt;a href=&quot;#&quot;&gt;Link&lt;/a&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTextEdit" name="descriptionText">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="screenshotLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QStackedWidget" name="stepsStack">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="manualBtn">
<property name="text">
<string>Manual</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="prevBtn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="nextBtn">
<property name="text">
<string>Next</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelBtn">
<property name="text">
<string>Cancel</string>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

Some files were not shown because too many files have changed in this diff Show More