private static void SaveConfiguration(GUIConfiguration configuration) { var serializer = new XmlSerializer(typeof(GUIConfiguration)); using (var writer = new StreamWriter(configuration.path)) { serializer.Serialize(writer, configuration); writer.Close(); } }
public static void RegisterURLHandler(GUIConfiguration config, IUser user) { try { if (Platform.IsUnix) { RegisterURLHandler_Linux(); } else if (Platform.IsWindows) { try { RegisterURLHandler_Win32(); } catch (UnauthorizedAccessException) { if (config.URLHandlerNoNag) { return; } if (user.RaiseYesNoDialog(Properties.Resources.URLHandlersPrompt)) { // we need elevation to write to the registry ProcessStartInfo startInfo = new ProcessStartInfo( Assembly.GetEntryAssembly().Location) { // trigger a UAC prompt (if UAC is enabled) Verb = "runas", Arguments = $"gui {UrlRegistrationArgument}" }; Process.Start(startInfo); } else { config.URLHandlerNoNag = true; config.Save(); } // Don't re-throw the exception because we just dealt with it } } else if (Platform.IsMac) { //TODO } } catch (Exception ex) { log.ErrorFormat( "There was an error while registering the URL handler for ckan:// - {0}", ex.Message ); log.ErrorFormat("{0}", ex.StackTrace); } }
public static GUIConfiguration LoadOrCreateConfiguration(string path) { if (!File.Exists(path) || new FileInfo(path).Length == 0) { var configuration = new GUIConfiguration { path = path, CommandLineArguments = Main.Instance.CurrentInstance.game.DefaultCommandLine }; SaveConfiguration(configuration); } return(LoadConfiguration(path)); }
public static GUIConfiguration LoadOrCreateConfiguration(string path) { if (!File.Exists(path) || new FileInfo(path).Length == 0) { var configuration = new GUIConfiguration { path = path, CommandLineArguments = Platform.IsUnix ? "./KSP.x86_64 -single-instance" : Platform.IsMac ? "./KSP.app/Contents/MacOS/KSP" : "KSP_x64.exe -single-instance" }; SaveConfiguration(configuration); } return(LoadConfiguration(path)); }
/// <summary> /// Apply fixes and migrations after deserialization. /// </summary> /// <param name="configuration">The current configuration to apply the fixes on</param> /// <returns>A bool indicating whether something changed and the configuration should be saved to disk</returns> private static bool DeserializationFixes(GUIConfiguration configuration) { bool needsSave = false; // KSPCompatibility column got renamed to GameCompatibility int kspCompatibilitySortIndex = configuration.SortColumns.IndexOf("KSPCompatibility"); if (kspCompatibilitySortIndex > -1) { configuration.SortColumns[kspCompatibilitySortIndex] = "GameCompatibility"; needsSave = true; } int kspCompatibilityHiddenIndex = configuration.HiddenColumnNames.IndexOf("KSPCompatibility"); if (kspCompatibilityHiddenIndex > -1) { configuration.HiddenColumnNames[kspCompatibilityHiddenIndex] = "GameCompatibility"; needsSave = true; } return(needsSave); }
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(); }
/// <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) { // 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) { 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); }
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(); } }
/// <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)}"; StatusInstanceLabel.Text = string.Format( Properties.Resources.StatusInstanceLabelText, CurrentInstance.Name, CurrentInstance.game.ShortName, CurrentInstance.Version()?.ToString() ); }); 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); }