Compare commits

..
Author SHA1 Message Date
Tannin 25348238b2 bugfix: translations for configurator plugin weren't named correctly 2015-01-08 20:07:58 +01:00
Tannin 8b3a42bd17 bugfix: translations for plugins were not used 2015-01-08 20:07:32 +01:00
Tannin 6f1162c23f bugfix: showEvent contains initializion code that should be run only on first start of the application 2015-01-08 20:06:56 +01:00
Tannin 2b21463514 - download servers that haven't been available for over a month are now purged from the known servers list
- bugfix: encoding detection for fomod xmls could incorrectly interpret files as utf16 encoded
- bugfix: hashing algorithm for bsa files was wrong
- bugfix: nxmhandler reported non-issues as errors
- bugfix: nxmhandler tried to apply chrome fix on every start
- bugfix: "not endorsed" icon displayed for non-nexus mods
- bugfix: when drag&dropping within the overwrite dialog the file might still get moved to a mod (and probably not the intended one)
- bugfix: dropping files from overwrite on the modlist was refused when not sorting by priority (only in 1.2.15)
- bugfix: unmanaged mods couldn't be reordered (only in 1.2.15)
2015-01-07 23:13:40 +01:00
Tannin d20a26e0eb Added tag release v1.2.15 for changeset d1946676ce17 2015-01-07 23:09:58 +01:00
Tannin 459816ab71 updated packaging and build scripts 2015-01-03 15:09:25 +01:00
Tannin 9b5c238938 - repository info is now stored with the mod 2015-01-03 12:35:25 +01:00
Tannin e7b6a7cbdd - bugfix: no exec info returned for .exe
- bugfix: wide string conversion functions seem to have failed for empty string
2015-01-03 12:34:26 +01:00
Tannin ab925e1e7c added/updated translation files 2014-12-20 17:25:12 +01:00
Tannin 7bfb48d6ab cleanup 2014-12-20 14:45:08 +01:00
Tannin 88817c7f3b - drag&drop in the plugin list now also prompts a message instead of being impossible 2014-12-20 14:44:40 +01:00
Tannin ee0041ba18 - bugfix: file extensions when adding executables were treated case sensitive
- exe files are now started directly, not through cmd
2014-12-20 14:43:22 +01:00
Tannin 306ba78b0f bugfix: when merging mods with a custom installer, various ini settings (incl. category) were reset 2014-12-20 14:42:43 +01:00
Tannin e33406b4b5 endorsing is now only offered for mods with a valid nexus id 2014-12-20 14:42:00 +01:00
Tannin a5906f1044 workaround to prevent executables dialog from auto-selecting the top-most executable 2014-12-20 14:41:28 +01:00
Tannin ebfeb2fbf9 - mod-list can now be re-ordered with drag&drop while grouping is active
- drag&drop is not disabled when ordering by other columns than priority. MO will notify using messagedialog that it's impossible instead.
2014-12-14 18:25:26 +01:00
Tannin f666e3d835 when reinstalling a mod the existing mods name is used by default 2014-12-14 16:32:57 +01:00
Tannin 003cb6dec5 if a shortcut-started application is the same binary as a configured one, the corresponding steam app id is used 2014-12-14 16:32:30 +01:00
Tannin 7fb7207ac7 custom installers can now set the installation file (and the ncc installer now does) 2014-12-14 16:30:23 +01:00
Tannin 64eced4614 - NCC installer can now discover files in other mods (thanks Reunion!) and knows the script extender version 2014-12-13 16:47:11 +01:00
Tannin 8634b97bea all executables can now be repositioned, including auto-detected ones 2014-12-09 20:02:28 +01:00
Tannin 116a36b943 searching for steam process will no longer fail when more than 1024 processes are running (and steam is past the 1024th) 2014-12-09 18:35:32 +01:00
Tannin 479fdb3dcd removed use of ModInfo::internalName 2014-12-09 18:34:09 +01:00
Tannin acf35da699 now stored installed files with each mod 2014-12-09 18:09:11 +01:00
Tannin 6eb05396e4 bugfix: hitting the fix button in the diagnosis plugin could crash MO if the
line didn't have mouse focus
2014-12-04 19:30:07 +01:00
Tannin 9fcf34fec7 bugfix: ini tweaks were not applied in priority order 2014-12-04 19:27:55 +01:00
Tannin 6c1e63258c minor fixes 2014-12-04 19:25:07 +01:00
Tannin 226993eece - added error handling when a file can't be deleted from vfs
- minor bugfixes
2014-12-01 18:44:37 +01:00
Tannin 78da5fc37f more bugfixes 2014-11-26 20:22:00 +01:00
Tannin ffef339e2b several bugfixes from the bugfix-wc that I forgot to backport 2014-11-26 20:21:33 +01:00
Tannin 4fa700bb55 undid some changes that accidentally made it to this branch 2014-11-26 20:19:07 +01:00
Tannin 9907437d93 - fixed manifest for qt5
- download messages can now be sent from different user accounts
2014-11-14 23:33:49 +01:00
Tannin 3b7a468f73 - updated staging script to use qt5 and to fetch translations from transifex
- removed call to function unavailable in Windows XP
2014-11-11 23:48:22 +01:00
Tannin 0b14949d0e some work on installer scripts 2014-11-11 21:41:22 +01:00
Tannin 2237d7c103 - re-enabled use of img-tags in bbcode converter
- addded a workaround for cases where, after a MO update, the stored modlist layout has no size for new columns
- using a webview again for the nexus view of the modinfo dialog
2014-11-11 21:46:16 +01:00
Tannin 1eea3bd90e - bsa parser will now cancel in case of a read error. Before, when attempting to parse a broken bsa it could take forever and continuously allocate memory
- better error message when bsa parsing fails
- slightly better support for font colors in bbcode converter
- configurator now also uses pyqt5
- bugfix: bsa hashing function converted backslashes to slashes instead of the other way around. hash calculation is still often wrong on folder names...
2014-11-09 14:01:48 +01:00
Tannin 20db939501 - workaround for GetModuleFileName-calls that supply wrong buffer size
- removed obsoleted calls to GetVersionEx
- bugfix: download urls were potentially not encoded correctly
- bugfixes to tls-based recursion protection
2014-11-06 00:03:44 +01:00
Tannin bfa6c9ab1e - moved the hook-recursion-protection to tls
- some code cleanup and consolidation
- hook.dll will now report all of its own exceptions
- some more logging during startup
- changed the way urls are encoded for download requests
- now displaying (one of the) process name(s) while waiting for a program to end
- bugfix: spawned processes were forced to leave the job
2014-09-29 20:35:35 +02:00
Tannin 7a7c464b18 - archive library can now query for password during extraction (seems to be necessary for rars)
- process blacklist is now taken from a file if there is one, not hardcoded
- removed workaround for the papyrus compiler
- updated loot client to work with the actual api
- loot client now links with loot32.dll at runtime
- loot client now produces its output in a (json-)file which includes all plugin messages and dirty flags
- fomod installer now tries to parse the xml with several encodings
- fomod installer will now display a diagnostics warning if the jpg imageformat isn't supported
- base preview plugin now tries to be a bit smarter about resizing images to fit the screen
- bugfix: fomod installer no longer tries to open an image even after detecting its invalid
- bugfix: potential null-pointer dereferentiation in getprivateprofile... hooks
- bugfix: potential null-pointer dereferentiation in download manager
- bugfix: internal origin name showed up in one more place
- bugfix: ToString function produced strings that were one (zero-termination-)character too long
2014-11-05 23:48:06 +01:00
Tannin a62ecc5bf1 - several style fixes suggested by static analysis
- will now support up to 4 levels of version numbers (major.minor.subminor.subsubminor
2014-09-24 19:51:51 +02:00
Tannin 5f1022917b - removed a use of wostringstream which seems to have been involved in a bug. Still not sure how
- rewrote widechar <-> multibyte conversion functions to handle arbitrary string lengths
2014-09-19 22:01:37 +02:00
Tannin b77dcb2206 non-mo mods now have a constructed name that cannot conflict with a regular mod 2014-09-10 20:44:39 +02:00
Tannin 430048d201 when MO fails to overwrite its ini file it tries another method using qt functions 2014-09-10 20:43:33 +02:00
Tannin 4c42a6fbf1 plugins can now query the list of masters for a plugin 2014-09-10 20:37:17 +02:00
Tannin 243b59c64c profiles are now created with an (empty) archives.txt 2014-09-10 20:35:57 +02:00
Tannin b0a4748da5 - descriptions for plugin settings are now displayed 2014-09-10 20:34:31 +02:00
Tannin 9daeb9479b - re-enabled building of loot_cli and started developing against the new api
- extended set of default categories
- more tolerand bbcode parser
- added a few colors for the bbcode parser
- more fixes to qt5 compatibility
- started work on ability to unloading (and thus re-loading) of plugins
- names of plugins are no longer localizable (because those names are also used to store settings)
- added settings to disable individual diagnosis settings
- path of dependencies is now configured in a .pri file instead of environment variablees
- bugfix: if the modid-input is canceled, the id was saved as -1 and wasn't re-requested from the user
- bugfix: moving files with the SHFileOperation-Api didn't update the vfs correctly (still not perfect but better)
- bugfix: attempt to remove the deleter-file seems to have caused error messages for some users
- bugfix: fixed a couple of cases that might have caused the tutorial to hang
2014-09-08 20:37:23 +02:00
Tannin 07bae15d7c - bugfix: MO would report invalid index errors when downloading while download list is sorted by filetime descending 2014-08-25 21:07:29 +02:00
Tannin 778160cf0d - processes spawned from MO are now themselves allowed to break away from the job.
Without this the CEF (chromium embedded framework) seems to fail
- bugfix: Fixed an error message when installing a fomod wrapped in an archive
- bugfix: sorting plugins had no effect on non-skyrim games
- bugfix: fomod parser quit installing filelists after one file
- bugfix: function retrieving local appdata path read wrong directory
2014-08-25 20:12:25 +02:00
Tannin 14106436ca - bugfix: mods were specified by internal name in archive and data tab 2014-08-19 18:44:35 +02:00
Tannin 4f509e365e - new plugin-api to determine the origin of a file 2014-08-18 23:01:25 +02:00
Tannin 4ebc8dc014 - bugfix: text files weren't displayed in the mod-info-dialog 2014-08-18 23:01:02 +02:00
Tannin 5d3c1f34f4 - login package now also uses a "proper" user-agent 2014-08-18 22:57:00 +02:00
Tannin 844ba99892 - performance optimizations for detection of file changes in mod directories
- added a workaround for download-link handling in chrome
- MO will now create a profile even if the game-launcher has never been run
- bugfix: files weren't cleanly removed from vfs file register
2014-08-01 12:10:49 +02:00
Tannin 715623e790 - browser dialog now has a hidden url-field (for testing only)
- loot_cli is no longer part of this project. I will probably create a fork of loot that allows command-line usage instead
- loot integration now works with such a modified loot version
- integrated loot will now also integrate incompatibility messages in the MO UI
- overwrite-markers are now updated as the list order is changed
- fnis checker will now always allow the user to ignore fnis errors
- plugin interface now has a function to wait for handles returned from startApplication (which can be job or process handles)
- bugfix: non-mo mods sharing the name with regular mods now have a different internal name
- bugfix: using hotkeys the vanilla game-plugins could be moved
2014-07-27 18:34:32 +02:00
Tannin 9879aae575 - download-list will no longer show a file as having incomplete data if there is no file version
- added a new mod column with icons displaying the content of the mod
- MO now differentiates between mods using an internal name that disambiguates between foreign and regular mods
2014-07-21 19:14:24 +02:00
Tannin cc9827cdda normalized eol style (all files should now have windows line endings) 2014-07-17 22:02:15 +02:00
Tannin 4e5a67fc06 - bugfix: broke qt4 compatibility in trying to support qt5
- bugfix: overwrite dialog displayed system drives if the overwrite directory didn't exist
- bugfix: ini tweak activation wasn't saved
2014-07-17 20:04:22 +02:00
Tannin 67b0268e70 - qt 5 compatibility fixes
- detection for support of optimized find no longer depends on deprecated api
2014-07-15 17:31:44 +02:00
Tannin b1ac479fb6 slight fixes to qt5 compatibility 2014-07-03 17:42:31 +02:00
Tannin 80b10107d9 - Disabled compilation of loot_cli as the current loot version can't be compiled or linked against with vs 2010
- bugfix: some incompatibilities with non-skyrim games
- bugfix: incorrect handling of plurals in translateable strings
2014-07-15 20:37:10 +02:00
TheBloke 1707941f6e deleteSavegame:
- Confirmation question shows number of saves to be deleted, when more than 1
2014-07-13 16:11:30 +01:00
TheBloke d0b75e8b25 savegameList: more minor changes
- Context Menu - can do same job with fewer variables and assignments
- deleteSaveGame_clicked - const reference, not new value, in foreach loop
2014-07-13 15:45:19 +01:00
TheBloke 4fc441b249 savegameList:
- Context menu bugfix, previous method of getting rows didn't work when items
 were selected in certain ways, e.g. Control-A
- Context menu now uses selectedIndexes(), which always works with all selections.
- Renamed enableFixMods to multipleSelected so same value can be used to decide
 whether to show single or plural version of "Delete save(s)"
2014-07-13 15:24:46 +01:00
TheBloke 581d065d7a savegameList: A few cleanups and minor code improvements
- Slight improvements over previous commits, using more appropriate methods and
 removing some unnecessary code. No functional changes.
2014-07-12 11:15:34 +01:00
TheBloke 5d2b5202af - savegameList: Improved save game handling from MainWindow
-- Save game deletion now does Recycle Bin delete (wishlist #675)
-- Save game deletion now also deletes .skse file (bug #687)
-- Can select and delete multiple save games (ExtendedSelection) (wishlist #675)
-- Uses new SaveGame->saveFiles() method to get filenames (eg .ess & .skse)
-- Context menu - "Fix Mods.." option only appears if 1 save is selected
-- Context menu - delete menu option labelled "Delete save" or "Delete saves",
 according to 1 or >1 saves selected.
-- Context menu - delete menu confirmation shows list of all selected saves
2014-07-11 01:46:42 +01:00
TheBloke 8044ef4f1d - Save game management: re-factored getting of filenames including .skse
-- New - SaveGame->saveFiles(), returns all filenames for save (eg. ess + skse)
-- Moved - SaveGameGameBryo->attachedFiles() to SaveGame->attachedFiles()
-- This allows the getting of save file names with just a SaveGame object, not
 a GameBryo object, which would do a full file read including plugins and image etc.
-- Therefore SaveGame is no longer abstract.

- Transfer Saves: re-factored to use new SaveGame->saveFiles() method
-- Removed - TransferSavesDialog->getFilesToProcess, now redundant as information
 is now provided by SaveGame class itself.
2014-07-11 01:29:33 +01:00
TheBloke 3d98491ebc Additional 'make install' step - install boost_python DLL to output(d)\DLLs
Extended the new ModOrganizer.pro 'make install' steps, to now also copy
  $$(BOOSTPATH)\stage\lib\boost_python-vc*-mt-1*.dll
 This is the final install step required, so that now ModOrganizer.exe works
  fully when a Qt-Creator "Run" step is performed.
 The wildcard should pick up the right version of the library regardless of
  MSVC compiler version used.

Updated Qt5 version check to the standardised greaterThan check.
2014-07-08 04:05:33 +01:00
TheBloke 923654961b Compilation dependency tracking enabled for organizer, hook, bsaExtractor, shared
Previously, qmake did not detect when code was changed in the static libraries
 So for example, changing code in shared/*.cpp and then Build, would not cause
  a re-link and re-deploy of ModOrganizer.exe.
 This has been fixed by adding PRE_TARGETDEPS references to each project that
  depend on static libraries provided by other sub-projects.
 These checks are conditional on debug|release, to point to the correct lib.

 List of currently configured static library dependency checks -
  organizer - mo_shared.lib, bsatk.lib
  hookdll - mo_shared.lib, bsatk.lib
  shared - bsatk.lib
  bsaExtractor - bsatk.lib

 I have tested to confirm that changing a shared file results in re-linking and
  re-deplomyent of both ModOrganizer.exe and hook.dll.

 Note that dependencies have not been configured for DLLs, as these are
  loaded dynamically and so recompilation is not required.
  But there could be an argument for configuring DLLs as dependencies too -
   as if you make a change in DLL code, you might want all clients of the DLL to
    be recompiled to check that they have not been broken by the changes?
  The downside of that would be extra re-compilation every time.
2014-07-08 04:01:24 +01:00
TheBloke 76c861ed12 .pro files - formatting/consistency fixes
Many small formatting changes to the majority of .pro files
 Consistent style for Qt version checking, using greaterThan(QT_MAJOR_VERSION, 4)
  This seems safest, as would continue to work for a future Qt 6 etc.
  Note that this makes redudundant the commit before this one, to organizer.pro
 Consistent indenting
 Moved some file configuration sections to be together with related sections
 Moved some installation-related sections (e.g. OUTDIR/DSTDIR) to be at the bottom,
  immediately before the related POST_LINK install lines.
 Similarly, in some cases separated out CONFIG(debug,.. checks into separate
  LIB/INCLUDE sections (high in file) and installation directory sections (low
   in file)
2014-07-07 23:32:18 +01:00
TheBloke 31cab54861 organizer.pro - tiny tweak to Qt5 version check
Directly checking QT_MAJOR_VERSION instead of pattern matching on QT_VERSION
2014-07-07 21:51:35 +01:00
TheBloke 2a16cc4262 Added 'make install' steps in ModOrganizer.pro -
Added config to install required libraries to output(d) directory
 If the user adds a Deploy step, that runs 'jom install', he will have the
  necessary libraries copied to output(d)\dlls
 These libraries are -
  7z.dll
  Qt4 Core Declarative Gui Network OpenGL Script Sql Svg Webkit Xml XmlPatterns
   Different set configured for Qt5, e.g. adding Widgets, Qml, Quick
   In a debug build, the 'd' DLLs will be used instead.
   Qt4 libraries are copied from system Qt4 installation directory.
 This allows the Qt-Creator user to hit "Run" in Qt-C and end up with a complete
  install, including all DLLs; no manual Exporer copying required.
 This therefore removes the need for post-build steps 10 & 11 in Readme.txt.
 Future thought - Update all current POST_LINK (x)copy steps to make install?

Fixed DESTDIR in ModOrganizer.pro
 It was pointing to source/output(d) before, should be ..\output(d)
 It was not used before so didn't matter, but is now referenced for install.
2014-07-07 21:39:27 +01:00
182 changed files with 20765 additions and 59553 deletions
+1
View File
@@ -33,3 +33,4 @@ html
*.lib
syntax: regexp
Makefile\.(Debug|Release)
source/.*/debug/.*
+22 -8
View File
@@ -10,7 +10,7 @@ Please note that if you only want to work on and build a plugin you can save you
Overview:
---------
As of December 2013 MO consists of the following subprojects:
As of Juli 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
@@ -24,13 +24,14 @@ As of December 2013 MO consists of the following subprojects:
- 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 pyqt4
- 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
- installerBCF: no functionality. Supposed to eventually allow installations using bcfs (bain conversion file). python code
- 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)
@@ -39,7 +40,13 @@ And various plugins:
- 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:
-------------
@@ -50,13 +57,20 @@ Visual C++ compiler 2010 (VC 10.0) or up
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 4.8.x (http://qt-project.org/downloads)
- i.e. "Qt libraries 4.8.5 for Windows (VS 2010, 235 MB)"
- tested: 4.8.5
- Qt5 is not yet supported but WIP. You will see a few conditional qt5 pathes
- i.e. "Qt libraries 4.8.6 for Windows (VS 2010, 235 MB)"
- tested: 4.8.6
- Install according to instruction
Qt 5 Compatibility:
MO compiles and mostly runs correctly built with Qt 5.3 and VC++ 2013 but
- python plugins haven't been rewritten to use qt5 yet
- pyqt5 isn't distributed as binaries for python 2.7 so this needs to be set up and built first
- tutorial doesn't work because it seems to be impossible to create a transparent Qt Quick control...
- the previewdds plugin only compiles with the opengl variant of the qt 5 distribution
- Qt5 is a bi*** to distribute
boost libraries (http://www.boost.org/)
- tested: 1.49
- tested: 1.55
- Build according to their instructions (using vc++): http://www.boost.org/doc/libs/1_54_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)
@@ -105,8 +119,8 @@ Set up (using Qt Creator):
2. Open the "Projects" tab, open the "Details" for "Build Environment"
3a. Click "Add" to add a variable called "BOOSTPATH" with the path of your boost installation as the value (i.e. C:\code\boost_1_49_0)
3b. Click "Add" to add a variable called "ZLIBPATH" with the path of your zlib installation as the value (i.e. C:\code\zlib-1.2.7)
3c. Click "Add" to add a variable called "7ZIPPATH" with the path of your zlib installation as the value (i.e. C:\code\7zip)
3d. Click "Add" to add a variable called "PYTHONPATH" with the path of your zlib installation as the value (i.e. C:\code\python)
3c. Click "Add" to add a variable called "SEVENZIPPATH" with the path of your 7zip installation as the value (i.e. C:\code\7zip)
3d. Click "Add" to add a variable called "PYTHONPATH" with the path of your python installation as the value (i.e. C:\code\python)
4. Switch the build configuration at the very top of the same page from "debug" to "release" (or vice versa) and repeat step 3
5. Compile the configuration(s) you want to use (debug and/or release) (Build All). This should compile correctly.
6. <reserved for future use. Maybe grab a coffee?>
+31 -7
View File
@@ -1,6 +1,5 @@
TEMPLATE = subdirs
SUBDIRS = bsatk \
shared \
uibase \
@@ -13,15 +12,40 @@ SUBDIRS = bsatk \
nxmhandler \
BossDummy \
pythonRunner \
esptk \
loot_cli
esptk
plugins.depends = pythonRunner
pythonRunner.depends = uibase
plugins.depends = pythonRunner uibase
hookdll.depends = shared
organizer.depends = shared uibase plugins loot_cli
organizer.depends = shared uibase plugins
CONFIG(debug, debug|release) {
DESTDIR = outputd
DESTDIR = $$PWD/../outputd
} else {
DESTDIR = output
DESTDIR = $$PWD/../output
}
STATICDATAPATH = $${DESTDIR}\\..\\tools\\static_data\\dlls
DLLSPATH = $${DESTDIR}\\dlls
otherlibs.path = $$DLLSPATH
otherlibs.files += $${STATICDATAPATH}\\7z.dll \
$${BOOSTPATH}\\stage\\lib\\boost_python-vc*-mt-1*.dll
qtlibs.path = $$DLLSPATH
greaterThan(QT_MAJOR_VERSION, 4) {
QTLIBNAMES += Core Gui Network OpenGL Script Sql Svg Qml Quick Webkit Widgets Xml XmlPatterns
} else {
QTLIBNAMES += Core Declarative Gui Network OpenGL Script Sql Svg Webkit Xml XmlPatterns
}
QTLIBSUFFIX = $${QT_MAJOR_VERSION}.dll
CONFIG(debug, debug|release): QTLIBSUFFIX = "d$${QTLIBSUFFIX}" # Can't use Debug: .. here, it ignores the line - no idea why, as it works in BossDummy.pro
for(QTNAME, QTLIBNAMES) {
QTFILE = Qt$${QTNAME}
qtlibs.files += $$[QT_INSTALL_BINS]\\$${QTFILE}$${QTLIBSUFFIX}
}
INSTALLS += qtlibs otherlibs
+2
View File
@@ -35,6 +35,7 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent)
m_LicenseFiles[LICENSE_BOOST] = "boost.txt";
m_LicenseFiles[LICENSE_CCBY3] = "by-sa3.txt";
m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt";
m_LicenseFiles[LICENSE_APACHE2] = "apache-license-2.0.txt";
addLicense("Qt 4.8.5", LICENSE_LGPL3);
addLicense("Qt Json", LICENSE_GPL3);
@@ -46,6 +47,7 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent)
addLicense("NIF File Format Library", LICENSE_BSD3);
addLicense("BOSS (modified)", LICENSE_GPL3);
addLicense("Alphanum Algorithm", LICENSE_ZLIB);
addLicense("Castle Core", LICENSE_APACHE2);
ui->nameLabel->setText(QString("<span style=\"font-size:12pt; font-weight:600;\">%1 %2</span>").arg(ui->nameLabel->text()).arg(version));
#ifdef HGID
+2 -1
View File
@@ -48,7 +48,8 @@ private:
LICENSE_BSD3,
LICENSE_BOOST,
LICENSE_CCBY3,
LICENSE_ZLIB
LICENSE_ZLIB,
LICENSE_APACHE2
};
private:
+15
View File
@@ -178,6 +178,11 @@
<string notr="true">tokcdk (Russian)</string>
</property>
</item>
<item>
<property name="text">
<string>Ren (Korean)</string>
</property>
</item>
</widget>
</item>
</layout>
@@ -214,6 +219,16 @@
<string notr="true">Bridger</string>
</property>
</item>
<item>
<property name="text">
<string>GamerPoet</string>
</property>
</item>
<item>
<property name="text">
<string>Gopher</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">GSDFan</string>
+97 -97
View File
@@ -1,97 +1,97 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "activatemodsdialog.h"
#include "ui_activatemodsdialog.h"
#include <QComboBox>
#include <QLabel>
ActivateModsDialog::ActivateModsDialog(const std::map<QString, std::vector<QString> > &missingPlugins, QWidget *parent)
: TutorableDialog("ActivateMods", parent), ui(new Ui::ActivateModsDialog)
{
ui->setupUi(this);
QTableWidget *modsTable = findChild<QTableWidget*>("modsTable");
QHeaderView *headerView = modsTable->horizontalHeader();
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
headerView->setSectionResizeMode(1, QHeaderView::Interactive);
#else
headerView->setResizeMode(0, QHeaderView::Stretch);
headerView->setResizeMode(1, QHeaderView::Interactive);
#endif
int row = 0;
modsTable->setRowCount(missingPlugins.size());
for (std::map<QString, std::vector<QString> >::const_iterator espIter = missingPlugins.begin();
espIter != missingPlugins.end(); ++espIter, ++row) {
modsTable->setCellWidget(row, 0, new QLabel(espIter->first));
if (espIter->second.size() == 0) {
modsTable->setCellWidget(row, 1, new QLabel(tr("not found")));
} else {
QComboBox* combo = new QComboBox();
for (std::vector<QString>::const_iterator modIter = espIter->second.begin();
modIter != espIter->second.end(); ++modIter) {
combo->addItem(*modIter);
}
modsTable->setCellWidget(row, 1, combo);
}
}
}
ActivateModsDialog::~ActivateModsDialog()
{
delete ui;
}
std::set<QString> ActivateModsDialog::getModsToActivate()
{
std::set<QString> result;
QTableWidget *modsTable = findChild<QTableWidget*>("modsTable");
for (int row = 0; row < modsTable->rowCount(); ++row) {
QComboBox *comboBox = dynamic_cast<QComboBox*>(modsTable->cellWidget(row, 1));
if (comboBox != NULL) {
result.insert(comboBox->currentText());
}
}
return result;
}
std::set<QString> ActivateModsDialog::getESPsToActivate()
{
std::set<QString> result;
QTableWidget *modsTable = findChild<QTableWidget*>("modsTable");
for (int row = 0; row < modsTable->rowCount(); ++row) {
QComboBox *comboBox = dynamic_cast<QComboBox*>(modsTable->cellWidget(row, 1));
if (comboBox != NULL) {
QLabel *espName = dynamic_cast<QLabel*>(modsTable->cellWidget(row, 0));
result.insert(espName->text());
}
}
return result;
}
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "activatemodsdialog.h"
#include "ui_activatemodsdialog.h"
#include <QComboBox>
#include <QLabel>
ActivateModsDialog::ActivateModsDialog(const std::map<QString, std::vector<QString> > &missingPlugins, QWidget *parent)
: TutorableDialog("ActivateMods", parent), ui(new Ui::ActivateModsDialog)
{
ui->setupUi(this);
QTableWidget *modsTable = findChild<QTableWidget*>("modsTable");
QHeaderView *headerView = modsTable->horizontalHeader();
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
headerView->setSectionResizeMode(1, QHeaderView::Interactive);
#else
headerView->setResizeMode(0, QHeaderView::Stretch);
headerView->setResizeMode(1, QHeaderView::Interactive);
#endif
int row = 0;
modsTable->setRowCount(missingPlugins.size());
for (std::map<QString, std::vector<QString> >::const_iterator espIter = missingPlugins.begin();
espIter != missingPlugins.end(); ++espIter, ++row) {
modsTable->setCellWidget(row, 0, new QLabel(espIter->first));
if (espIter->second.size() == 0) {
modsTable->setCellWidget(row, 1, new QLabel(tr("not found")));
} else {
QComboBox* combo = new QComboBox();
for (std::vector<QString>::const_iterator modIter = espIter->second.begin();
modIter != espIter->second.end(); ++modIter) {
combo->addItem(*modIter);
}
modsTable->setCellWidget(row, 1, combo);
}
}
}
ActivateModsDialog::~ActivateModsDialog()
{
delete ui;
}
std::set<QString> ActivateModsDialog::getModsToActivate()
{
std::set<QString> result;
QTableWidget *modsTable = findChild<QTableWidget*>("modsTable");
for (int row = 0; row < modsTable->rowCount(); ++row) {
QComboBox *comboBox = dynamic_cast<QComboBox*>(modsTable->cellWidget(row, 1));
if (comboBox != NULL) {
result.insert(comboBox->currentText());
}
}
return result;
}
std::set<QString> ActivateModsDialog::getESPsToActivate()
{
std::set<QString> result;
QTableWidget *modsTable = findChild<QTableWidget*>("modsTable");
for (int row = 0; row < modsTable->rowCount(); ++row) {
QComboBox *comboBox = dynamic_cast<QComboBox*>(modsTable->cellWidget(row, 1));
if (comboBox != NULL) {
QLabel *espName = dynamic_cast<QLabel*>(modsTable->cellWidget(row, 0));
result.insert(espName->text());
}
}
return result;
}
+70 -70
View File
@@ -1,70 +1,70 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACTIVATEMODSDIALOG_H
#define ACTIVATEMODSDIALOG_H
#include "tutorabledialog.h"
#include <map>
#include <set>
namespace Ui {
class ActivateModsDialog;
}
/**
* @brief Dialog that is used to batch activate/deactivate mods and plugins
**/
class ActivateModsDialog : public MOBase::TutorableDialog
{
Q_OBJECT
public:
/**
* @brief constructor
*
* @param missingPlugins a map containing missing plugins that need to be activated
* @param parent ... Defaults to 0.
**/
explicit ActivateModsDialog(const std::map<QString, std::vector<QString> > &missingPlugins, QWidget *parent = 0);
~ActivateModsDialog();
/**
* @brief get a list of mods that the user chose to activate
*
* @note This can of ocurse only be called after the dialog has been displayed
*
* @return set< QString > the mods to activate
**/
std::set<QString> getModsToActivate();
/**
* @brief get a list of plugins that should be activated
*
* @return set< QString > the plugins to activate. This contains only plugins that become available after enabling the mods retrieved with getModsToActivate
**/
std::set<QString> getESPsToActivate();
private slots:
private:
Ui::ActivateModsDialog *ui;
};
#endif // ACTIVATEMODSDIALOG_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACTIVATEMODSDIALOG_H
#define ACTIVATEMODSDIALOG_H
#include "tutorabledialog.h"
#include <map>
#include <set>
namespace Ui {
class ActivateModsDialog;
}
/**
* @brief Dialog that is used to batch activate/deactivate mods and plugins
**/
class ActivateModsDialog : public MOBase::TutorableDialog
{
Q_OBJECT
public:
/**
* @brief constructor
*
* @param missingPlugins a map containing missing plugins that need to be activated
* @param parent ... Defaults to 0.
**/
explicit ActivateModsDialog(const std::map<QString, std::vector<QString> > &missingPlugins, QWidget *parent = 0);
~ActivateModsDialog();
/**
* @brief get a list of mods that the user chose to activate
*
* @note This can of ocurse only be called after the dialog has been displayed
*
* @return set< QString > the mods to activate
**/
std::set<QString> getModsToActivate();
/**
* @brief get a list of plugins that should be activated
*
* @return set< QString > the plugins to activate. This contains only plugins that become available after enabling the mods retrieved with getModsToActivate
**/
std::set<QString> getESPsToActivate();
private slots:
private:
Ui::ActivateModsDialog *ui;
};
#endif // ACTIVATEMODSDIALOG_H
+274 -234
View File
File diff suppressed because it is too large Load Diff
+40 -40
View File
@@ -1,40 +1,40 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BBCODE_H
#define BBCODE_H
#include <QString>
namespace BBCode {
/**
* @brief convert a string with BB Code-Tags to HTML
* @param input the input string with BB tags
* @param replaceOccured if not NULL, this parameter will be set to true if any bb tags were replaced
* @return the same string in html representation
**/
QString convertToHTML(const QString &input);
}
#endif // BBCODE_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BBCODE_H
#define BBCODE_H
#include <QString>
namespace BBCode {
/**
* @brief convert a string with BB Code-Tags to HTML
* @param input the input string with BB tags
* @param replaceOccured if not NULL, this parameter will be set to true if any bb tags were replaced
* @return the same string in html representation
**/
QString convertToHTML(const QString &input);
}
#endif // BBCODE_H
+296 -270
View File
File diff suppressed because it is too large Load Diff
+128 -124
View File
@@ -1,124 +1,128 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BROWSERDIALOG_H
#define BROWSERDIALOG_H
#include "browserview.h"
#include "tutorialcontrol.h"
#include <QDialog>
#include <QProgressBar>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QTimer>
#include <QWebView>
#include <QQueue>
#include <QTabWidget>
#include <QAtomicInt>
namespace Ui {
class BrowserDialog;
}
/**
* @brief a dialog containing a webbrowser that is intended to browse the nexus network
**/
class BrowserDialog : public QDialog
{
Q_OBJECT
public:
/**
* @brief constructor
*
* @param accessManager the access manager to use for network requests
* @param parent parent widget
**/
explicit BrowserDialog(QWidget *parent = 0);
~BrowserDialog();
/**
* @brief set the url to open. If automatic login is enabled, the url is opened after login
*
* @param url the url to open
**/
void openUrl(const QUrl &url);
signals:
/**
* @brief emitted when the user starts a download
* @param pageUrl url of the current web site from which the download was started
* @param reply network reply of the started download
*/
void requestDownload(const QUrl &pageUrl, QNetworkReply *reply);
protected:
virtual void closeEvent(QCloseEvent *);
private slots:
void initTab(BrowserView *newView);
void openInNewTab(const QUrl &url);
void progress(int value);
void titleChanged(const QString &title);
void unsupportedContent(QNetworkReply *reply);
void downloadRequested(const QNetworkRequest &request);
void tabCloseRequested(int index);
void urlChanged(const QUrl &url);
void on_backBtn_clicked();
void on_fwdBtn_clicked();
void on_searchEdit_returnPressed();
void startSearch();
void on_refreshBtn_clicked();
void on_browserTabWidget_currentChanged(int index);
private:
QString guessFileName(const QString &url);
BrowserView *getCurrentView();
void maximizeWidth();
private:
Ui::BrowserDialog *ui;
QNetworkAccessManager *m_AccessManager;
QTabWidget *m_Tabs;
};
#endif // BROWSERDIALOG_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BROWSERDIALOG_H
#define BROWSERDIALOG_H
#include "browserview.h"
#include "tutorialcontrol.h"
#include <QDialog>
#include <QProgressBar>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QTimer>
#include <QWebView>
#include <QQueue>
#include <QTabWidget>
#include <QAtomicInt>
namespace Ui {
class BrowserDialog;
}
/**
* @brief a dialog containing a webbrowser that is intended to browse the nexus network
**/
class BrowserDialog : public QDialog
{
Q_OBJECT
public:
/**
* @brief constructor
*
* @param accessManager the access manager to use for network requests
* @param parent parent widget
**/
explicit BrowserDialog(QWidget *parent = 0);
~BrowserDialog();
/**
* @brief set the url to open. If automatic login is enabled, the url is opened after login
*
* @param url the url to open
**/
void openUrl(const QUrl &url);
virtual bool eventFilter(QObject *object, QEvent *event);
signals:
/**
* @brief emitted when the user starts a download
* @param pageUrl url of the current web site from which the download was started
* @param reply network reply of the started download
*/
void requestDownload(const QUrl &pageUrl, QNetworkReply *reply);
protected:
virtual void closeEvent(QCloseEvent *);
private slots:
void initTab(BrowserView *newView);
void openInNewTab(const QUrl &url);
void progress(int value);
void titleChanged(const QString &title);
void unsupportedContent(QNetworkReply *reply);
void downloadRequested(const QNetworkRequest &request);
void tabCloseRequested(int index);
void urlChanged(const QUrl &url);
void on_backBtn_clicked();
void on_fwdBtn_clicked();
void on_searchEdit_returnPressed();
void startSearch();
void on_refreshBtn_clicked();
void on_browserTabWidget_currentChanged(int index);
void on_urlEdit_returnPressed();
private:
QString guessFileName(const QString &url);
BrowserView *getCurrentView();
void maximizeWidth();
private:
Ui::BrowserDialog *ui;
QNetworkAccessManager *m_AccessManager;
QTabWidget *m_Tabs;
};
#endif // BROWSERDIALOG_H
+27 -2
View File
@@ -17,7 +17,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -180,7 +189,16 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -237,6 +255,13 @@
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="urlEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
+75 -76
View File
@@ -1,76 +1,75 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "browserview.h"
#include <QEvent>
#include <QKeyEvent>
#include <QWebFrame>
#include <QWebElement>
#include <QNetworkDiskCache>
#include <QMenu>
#include <Shlwapi.h>
#include "utility.h"
BrowserView::BrowserView(QWidget *parent)
: QWebView(parent)
{
installEventFilter(this);
page()->settings()->setMaximumPagesInCache(10);
}
QWebView *BrowserView::createWindow(QWebPage::WebWindowType)
{
BrowserView *newView = new BrowserView(parentWidget());
emit initTab(newView);
return newView;
}
bool BrowserView::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::ShortcutOverride) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->matches(QKeySequence::Find)) {
emit startFind();
} else if (keyEvent->matches(QKeySequence::FindNext)) {
emit findAgain();
}
} else if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::MidButton) {
mouseEvent->ignore();
return true;
}
} else if (event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::MidButton) {
QWebHitTestResult hitTest = page()->frameAt(mouseEvent->pos())->hitTestContent(mouseEvent->pos());
if (hitTest.linkUrl().isValid()) {
emit openUrlInNewTab(hitTest.linkUrl());
}
mouseEvent->ignore();
return true;
}
}
return QWebView::eventFilter(obj, event);
}
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "browserview.h"
#include <QEvent>
#include <QKeyEvent>
#include <QWebFrame>
#include <QWebElement>
#include <QNetworkDiskCache>
#include <QMenu>
#include <Shlwapi.h>
#include "utility.h"
BrowserView::BrowserView(QWidget *parent)
: QWebView(parent)
{
installEventFilter(this);
page()->settings()->setMaximumPagesInCache(10);
}
QWebView *BrowserView::createWindow(QWebPage::WebWindowType)
{
BrowserView *newView = new BrowserView(parentWidget());
emit initTab(newView);
return newView;
}
bool BrowserView::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::ShortcutOverride) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->matches(QKeySequence::Find)) {
emit startFind();
} else if (keyEvent->matches(QKeySequence::FindNext)) {
emit findAgain();
}
} else if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::MidButton) {
mouseEvent->ignore();
return true;
}
} else if (event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::MidButton) {
QWebHitTestResult hitTest = page()->frameAt(mouseEvent->pos())->hitTestContent(mouseEvent->pos());
if (hitTest.linkUrl().isValid()) {
emit openUrlInNewTab(hitTest.linkUrl());
}
mouseEvent->ignore();
return true;
}
}
return QWebView::eventFilter(obj, event);
}
+80 -80
View File
@@ -1,80 +1,80 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NEXUSVIEW_H
#define NEXUSVIEW_H
#include "finddialog.h"
#include <QWebView>
#include <QWebPage>
#include <QTabWidget>
/**
* @brief web view used to display a nexus page
**/
class BrowserView : public QWebView
{
Q_OBJECT
public:
explicit BrowserView(QWidget *parent = 0);
signals:
/**
* @brief emitted when the user opens a new window to be displayed in another tab
*
* @param newView the view for the newly opened window
**/
void initTab(BrowserView *newView);
/**
* @brief emitted when the user requests a link to be opened in a new tab by middle-clicking
*
* @param url the url to open
*/
void openUrlInNewTab(const QUrl &url);
/**
* @brief Ctrl-f was clicked. The containing dialog should activate its find-facility
*/
void startFind();
/**
* @brief F3 was pressed. The containing dialog should search again
*/
void findAgain();
protected:
virtual QWebView *createWindow(QWebPage::WebWindowType type);
virtual bool eventFilter(QObject *obj, QEvent *event);
private:
QString m_FindPattern;
bool m_MiddleClick;
};
#endif // NEXUSVIEW_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NEXUSVIEW_H
#define NEXUSVIEW_H
#include "finddialog.h"
#include <QWebView>
#include <QWebPage>
#include <QTabWidget>
/**
* @brief web view used to display a nexus page
**/
class BrowserView : public QWebView
{
Q_OBJECT
public:
explicit BrowserView(QWidget *parent = 0);
signals:
/**
* @brief emitted when the user opens a new window to be displayed in another tab
*
* @param newView the view for the newly opened window
**/
void initTab(BrowserView *newView);
/**
* @brief emitted when the user requests a link to be opened in a new tab by middle-clicking
*
* @param url the url to open
*/
void openUrlInNewTab(const QUrl &url);
/**
* @brief Ctrl-f was clicked. The containing dialog should activate its find-facility
*/
void startFind();
/**
* @brief F3 was pressed. The containing dialog should search again
*/
void findAgain();
protected:
virtual QWebView *createWindow(QWebPage::WebWindowType type);
virtual bool eventFilter(QObject *obj, QEvent *event);
private:
QString m_FindPattern;
bool m_MiddleClick;
};
#endif // NEXUSVIEW_H
+319 -301
View File
File diff suppressed because it is too large Load Diff
+200 -200
View File
@@ -1,200 +1,200 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CATEGORIES_H
#define CATEGORIES_H
#include <QString>
#include <vector>
#include <map>
#include <functional>
/**
* @brief Manage the available mod categories
* @warning member functions of this class currently use a wild mix of ids and indexes to look up categories,
* optimized to where the request comes from. Therefore be very careful which of the two you have available
**/
class CategoryFactory {
friend class CategoriesDialog;
public:
static const int CATEGORY_NONE = 0;
static const int CATEGORY_SPECIAL_FIRST = 10000;
static const int CATEGORY_SPECIAL_CHECKED = CATEGORY_SPECIAL_FIRST;
static const int CATEGORY_SPECIAL_UNCHECKED = 10001;
static const int CATEGORY_SPECIAL_UPDATEAVAILABLE = 10002;
static const int CATEGORY_SPECIAL_NOCATEGORY = 10003;
static const int CATEGORY_SPECIAL_CONFLICT = 10004;
static const int CATEGORY_SPECIAL_NOTENDORSED = 10005;
static const int CATEGORY_SPECIAL_MANAGED = 10006;
static const int CATEGORY_SPECIAL_UNMANAGED = 10007;
public:
struct Category {
Category(int sortValue, int id, const QString &name, const std::vector<int> &nexusIDs, int parentID)
: m_SortValue(sortValue), m_ID(id), m_Name(name), m_HasChildren(false),
m_NexusIDs(nexusIDs), m_ParentID(parentID) {}
int m_SortValue;
int m_ID;
int m_ParentID;
bool m_HasChildren;
QString m_Name;
std::vector<int> m_NexusIDs;
friend bool operator<(const Category &LHS, const Category &RHS) {
return LHS.m_SortValue < RHS.m_SortValue;
}
};
public:
/**
* @brief reset the list of categories
**/
void reset();
/**
* @brief save the categories to the categories.dat file
**/
void saveCategories();
/**
* @brief retrieve the number of available categories
*
* @return unsigned int number of categories
**/
unsigned numCategories() const { return m_Categories.size(); }
/**
* @brief count all categories that match a specified filter
* @param filter the filter to test
* @return number of matching categories
*/
unsigned int countCategories(std::tr1::function<bool (const Category &category)> filter);
/**
* @brief get the id of the parent category
*
* @param index the index to look up
* @return int id of the parent category
**/
int getParentID(unsigned int index) const;
/**
* @brief determine if a category exists (by id)
*
* @param id the id to check for existance
* @return true if the category exists, false otherwise
**/
bool categoryExists(int id) const;
/**
* @brief test if a category is child of a second one
* @param id the presumed child id
* @param parentID the parent id to test for
* @return true if id is a child of parentID
**/
bool isDecendantOf(int id, int parentID) const;
/**
* @brief test if the specified category has child categories
*
* @param index index of the category to look up
* @return bool true if the category has child categories
**/
bool hasChildren(unsigned int index) const;
/**
* @brief retrieve the name of a category
*
* @param index index of the category to look up
* @return QString name of the category
**/
QString getCategoryName(unsigned int index) const;
/**
* @brief look up the id of a category by its index
*
* @param index index of the category to look up
* @return int id of the category
**/
int getCategoryID(unsigned int index) const;
/**
* @brief look up the index of a category by its id
*
* @param id index of the category to look up
* @return unsigned int index of the category
**/
int getCategoryIndex(int ID) const;
/**
* @brief retrieve the index of a category by its nexus id
*
* @param nexusID nexus id of the category to look up
* @return unsigned int index of the category or 0 if no category matches
**/
unsigned int resolveNexusID(int nexusID) const;
public:
/**
* @brief retrieve a reference to the singleton instance
*
* @return the reference to the singleton
**/
static CategoryFactory &instance();
/**
* @return path to the file that contains the categories list
*/
static QString categoriesFilePath();
private:
CategoryFactory();
void loadDefaultCategories();
void addCategory(int id, const QString &name, const std::vector<int> &nexusID, int parentID);
void setParents();
static void cleanup();
private:
static CategoryFactory *s_Instance;
std::vector<Category> m_Categories;
std::map<int, unsigned int> m_IDMap;
std::map<int, unsigned int> m_NexusMap;
private:
};
#endif // CATEGORIES_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CATEGORIES_H
#define CATEGORIES_H
#include <QString>
#include <vector>
#include <map>
#include <functional>
/**
* @brief Manage the available mod categories
* @warning member functions of this class currently use a wild mix of ids and indexes to look up categories,
* optimized to where the request comes from. Therefore be very careful which of the two you have available
**/
class CategoryFactory {
friend class CategoriesDialog;
public:
static const int CATEGORY_NONE = 0;
static const int CATEGORY_SPECIAL_FIRST = 10000;
static const int CATEGORY_SPECIAL_CHECKED = CATEGORY_SPECIAL_FIRST;
static const int CATEGORY_SPECIAL_UNCHECKED = 10001;
static const int CATEGORY_SPECIAL_UPDATEAVAILABLE = 10002;
static const int CATEGORY_SPECIAL_NOCATEGORY = 10003;
static const int CATEGORY_SPECIAL_CONFLICT = 10004;
static const int CATEGORY_SPECIAL_NOTENDORSED = 10005;
static const int CATEGORY_SPECIAL_MANAGED = 10006;
static const int CATEGORY_SPECIAL_UNMANAGED = 10007;
public:
struct Category {
Category(int sortValue, int id, const QString &name, const std::vector<int> &nexusIDs, int parentID)
: m_SortValue(sortValue), m_ID(id), m_Name(name), m_HasChildren(false),
m_NexusIDs(nexusIDs), m_ParentID(parentID) {}
int m_SortValue;
int m_ID;
int m_ParentID;
bool m_HasChildren;
QString m_Name;
std::vector<int> m_NexusIDs;
friend bool operator<(const Category &LHS, const Category &RHS) {
return LHS.m_SortValue < RHS.m_SortValue;
}
};
public:
/**
* @brief reset the list of categories
**/
void reset();
/**
* @brief save the categories to the categories.dat file
**/
void saveCategories();
/**
* @brief retrieve the number of available categories
*
* @return unsigned int number of categories
**/
unsigned numCategories() const { return m_Categories.size(); }
/**
* @brief count all categories that match a specified filter
* @param filter the filter to test
* @return number of matching categories
*/
unsigned int countCategories(std::tr1::function<bool (const Category &category)> filter);
/**
* @brief get the id of the parent category
*
* @param index the index to look up
* @return int id of the parent category
**/
int getParentID(unsigned int index) const;
/**
* @brief determine if a category exists (by id)
*
* @param id the id to check for existance
* @return true if the category exists, false otherwise
**/
bool categoryExists(int id) const;
/**
* @brief test if a category is child of a second one
* @param id the presumed child id
* @param parentID the parent id to test for
* @return true if id is a child of parentID
**/
bool isDecendantOf(int id, int parentID) const;
/**
* @brief test if the specified category has child categories
*
* @param index index of the category to look up
* @return bool true if the category has child categories
**/
bool hasChildren(unsigned int index) const;
/**
* @brief retrieve the name of a category
*
* @param index index of the category to look up
* @return QString name of the category
**/
QString getCategoryName(unsigned int index) const;
/**
* @brief look up the id of a category by its index
*
* @param index index of the category to look up
* @return int id of the category
**/
int getCategoryID(unsigned int index) const;
/**
* @brief look up the index of a category by its id
*
* @param id index of the category to look up
* @return unsigned int index of the category
**/
int getCategoryIndex(int ID) const;
/**
* @brief retrieve the index of a category by its nexus id
*
* @param nexusID nexus id of the category to look up
* @return unsigned int index of the category or 0 if no category matches
**/
unsigned int resolveNexusID(int nexusID) const;
public:
/**
* @brief retrieve a reference to the singleton instance
*
* @return the reference to the singleton
**/
static CategoryFactory &instance();
/**
* @return path to the file that contains the categories list
*/
static QString categoriesFilePath();
private:
CategoryFactory();
void loadDefaultCategories();
void addCategory(int id, const QString &name, const std::vector<int> &nexusID, int parentID);
void setParents();
static void cleanup();
private:
static CategoryFactory *s_Instance;
std::vector<Category> m_Categories;
std::map<int, unsigned int> m_IDMap;
std::map<int, unsigned int> m_NexusMap;
private:
};
#endif // CATEGORIES_H
+243 -243
View File
@@ -1,243 +1,243 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "categoriesdialog.h"
#include "ui_categoriesdialog.h"
#include "categories.h"
#include "utility.h"
#include <QItemDelegate>
#include <QRegExpValidator>
#include <QLineEdit>
#include <QMenu>
class NewIDValidator : public QIntValidator {
public:
NewIDValidator(const std::set<int> &ids)
: m_UsedIDs(ids) {}
virtual State validate(QString &input, int &pos) const {
State intRes = QIntValidator::validate(input, pos);
if (intRes == Acceptable) {
bool ok = false;
int id = input.toInt(&ok);
if (m_UsedIDs.find(id) != m_UsedIDs.end()) {
return QValidator::Intermediate;
}
}
return intRes;
}
private:
const std::set<int> &m_UsedIDs;
};
class ExistingIDValidator : public QIntValidator {
public:
ExistingIDValidator(const std::set<int> &ids)
: m_UsedIDs(ids) {}
virtual State validate(QString &input, int &pos) const {
State intRes = QIntValidator::validate(input, pos);
if (intRes == Acceptable) {
bool ok = false;
int id = input.toInt(&ok);
if ((id == 0) || (m_UsedIDs.find(id) != m_UsedIDs.end())) {
return QValidator::Acceptable;
} else {
return QValidator::Intermediate;
}
} else {
return intRes;
}
}
private:
const std::set<int> &m_UsedIDs;
};
class ValidatingDelegate : public QItemDelegate {
public:
ValidatingDelegate(QObject *parent, QValidator *validator)
: QItemDelegate(parent), m_Validator(validator) {}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex&) const
{
QLineEdit *edit = new QLineEdit(parent);
edit->setValidator(m_Validator);
return edit;
}
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
int pos = 0;
QString editText = edit->text();
if (m_Validator->validate(editText, pos) == QValidator::Acceptable) {
QItemDelegate::setModelData(editor, model, index);
}
}
private:
QValidator *m_Validator;
};
CategoriesDialog::CategoriesDialog(QWidget *parent)
: TutorableDialog("Categories", parent), ui(new Ui::CategoriesDialog)
{
ui->setupUi(this);
fillTable();
connect(ui->categoriesTable, SIGNAL(cellChanged(int,int)), this, SLOT(cellChanged(int,int)));
}
CategoriesDialog::~CategoriesDialog()
{
delete ui;
}
void CategoriesDialog::cellChanged(int row, int)
{
int currentID = ui->categoriesTable->item(row, 0)->text().toInt();
if (currentID > m_HighestID) {
m_HighestID = currentID;
}
}
void CategoriesDialog::commitChanges()
{
CategoryFactory &categories = CategoryFactory::instance();
categories.reset();
for (int i = 0; i < ui->categoriesTable->rowCount(); ++i) {
int index = ui->categoriesTable->verticalHeader()->logicalIndex(i);
QString nexusIDString = ui->categoriesTable->item(index, 2)->text();
QStringList nexusIDStringList = nexusIDString.split(',', QString::SkipEmptyParts);
std::vector<int> nexusIDs;
for (QStringList::iterator iter = nexusIDStringList.begin();
iter != nexusIDStringList.end(); ++iter) {
nexusIDs.push_back(iter->toInt());
}
categories.addCategory(
ui->categoriesTable->item(index, 0)->text().toInt(),
ui->categoriesTable->item(index, 1)->text(),
nexusIDs,
ui->categoriesTable->item(index, 3)->text().toInt());
}
categories.setParents();
categories.saveCategories();
}
void CategoriesDialog::refreshIDs()
{
m_HighestID = 0;
for (int i = 0; i < ui->categoriesTable->rowCount(); ++i) {
int id = ui->categoriesTable->item(i, 0)->text().toInt();
if (id > m_HighestID) {
m_HighestID = id;
}
m_IDs.insert(id);
}
}
void CategoriesDialog::fillTable()
{
CategoryFactory &categories = CategoryFactory::instance();
QTableWidget *table = ui->categoriesTable;
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
table->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
table->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed);
table->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed);
table->verticalHeader()->setSectionsMovable(true);
table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
#else
table->horizontalHeader()->setResizeMode(0, QHeaderView::Fixed);
table->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
table->horizontalHeader()->setResizeMode(2, QHeaderView::Fixed);
table->horizontalHeader()->setResizeMode(3, QHeaderView::Fixed);
table->verticalHeader()->setMovable(true);
table->verticalHeader()->setResizeMode(QHeaderView::Fixed);
#endif
table->setItemDelegateForColumn(0, new ValidatingDelegate(this, new NewIDValidator(m_IDs)));
table->setItemDelegateForColumn(2, new ValidatingDelegate(this, new QRegExpValidator(QRegExp("([0-9]+)?(,[0-9]+)*"), this)));
table->setItemDelegateForColumn(3, new ValidatingDelegate(this, new ExistingIDValidator(m_IDs)));
int row = 0;
for (std::vector<CategoryFactory::Category>::const_iterator iter = categories.m_Categories.begin();
iter != categories.m_Categories.end(); ++iter, ++row) {
const CategoryFactory::Category &category = *iter;
if (category.m_ID == 0) {
--row;
continue;
}
table->insertRow(row);
// table->setVerticalHeaderItem(row, new QTableWidgetItem(" "));
QScopedPointer<QTableWidgetItem> idItem(new QTableWidgetItem());
idItem->setData(Qt::DisplayRole, category.m_ID);
QScopedPointer<QTableWidgetItem> nameItem(new QTableWidgetItem(category.m_Name));
QScopedPointer<QTableWidgetItem> nexusIDItem(new QTableWidgetItem(MOBase::VectorJoin(category.m_NexusIDs, ",")));
QScopedPointer<QTableWidgetItem> parentIDItem(new QTableWidgetItem());
parentIDItem->setData(Qt::DisplayRole, category.m_ParentID);
table->setItem(row, 0, idItem.take());
table->setItem(row, 1, nameItem.take());
table->setItem(row, 2, nexusIDItem.take());
table->setItem(row, 3, parentIDItem.take());
}
refreshIDs();
}
void CategoriesDialog::addCategory_clicked()
{
int row = m_ContextRow >= 0 ? m_ContextRow : 0;
ui->categoriesTable->insertRow(row);
ui->categoriesTable->setVerticalHeaderItem(row, new QTableWidgetItem(" "));
ui->categoriesTable->setItem(row, 0, new QTableWidgetItem(QString::number(++m_HighestID)));
ui->categoriesTable->setItem(row, 1, new QTableWidgetItem("new"));
ui->categoriesTable->setItem(row, 2, new QTableWidgetItem(""));
ui->categoriesTable->setItem(row, 3, new QTableWidgetItem("0"));
}
void CategoriesDialog::removeCategory_clicked()
{
ui->categoriesTable->removeRow(m_ContextRow);
}
void CategoriesDialog::on_categoriesTable_customContextMenuRequested(const QPoint &pos)
{
m_ContextRow = ui->categoriesTable->rowAt(pos.y());
QMenu menu;
menu.addAction(tr("Add"), this, SLOT(addCategory_clicked()));
menu.addAction(tr("Remove"), this, SLOT(removeCategory_clicked()));
menu.exec(ui->categoriesTable->mapToGlobal(pos));
}
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "categoriesdialog.h"
#include "ui_categoriesdialog.h"
#include "categories.h"
#include "utility.h"
#include <QItemDelegate>
#include <QRegExpValidator>
#include <QLineEdit>
#include <QMenu>
class NewIDValidator : public QIntValidator {
public:
NewIDValidator(const std::set<int> &ids)
: m_UsedIDs(ids) {}
virtual State validate(QString &input, int &pos) const {
State intRes = QIntValidator::validate(input, pos);
if (intRes == Acceptable) {
bool ok = false;
int id = input.toInt(&ok);
if (m_UsedIDs.find(id) != m_UsedIDs.end()) {
return QValidator::Intermediate;
}
}
return intRes;
}
private:
const std::set<int> &m_UsedIDs;
};
class ExistingIDValidator : public QIntValidator {
public:
ExistingIDValidator(const std::set<int> &ids)
: m_UsedIDs(ids) {}
virtual State validate(QString &input, int &pos) const {
State intRes = QIntValidator::validate(input, pos);
if (intRes == Acceptable) {
bool ok = false;
int id = input.toInt(&ok);
if ((id == 0) || (m_UsedIDs.find(id) != m_UsedIDs.end())) {
return QValidator::Acceptable;
} else {
return QValidator::Intermediate;
}
} else {
return intRes;
}
}
private:
const std::set<int> &m_UsedIDs;
};
class ValidatingDelegate : public QItemDelegate {
public:
ValidatingDelegate(QObject *parent, QValidator *validator)
: QItemDelegate(parent), m_Validator(validator) {}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex&) const
{
QLineEdit *edit = new QLineEdit(parent);
edit->setValidator(m_Validator);
return edit;
}
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
int pos = 0;
QString editText = edit->text();
if (m_Validator->validate(editText, pos) == QValidator::Acceptable) {
QItemDelegate::setModelData(editor, model, index);
}
}
private:
QValidator *m_Validator;
};
CategoriesDialog::CategoriesDialog(QWidget *parent)
: TutorableDialog("Categories", parent), ui(new Ui::CategoriesDialog)
{
ui->setupUi(this);
fillTable();
connect(ui->categoriesTable, SIGNAL(cellChanged(int,int)), this, SLOT(cellChanged(int,int)));
}
CategoriesDialog::~CategoriesDialog()
{
delete ui;
}
void CategoriesDialog::cellChanged(int row, int)
{
int currentID = ui->categoriesTable->item(row, 0)->text().toInt();
if (currentID > m_HighestID) {
m_HighestID = currentID;
}
}
void CategoriesDialog::commitChanges()
{
CategoryFactory &categories = CategoryFactory::instance();
categories.reset();
for (int i = 0; i < ui->categoriesTable->rowCount(); ++i) {
int index = ui->categoriesTable->verticalHeader()->logicalIndex(i);
QString nexusIDString = ui->categoriesTable->item(index, 2)->text();
QStringList nexusIDStringList = nexusIDString.split(',', QString::SkipEmptyParts);
std::vector<int> nexusIDs;
for (QStringList::iterator iter = nexusIDStringList.begin();
iter != nexusIDStringList.end(); ++iter) {
nexusIDs.push_back(iter->toInt());
}
categories.addCategory(
ui->categoriesTable->item(index, 0)->text().toInt(),
ui->categoriesTable->item(index, 1)->text(),
nexusIDs,
ui->categoriesTable->item(index, 3)->text().toInt());
}
categories.setParents();
categories.saveCategories();
}
void CategoriesDialog::refreshIDs()
{
m_HighestID = 0;
for (int i = 0; i < ui->categoriesTable->rowCount(); ++i) {
int id = ui->categoriesTable->item(i, 0)->text().toInt();
if (id > m_HighestID) {
m_HighestID = id;
}
m_IDs.insert(id);
}
}
void CategoriesDialog::fillTable()
{
CategoryFactory &categories = CategoryFactory::instance();
QTableWidget *table = ui->categoriesTable;
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
table->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
table->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed);
table->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed);
table->verticalHeader()->setSectionsMovable(true);
table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
#else
table->horizontalHeader()->setResizeMode(0, QHeaderView::Fixed);
table->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
table->horizontalHeader()->setResizeMode(2, QHeaderView::Fixed);
table->horizontalHeader()->setResizeMode(3, QHeaderView::Fixed);
table->verticalHeader()->setMovable(true);
table->verticalHeader()->setResizeMode(QHeaderView::Fixed);
#endif
table->setItemDelegateForColumn(0, new ValidatingDelegate(this, new NewIDValidator(m_IDs)));
table->setItemDelegateForColumn(2, new ValidatingDelegate(this, new QRegExpValidator(QRegExp("([0-9]+)?(,[0-9]+)*"), this)));
table->setItemDelegateForColumn(3, new ValidatingDelegate(this, new ExistingIDValidator(m_IDs)));
int row = 0;
for (std::vector<CategoryFactory::Category>::const_iterator iter = categories.m_Categories.begin();
iter != categories.m_Categories.end(); ++iter, ++row) {
const CategoryFactory::Category &category = *iter;
if (category.m_ID == 0) {
--row;
continue;
}
table->insertRow(row);
// table->setVerticalHeaderItem(row, new QTableWidgetItem(" "));
QScopedPointer<QTableWidgetItem> idItem(new QTableWidgetItem());
idItem->setData(Qt::DisplayRole, category.m_ID);
QScopedPointer<QTableWidgetItem> nameItem(new QTableWidgetItem(category.m_Name));
QScopedPointer<QTableWidgetItem> nexusIDItem(new QTableWidgetItem(MOBase::VectorJoin(category.m_NexusIDs, ",")));
QScopedPointer<QTableWidgetItem> parentIDItem(new QTableWidgetItem());
parentIDItem->setData(Qt::DisplayRole, category.m_ParentID);
table->setItem(row, 0, idItem.take());
table->setItem(row, 1, nameItem.take());
table->setItem(row, 2, nexusIDItem.take());
table->setItem(row, 3, parentIDItem.take());
}
refreshIDs();
}
void CategoriesDialog::addCategory_clicked()
{
int row = m_ContextRow >= 0 ? m_ContextRow : 0;
ui->categoriesTable->insertRow(row);
ui->categoriesTable->setVerticalHeaderItem(row, new QTableWidgetItem(" "));
ui->categoriesTable->setItem(row, 0, new QTableWidgetItem(QString::number(++m_HighestID)));
ui->categoriesTable->setItem(row, 1, new QTableWidgetItem("new"));
ui->categoriesTable->setItem(row, 2, new QTableWidgetItem(""));
ui->categoriesTable->setItem(row, 3, new QTableWidgetItem("0"));
}
void CategoriesDialog::removeCategory_clicked()
{
ui->categoriesTable->removeRow(m_ContextRow);
}
void CategoriesDialog::on_categoriesTable_customContextMenuRequested(const QPoint &pos)
{
m_ContextRow = ui->categoriesTable->rowAt(pos.y());
QMenu menu;
menu.addAction(tr("Add"), this, SLOT(addCategory_clicked()));
menu.addAction(tr("Remove"), this, SLOT(removeCategory_clicked()));
menu.exec(ui->categoriesTable->mapToGlobal(pos));
}
+71 -71
View File
@@ -1,71 +1,71 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CATEGORIESDIALOG_H
#define CATEGORIESDIALOG_H
#include "tutorabledialog.h"
#include <set>
namespace Ui {
class CategoriesDialog;
}
/**
* @brief Dialog that allows users to configure mod categories
**/
class CategoriesDialog : public MOBase::TutorableDialog
{
Q_OBJECT
public:
explicit CategoriesDialog(QWidget *parent = 0);
~CategoriesDialog();
/**
* @brief store changes here to the global categories store (categories.h)
*
**/
void commitChanges();
private slots:
void on_categoriesTable_customContextMenuRequested(const QPoint &pos);
void addCategory_clicked();
void removeCategory_clicked();
void cellChanged(int row, int column);
private:
void refreshIDs();
void fillTable();
private:
Ui::CategoriesDialog *ui;
int m_ContextRow;
int m_HighestID;
std::set<int> m_IDs;
};
#endif // CATEGORIESDIALOG_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CATEGORIESDIALOG_H
#define CATEGORIESDIALOG_H
#include "tutorabledialog.h"
#include <set>
namespace Ui {
class CategoriesDialog;
}
/**
* @brief Dialog that allows users to configure mod categories
**/
class CategoriesDialog : public MOBase::TutorableDialog
{
Q_OBJECT
public:
explicit CategoriesDialog(QWidget *parent = 0);
~CategoriesDialog();
/**
* @brief store changes here to the global categories store (categories.h)
*
**/
void commitChanges();
private slots:
void on_categoriesTable_customContextMenuRequested(const QPoint &pos);
void addCategory_clicked();
void removeCategory_clicked();
void cellChanged(int row, int column);
private:
void refreshIDs();
void fillTable();
private:
Ui::CategoriesDialog *ui;
int m_ContextRow;
int m_HighestID;
std::set<int> m_IDs;
};
#endif // CATEGORIESDIALOG_H
+19 -19
View File
@@ -1,22 +1,22 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "credentialsdialog.h"
#include "ui_credentialsdialog.h"

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