summaryrefslogtreecommitdiff
path: root/src/organizercore.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Improve code for reading text files line-by-lineJonathan Feenstra2026-05-171-4/+8
|
* Add setting to show notifications when downloads complete or fail (#2338)Jonathan Feenstra2026-05-151-0/+9
|
* Migrating to OAuth Authentication (#2374)Jeremy Rimpo2026-05-121-7/+9
| | | | Co-authored-by: aglowinthefield <146008217+aglowinthefield@users.noreply.github.com> Co-authored-by: Jonathan Feenstra <26406078+JonathanFeenstra@users.noreply.github.com>
* Stable DownloadId refactor (#2375)Al2026-05-071-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Encapsulate the downloads directory watcher in DirWatcherManager QFileSystemWatcher suppression currently relies on public static start/end methods and a static counter. Seven call sites pair them raw, one of them outside the class. Any exception between a pair permanently disables the watcher, and the static counter implies a singleton DownloadManager. A new DirWatcherManager owns the watcher, the counter (now an instance member), and the filtering. The only way to suspend is an RAII Guard obtained via a scopedGuard() factory. All raw pairs migrate to guards. A TODO flags the existing processEvents() in the dtor as a known reentrancy hazard worth replacing later. * Replace aboutToUpdate/update(int) with ModelResetGuard Replace the fragile two-signal protocol with a refcounted RAII ModelResetGuard. Split update(int) into aboutToResetModel/modelReset (guard only) and rowChanged(int); notifyRowChanged() is suppressed while a reset is active. Fixes "beginResetModel without endResetModel" warnings from three sites in downloadFinished/removeDownload that were pairing reset with a row update. removePending only opens a guard when an actual match is removed. * Centralize row notifications in setState and fix missed emits setState emits notifyRowChanged itself, uses indexByInfo (-1 when untracked), and re-looks up the row at each use so reply->abort() and plugin callbacks that re-enter and erase info don't produce stale signals. Remove the trailing emit loop from createMetaFile and the now-redundant notifyRowChanged calls scattered after setState. Add the two missing emits in restoreDownload (after m_Hidden) and metaDataChanged (after rename). Guard downloadFinished with a top-level DirWatcherGuard to prevent filesystem events from its writes racing with model updates. * Fix comma operator in addNXMDownload pending-dedup check The game-name comparison result was discarded by the comma operator, so the dedup only matched modId/fileId across all games. * Fix lost finished() signal on fast downloads Hoist the file-exists prompt out of startDownload so setup is straight-line. Connect finished() last and dispatch manually if the reply already finished. * Fix memory leak in DownloadInfo::createFromMeta Move the allocation past the early-return checks so path-mismatch and hidden-skip paths no longer leak a fresh DownloadInfo. * Sanitize suffix path in getDownloadFileName The collision-avoidance branch was using the raw baseName, so invalid characters sanitized out of the initial path leaked into the suffixed one. * [pre-commit.ci] Auto fixes from pre-commit.com hooks. * Remove unused alphabetical translation vector m_AlphabeticalTranslation was written but never read; drop it along with refreshAlphabeticalTranslation, ByName, and the LessThanWrapper helper. * Address PR feedback: fix redundant check and move refresh outside try catch. * Coalesce the removeDownload reset with the following refreshList Moves the ModelResetGuard out of the try-catch so it also wraps the refreshList() call below. Without this, one reset fires when the guard destructs at the end of the try block and another fires from refreshList's own guard, producing two resets where one is sufficient. * Guard the .meta creation in openMetaFile against the directory watcher openMetaFile creates the .meta file via QSettings when one does not exist; the disk write fires directoryChanged and triggers a spurious refreshList. Wrap it in a DirWatcherManager::Guard like the other meta-file editing paths. * Extract getValidGameShortName method in download manager (#2380) * Add stable download id index and PendingDownload struct Replace the (game, mod, file) tuple backing m_PendingDownloads with a named struct, and add m_ByID as an O(1) m_DownloadID-to-info index kept in sync with every m_ActiveDownloads mutation. Encapsulate the id counter behind DownloadInfo::newDownloadID(), the only supported way to consume from s_NextDownloadID. Infrastructure only; external behaviour is unchanged. * Return stable ids from the plugin-facing download API startDownloadURLs / startDownloadNexusFile / addNXMDownload now reserve and return m_DownloadID instead of a stale index. Plugin callbacks fire with m_DownloadID; downloadPath looks up via m_ByID. nxmDownloadURLsAvailable threads the reserved id into the materializing DownloadInfo, and Nexus API failures wake waiting plugins via notifyPendingDownloadFailed. Incidental: startDownload now returns bool and frees newDownload on output-open failure; createMetaFile is deferred past that check so failed starts no longer leave an orphan .meta. * Split downloadFinished into onReplyFinished slot and finishDownload The old dual-use downloadFinished(int = 0) took either an explicit index or relied on sender() when called as a slot. Split into a sender-resolved slot and an id-based direct call, removing the ambiguous index-zero path. * Introduce DownloadID alias and row/id accessors Add a DownloadID type alias for the stable per-download handle and two public accessors (downloadIDAtRow, rowForDownloadID) so callers can translate between the view's row vocabulary and the model's id vocabulary without reaching into the manager's internals. DownloadList now embeds the DownloadID in QModelIndex::internalId() so any code holding an index can identify the download directly. * Convert cancel/pause/resume action methods to take DownloadID The four methods (cancel, pause, resume, resumeDownloadInt) now accept a DownloadID, resolve through m_ByID, and no longer care about row positions. Internal callers iterate DownloadInfo* or look up via id; DownloadsTab translates row -> id at the connect boundary so the view's int-shaped signals keep working unchanged. Also switches the remaining unsigned int signatures that refer to the download id (finishDownload, downloadInfoByID, PendingDownload::reservedID, m_ByID, newDownloadID, s_NextDownloadID) to the DownloadID alias. Drive-by fix: finishDownload's retry branch could read info->m_Tries after info had been deleted in the CANCELED/retries-exhausted branch above; now re-resolves via m_ByID.value(id) before touching any fields. * [pre-commit.ci] Auto fixes from pre-commit.com hooks. * fix warnings about unused variables and size_t types * cleanup dead code * avoid calling processEvents when releasing the DirWatcherGuard * [pre-commit.ci] Auto fixes from pre-commit.com hooks. * use QEventLoop instead of manual ProcessEvents * don't call processEvents in download started and defer handling finish state in event loop * Cleanup pending download in case of failure. * Add missing notifyPendingDownloadFailed if user cancels * [pre-commit.ci] Auto fixes from pre-commit.com hooks. * Refactor pending download failure handling and cover rename failures * fix rebase bug, addNXMDownload not returning the correct type --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Jonathan Feenstra <26406078+JonathanFeenstra@users.noreply.github.com>
* Add instanceName and profiles methods to plugin API (#2321)Jonathan Feenstra2026-01-111-0/+19
|
* Move to VCPKG (#2068)Mikaël Capelle2025-05-291-8/+8
| | | | | | | | | * Remove SConscript related files. * Force-load translations from uibase and gamebryo/creation. * Bring githubpp here and add a standalone preset. * Switch VersionInfo -> Version for ModOrganizer2. (#2063) * Add pre-commit hook. * Use 7zip build from VCPKG registry. * Use archive.dll from the bin folder instead of dlls.
* Oblivion Remastered Meta PR (#2241)Jeremy Rimpo2025-05-231-16/+37
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Allow for mod directory maps - Set main data files based on game - Mapped mod directories to VFS - Update overwrite setup * Skip if mod contains no 'data' dir * More mod directory compatibility fixes * Workaround for Obl:Rem save location - SLocalSavePath does nothing yet MO2 wants to use it to override the default save location - This only applies to BGS games anyway, we should move this logic * First pass for overwrite mod directory support * More overwrite move / delete restrictions * Fix issue with moving directories that are not required * Formatting pass * More modDataDirectory updates * Formatting --------- Co-authored-by: Mikaël Capelle <capelle.mikael@gmail.com>
* Update following USVFS move to VCPKG. (#2244)Mikaël Capelle2025-05-221-1/+1
|
* Archive preview support (#2056)Jeremy Rimpo2024-07-111-3/+24
| | | | | * Support for archive file previews - Should account for alternates - Extracts files and requests preview from plugins that claim support
* Use new Skip File & Skip Directory in usvfs (#2033)Twinki2024-06-151-3/+6
| | | | | | | | | | | | * Use new Skip File & Skip Directory in usvfs. # Motivations https://github.com/ModOrganizer2/usvfs/pull/61 Highlights some reasons why the ability to skip files & directories would be beneficial # Modifications - Add two new settings, `skip_file_suffixes` and `skip_directories` - Wire the two new settings up to usvfs - Add two new buttons to the `Workarounds` dialog, one to adjust Skip File Suffixes and another for Skip Directories, both buttons act nearly identical to the Executable Blacklist button - Add a new grouping in the `Workarounds` dialog box that contains the usvfs buttons to keep the dialog a tad organized
* Refactoring of game features for better management. (#2043)Mikaël Capelle2024-06-091-20/+27
|
* Switch from fmtlib to std::format. (#2031)Mikaël Capelle2024-05-251-2/+2
| | | | | * Switch from fmtlib to std::format. * Remove libffi from dependencies in Github action.
* Download issue fixesJeremy Rimpo2023-11-051-0/+2
| | | | | | - Add scoped watcher disabler - Disable during mod install - Update interprocess message handler to fix 'unable to communicate' issues
* Merge pull request #1894 from ModOrganizer2/loot_0_22Jeremy Rimpo2023-10-031-0/+2
|\ | | | | WIP: Plugin sorting updates
| * Updates to refresh sort button after various eventsJeremy Rimpo2023-10-021-0/+2
| |
* | Fix QTimer being created on incorrect thread after refresh.Mikaël Capelle2023-10-021-3/+3
|/
* Refresh Callback (+ Extra for AboutToRun) (#1884)Mikaël Capelle2023-09-291-52/+47
| | | | | * Add working directory and arguments to onAboutToRun (optional). * Add onRefreshCallback functionality.
* Remove download refresh scoped blockerJeremy Rimpo2023-09-231-1/+0
| | | | - Accidentally added to this branch
* Restructure category refresh actionJeremy Rimpo2023-09-231-1/+2
| | | | | | | - Remove plugins class - Route signals to run Nexus API call from MainWindow - Pass Dialog instance to route response data - Revert CategoryFactory::instance to return reference
* Several updatesJeremy Rimpo2023-09-211-12/+24
| | | | | | | | * No longer cause an error when deleting a category that's being used * Add a dialog when installing a mod with no Nexus mapping (if not disabled) * Allow disabling Nexus category mapping in Settings (Nexus tab) * Add context option to remove nexus mappings in the category editor * Some clang style fixes
* Code cleanupJeremy Rimpo2023-09-091-8/+5
|
* Merge remote-tracking branch 'origin/qt6'Jeremy Rimpo2023-09-041-5/+18
|\
| * Map multiple data directories to USVFSJeremy Rimpo2023-09-041-10/+18
| |
* | Apply clang-format.Mikaël Capelle2023-07-091-443/+444
|/
* Notify mod installation to plugins after directory structure is ready.Mikaël Capelle2023-07-031-113/+95
|
* First pass for Qt6 compatibilityJeremy Rimpo2022-04-191-9/+12
|
* Add IOrganizer::virtualFileTree().Mikaël Capelle2021-05-141-0/+3
|
* Better refresh of override markers and conflicts.Mikaël Capelle2021-02-091-28/+49
|
* Remove LoadMechanism completely.Mikaël Capelle2021-01-291-1/+0
|
* Move settings around. Remove unused settings.Mikaël Capelle2021-01-291-4/+1
|
* Move update of directory structure after mod priority change to organizer core.Mikaël Capelle2021-01-211-2/+43
|
* INT_MAX -> std::numeric_limits, plus minor clean.Mikaël Capelle2021-01-211-1/+1
|
* Don't look for mods with -1 as mod ID when suggesting namesAL2021-01-191-1/+1
|
* Merge pull request #1372 from Holt59/install-mod-atMikaël Capelle2021-01-181-1/+2
|\ | | | | Modify 'Install mod... ' in context menu to install above current mod.
| * Modify 'Install mod... ' in context menu to install above current mod.Mikaël Capelle2021-01-181-1/+2
| |
* | moved criticalOnTop() to uibaseisanae2021-01-181-3/+2
| | | | | | | | | | | | changed all calls to reportError(), which now uses the main window if it exists as a parent, or calls criticalOnTop() added errors when running something from the command line for a different instance/profile removed unused crap
* | renamed Refresh to TriggerRefresh, added WaitForRefreshisanae2021-01-181-3/+1
| | | | | | | | | | | | | | | | removed duplicate refreshDirectoryStructure() call that could never work added --logs to output logs to stdout, added final "mod organizer done" log added -i with no arguments to output the current instance name `run -e` now does an additional, case insensitive check for names fixed error being output along with --help
* | moved externalMessage() to MOApplicationisanae2021-01-181-19/+0
| | | | | | | | | | | | commands can forward to the primary instance added reload-plugin command MessageDialog now tries to find the main window when the reference is null, which actually used to happen often because activeWindow() is typically used, but that's null when the main window doesn't have focus (like when downloading from nexus, for example)
* | merged exe and run commands, added -e flag insteadisanae2021-01-181-0/+5
|/ | | | added dialog when selected profile doesn't exist, this can happen with -p on the command line
* Add setting to automatically hide download after installation.Mikaël Capelle2021-01-141-0/+3
|
* Remove OrganizerCore::modsSortedByProfilePriority.Mikaël Capelle2021-01-131-16/+0
|
* Remove archive parsing attribute from core and use the one from settings ↵Mikaël Capelle2021-01-131-1/+1
| | | | directly.
* Add option to have different separator collapsed/expanded states between ↵Mikaël Capelle2021-01-101-0/+1
| | | | profiles.
* Refactoring of ModInfo to give access to the core. Remove ModInfo::remove() ↵Mikaël Capelle2021-01-021-10/+5
| | | | completely.
* Add index attribute to ModInfo.Mikaël Capelle2021-01-021-0/+2
|
* Move connection from organizer to mainwindow.Mikaël Capelle2021-01-021-15/+0
|
* Minor refactoring.Mikaël Capelle2021-01-021-4/+1
|
* Remove selection-related stuff from plugin/mod lists.Mikaël Capelle2021-01-021-4/+0
|
* Start moving stuff from MainWindow to PluginListView.Mikaël Capelle2021-01-021-8/+0
|
* Move more stuff from MainWindow. Minor improvements for prev/next button in ↵Mikaël Capelle2021-01-021-1/+0
| | | | ModInfoDialog.