public static void RecordNotificationReceived(UILocalNotification message) { CurrentInstance.RecordNotificationReceived(message); }
public Main(string[] cmdlineArgs, KSPManager mgr, GUIUser user, bool showConsole) { log.Info("Starting the GUI"); commandLineArgs = cmdlineArgs; // These are used by KSPManager's constructor to show messages about directory creation user.displayMessage = AddStatusMessage; user.displayError = ErrorDialog; manager = mgr ?? new KSPManager(user); currentUser = user; controlFactory = new ControlFactory(); Instance = this; mainModList = new MainModList(source => UpdateFilters(this), TooManyModsProvide, user); // History is read-only until the UI is started. We switch // out of it at the end of OnLoad() when we call NavInit(). navHistory = new NavigationHistory <GUIMod> { IsReadOnly = true }; InitializeComponent(); // Replace mono's broken, ugly toolstrip renderer menuStrip1.Renderer = new FlatToolStripRenderer(); menuStrip2.Renderer = new FlatToolStripRenderer(); fileToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); settingsToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); helpToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); FilterToolButton.DropDown.Renderer = new FlatToolStripRenderer(); this.minimizedContextMenuStrip.Renderer = new FlatToolStripRenderer(); // We need to initialize the error dialog first to display errors. errorDialog = controlFactory.CreateControl <ErrorDialog>(); // We want to check if our current instance is null first, // as it may have already been set by a command-line option. if (CurrentInstance == null && manager.GetPreferredInstance() == null) { Hide(); var result = new ChooseKSPInstance(!actuallyVisible).ShowDialog(); if (result == DialogResult.Cancel || result == DialogResult.Abort) { Application.Exit(); return; } } configuration = Configuration.LoadOrCreateConfiguration ( Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml"), CKAN.Repository.default_ckan_repo_uri.ToString() ); // Check if there is any other instances already running. // This is not entirely necessary, but we can show a nicer error message this way. try { #pragma warning disable 219 var lockedReg = RegistryManager.Instance(CurrentInstance).registry; #pragma warning restore 219 } catch (RegistryInUseKraken kraken) { errorDialog.ShowErrorDialog(kraken.ToString()); return; } FilterToolButton.MouseHover += (sender, args) => FilterToolButton.ShowDropDown(); launchKSPToolStripMenuItem.MouseHover += (sender, args) => launchKSPToolStripMenuItem.ShowDropDown(); ApplyToolButton.MouseHover += (sender, args) => ApplyToolButton.ShowDropDown(); ModList.CurrentCellDirtyStateChanged += ModList_CurrentCellDirtyStateChanged; ModList.CellValueChanged += ModList_CellValueChanged; tabController = new TabController(MainTabControl); tabController.ShowTab("ManageModsTabPage"); RecreateDialogs(); if (!showConsole) { Util.HideConsoleWindow(); } // Disable the modinfo controls until a mod has been choosen. ActiveModInfo = null; // WinForms on Mac OS X has a nasty bug where the UI thread hogs the CPU, // making our download speeds really slow unless you move the mouse while // downloading. Yielding periodically addresses that. // https://bugzilla.novell.com/show_bug.cgi?id=663433 if (Platform.IsMac) { var timer = new Timer { Interval = 2 }; timer.Tick += (sender, e) => { Thread.Yield(); }; timer.Start(); } // Set the window name and class for X11 if (Platform.IsUnix) { HandleCreated += (sender, e) => X11.SetWMClass("CKAN", "CKAN", Handle); } Application.Run(this); var registry = RegistryManager.Instance(Manager.CurrentInstance); registry?.Dispose(); }
private void CurrentInstanceUpdated() { Util.Invoke(this, () => { Text = $"CKAN {Meta.GetVersion()} - KSP {CurrentInstance.Version()} -- {CurrentInstance.GameDir()}"; }); configuration = Configuration.LoadOrCreateConfiguration( Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml"), CKAN.Repository.default_ckan_repo_uri.ToString() ); if (CurrentInstance.CompatibleVersionsAreFromDifferentKsp) { new CompatibleKspVersionsDialog(CurrentInstance, !actuallyVisible) .ShowDialog(); } UpdateModsList(); ChangeSet = null; Conflicts = null; Filter((GUIModFilter)configuration.ActiveFilter); }
// this probably needs to be refactored private void InstallMods(object sender, DoWorkEventArgs e) { installCanceled = false; Wait.ClearLog(); var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument; RegistryManager registry_manager = RegistryManager.Instance(manager.CurrentInstance); Registry registry = registry_manager.registry; ModuleInstaller installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser); // Avoid accumulating multiple event handlers installer.onReportModInstalled -= OnModInstalled; installer.onReportModInstalled += OnModInstalled; // setup progress callback // this will be the final list of mods we want to install HashSet <CkanModule> toInstall = new HashSet <CkanModule>(); var toUninstall = new HashSet <string>(); var toUpgrade = new HashSet <string>(); // First compose sets of what the user wants installed, upgraded, and removed. foreach (ModChange change in opts.Key) { switch (change.ChangeType) { case GUIModChangeType.Remove: toUninstall.Add(change.Mod.identifier); break; case GUIModChangeType.Update: toUpgrade.Add(change.Mod.identifier); break; case GUIModChangeType.Install: toInstall.Add(change.Mod); break; case GUIModChangeType.Replace: ModuleReplacement repl = registry.GetReplacement(change.Mod, CurrentInstance.VersionCriteria()); if (repl != null) { toUninstall.Add(repl.ToReplace.identifier); toInstall.Add(repl.ReplaceWith); } break; } } // Prompt for recommendations and suggestions, if any if (installer.FindRecommendations( opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install) .Select(ch => ch.Mod) .ToHashSet(), toInstall, registry, out Dictionary <CkanModule, Tuple <bool, List <string> > > recommendations, out Dictionary <CkanModule, List <string> > suggestions, out Dictionary <CkanModule, HashSet <string> > supporters )) { tabController.ShowTab("ChooseRecommendedModsTabPage", 3); ChooseRecommendedMods.LoadRecommendations( registry, CurrentInstance.VersionCriteria(), Manager.Cache, recommendations, suggestions, supporters); tabController.SetTabLock(true); var result = ChooseRecommendedMods.Wait(); if (result == null) { installCanceled = true; } else { toInstall.UnionWith(result); } tabController.SetTabLock(false); tabController.HideTab("ChooseRecommendedModsTabPage"); } if (installCanceled) { tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } // Now let's make all our changes. Util.Invoke(this, () => { // Need to be on the GUI thread to get the translated string tabController.RenameTab("WaitTabPage", Properties.Resources.MainInstallWaitTitle); }); ShowWaitDialog(); tabController.SetTabLock(true); IDownloader downloader = new NetAsyncModulesDownloader(currentUser, Manager.Cache); cancelCallback = () => { downloader.CancelDownload(); installCanceled = true; }; HashSet <string> possibleConfigOnlyDirs = null; // checks if all actions were successfull bool processSuccessful = false; bool resolvedAllProvidedMods = false; // uninstall/installs/upgrades until every list is empty // if the queue is NOT empty, resolvedAllProvidedMods is set to false until the action is done while (!resolvedAllProvidedMods) { try { e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); if (toUninstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.UninstallList(toUninstall, ref possibleConfigOnlyDirs, registry_manager, false, toInstall); processSuccessful = true; } } if (toUpgrade.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.Upgrade(toUpgrade, downloader, ref possibleConfigOnlyDirs, registry_manager); processSuccessful = true; } } if (toInstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.InstallList(toInstall, opts.Value, registry_manager, downloader, false); processSuccessful = true; } } HandlePossibleConfigOnlyDirs(registry, possibleConfigOnlyDirs); e.Result = new KeyValuePair <bool, ModChanges>(processSuccessful, opts.Key); if (installCanceled) { return; } resolvedAllProvidedMods = true; } catch (TooManyModsProvideKraken k) { // Prompt user to choose which mod to use tabController.ShowTab("ChooseProvidedModsTabPage", 3); ChooseProvidedMods.LoadProviders(k.requested, k.modules, Manager.Cache); tabController.SetTabLock(true); CkanModule chosen = ChooseProvidedMods.Wait(); // Close the selection prompt tabController.SetTabLock(false); tabController.HideTab("ChooseProvidedModsTabPage"); if (chosen != null) { // User picked a mod, queue it up for installation toInstall.Add(chosen); // DON'T return so we can loop around and try the above InstallList call again tabController.ShowTab("WaitTabPage"); } else { // User cancelled, get out tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } } catch (DependencyNotSatisfiedKraken ex) { currentUser.RaiseMessage(Properties.Resources.MainInstallDepNotSatisfied, ex.parent, ex.module); return; } catch (ModuleNotFoundKraken ex) { currentUser.RaiseMessage(Properties.Resources.MainInstallNotFound, ex.module); return; } catch (BadMetadataKraken ex) { currentUser.RaiseMessage(Properties.Resources.MainInstallBadMetadata, ex.module, ex.Message); return; } catch (FileExistsKraken ex) { if (ex.owningModule != null) { currentUser.RaiseMessage( Properties.Resources.MainInstallFileExists, ex.filename, ex.installingModule, ex.owningModule, Meta.GetVersion() ); } else { currentUser.RaiseMessage( Properties.Resources.MainInstallUnownedFileExists, ex.installingModule, ex.filename ); } currentUser.RaiseMessage(Properties.Resources.MainInstallGameDataReverted); return; } catch (InconsistentKraken ex) { // The prettiest Kraken formats itself for us. currentUser.RaiseMessage(ex.InconsistenciesPretty); return; } catch (CancelledActionKraken) { return; } catch (MissingCertificateKraken kraken) { // Another very pretty kraken. currentUser.RaiseMessage(kraken.ToString()); return; } catch (DownloadThrottledKraken kraken) { string msg = kraken.ToString(); currentUser.RaiseMessage(msg); if (YesNoDialog(string.Format(Properties.Resources.MainInstallOpenSettingsPrompt, msg), Properties.Resources.MainInstallOpenSettings, Properties.Resources.MainInstallNo)) { // Launch the URL describing this host's throttling practices, if any if (kraken.infoUrl != null) { Utilities.ProcessStartURL(kraken.infoUrl.ToString()); } // Now pretend they clicked the menu option for the settings Enabled = false; new SettingsDialog(currentUser).ShowDialog(); Enabled = true; } return; } catch (ModuleDownloadErrorsKraken kraken) { currentUser.RaiseMessage(kraken.ToString()); currentUser.RaiseError(kraken.ToString()); return; } catch (DirectoryNotFoundKraken kraken) { currentUser.RaiseMessage("\r\n{0}", kraken.Message); return; } catch (DllNotFoundException) { if (currentUser.RaiseYesNoDialog(Properties.Resources.MainInstallLibCurlMissing)) { Utilities.ProcessStartURL("https://github.com/KSP-CKAN/CKAN/wiki/libcurl"); } throw; } catch (ModuleIsDLCKraken kraken) { string msg = string.Format(Properties.Resources.MainInstallCantInstallDLC, kraken.module.name); currentUser.RaiseMessage(msg); currentUser.RaiseError(msg); return; } } }
private void _UpdateModsList(bool repo_updated, List <ModChange> mc) { log.Info("Updating the mod list"); KspVersionCriteria versionCriteria = CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; var gui_mods = new HashSet <GUIMod>(registry.Available(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria))); gui_mods.UnionWith(registry.Incompatible(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria, true))); var installed = registry.InstalledModules .Select(m => new GUIMod(m.Module, registry, versionCriteria)); //Hashset does not define if add/unionwith replaces existing elements. //In this case that could cause a CkanModule to be replaced by a Module. //Hence the explicit checking foreach (var mod in installed.Where(mod => !gui_mods.Contains(mod))) { gui_mods.Add(mod); } var old_modules = new HashSet <GUIMod>(mainModList.Modules); if (repo_updated) { foreach (var gui_mod in gui_mods.Where(m => !old_modules.Contains(m))) { gui_mod.IsNew = true; } } else { //Copy the new mod flag from the old list. var old_new_mods = new HashSet <GUIMod>(old_modules.Where(m => m.IsNew)); foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m))) { gui_mod.IsNew = true; } } // Update our mod listing. If we're doing a repo update, then we don't refresh // all (in case the user has selected changes they wish to apply). mainModList.ConstructModList(gui_mods.ToList(), mc, !repo_updated, configuration.HideEpochs); mainModList.Modules = new ReadOnlyCollection <GUIMod>( mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList()); //TODO Consider using smart enumeration pattern so stuff like this is easier FilterToolButton.DropDownItems[0].Text = String.Format("Compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Compatible)); FilterToolButton.DropDownItems[1].Text = String.Format("Installed ({0})", mainModList.CountModsByFilter(GUIModFilter.Installed)); FilterToolButton.DropDownItems[2].Text = String.Format("Upgradeable ({0})", mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable)); FilterToolButton.DropDownItems[3].Text = String.Format("Cached ({0})", mainModList.CountModsByFilter(GUIModFilter.Cached)); FilterToolButton.DropDownItems[4].Text = String.Format("New in repository ({0})", mainModList.CountModsByFilter(GUIModFilter.NewInRepository)); FilterToolButton.DropDownItems[5].Text = String.Format("Not installed ({0})", mainModList.CountModsByFilter(GUIModFilter.NotInstalled)); FilterToolButton.DropDownItems[6].Text = String.Format("Incompatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Incompatible)); FilterToolButton.DropDownItems[7].Text = String.Format("All ({0})", mainModList.CountModsByFilter(GUIModFilter.All)); var has_any_updates = gui_mods.Any(mod => mod.HasUpdate); UpdateAllToolButton.Enabled = has_any_updates; UpdateFilters(this); }
protected override void OnLoad(EventArgs e) { SetStartPosition(); Size = configuration.WindowSize; WindowState = configuration.IsWindowMaximised ? FormWindowState.Maximized : FormWindowState.Normal; if (!configuration.CheckForUpdatesOnLaunchNoNag && AutoUpdate.CanUpdate) { log.Debug("Asking user if they wish for auto-updates"); if (new AskUserForAutoUpdatesDialog().ShowDialog() == DialogResult.OK) { configuration.CheckForUpdatesOnLaunch = true; } configuration.CheckForUpdatesOnLaunchNoNag = true; configuration.Save(); } bool autoUpdating = false; if (configuration.CheckForUpdatesOnLaunch && AutoUpdate.CanUpdate) { try { log.Info("Making auto-update call"); AutoUpdate.Instance.FetchLatestReleaseInfo(); var latest_version = AutoUpdate.Instance.latestUpdate.Version; var current_version = new ModuleVersion(Meta.GetVersion()); if (AutoUpdate.Instance.IsFetched() && latest_version.IsGreaterThan(current_version)) { log.Debug("Found higher ckan version"); var release_notes = AutoUpdate.Instance.latestUpdate.ReleaseNotes; var dialog = new NewUpdateDialog(latest_version.ToString(), release_notes); if (dialog.ShowDialog() == DialogResult.OK) { UpdateCKAN(); autoUpdating = true; } } } catch (Exception exception) { currentUser.RaiseError(Properties.Resources.MainAutoUpdateFailed, exception.Message); log.Error("Error in auto-update", exception); } } CheckTrayState(); InitRefreshTimer(); m_UpdateRepoWorker = new BackgroundWorker { WorkerReportsProgress = false, WorkerSupportsCancellation = true }; m_UpdateRepoWorker.RunWorkerCompleted += PostUpdateRepo; m_UpdateRepoWorker.DoWork += UpdateRepo; installWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; installWorker.RunWorkerCompleted += PostInstallMods; installWorker.DoWork += InstallMods; URLHandlers.RegisterURLHandler(configuration, currentUser); CurrentInstanceUpdated(!autoUpdating); if (commandLineArgs.Length >= 2) { var identifier = commandLineArgs[1]; if (identifier.StartsWith("//")) { identifier = identifier.Substring(2); } else if (identifier.StartsWith("ckan://")) { identifier = identifier.Substring(7); } if (identifier.EndsWith("/")) { identifier = identifier.Substring(0, identifier.Length - 1); } log.Debug("Attempting to select mod from startup parameters"); ManageMods.FocusMod(identifier, true, true); ManageMods.ModGrid.Refresh(); log.Debug("Failed to select mod from startup parameters"); } var pluginsPath = Path.Combine(CurrentInstance.CkanDir(), "Plugins"); if (!Directory.Exists(pluginsPath)) { Directory.CreateDirectory(pluginsPath); } pluginController = new PluginController(pluginsPath); CurrentInstance.game.RebuildSubdirectories(CurrentInstance); log.Info("GUI started"); base.OnLoad(e); }
public Main(string[] cmdlineArgs, GameInstanceManager mgr, bool showConsole) { log.Info("Starting the GUI"); commandLineArgs = cmdlineArgs; Configuration.IConfiguration mainConfig = ServiceLocator.Container.Resolve <Configuration.IConfiguration>(); // If the language is not set yet in the config, try to save the current language. // If it isn't supported, it'll still be null afterwards. Doesn't matter, .NET handles the resource selection. // Once the user chooses a language in the settings, the string will be no longer null, and we can change // CKAN's language here before any GUI components are initialized. if (string.IsNullOrEmpty(mainConfig.Language)) { string runtimeLanguage = Thread.CurrentThread.CurrentUICulture.IetfLanguageTag; mainConfig.Language = runtimeLanguage; } else { Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(mainConfig.Language); } InitializeComponent(); Instance = this; currentUser = new GUIUser(this, this.Wait); manager = mgr ?? new GameInstanceManager(currentUser); controlFactory = new ControlFactory(); // React when the user clicks a tag or filter link in mod info ModInfo.OnChangeFilter += ManageMods.Filter; // Replace mono's broken, ugly toolstrip renderer if (Platform.IsMono) { menuStrip1.Renderer = new FlatToolStripRenderer(); fileToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); settingsToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); helpToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); minimizedContextMenuStrip.Renderer = new FlatToolStripRenderer(); } // Initialize all user interaction dialogs. RecreateDialogs(); // We want to check if our current instance is null first, // as it may have already been set by a command-line option. if (CurrentInstance == null && manager.GetPreferredInstance() == null) { Hide(); var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(); if (result == DialogResult.Cancel || result == DialogResult.Abort) { Application.Exit(); return; } } configuration = GUIConfiguration.LoadOrCreateConfiguration ( Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml") ); // Check if there is any other instances already running. // This is not entirely necessary, but we can show a nicer error message this way. try { #pragma warning disable 219 var lockedReg = RegistryManager.Instance(CurrentInstance).registry; #pragma warning restore 219 } catch (RegistryInUseKraken kraken) { errorDialog.ShowErrorDialog(kraken.ToString()); return; } tabController = new TabController(MainTabControl); tabController.ShowTab("ManageModsTabPage"); if (!showConsole) { Util.HideConsoleWindow(); } // Disable the modinfo controls until a mod has been choosen. This has an effect if the modlist is empty. ActiveModInfo = null; // WinForms on Mac OS X has a nasty bug where the UI thread hogs the CPU, // making our download speeds really slow unless you move the mouse while // downloading. Yielding periodically addresses that. // https://bugzilla.novell.com/show_bug.cgi?id=663433 if (Platform.IsMac) { var timer = new Timer { Interval = 2 }; timer.Tick += (sender, e) => { Thread.Yield(); }; timer.Start(); } // Set the window name and class for X11 if (Platform.IsX11) { HandleCreated += (sender, e) => X11.SetWMClass("CKAN", "CKAN", Handle); } Application.Run(this); var registry = RegistryManager.Instance(Manager.CurrentInstance); registry?.Dispose(); }
public Main(string[] cmdlineArgs, GameInstanceManager mgr, bool showConsole) { log.Info("Starting the GUI"); commandLineArgs = cmdlineArgs; Configuration.IConfiguration mainConfig = ServiceLocator.Container.Resolve <Configuration.IConfiguration>(); // If the language is not set yet in the config, try to save the current language. // If it isn't supported, it'll still be null afterwards. Doesn't matter, .NET handles the resource selection. // Once the user chooses a language in the settings, the string will be no longer null, and we can change // CKAN's language here before any GUI components are initialized. if (string.IsNullOrEmpty(mainConfig.Language)) { string runtimeLanguage = Thread.CurrentThread.CurrentUICulture.IetfLanguageTag; mainConfig.Language = runtimeLanguage; } else { CultureInfo.DefaultThreadCurrentUICulture = Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(mainConfig.Language); } InitializeComponent(); Instance = this; currentUser = new GUIUser(this, this.Wait); if (mgr != null) { // With a working GUI, assign a GUIUser to the GameInstanceManager to replace the ConsoleUser mgr.User = currentUser; manager = mgr; } else { manager = new GameInstanceManager(currentUser); } controlFactory = new ControlFactory(); // React when the user clicks a tag or filter link in mod info ModInfo.OnChangeFilter += ManageMods.Filter; // Replace mono's broken, ugly toolstrip renderer if (Platform.IsMono) { menuStrip1.Renderer = new FlatToolStripRenderer(); fileToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); settingsToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); helpToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer(); minimizedContextMenuStrip.Renderer = new FlatToolStripRenderer(); } // Initialize all user interaction dialogs. RecreateDialogs(); // Make sure we have an instance if (CurrentInstance == null) { // Maybe we can find an instance automatically (e.g., portable, only, default) manager.GetPreferredInstance(); } // A loop that ends when we have a valid instance or the user gives up do { if (CurrentInstance == null && !InstancePromptAtStart()) { // User cancelled, give up return; } // We now have a tentative instance. Check if it's locked. try { // This will throw RegistryInUseKraken if locked by another process var regMgr = RegistryManager.Instance(CurrentInstance); // Tell the user their registry was reset if it was corrupted if (!string.IsNullOrEmpty(regMgr.previousCorruptedMessage) && !string.IsNullOrEmpty(regMgr.previousCorruptedPath)) { errorDialog.ShowErrorDialog(Properties.Resources.MainCorruptedRegistry, regMgr.previousCorruptedPath, regMgr.previousCorruptedMessage, Path.Combine(Path.GetDirectoryName(regMgr.previousCorruptedPath) ?? "", regMgr.LatestInstalledExportFilename())); regMgr.previousCorruptedMessage = null; regMgr.previousCorruptedPath = null; // But the instance is actually fine because a new registry was just created } } catch (RegistryInUseKraken kraken) { errorDialog.ShowErrorDialog(kraken.ToString()); // Couldn't get the lock, there is no current instance manager.CurrentInstance = null; if (manager.Instances.All(inst => !inst.Value.Valid || inst.Value.IsMaybeLocked)) { // Everything's invalid or locked, give up Application.Exit(); return; } } } while (CurrentInstance == null); // We can only reach this point if CurrentInstance is not null // AND we acquired the lock for it successfully // Get the instance's GUI onfig configuration = GUIConfiguration.LoadOrCreateConfiguration( Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml")); tabController = new TabController(MainTabControl); tabController.ShowTab("ManageModsTabPage"); if (!showConsole) { Util.HideConsoleWindow(); } // Disable the modinfo controls until a mod has been choosen. This has an effect if the modlist is empty. ActiveModInfo = null; // WinForms on Mac OS X has a nasty bug where the UI thread hogs the CPU, // making our download speeds really slow unless you move the mouse while // downloading. Yielding periodically addresses that. // https://bugzilla.novell.com/show_bug.cgi?id=663433 if (Platform.IsMac) { var timer = new Timer { Interval = 2 }; timer.Tick += (sender, e) => { Thread.Yield(); }; timer.Start(); } // Set the window name and class for X11 if (Platform.IsX11) { HandleCreated += (sender, e) => X11.SetWMClass("CKAN", "CKAN", Handle); } Application.Run(this); if (CurrentInstance != null) { var registry = RegistryManager.Instance(Manager.CurrentInstance); registry?.Dispose(); } }
public void LaunchGame() { var split = configuration.CommandLineArguments.Split(' '); if (split.Length == 0) { return; } var registry = RegistryManager.Instance(CurrentInstance).registry; var suppressedIdentifiers = CurrentInstance.GetSuppressedCompatWarningIdentifiers; var incomp = registry.IncompatibleInstalled(CurrentInstance.VersionCriteria()) .Where(m => !m.Module.IsDLC && !suppressedIdentifiers.Contains(m.identifier)) .ToList(); if (incomp.Any()) { // Warn that it might not be safe to run Game with incompatible modules installed string incompatDescrip = incomp .Select(m => $"{m.Module} ({registry.CompatibleGameVersions(CurrentInstance.game, m.Module)})") .Aggregate((a, b) => $"{a}{Environment.NewLine}{b}"); var ver = CurrentInstance.Version(); var result = SuppressableYesNoDialog( string.Format(Properties.Resources.MainLaunchWithIncompatible, incompatDescrip), string.Format(Properties.Resources.MainLaunchDontShow, CurrentInstance.game.ShortName, new GameVersion(ver.Major, ver.Minor, ver.Patch)), Properties.Resources.MainLaunch, Properties.Resources.MainGoBack ); if (result.Item1 != DialogResult.Yes) { return; } else if (result.Item2) { CurrentInstance.AddSuppressedCompatWarningIdentifiers( incomp.Select(m => m.identifier).ToHashSet() ); } } split = CurrentInstance.game.AdjustCommandLine(split, Main.Instance.CurrentInstance.Version()); var binary = split[0]; var args = string.Join(" ", split.Skip(1)); try { Directory.SetCurrentDirectory(CurrentInstance.GameDir()); Process p = new Process() { StartInfo = new ProcessStartInfo() { FileName = binary, Arguments = args }, EnableRaisingEvents = true }; GameInstance inst = CurrentInstance; p.Exited += (sender, e) => GameExit(inst); p.Start(); CurrentInstance.playTime.Start(); } catch (Exception exception) { currentUser.RaiseError(Properties.Resources.MainLaunchFailed, exception.Message); } }
/// <summary> /// React to switching to a new game instance /// </summary> /// <param name="allowRepoUpdate">true if a repo update is allowed if needed (e.g. on initial load), false otherwise</param> private void CurrentInstanceUpdated(bool allowRepoUpdate) { log.Debug("Current instance updated, scanning"); CurrentInstance.Scan(); Util.Invoke(this, () => { Text = $"CKAN {Meta.GetVersion()} - {CurrentInstance.game.ShortName} {CurrentInstance.Version()} -- {CurrentInstance.GameDir().Replace('/', Path.DirectorySeparatorChar)}"; UpdateStatusBar(); }); if (CurrentInstance.CompatibleVersionsAreFromDifferentGameVersion) { new CompatibleGameVersionsDialog(CurrentInstance, !actuallyVisible) .ShowDialog(); } // This will throw RegistryInUseKraken if locked by another process var regMgr = RegistryManager.Instance(CurrentInstance); var registry = regMgr.registry; if (!string.IsNullOrEmpty(regMgr.previousCorruptedMessage) && !string.IsNullOrEmpty(regMgr.previousCorruptedPath)) { errorDialog.ShowErrorDialog(Properties.Resources.MainCorruptedRegistry, regMgr.previousCorruptedPath, regMgr.previousCorruptedMessage, Path.Combine(Path.GetDirectoryName(regMgr.previousCorruptedPath) ?? "", regMgr.LatestInstalledExportFilename())); regMgr.previousCorruptedMessage = null; regMgr.previousCorruptedPath = null; } registry.BuildTagIndex(ManageMods.mainModList.ModuleTags); configuration = GUIConfiguration.LoadOrCreateConfiguration( Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml")); bool repoUpdateNeeded = configuration.RefreshOnStartup || !RegistryManager.Instance(CurrentInstance).registry.HasAnyAvailable(); if (allowRepoUpdate) { // If not allowing, don't do anything if (repoUpdateNeeded) { // Update the filters after UpdateRepo() completed. // Since this happens with a backgroundworker, Filter() is added as callback for RunWorkerCompleted. // Remove it again after it ran, else it stays there and is added again and again. void filterUpdate(object sender, RunWorkerCompletedEventArgs e) { SetupDefaultSearch(); m_UpdateRepoWorker.RunWorkerCompleted -= filterUpdate; } m_UpdateRepoWorker.RunWorkerCompleted += filterUpdate; ManageMods.ModGrid.Rows.Clear(); UpdateRepo(); } else { SetupDefaultSearch(); ManageMods.UpdateModsList(); } } ManageMods.InstanceUpdated(CurrentInstance); }
protected override void OnLoad(EventArgs e) { SetStartPosition(); Size = configuration.WindowSize; WindowState = configuration.IsWindowMaximised ? FormWindowState.Maximized : FormWindowState.Normal; if (!configuration.CheckForUpdatesOnLaunchNoNag && AutoUpdate.CanUpdate) { log.Debug("Asking user if they wish for auto-updates"); if (new AskUserForAutoUpdatesDialog().ShowDialog() == DialogResult.OK) { configuration.CheckForUpdatesOnLaunch = true; } configuration.CheckForUpdatesOnLaunchNoNag = true; configuration.Save(); } bool autoUpdating = CheckForCKANUpdate(); CheckTrayState(); InitRefreshTimer(); m_UpdateRepoWorker = new BackgroundWorker { WorkerReportsProgress = false, WorkerSupportsCancellation = true }; m_UpdateRepoWorker.RunWorkerCompleted += PostUpdateRepo; m_UpdateRepoWorker.DoWork += UpdateRepo; installWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; installWorker.RunWorkerCompleted += PostInstallMods; installWorker.DoWork += InstallMods; URLHandlers.RegisterURLHandler(configuration, currentUser); if (CurrentInstance != null) { CurrentInstanceUpdated(!autoUpdating); } if (commandLineArgs.Length >= 2) { var identifier = commandLineArgs[1]; if (identifier.StartsWith("//")) { identifier = identifier.Substring(2); } else if (identifier.StartsWith("ckan://")) { identifier = identifier.Substring(7); } if (identifier.EndsWith("/")) { identifier = identifier.Substring(0, identifier.Length - 1); } log.Debug("Attempting to select mod from startup parameters"); ManageMods.FocusMod(identifier, true, true); ManageMods.ModGrid.Refresh(); log.Debug("Failed to select mod from startup parameters"); } if (CurrentInstance != null) { var pluginsPath = Path.Combine(CurrentInstance.CkanDir(), "Plugins"); if (!Directory.Exists(pluginsPath)) { Directory.CreateDirectory(pluginsPath); } pluginController = new PluginController(pluginsPath); CurrentInstance.game.RebuildSubdirectories(CurrentInstance); } log.Info("GUI started"); base.OnLoad(e); }
private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry) { IEnumerable <ModChange> full_change_set = null; Dictionary <GUIMod, string> new_conflicts = null; bool too_many_provides_thrown = false; var user_change_set = mainModList.ComputeUserChangeSet(); try { var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user); full_change_set = await mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.VersionCriteria()); } catch (InconsistentKraken) { // Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling. user_change_set = mainModList.ComputeUserChangeSet(); new_conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria()); full_change_set = null; } catch (TooManyModsProvideKraken) { // Can be thrown by ComputeChangeSetFromModList if the user cancels out of it. // We can just rerun it as the ModInfoTabControl has been removed. too_many_provides_thrown = true; } if (too_many_provides_thrown) { await UpdateChangeSetAndConflicts(registry); new_conflicts = Conflicts; full_change_set = ChangeSet; } last_mod_to_have_install_toggled.Clear(); Conflicts = new_conflicts; ChangeSet = full_change_set; }
protected override void OnLoad(EventArgs e) { if (configuration.WindowLoc.X == -1 && configuration.WindowLoc.Y == -1) { // Center on screen for first launch StartPosition = FormStartPosition.CenterScreen; } else if (Platform.IsMac) { // Make sure there's room at the top for the MacOSX menu bar Location = Util.ClampedLocationWithMargins( configuration.WindowLoc, configuration.WindowSize, new Size(0, 30), new Size(0, 0) ); } else { // Just make sure it's fully on screen Location = Util.ClampedLocation(configuration.WindowLoc, configuration.WindowSize); } Size = configuration.WindowSize; WindowState = configuration.IsWindowMaximised ? FormWindowState.Maximized : FormWindowState.Normal; #if (!ONI) if (!configuration.CheckForUpdatesOnLaunchNoNag && AutoUpdate.CanUpdate) { log.Debug("Asking user if they wish for auto-updates"); if (new AskUserForAutoUpdatesDialog().ShowDialog() == DialogResult.OK) { configuration.CheckForUpdatesOnLaunch = true; } configuration.CheckForUpdatesOnLaunchNoNag = true; configuration.Save(); } #else configuration.CheckForUpdatesOnLaunch = false; configuration.CheckForUpdatesOnLaunchNoNag = false; configuration.Save(); #endif bool autoUpdating = false; if (configuration.CheckForUpdatesOnLaunch && AutoUpdate.CanUpdate) { try { log.Info("Making auto-update call"); AutoUpdate.Instance.FetchLatestReleaseInfo(); var latest_version = AutoUpdate.Instance.latestUpdate.Version; var current_version = new ModuleVersion(Meta.GetVersion()); if (AutoUpdate.Instance.IsFetched() && latest_version.IsGreaterThan(current_version)) { log.Debug("Found higher ckan version"); var release_notes = AutoUpdate.Instance.latestUpdate.ReleaseNotes; var dialog = new NewUpdateDialog(latest_version.ToString(), release_notes); if (dialog.ShowDialog() == DialogResult.OK) { UpdateCKAN(); autoUpdating = true; } } } catch (Exception exception) { currentUser.RaiseError($"Error in auto-update:\n\t{exception.Message}"); log.Error("Error in auto-update", exception); } } CheckTrayState(); InitRefreshTimer(); m_UpdateRepoWorker = new BackgroundWorker { WorkerReportsProgress = false, WorkerSupportsCancellation = true }; m_UpdateRepoWorker.RunWorkerCompleted += PostUpdateRepo; m_UpdateRepoWorker.DoWork += UpdateRepo; installWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; installWorker.RunWorkerCompleted += PostInstallMods; installWorker.DoWork += InstallMods; #if (!ONI) URLHandlers.RegisterURLHandler(configuration, currentUser); #endif ApplyToolButton.Enabled = false; CurrentInstanceUpdated(); // We would like to refresh if we're configured to refresh on startup, // or if we have no currently available modules. bool repoUpdateNeeded = configuration.RefreshOnStartup || !RegistryManager.Instance(CurrentInstance).registry.HasAnyAvailable(); // If we're auto-updating the client then we shouldn't interfere with the progress tab if (!autoUpdating && repoUpdateNeeded) { UpdateRepo(); } Text = $"CKAN {Meta.GetVersion()} - {GameConfig.Constants.GameNameShort} {CurrentInstance.Version()} -- {CurrentInstance.GameDir()}"; if (commandLineArgs.Length >= 2) { var identifier = commandLineArgs[1]; if (identifier.StartsWith("//")) { identifier = identifier.Substring(2); } else if (identifier.StartsWith("ckan://")) { identifier = identifier.Substring(7); } if (identifier.EndsWith("/")) { identifier = identifier.Substring(0, identifier.Length - 1); } log.Debug("Attempting to select mod from startup parameters"); FocusMod(identifier, true, true); ModList.Refresh(); log.Debug("Failed to select mod from startup parameters"); } var pluginsPath = Path.Combine(CurrentInstance.CkanDir(), "Plugins"); if (!Directory.Exists(pluginsPath)) { Directory.CreateDirectory(pluginsPath); } pluginController = new PluginController(pluginsPath); CurrentInstance.RebuildKSPSubDir(); // Initialize navigation. This should be called as late as // possible, once the UI is "settled" from its initial load. NavInit(); log.Info("GUI started"); base.OnLoad(e); }
protected override void OnLoad(EventArgs e) { Location = m_Configuration.WindowLoc; Size = m_Configuration.WindowSize; if (!m_Configuration.CheckForUpdatesOnLaunchNoNag) { log.Debug("Asking user if they wish for autoupdates"); if (new AskUserForAutoUpdatesDialog().ShowDialog() == DialogResult.OK) { m_Configuration.CheckForUpdatesOnLaunch = true; } m_Configuration.CheckForUpdatesOnLaunchNoNag = true; m_Configuration.Save(); } if (m_Configuration.CheckForUpdatesOnLaunch) { try { log.Info("Making autoupdate call"); AutoUpdate.Instance.FetchLatestReleaseInfo(); var latest_version = AutoUpdate.Instance.LatestVersion; var current_version = new Version(Meta.Version()); if (AutoUpdate.Instance.IsFetched() && latest_version.IsGreaterThan(current_version)) { log.Debug("Found higher ckan version"); var release_notes = AutoUpdate.Instance.ReleaseNotes; var dialog = new NewUpdateDialog(latest_version.ToString(), release_notes); if (dialog.ShowDialog() == DialogResult.OK) { log.Info("Start ckan update"); AutoUpdate.Instance.StartUpdateProcess(true); } } } catch (Exception exception) { m_User.RaiseError("Error in autoupdate: \n\t" + exception.Message + ""); log.Error("Error in autoupdate", exception); } } m_UpdateRepoWorker = new BackgroundWorker { WorkerReportsProgress = false, WorkerSupportsCancellation = true }; m_UpdateRepoWorker.RunWorkerCompleted += PostUpdateRepo; m_UpdateRepoWorker.DoWork += UpdateRepo; m_InstallWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; m_InstallWorker.RunWorkerCompleted += PostInstallMods; m_InstallWorker.DoWork += InstallMods; m_CacheWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; m_CacheWorker.RunWorkerCompleted += PostModCaching; m_CacheWorker.DoWork += CacheMod; m_User.displayYesNo = YesNoDialog; URLHandlers.RegisterURLHandler(m_Configuration, m_User); m_User.displayYesNo = null; ApplyToolButton.Enabled = false; CurrentInstanceUpdated(); if (m_Configuration.RefreshOnStartup) { UpdateRepo(); } Text = String.Format("CKAN {0} - KSP {1} -- {2}", Meta.Version(), CurrentInstance.Version(), CurrentInstance.GameDir()); KSPVersionLabel.Text = String.Format("Kerbal Space Program {0}", CurrentInstance.Version()); if (m_CommandLineArgs.Length >= 2) { var identifier = m_CommandLineArgs[1]; if (identifier.StartsWith("//")) { identifier = identifier.Substring(2); } else if (identifier.StartsWith("ckan://")) { identifier = identifier.Substring(7); } if (identifier.EndsWith("/")) { identifier = identifier.Substring(0, identifier.Length - 1); } int i = 0; log.Debug("Attempting to select mod from startup parameters"); FocusMod(identifier, true, true); ModList.Refresh(); log.Debug("Failed to select mod from startup parameters"); } var pluginsPath = Path.Combine(CurrentInstance.CkanDir(), "Plugins"); if (!Directory.Exists(pluginsPath)) { Directory.CreateDirectory(pluginsPath); } m_PluginController = new PluginController(pluginsPath, true); CurrentInstance.RebuildKSPSubDir(); log.Info("GUI started"); ModList.Select(); base.OnLoad(e); }
public void CurrentInstanceUpdated() { Util.Invoke(this, () => { Text = String.Format("CKAN {0} - KSP {1} -- {2}", Meta.Version(), CurrentInstance.Version(), CurrentInstance.GameDir()); KSPVersionLabel.Text = String.Format("Kerbal Space Program {0}", CurrentInstance.Version()); }); // Update the settings dialog to reflect the changes made. Util.Invoke(m_SettingsDialog, () => { m_SettingsDialog.UpdateDialog(); }); m_Configuration = Configuration.LoadOrCreateConfiguration ( Path.Combine(CurrentInstance.GameDir(), "CKAN/GUIConfig.xml"), Repo.default_ckan_repo.ToString() ); UpdateModsList(); ChangeSet = null; Conflicts = null; }
private void _UpdateModsList(bool repo_updated, IEnumerable <ModChange> mc) { log.Info("Updating the mod list"); ResetProgress(); tabController.RenameTab("WaitTabPage", "Loading modules"); ShowWaitDialog(false); tabController.SetTabLock(true); Util.Invoke(this, SwitchEnabledState); ClearLog(); AddLogMessage("Loading registry..."); KspVersionCriteria versionCriteria = CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; AddLogMessage("Loading installed modules..."); var gui_mods = new HashSet <GUIMod>(); gui_mods.UnionWith( registry.InstalledModules .Select(instMod => new GUIMod(instMod, registry, versionCriteria)) ); AddLogMessage("Loading available modules..."); gui_mods.UnionWith( registry.Available(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria)) ); AddLogMessage("Loading incompatible modules..."); gui_mods.UnionWith( registry.Incompatible(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria, true)) ); if (mc != null) { AddLogMessage("Restoring change set..."); foreach (ModChange change in mc) { // Propagate IsInstallChecked and IsUpgradeChecked to the next generation gui_mods.FirstOrDefault( mod => mod.Identifier == change.Mod.Identifier )?.SetRequestedChange(change.ChangeType); } } AddLogMessage("Preserving new flags..."); var old_modules = mainModList.Modules.ToDictionary(m => m, m => m.IsIncompatible); if (repo_updated) { foreach (GUIMod gm in gui_mods) { bool oldIncompat; if (old_modules.TryGetValue(gm, out oldIncompat)) { // Found it; check if newly compatible if (!gm.IsIncompatible && oldIncompat) { gm.IsNew = true; } } else { // Newly indexed, show regardless of compatibility gm.IsNew = true; } } } else { //Copy the new mod flag from the old list. var old_new_mods = new HashSet <GUIMod>(old_modules.Keys.Where(m => m.IsNew)); foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m))) { gui_mod.IsNew = true; } } AddLogMessage("Populating mod list..."); // Update our mod listing mainModList.ConstructModList(gui_mods.ToList(), mc, configuration.HideEpochs, configuration.HideV); mainModList.Modules = new ReadOnlyCollection <GUIMod>( mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList()); AddLogMessage("Updating filters..."); var has_any_updates = gui_mods.Any(mod => mod.HasUpdate); var has_any_replacements = gui_mods.Any(mod => mod.HasReplacement); //TODO Consider using smart enumeration pattern so stuff like this is easier Util.Invoke(menuStrip2, () => { FilterToolButton.DropDownItems[0].Text = String.Format("Compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Compatible)); FilterToolButton.DropDownItems[1].Text = String.Format("Installed ({0})", mainModList.CountModsByFilter(GUIModFilter.Installed)); FilterToolButton.DropDownItems[2].Text = String.Format("Upgradeable ({0})", mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable)); FilterToolButton.DropDownItems[3].Text = String.Format("Replaceable ({0})", mainModList.CountModsByFilter(GUIModFilter.Replaceable)); FilterToolButton.DropDownItems[4].Text = String.Format("Cached ({0})", mainModList.CountModsByFilter(GUIModFilter.Cached)); FilterToolButton.DropDownItems[5].Text = String.Format("Newly compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.NewInRepository)); FilterToolButton.DropDownItems[6].Text = String.Format("Not installed ({0})", mainModList.CountModsByFilter(GUIModFilter.NotInstalled)); FilterToolButton.DropDownItems[7].Text = String.Format("Incompatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Incompatible)); FilterToolButton.DropDownItems[8].Text = String.Format("All ({0})", mainModList.CountModsByFilter(GUIModFilter.All)); UpdateAllToolButton.Enabled = has_any_updates; }); UpdateFilters(this); // Hide update and replacement columns if not needed. // Write it to the configuration, else they are hidden agian after a filter change. // After the update / replacement, they are hidden again. ModList.Columns[1].Visible = has_any_updates; ModList.Columns[2].Visible = has_any_replacements; AddLogMessage("Updating tray..."); UpdateTrayInfo(); HideWaitDialog(true); tabController.HideTab("WaitTabPage"); tabController.SetTabLock(false); Util.Invoke(this, SwitchEnabledState); Util.Invoke(this, () => Main.Instance.ModList.Focus()); }
private void UpdateChangeSetAndConflicts(Registry registry) { IEnumerable <KeyValuePair <CkanModule, GUIModChangeType> > full_change_set; Dictionary <Module, string> conflicts; var user_change_set = mainModList.ComputeUserChangeSet(); try { var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user); full_change_set = MainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.Version()); conflicts = null; } catch (InconsistentKraken) { conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.Version()); full_change_set = null; } Conflicts = conflicts; ChangeSet = full_change_set; }
// this probably needs to be refactored private void InstallMods(object sender, DoWorkEventArgs e) { installCanceled = false; Wait.ClearLog(); var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument; RegistryManager registry_manager = RegistryManager.Instance(manager.CurrentInstance); Registry registry = registry_manager.registry; ModuleInstaller installer = new ModuleInstaller(CurrentInstance, Manager.Cache, currentUser); // Avoid accumulating multiple event handlers installer.onReportModInstalled -= OnModInstalled; installer.onReportModInstalled += OnModInstalled; // setup progress callback // this will be the final list of mods we want to install HashSet <CkanModule> toInstall = new HashSet <CkanModule>(); var toUninstall = new HashSet <CkanModule>(); var toUpgrade = new HashSet <CkanModule>(); // First compose sets of what the user wants installed, upgraded, and removed. foreach (ModChange change in opts.Key) { switch (change.ChangeType) { case GUIModChangeType.Remove: toUninstall.Add(change.Mod); break; case GUIModChangeType.Update: toUpgrade.Add(change is ModUpgrade mu ? mu.targetMod : change.Mod); break; case GUIModChangeType.Install: toInstall.Add(change.Mod); break; case GUIModChangeType.Replace: ModuleReplacement repl = registry.GetReplacement(change.Mod, CurrentInstance.VersionCriteria()); if (repl != null) { toUninstall.Add(repl.ToReplace); toInstall.Add(repl.ReplaceWith); } break; } } // Prompt for recommendations and suggestions, if any if (installer.FindRecommendations( opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install) .Select(ch => ch.Mod) .ToHashSet(), toInstall, registry, out Dictionary <CkanModule, Tuple <bool, List <string> > > recommendations, out Dictionary <CkanModule, List <string> > suggestions, out Dictionary <CkanModule, HashSet <string> > supporters )) { tabController.ShowTab("ChooseRecommendedModsTabPage", 3); ChooseRecommendedMods.LoadRecommendations( registry, toInstall, toUninstall, CurrentInstance.VersionCriteria(), Manager.Cache, recommendations, suggestions, supporters); tabController.SetTabLock(true); var result = ChooseRecommendedMods.Wait(); if (result == null) { installCanceled = true; } else { toInstall.UnionWith(result); } tabController.SetTabLock(false); tabController.HideTab("ChooseRecommendedModsTabPage"); } if (installCanceled) { Util.Invoke(this, () => Enabled = true); Util.Invoke(menuStrip1, () => menuStrip1.Enabled = true); tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } // Now let's make all our changes. Util.Invoke(this, () => { // Need to be on the GUI thread to get the translated string tabController.RenameTab("WaitTabPage", Properties.Resources.MainInstallWaitTitle); }); ShowWaitDialog(); tabController.SetTabLock(true); IDownloader downloader = new NetAsyncModulesDownloader(currentUser, Manager.Cache); downloader.Progress += Wait.SetModuleProgress; downloader.AllComplete += Wait.DownloadsComplete; cancelCallback = () => { downloader.CancelDownload(); installCanceled = true; }; HashSet <string> possibleConfigOnlyDirs = null; // checks if all actions were successfull bool processSuccessful = false; bool resolvedAllProvidedMods = false; // uninstall/installs/upgrades until every list is empty // if the queue is NOT empty, resolvedAllProvidedMods is set to false until the action is done while (!resolvedAllProvidedMods) { try { e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); if (toUninstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.UninstallList(toUninstall.Select(m => m.identifier), ref possibleConfigOnlyDirs, registry_manager, false, toInstall); toUninstall.Clear(); processSuccessful = true; } } if (toInstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.InstallList(toInstall, opts.Value, registry_manager, ref possibleConfigOnlyDirs, downloader, false); toInstall.Clear(); processSuccessful = true; } } if (toUpgrade.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.Upgrade(toUpgrade, downloader, ref possibleConfigOnlyDirs, registry_manager, true, true, false); toUpgrade.Clear(); processSuccessful = true; } } HandlePossibleConfigOnlyDirs(registry, possibleConfigOnlyDirs); e.Result = new KeyValuePair <bool, ModChanges>(processSuccessful, opts.Key); if (installCanceled) { return; } resolvedAllProvidedMods = true; } catch (TooManyModsProvideKraken k) { // Prompt user to choose which mod to use tabController.ShowTab("ChooseProvidedModsTabPage", 3); ChooseProvidedMods.LoadProviders(k.requested, k.modules, Manager.Cache); tabController.SetTabLock(true); CkanModule chosen = ChooseProvidedMods.Wait(); // Close the selection prompt tabController.SetTabLock(false); tabController.HideTab("ChooseProvidedModsTabPage"); if (chosen != null) { // User picked a mod, queue it up for installation toInstall.Add(chosen); // DON'T return so we can loop around and try the above InstallList call again tabController.ShowTab("WaitTabPage"); } else { // User cancelled, get out tabController.ShowTab("ManageModsTabPage"); Util.Invoke(this, () => Enabled = true); Util.Invoke(menuStrip1, () => menuStrip1.Enabled = true); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } } } }
/// <summary> /// React to switching to a new game instance /// </summary> /// <param name="allowRepoUpdate">true if a repo update is allowed if needed (e.g. on initial load), false otherwise</param> private void CurrentInstanceUpdated(bool allowRepoUpdate) { CurrentInstance.Scan(); Util.Invoke(this, () => { Text = $"CKAN {Meta.GetVersion()} - {CurrentInstance.game.ShortName} {CurrentInstance.Version()} -- {CurrentInstance.GameDir().Replace('/', Path.DirectorySeparatorChar)}"; StatusInstanceLabel.Text = string.Format( Properties.Resources.StatusInstanceLabelText, CurrentInstance.Name, CurrentInstance.game.ShortName, CurrentInstance.Version()?.ToString() ); }); configuration = GUIConfiguration.LoadOrCreateConfiguration( Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml") ); if (CurrentInstance.CompatibleVersionsAreFromDifferentGameVersion) { new CompatibleGameVersionsDialog(CurrentInstance, !actuallyVisible) .ShowDialog(); } (RegistryManager.Instance(CurrentInstance).registry as Registry) ?.BuildTagIndex(ManageMods.mainModList.ModuleTags); bool repoUpdateNeeded = configuration.RefreshOnStartup || !RegistryManager.Instance(CurrentInstance).registry.HasAnyAvailable(); if (allowRepoUpdate && repoUpdateNeeded) { // Update the filters after UpdateRepo() completed. // Since this happens with a backgroundworker, Filter() is added as callback for RunWorkerCompleted. // Remove it again after it ran, else it stays there and is added again and again. void filterUpdate(object sender, RunWorkerCompletedEventArgs e) { ManageMods.Filter( (GUIModFilter)configuration.ActiveFilter, ManageMods.mainModList.ModuleTags.Tags.GetOrDefault(configuration.TagFilter), ManageMods.mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name) .FirstOrDefault(l => l.Name == configuration.CustomLabelFilter) ); m_UpdateRepoWorker.RunWorkerCompleted -= filterUpdate; } m_UpdateRepoWorker.RunWorkerCompleted += filterUpdate; ManageMods.ModGrid.Rows.Clear(); UpdateRepo(); } else { ManageMods.UpdateModsList(); ManageMods.Filter( (GUIModFilter)configuration.ActiveFilter, ManageMods.mainModList.ModuleTags.Tags.GetOrDefault(configuration.TagFilter), ManageMods.mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name) .FirstOrDefault(l => l.Name == configuration.CustomLabelFilter) ); } ManageMods.InstanceUpdated(CurrentInstance); }
private IEnumerable <ListViewItem> getRecSugRows( IEnumerable <CkanModule> sourceModules, IRegistryQuerier registry, HashSet <CkanModule> toInstall ) { Dictionary <CkanModule, List <string> > dependersIndex = getDependersIndex(sourceModules, registry, toInstall); foreach (CkanModule mod in sourceModules.Where(m => m.recommends != null)) { foreach (RelationshipDescriptor rel in mod.recommends) { List <CkanModule> providers = rel.LatestAvailableWithProvides( registry, CurrentInstance.VersionCriteria() ); foreach (CkanModule provider in providers) { List <string> dependers; if (!registry.IsInstalled(provider.identifier) && !toInstall.Any(m => m.identifier == provider.identifier) && dependersIndex.TryGetValue(provider, out dependers) && CanInstall(registry, CurrentInstance.VersionCriteria(), RelationshipResolver.DependsOnlyOpts(), toInstall.ToList().Concat(new List <CkanModule>() { provider }).ToList())) { dependersIndex.Remove(provider); yield return(getRecSugItem( provider, string.Join(", ", dependers), RecommendationsGroup, providers.Count <= 1 || provider.identifier == (rel as ModuleRelationshipDescriptor)?.name )); } } } } foreach (CkanModule mod in sourceModules.Where(m => m.suggests != null)) { foreach (RelationshipDescriptor rel in mod.suggests) { List <CkanModule> providers = rel.LatestAvailableWithProvides( registry, CurrentInstance.VersionCriteria() ); foreach (CkanModule provider in providers) { List <string> dependers; if (!registry.IsInstalled(provider.identifier) && !toInstall.Any(m => m.identifier == provider.identifier) && dependersIndex.TryGetValue(provider, out dependers) && CanInstall(registry, CurrentInstance.VersionCriteria(), RelationshipResolver.DependsOnlyOpts(), toInstall.ToList().Concat(new List <CkanModule>() { provider }).ToList())) { dependersIndex.Remove(provider); yield return(getRecSugItem( provider, string.Join(", ", dependers), SuggestionsGroup, false )); } } } } }
/// <summary> /// Tries to get every mod in the Dictionary, which can be installed /// It also transforms the Recommender list to a string /// </summary> /// <param name="mods"></param> /// <returns></returns> private Dictionary <CkanModule, string> GetShowableMods(Dictionary <string, List <string> > mods) { Dictionary <CkanModule, string> modules = new Dictionary <CkanModule, string>(); var opts = new RelationshipResolverOptions { with_all_suggests = false, with_recommends = false, with_suggests = false, without_enforce_consistency = false, without_toomanyprovides_kraken = true }; foreach (var pair in mods) { CkanModule module; try { var resolver = new RelationshipResolver(new List <string> { pair.Key }, opts, RegistryManager.Instance(manager.CurrentInstance).registry, CurrentInstance.VersionCriteria()); if (!resolver.ModList().Any()) { continue; } module = RegistryManager.Instance(manager.CurrentInstance) .registry.LatestAvailable(pair.Key, CurrentInstance.VersionCriteria()); } catch { continue; } if (module == null) { continue; } modules.Add(module, String.Join(",", pair.Value.ToArray())); } return(modules); }
/// <summary> /// React to switching to a new game instance /// </summary> /// <param name="onStartup">true if this is the initial load and should trigger auto repo updates, false otherwise</param> private void CurrentInstanceUpdated(bool onStartup) { Util.Invoke(this, () => { Text = $"CKAN {Meta.GetVersion()} - KSP {CurrentInstance.Version()} -- {CurrentInstance.GameDir()}"; }); configuration = Configuration.LoadOrCreateConfiguration( Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml") ); if (CurrentInstance.CompatibleVersionsAreFromDifferentKsp) { new CompatibleKspVersionsDialog(CurrentInstance, !actuallyVisible) .ShowDialog(); } bool repoUpdateNeeded = configuration.RefreshOnStartup || !RegistryManager.Instance(CurrentInstance).registry.HasAnyAvailable(); if (onStartup && repoUpdateNeeded) { UpdateRepo(); } else { UpdateModsList(); } ChangeSet = null; Conflicts = null; Filter((GUIModFilter)configuration.ActiveFilter); }
private void _UpdateModsList(bool repo_updated, List <ModChange> mc) { log.Info("Updating the mod list"); KspVersionCriteria versionCriteria = CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; var gui_mods = new HashSet <GUIMod>(); gui_mods.UnionWith( registry.InstalledModules .Select(instMod => new GUIMod(instMod, registry, versionCriteria)) ); gui_mods.UnionWith( registry.Available(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria)) ); gui_mods.UnionWith( registry.Incompatible(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria, true)) ); var old_modules = mainModList.Modules.ToDictionary(m => m, m => m.IsIncompatible); if (repo_updated) { foreach (GUIMod gm in gui_mods) { bool oldIncompat; if (old_modules.TryGetValue(gm, out oldIncompat)) { // Found it; check if newly compatible if (!gm.IsIncompatible && oldIncompat) { gm.IsNew = true; } } else { // Newly indexed, show regardless of compatibility gm.IsNew = true; } } } else { //Copy the new mod flag from the old list. var old_new_mods = new HashSet <GUIMod>(old_modules.Keys.Where(m => m.IsNew)); foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m))) { gui_mod.IsNew = true; } } // Update our mod listing. If we're doing a repo update, then we don't refresh // all (in case the user has selected changes they wish to apply). mainModList.ConstructModList(gui_mods.ToList(), mc, !repo_updated, configuration.HideEpochs, configuration.HideV); mainModList.Modules = new ReadOnlyCollection <GUIMod>( mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList()); //TODO Consider using smart enumeration pattern so stuff like this is easier FilterToolButton.DropDownItems[0].Text = String.Format("Compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Compatible)); FilterToolButton.DropDownItems[1].Text = String.Format("Installed ({0})", mainModList.CountModsByFilter(GUIModFilter.Installed)); FilterToolButton.DropDownItems[2].Text = String.Format("Upgradeable ({0})", mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable)); FilterToolButton.DropDownItems[3].Text = String.Format("Cached ({0})", mainModList.CountModsByFilter(GUIModFilter.Cached)); FilterToolButton.DropDownItems[4].Text = String.Format("Newly compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.NewInRepository)); FilterToolButton.DropDownItems[5].Text = String.Format("Not installed ({0})", mainModList.CountModsByFilter(GUIModFilter.NotInstalled)); FilterToolButton.DropDownItems[6].Text = String.Format("Incompatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Incompatible)); FilterToolButton.DropDownItems[7].Text = String.Format("All ({0})", mainModList.CountModsByFilter(GUIModFilter.All)); var has_any_updates = gui_mods.Any(mod => mod.HasUpdate); UpdateAllToolButton.Enabled = has_any_updates; UpdateFilters(this); }
private void UpdateRecommendedDialog(Dictionary <string, List <string> > mods, bool suggested = false) { if (!suggested) { RecommendedDialogLabel.Text = "The following modules have been recommended by one or more of the chosen modules:"; RecommendedModsListView.Columns[1].Text = "Recommended by:"; RecommendedModsToggleCheckbox.Text = "(De-)select all recommended mods."; RecommendedModsToggleCheckbox.Checked = true; m_TabController.RenameTab("ChooseRecommendedModsTabPage", "Choose recommended mods"); } else { RecommendedDialogLabel.Text = "The following modules have been suggested by one or more of the chosen modules:"; RecommendedModsListView.Columns[1].Text = "Suggested by:"; RecommendedModsToggleCheckbox.Text = "(De-)select all suggested mods."; RecommendedModsToggleCheckbox.Checked = false; m_TabController.RenameTab("ChooseRecommendedModsTabPage", "Choose suggested mods"); } RecommendedModsListView.Items.Clear(); foreach (var pair in mods) { CkanModule module; try { var opts = new RelationshipResolverOptions { with_all_suggests = false, with_recommends = false, with_suggests = false, without_enforce_consistency = false, without_toomanyprovides_kraken = true }; var resolver = new RelationshipResolver(new List <string> { pair.Key }, opts, RegistryManager.Instance(manager.CurrentInstance).registry, CurrentInstance.Version()); if (!resolver.ModList().Any()) { continue; } module = RegistryManager.Instance(manager.CurrentInstance) .registry.LatestAvailable(pair.Key, CurrentInstance.Version()); } catch { continue; } if (module == null) { continue; } ListViewItem item = new ListViewItem { Tag = module, Checked = !suggested, Text = pair.Key }; ListViewItem.ListViewSubItem recommendedBy = new ListViewItem.ListViewSubItem(); string recommendedByString = ""; bool first = true; foreach (string mod in pair.Value) { if (!first) { recommendedByString += ", "; } else { first = false; } recommendedByString += mod; } recommendedBy.Text = recommendedByString; item.SubItems.Add(recommendedBy); ListViewItem.ListViewSubItem description = new ListViewItem.ListViewSubItem { Text = module.@abstract }; item.SubItems.Add(description); RecommendedModsListView.Items.Add(item); } }
private void _UpdateModsList(bool repo_updated) { log.Debug("Updating the mod list"); KSPVersion version = CurrentInstance.Version(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; var gui_mods = new HashSet <GUIMod>(registry.Available(version) .Select(m => new GUIMod(m, registry, version))); gui_mods.UnionWith(registry.Incompatible(version) .Select(m => new GUIMod(m, registry, version))); var installed = registry.InstalledModules .Select(m => new GUIMod(m.Module, registry, version)); //Hashset does not define if add/unionwith replaces existing elements. //In this case that could cause a CkanModule to be replaced by a Module. //Hence the explicit checking foreach (var mod in installed.Where(mod => !gui_mods.Contains(mod))) { gui_mods.Add(mod); } var old_modules = new HashSet <GUIMod>(mainModList.Modules); if (repo_updated) { foreach (var gui_mod in gui_mods.Where(m => !old_modules.Contains(m))) { gui_mod.IsNew = true; } } else { //Copy the new mod flag from the old list. var old_new_mods = new HashSet <GUIMod>(old_modules.Where(m => m.IsNew)); foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m))) { gui_mod.IsNew = true; } } mainModList.Modules = new ReadOnlyCollection <GUIMod>(gui_mods.ToList()); mainModList.ConstructModList(mainModList.Modules); //TODO Consider using smart enum patten so stuff like this is easier FilterToolButton.DropDownItems[0].Text = String.Format("Compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Compatible)); FilterToolButton.DropDownItems[1].Text = String.Format("Installed ({0})", mainModList.CountModsByFilter(GUIModFilter.Installed)); FilterToolButton.DropDownItems[2].Text = String.Format("Upgradeable ({0})", mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable)); FilterToolButton.DropDownItems[3].Text = String.Format("New in repository ({0})", mainModList.CountModsByFilter(GUIModFilter.NewInRepository)); FilterToolButton.DropDownItems[4].Text = String.Format("Not installed ({0})", mainModList.CountModsByFilter(GUIModFilter.NotInstalled)); FilterToolButton.DropDownItems[5].Text = String.Format("Incompatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Incompatible)); FilterToolButton.DropDownItems[6].Text = String.Format("All ({0})", mainModList.CountModsByFilter(GUIModFilter.All)); var has_any_updates = gui_mods.Any(mod => mod.HasUpdate); UpdateAllToolButton.Enabled = has_any_updates; UpdateFilters(this); }
public Main(string[] cmdlineArgs, GUIUser User, bool showConsole) { log.Info("Starting the GUI"); m_CommandLineArgs = cmdlineArgs; m_User = User; User.displayMessage = AddStatusMessage; User.displayError = ErrorDialog; controlFactory = new ControlFactory(); Instance = this; mainModList = new MainModList(source => UpdateFilters(this)); InitializeComponent(); // We need to initialize error dialog first to display errors m_ErrorDialog = controlFactory.CreateControl <ErrorDialog>(); // We want to check our current instance is null first, as it may // have already been set by a command-line option. Manager = new KSPManager(User); if (CurrentInstance == null && manager.GetPreferredInstance() == null) { Hide(); var result = new ChooseKSPInstance().ShowDialog(); if (result == DialogResult.Cancel || result == DialogResult.Abort) { Application.Exit(); return; } } m_Configuration = Configuration.LoadOrCreateConfiguration ( Path.Combine(CurrentInstance.GameDir(), "CKAN/GUIConfig.xml"), Repo.default_ckan_repo.ToString() ); FilterToolButton.MouseHover += (sender, args) => FilterToolButton.ShowDropDown(); launchKSPToolStripMenuItem.MouseHover += (sender, args) => launchKSPToolStripMenuItem.ShowDropDown(); ApplyToolButton.MouseHover += (sender, args) => ApplyToolButton.ShowDropDown(); ModList.CurrentCellDirtyStateChanged += ModList_CurrentCellDirtyStateChanged; ModList.CellValueChanged += ModList_CellValueChanged; m_TabController = new TabController(MainTabControl); m_TabController.ShowTab("ManageModsTabPage"); RecreateDialogs(); if (!showConsole) { Util.HideConsoleWindow(); } // Disable the modinfo controls until a mod has been choosen. ModInfoTabControl.Enabled = false; // WinForms on Mac OS X has a nasty bug where the UI thread hogs the CPU, // making our download speeds really slow unless you move the mouse while // downloading. Yielding periodically addresses that. // https://bugzilla.novell.com/show_bug.cgi?id=663433 if (Platform.IsMac) { var yield_timer = new Timer { Interval = 2 }; yield_timer.Tick += (sender, e) => { Thread.Yield(); }; yield_timer.Start(); } Application.Run(this); }
protected override void OnLoad(EventArgs e) { Location = configuration.WindowLoc; Size = configuration.WindowSize; WindowState = configuration.IsWindowMaximised ? FormWindowState.Maximized : FormWindowState.Normal; try { splitContainer1.SplitterDistance = configuration.PanelPosition; } catch { // SplitContainer is mis-designed to throw exceptions // if the min/max limits are exceeded rather than simply obeying them. } ModInfoTabControl.ModMetaSplitPosition = configuration.ModInfoPosition; if (!configuration.CheckForUpdatesOnLaunchNoNag && AutoUpdate.CanUpdate) { log.Debug("Asking user if they wish for auto-updates"); if (new AskUserForAutoUpdatesDialog().ShowDialog() == DialogResult.OK) { configuration.CheckForUpdatesOnLaunch = true; } configuration.CheckForUpdatesOnLaunchNoNag = true; configuration.Save(); } bool autoUpdating = false; if (configuration.CheckForUpdatesOnLaunch && AutoUpdate.CanUpdate) { try { log.Info("Making auto-update call"); AutoUpdate.Instance.FetchLatestReleaseInfo(); var latest_version = AutoUpdate.Instance.latestUpdate.Version; var current_version = new ModuleVersion(Meta.GetVersion()); if (AutoUpdate.Instance.IsFetched() && latest_version.IsGreaterThan(current_version)) { log.Debug("Found higher ckan version"); var release_notes = AutoUpdate.Instance.latestUpdate.ReleaseNotes; var dialog = new NewUpdateDialog(latest_version.ToString(), release_notes); if (dialog.ShowDialog() == DialogResult.OK) { UpdateCKAN(); autoUpdating = true; } } } catch (Exception exception) { currentUser.RaiseError($"Error in auto-update:\n\t{exception.Message}"); log.Error("Error in auto-update", exception); } } CheckTrayState(); InitRefreshTimer(); m_UpdateRepoWorker = new BackgroundWorker { WorkerReportsProgress = false, WorkerSupportsCancellation = true }; m_UpdateRepoWorker.RunWorkerCompleted += PostUpdateRepo; m_UpdateRepoWorker.DoWork += UpdateRepo; installWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; installWorker.RunWorkerCompleted += PostInstallMods; installWorker.DoWork += InstallMods; var old_YesNoDialog = currentUser.displayYesNo; currentUser.displayYesNo = YesNoDialog; URLHandlers.RegisterURLHandler(configuration, currentUser); currentUser.displayYesNo = old_YesNoDialog; ApplyToolButton.Enabled = false; CurrentInstanceUpdated(); // We would like to refresh if we're configured to refresh on startup, // or if we have no currently available modules. bool repoUpdateNeeded = configuration.RefreshOnStartup || !RegistryManager.Instance(CurrentInstance).registry.HasAnyAvailable(); // If we're auto-updating the client then we shouldn't interfere with the progress tab if (!autoUpdating && repoUpdateNeeded) { UpdateRepo(); } Text = $"CKAN {Meta.GetVersion()} - KSP {CurrentInstance.Version()} -- {CurrentInstance.GameDir()}"; if (commandLineArgs.Length >= 2) { var identifier = commandLineArgs[1]; if (identifier.StartsWith("//")) { identifier = identifier.Substring(2); } else if (identifier.StartsWith("ckan://")) { identifier = identifier.Substring(7); } if (identifier.EndsWith("/")) { identifier = identifier.Substring(0, identifier.Length - 1); } log.Debug("Attempting to select mod from startup parameters"); FocusMod(identifier, true, true); ModList.Refresh(); log.Debug("Failed to select mod from startup parameters"); } var pluginsPath = Path.Combine(CurrentInstance.CkanDir(), "Plugins"); if (!Directory.Exists(pluginsPath)) { Directory.CreateDirectory(pluginsPath); } pluginController = new PluginController(pluginsPath); CurrentInstance.RebuildKSPSubDir(); // Initialize navigation. This should be called as late as // possible, once the UI is "settled" from its initial load. NavInit(); log.Info("GUI started"); base.OnLoad(e); }
protected override void OnLoad(EventArgs e) { Location = m_Configuration.WindowLoc; Size = m_Configuration.WindowSize; if (!m_Configuration.CheckForUpdatesOnLaunchNoNag) { log.Debug("Asking user if they wish for autoupdates"); if (new AskUserForAutoUpdatesDialog().ShowDialog() == DialogResult.OK) { m_Configuration.CheckForUpdatesOnLaunch = true; } m_Configuration.CheckForUpdatesOnLaunchNoNag = true; m_Configuration.Save(); } if (m_Configuration.CheckForUpdatesOnLaunch) { try { log.Info("Making autoupdate call"); var latest_version = AutoUpdate.FetchLatestCkanVersion(); var current_version = new Version(Meta.Version()); if (latest_version.IsGreaterThan(current_version)) { log.Debug("Found higher ckan version"); var release_notes = AutoUpdate.FetchLatestCkanVersionReleaseNotes(); var dialog = new NewUpdateDialog(latest_version.ToString(), release_notes); if (dialog.ShowDialog() == DialogResult.OK) { log.Info("Start ckan update"); AutoUpdate.StartUpdateProcess(true); } } } catch (Exception exception) { m_User.RaiseError("Error in autoupdate: \n\t" + exception.Message + ""); log.Error("Error in autoupdate", exception); } } m_UpdateRepoWorker = new BackgroundWorker { WorkerReportsProgress = false, WorkerSupportsCancellation = true }; m_UpdateRepoWorker.RunWorkerCompleted += PostUpdateRepo; m_UpdateRepoWorker.DoWork += UpdateRepo; m_InstallWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; m_InstallWorker.RunWorkerCompleted += PostInstallMods; m_InstallWorker.DoWork += InstallMods; UpdateModsList(); m_User.displayYesNo = YesNoDialog; URLHandlers.RegisterURLHandler(m_Configuration, m_User); m_User.displayYesNo = null; ApplyToolButton.Enabled = false; CurrentInstanceUpdated(); ModList.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); if (m_CommandLineArgs.Length >= 2) { var identifier = m_CommandLineArgs[1]; if (identifier.StartsWith("//")) { identifier = identifier.Substring(2); } else if (identifier.StartsWith("ckan://")) { identifier = identifier.Substring(7); } if (identifier.EndsWith("/")) { identifier = identifier.Substring(0, identifier.Length - 1); } int i = 0; log.Debug("Attempting to select mod from startup parameters"); foreach (DataGridViewRow row in ModList.Rows) { var module = ((GUIMod)row.Tag).ToCkanModule(); if (identifier == module.identifier) { ModList.FirstDisplayedScrollingRowIndex = i; row.Selected = true; break; } i++; } log.Debug("Failed to select mod from startup parameters"); } var pluginsPath = Path.Combine(CurrentInstance.CkanDir(), "Plugins"); if (!Directory.Exists(pluginsPath)) { Directory.CreateDirectory(pluginsPath); } m_PluginController = new PluginController(pluginsPath, true); log.Info("GUI started"); base.OnLoad(e); }
private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry) { IEnumerable <ModChange> full_change_set = null; Dictionary <GUIMod, string> new_conflicts = null; bool too_many_provides_thrown = false; var user_change_set = mainModList.ComputeUserChangeSet(); try { var module_installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user); full_change_set = await mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.VersionCriteria()); } catch (InconsistentKraken k) { // Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling. AddStatusMessage(k.ShortDescription); user_change_set = mainModList.ComputeUserChangeSet(); new_conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria()); full_change_set = null; } catch (TooManyModsProvideKraken) { // Can be thrown by ComputeChangeSetFromModList if the user cancels out of it. // We can just rerun it as the ModInfoTabControl has been removed. too_many_provides_thrown = true; } catch (DependencyNotSatisfiedKraken k) { GUI.user.RaiseError( "{0} depends on {1}, which is not compatible with the currently installed version of KSP", k.parent, k.module ); // Uncheck the box MarkModForInstall(k.parent.identifier, true); } if (too_many_provides_thrown) { await UpdateChangeSetAndConflicts(registry); new_conflicts = Conflicts; full_change_set = ChangeSet; } last_mod_to_have_install_toggled.Clear(); Conflicts = new_conflicts; ChangeSet = full_change_set; }
private void _UpdateModsList(IEnumerable <ModChange> mc, Dictionary <string, bool> old_modules = null) { log.Info("Updating the mod list"); ResetProgress(); tabController.RenameTab("WaitTabPage", Properties.Resources.MainModListWaitTitle); ShowWaitDialog(false); tabController.SetTabLock(true); Util.Invoke(this, SwitchEnabledState); ClearLog(); AddLogMessage(Properties.Resources.MainModListLoadingRegistry); KspVersionCriteria versionCriteria = CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; AddLogMessage(Properties.Resources.MainModListLoadingInstalled); var gui_mods = new HashSet <GUIMod>(); gui_mods.UnionWith( registry.InstalledModules .Select(instMod => new GUIMod(instMod, registry, versionCriteria)) ); AddLogMessage(Properties.Resources.MainModListLoadingAvailable); gui_mods.UnionWith( registry.Available(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria, false)) ); AddLogMessage(Properties.Resources.MainModListLoadingIncompatible); gui_mods.UnionWith( registry.Incompatible(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria, true)) ); AddLogMessage(Properties.Resources.MainModListPreservingNew); if (old_modules != null) { foreach (GUIMod gm in gui_mods) { if (old_modules.TryGetValue(gm.Identifier, out bool oldIncompat)) { // Found it; check if newly compatible if (!gm.IsIncompatible && oldIncompat) { gm.IsNew = true; } } else { // Newly indexed, show regardless of compatibility gm.IsNew = true; } } } else { // Copy the new mod flag from the old list. var old_new_mods = new HashSet <GUIMod>( mainModList.Modules.Where(m => m.IsNew)); foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m))) { gui_mod.IsNew = true; } } AddLogMessage(Properties.Resources.MainModListPopulatingList); // Update our mod listing mainModList.ConstructModList(gui_mods.ToList(), mc, configuration.HideEpochs, configuration.HideV); mainModList.Modules = new ReadOnlyCollection <GUIMod>( mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList()); UpdateChangeSetAndConflicts(registry); AddLogMessage(Properties.Resources.MainModListUpdatingFilters); var has_any_updates = gui_mods.Any(mod => mod.HasUpdate); var has_any_installed = gui_mods.Any(mod => mod.IsInstalled); var has_any_replacements = gui_mods.Any(mod => mod.IsInstalled && mod.HasReplacement); Util.Invoke(menuStrip2, () => { FilterCompatibleButton.Text = String.Format(Properties.Resources.MainModListCompatible, mainModList.CountModsByFilter(GUIModFilter.Compatible)); FilterInstalledButton.Text = String.Format(Properties.Resources.MainModListInstalled, mainModList.CountModsByFilter(GUIModFilter.Installed)); FilterInstalledUpdateButton.Text = String.Format(Properties.Resources.MainModListUpgradeable, mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable)); FilterReplaceableButton.Text = String.Format(Properties.Resources.MainModListReplaceable, mainModList.CountModsByFilter(GUIModFilter.Replaceable)); FilterCachedButton.Text = String.Format(Properties.Resources.MainModListCached, mainModList.CountModsByFilter(GUIModFilter.Cached)); FilterUncachedButton.Text = String.Format(Properties.Resources.MainModListUncached, mainModList.CountModsByFilter(GUIModFilter.Uncached)); FilterNewButton.Text = String.Format(Properties.Resources.MainModListNewlyCompatible, mainModList.CountModsByFilter(GUIModFilter.NewInRepository)); FilterNotInstalledButton.Text = String.Format(Properties.Resources.MainModListNotInstalled, mainModList.CountModsByFilter(GUIModFilter.NotInstalled)); FilterIncompatibleButton.Text = String.Format(Properties.Resources.MainModListIncompatible, mainModList.CountModsByFilter(GUIModFilter.Incompatible)); FilterAllButton.Text = String.Format(Properties.Resources.MainModListAll, mainModList.CountModsByFilter(GUIModFilter.All)); UpdateAllToolButton.Enabled = has_any_updates; }); UpdateFilters(this); // Hide update and replacement columns if not needed. // Write it to the configuration, else they are hidden agian after a filter change. // After the update / replacement, they are hidden again. Util.Invoke(ModList, () => { ModList.Columns["UpdateCol"].Visible = has_any_updates; ModList.Columns["AutoInstalled"].Visible = has_any_installed && !configuration.HiddenColumnNames.Contains("AutoInstalled"); ModList.Columns["ReplaceCol"].Visible = has_any_replacements; }); AddLogMessage(Properties.Resources.MainModListUpdatingTray); UpdateTrayInfo(); HideWaitDialog(true); tabController.HideTab("WaitTabPage"); tabController.SetTabLock(false); Util.Invoke(this, SwitchEnabledState); Util.Invoke(this, () => Main.Instance.ModList.Focus()); }