diff --git a/ConsoleUI/GameInstanceListScreen.cs b/ConsoleUI/GameInstanceListScreen.cs index ceca90932a..9baa672dba 100644 --- a/ConsoleUI/GameInstanceListScreen.cs +++ b/ConsoleUI/GameInstanceListScreen.cs @@ -185,7 +185,7 @@ public static bool TryGetInstance(ConsoleTheme theme, GameInstance ksp, Action() { Properties.Resources.Cancel, Properties.Resources.Force diff --git a/ConsoleUI/Properties/Resources.Designer.cs b/ConsoleUI/Properties/Resources.Designer.cs index bd5668ad29..b364fb735f 100644 --- a/ConsoleUI/Properties/Resources.Designer.cs +++ b/ConsoleUI/Properties/Resources.Designer.cs @@ -362,9 +362,6 @@ internal static string InstanceListDefaultToggle { internal static string InstanceListLoadingError { get { return (string)(ResourceManager.GetObject("InstanceListLoadingError", resourceCulture)); } } - internal static string InstanceListLocked { - get { return (string)(ResourceManager.GetObject("InstanceListLocked", resourceCulture)); } - } internal static string InstanceListNoVersion { get { return (string)(ResourceManager.GetObject("InstanceListNoVersion", resourceCulture)); } } diff --git a/ConsoleUI/Properties/Resources.fr-FR.resx b/ConsoleUI/Properties/Resources.fr-FR.resx index 0a5ad217a4..dd9810ce8d 100644 --- a/ConsoleUI/Properties/Resources.fr-FR.resx +++ b/ConsoleUI/Properties/Resources.fr-FR.resx @@ -420,13 +420,6 @@ Erreur lors du chargement de {0} : {1} - - - Fichier verrou avec un ID de processus actif à {0} - -Cela veut probablement dire qu'une autre instance de CKAN s'occupe de cette instance. Vous pouvez supprimer ce fichier pour continuer, mais cela risque fortement de corrompre des données. - -Voulez-vous supprimez ce fichier verrou pour forcer l'accès ? <AUCUNE> diff --git a/ConsoleUI/Properties/Resources.it-IT.resx b/ConsoleUI/Properties/Resources.it-IT.resx index d76a56f65c..dc11f476f0 100644 --- a/ConsoleUI/Properties/Resources.it-IT.resx +++ b/ConsoleUI/Properties/Resources.it-IT.resx @@ -420,13 +420,6 @@ Errore nel caricamento di {0}: {1} - - - File di blocco con ID di processo attivo trovato a {0} - -Ciò significa che probabilmente un'altra istanza di CKAN sta accedendo a questa istanza. Puoi eliminare il file per continuare, ma è molto probabile che i dati vengano danneggiati. - -Vuoi eliminare questo file di blocco per forzare l'accesso? <NESSUNA> @@ -907,7 +900,7 @@ Se la disinstalli, CKAN non sarà in grado di reinstallarla. STAI UTILIZZANDO {1}. -Grazie per aver scaricato {0}. Ci auguriamo che tu ti diverta +Grazie per aver scaricato {0}. Ci auguriamo che tu ti diverta a usarlo come ci siamo divertiti noi a crearlo. Se hai pagato per {0}, cerca di ottenere il rimborso, diff --git a/ConsoleUI/Properties/Resources.pl-PL.resx b/ConsoleUI/Properties/Resources.pl-PL.resx index d7d64f77fa..6f37a5fc53 100644 --- a/ConsoleUI/Properties/Resources.pl-PL.resx +++ b/ConsoleUI/Properties/Resources.pl-PL.resx @@ -420,13 +420,6 @@ Błąd ładowania {0}: {1} - - - Plik blokady znaleziony w {0} - -Oznacza to, że inna instancja CKAN prawdopodobnie ma dostęp do tej instalacji gry. Możesz usunąć plik, aby kontynuować, ale uszkodzenie danych jest bardzo prawdopodobne. - -Czy chcesz usunąć ten plik blokady, aby wymusić dostęp? <BRAK> diff --git a/ConsoleUI/Properties/Resources.resx b/ConsoleUI/Properties/Resources.resx index 80c1d6628b..95f2a7a09c 100644 --- a/ConsoleUI/Properties/Resources.resx +++ b/ConsoleUI/Properties/Resources.resx @@ -219,11 +219,6 @@ Default Error loading {0}: {1} - Lock file with live process ID found at {0} - -This means that another instance of CKAN probably is accessing this instance. You can delete the file to continue, but data corruption is very likely. - -Do you want to delete this lock file to force access? <NONE> Installing, Upgrading, and Removing Mods Calculating... diff --git a/ConsoleUI/Properties/Resources.ru-RU.resx b/ConsoleUI/Properties/Resources.ru-RU.resx index 8a8b0185a6..70e614ecb7 100644 --- a/ConsoleUI/Properties/Resources.ru-RU.resx +++ b/ConsoleUI/Properties/Resources.ru-RU.resx @@ -210,12 +210,6 @@ По умолчанию Ошибка загрузки «{0}»: {1} - Блокирующий файл с ID процесса найден в {0} - -Это может означать, что другой процесс CKAN работает с этой сборкой. -Вы можете удалить этот файл, но в таком случае вероятно повреждение данных. - -Хотите ли вы удалить блокирующий файл для получения доступа? <НЕТ> Установка, обновление и удаление модификаций Вычисление... diff --git a/Core/Properties/Resources.fr-FR.resx b/Core/Properties/Resources.fr-FR.resx index cadee7eaed..3717951ce6 100644 --- a/Core/Properties/Resources.fr-FR.resx +++ b/Core/Properties/Resources.fr-FR.resx @@ -552,10 +552,11 @@ Consultez cette page pour obtenir de l'aide : Pensez à ajouter un jeton d'authentification pour augmenter la limite avant bridage. - CKAN est déjà lancé pour cette instance ! + Fichier verrou avec un ID de processus actif à {0} -Si vous êtes certain que ce n'est pas le cas, alors supprimez : -"{0}" +Cela veut probablement dire qu'une autre instance de CKAN s'occupe de cette instance. Vous pouvez supprimer ce fichier pour continuer, mais cela risque fortement de corrompre des données. + +Voulez-vous supprimez ce fichier verrou pour forcer l'accès ? Pas assez d'espace dans le dossier temporaire pour télécharger les modules ! diff --git a/Core/Properties/Resources.it-IT.resx b/Core/Properties/Resources.it-IT.resx index 380e81baa1..2d98b7c075 100644 --- a/Core/Properties/Resources.it-IT.resx +++ b/Core/Properties/Resources.it-IT.resx @@ -552,10 +552,11 @@ Consulta questa pagina per aiuto: Prendi in considerazione l'aggiunta di un token di autenticazione per aumentare il limite prima del throttling. - CKAN è già in esecuzione per questa istanza! + File di blocco con ID di processo attivo trovato a {0} -Se sei sicuro che non sia questo il caso, elimina: -"{0}" +Ciò significa che probabilmente un'altra istanza di CKAN sta accedendo a questa istanza. Puoi eliminare il file per continuare, ma è molto probabile che i dati vengano danneggiati. + +Vuoi eliminare questo file di blocco per forzare l'accesso? Spazio insufficiente nella cartella temporanea per scaricare i moduli! diff --git a/Core/Properties/Resources.pl-PL.resx b/Core/Properties/Resources.pl-PL.resx index 894b4ca80b..8f76375558 100644 --- a/Core/Properties/Resources.pl-PL.resx +++ b/Core/Properties/Resources.pl-PL.resx @@ -552,10 +552,11 @@ Odwiedź tę stronę, aby uzyskać pomoc: Rozważ dodanie tokenu uwierzytelniającego, aby zwiększyć limit ograniczania. - CKAN jest już uruchomiony z tą instalacją gry! + Plik blokady znaleziony w {0} -Jeśli jesteś pewien, że tak nie jest, to usuń: -"{0}" +Oznacza to, że inna instancja CKAN prawdopodobnie ma dostęp do tej instalacji gry. Możesz usunąć plik, aby kontynuować, ale uszkodzenie danych jest bardzo prawdopodobne. + +Czy chcesz usunąć ten plik blokady, aby wymusić dostęp? Za mało miejsca w folderze tymczasowym do pobrania modułów! diff --git a/Core/Properties/Resources.resx b/Core/Properties/Resources.resx index 0bf27a2c1c..8ba7b7e3e4 100644 --- a/Core/Properties/Resources.resx +++ b/Core/Properties/Resources.resx @@ -271,10 +271,12 @@ Consult this page for help: Oh no! Our download failed with a certificate error! Download from {0} was throttled. Consider adding an authentication token to increase the throttling limit. - CKAN is already running for this instance! + Lock file with live process ID found at: +{0} -If you're certain this is not the case, then delete: -"{0}" +Another active CKAN process probably is accessing this game folder. Check your operating system's task manager application. If you are sure the lock file is stale, you may delete it to continue, but if it's not, then it's very likely that the two running CKANs will clash and corrupt your mod registry and game folder. + +Do you want to delete this lock file to force access? Not enough space in temp folder to download modules! Not enough space in cache folder to store modules! Not enough space in game folder to install modules! diff --git a/Core/Properties/Resources.ru-RU.resx b/Core/Properties/Resources.ru-RU.resx index 1ade0bf639..ffee56b450 100644 --- a/Core/Properties/Resources.ru-RU.resx +++ b/Core/Properties/Resources.ru-RU.resx @@ -267,10 +267,12 @@ https://github.com/KSP-CKAN/CKAN/wiki/SSL-certificate-errors О нет! Загрузка не завершена из-за ошибки сертификата! Загрузка из {0} была ограничена. Для увеличения квоты добавьте токен аутентификации. - CKAN уже запущен для этой сборки! + Блокирующий файл с ID процесса найден в {0} -Если вы уверены, что это не так, удалите: -"{0}" +Это может означать, что другой процесс CKAN работает с этой сборкой. +Вы можете удалить этот файл, но в таком случае вероятно повреждение данных. + +Хотите ли вы удалить блокирующий файл для получения доступа? {0} конфликтует с {1} Необходима {0}, но в ресольвере несовместимая версия Необходима {0}, но установлена несовместимая версия diff --git a/Core/Types/Kraken.cs b/Core/Types/Kraken.cs index 41af0fbc95..ea89a193cd 100644 --- a/Core/Types/Kraken.cs +++ b/Core/Types/Kraken.cs @@ -474,9 +474,8 @@ public RegistryInUseKraken(string path, string reason = null, Exception inner_ex } public override string ToString() - { - return String.Format(Properties.Resources.KrakenAlreadyRunning, lockfilePath); - } + => string.Format(Properties.Resources.KrakenAlreadyRunning, + lockfilePath.Replace('/', Path.DirectorySeparatorChar)); } /// diff --git a/GUI/Controls/EditModpack.cs b/GUI/Controls/EditModpack.cs index 5738640eff..e82997bb81 100644 --- a/GUI/Controls/EditModpack.cs +++ b/GUI/Controls/EditModpack.cs @@ -377,7 +377,7 @@ private bool TrySavePrompt(List exportOptions, out ExportOption se Filter = string.Join("|", exportOptions.Select(i => i.ToString()).ToArray()), Title = Properties.Resources.ExportInstalledModsDialogTitle }; - if (dlg.ShowDialog() == DialogResult.OK) + if (dlg.ShowDialog(Main.Instance) == DialogResult.OK) { selectedOption = exportOptions[dlg.FilterIndex - 1]; filename = dlg.FileName; diff --git a/GUI/Controls/ManageMods.cs b/GUI/Controls/ManageMods.cs index e330d9fca7..49e108a06c 100644 --- a/GUI/Controls/ManageMods.cs +++ b/GUI/Controls/ManageMods.cs @@ -1122,7 +1122,9 @@ private void _UpdateModsList(Dictionary old_modules = null) { log.Info("Updating the mod list"); - Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListLoadingRegistry); + Main.Instance.Wait.AddLogMessage(Properties.Resources.MainRepoScanning); + Main.Instance.CurrentInstance.Scan(); + GameVersionCriteria versionCriteria = Main.Instance.CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(Main.Instance.CurrentInstance).registry; diff --git a/GUI/Controls/ModInfo.cs b/GUI/Controls/ModInfo.cs index 325a889ffc..990e50d56f 100644 --- a/GUI/Controls/ModInfo.cs +++ b/GUI/Controls/ModInfo.cs @@ -94,7 +94,7 @@ private void ModInfoTabControl_SelectedIndexChanged(object sender, EventArgs e) LoadTab(ModInfoTabControl.SelectedTab.Name, SelectedModule); } - private GameInstanceManager manager => Main.Instance.manager; + private GameInstanceManager manager => Main.Instance.Manager; private int StringHeight(string text, Font font, int maxWidth) => (int)CreateGraphics().MeasureString(text, font, maxWidth).Height; diff --git a/GUI/Controls/ModInfoTabs/Contents.cs b/GUI/Controls/ModInfoTabs/Contents.cs index 1b3d8857d0..f6d6265654 100644 --- a/GUI/Controls/ModInfoTabs/Contents.cs +++ b/GUI/Controls/ModInfoTabs/Contents.cs @@ -41,7 +41,7 @@ public void Refresh() private GUIMod selectedModule; private CkanModule currentModContentsModule; - private GameInstanceManager manager => Main.Instance.manager; + private GameInstanceManager manager => Main.Instance.Manager; private void ContentsPreviewTree_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { diff --git a/GUI/Controls/ModInfoTabs/Metadata.cs b/GUI/Controls/ModInfoTabs/Metadata.cs index b64aea21fd..e6abe7ed0f 100644 --- a/GUI/Controls/ModInfoTabs/Metadata.cs +++ b/GUI/Controls/ModInfoTabs/Metadata.cs @@ -121,7 +121,7 @@ private void OnAuthorClick(object sender, LinkLabelLinkClickedEventArgs e) merge); } - private GameInstanceManager manager => Main.Instance.manager; + private GameInstanceManager manager => Main.Instance.Manager; private void LinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { diff --git a/GUI/Controls/ModInfoTabs/Relationships.cs b/GUI/Controls/ModInfoTabs/Relationships.cs index e69a5aabb8..5f42d60adb 100644 --- a/GUI/Controls/ModInfoTabs/Relationships.cs +++ b/GUI/Controls/ModInfoTabs/Relationships.cs @@ -73,7 +73,7 @@ private void UpdateModDependencyGraph(CkanModule module) } private GUIMod selectedModule; - private GameInstanceManager manager => Main.Instance.manager; + private GameInstanceManager manager => Main.Instance.Manager; private void DependsGraphTree_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { diff --git a/GUI/Dialogs/CloneFakeGameDialog.cs b/GUI/Dialogs/CloneFakeGameDialog.cs index 3399333d16..c40115183a 100644 --- a/GUI/Dialogs/CloneFakeGameDialog.cs +++ b/GUI/Dialogs/CloneFakeGameDialog.cs @@ -74,7 +74,7 @@ private void buttonInstancePathSelection_Click(object sender, EventArgs e) }; // Show the FileDialog and let the user search for the game directory. - if (instanceDialog.ShowDialog() != DialogResult.OK || !File.Exists(instanceDialog.FileName)) + if (instanceDialog.ShowDialog(this) != DialogResult.OK || !File.Exists(instanceDialog.FileName)) return; // Write the path to the textbox @@ -327,7 +327,7 @@ private void reactivateDialog() private void buttonPathBrowser_Click(object sender, EventArgs e) { - if (folderBrowserDialogNewPath.ShowDialog().Equals(DialogResult.OK)) + if (folderBrowserDialogNewPath.ShowDialog(this).Equals(DialogResult.OK)) { textBoxNewPath.Text = folderBrowserDialogNewPath.SelectedPath; } diff --git a/GUI/Dialogs/ManageGameInstancesDialog.cs b/GUI/Dialogs/ManageGameInstancesDialog.cs index 1671a0d32d..1045106b61 100644 --- a/GUI/Dialogs/ManageGameInstancesDialog.cs +++ b/GUI/Dialogs/ManageGameInstancesDialog.cs @@ -156,7 +156,7 @@ private static string FormatVersion(GameVersion v) private void AddToCKANMenuItem_Click(object sender, EventArgs e) { - if (_instanceDialog.ShowDialog() != DialogResult.OK + if (_instanceDialog.ShowDialog(this) != DialogResult.OK || !File.Exists(_instanceDialog.FileName)) return; @@ -187,7 +187,7 @@ private void CloneFakeInstanceMenuItem_Click(object sender, EventArgs e) { var old_instance = Main.Instance.CurrentInstance; - var result = new CloneFakeGameDialog(_manager, _user).ShowDialog(); + var result = new CloneFakeGameDialog(_manager, _user).ShowDialog(this); if (result == DialogResult.OK && !Equals(old_instance, Main.Instance.CurrentInstance)) { DialogResult = DialogResult.OK; diff --git a/GUI/Dialogs/PluginsDialog.cs b/GUI/Dialogs/PluginsDialog.cs index cf189a4247..27a3b15a56 100644 --- a/GUI/Dialogs/PluginsDialog.cs +++ b/GUI/Dialogs/PluginsDialog.cs @@ -118,7 +118,7 @@ private void UnloadPluginButton_Click(object sender, EventArgs e) private void AddNewPluginButton_Click(object sender, EventArgs e) { - if (m_AddNewPluginDialog.ShowDialog() == DialogResult.OK) + if (m_AddNewPluginDialog.ShowDialog(this) == DialogResult.OK) { var path = m_AddNewPluginDialog.FileName; Main.Instance.pluginController.AddNewAssemblyToPluginsPath(path); diff --git a/GUI/Dialogs/SettingsDialog.cs b/GUI/Dialogs/SettingsDialog.cs index 81fe456683..1cf1fa95b2 100644 --- a/GUI/Dialogs/SettingsDialog.cs +++ b/GUI/Dialogs/SettingsDialog.cs @@ -204,7 +204,7 @@ private void ChangeCacheButton_Click(object sender, EventArgs e) SelectedPath = config.DownloadCacheDir, ShowNewFolderButton = true }; - DialogResult result = cacheChooser.ShowDialog(); + DialogResult result = cacheChooser.ShowDialog(this); if (result == DialogResult.OK) { UpdateCacheInfo(cacheChooser.SelectedPath); @@ -309,7 +309,7 @@ private void DeleteRepoButton_Click(object sender, EventArgs e) private void NewRepoButton_Click(object sender, EventArgs e) { var dialog = new NewRepoDialog(); - if (dialog.ShowDialog() == DialogResult.OK) + if (dialog.ShowDialog(this) == DialogResult.OK) { try { @@ -548,25 +548,21 @@ private void InstallUpdateButton_Click(object sender, EventArgs e) private void CheckUpdateOnLaunchCheckbox_CheckedChanged(object sender, EventArgs e) { Main.Instance.configuration.CheckForUpdatesOnLaunch = CheckUpdateOnLaunchCheckbox.Checked; - Main.Instance.configuration.Save(); } private void RefreshOnStartupCheckbox_CheckedChanged(object sender, EventArgs e) { Main.Instance.configuration.RefreshOnStartup = RefreshOnStartupCheckbox.Checked; - Main.Instance.configuration.Save(); } private void HideEpochsCheckbox_CheckedChanged(object sender, EventArgs e) { Main.Instance.configuration.HideEpochs = HideEpochsCheckbox.Checked; - Main.Instance.configuration.Save(); } private void HideVCheckbox_CheckedChanged(object sender, EventArgs e) { Main.Instance.configuration.HideV = HideVCheckbox.Checked; - Main.Instance.configuration.Save(); } private void LanguageSelectionComboBox_SelectionChanged(object sender, EventArgs e) @@ -577,20 +573,17 @@ private void LanguageSelectionComboBox_SelectionChanged(object sender, EventArgs private void AutoSortUpdateCheckBox_CheckedChanged(object sender, EventArgs e) { Main.Instance.configuration.AutoSortByUpdate = AutoSortUpdateCheckBox.Checked; - Main.Instance.configuration.Save(); } private void EnableTrayIconCheckBox_CheckedChanged(object sender, EventArgs e) { MinimizeToTrayCheckBox.Enabled = Main.Instance.configuration.EnableTrayIcon = EnableTrayIconCheckBox.Checked; - Main.Instance.configuration.Save(); Main.Instance.CheckTrayState(); } private void MinimizeToTrayCheckBox_CheckedChanged(object sender, EventArgs e) { Main.Instance.configuration.MinimizeToTray = MinimizeToTrayCheckBox.Checked; - Main.Instance.configuration.Save(); Main.Instance.CheckTrayState(); } @@ -609,7 +602,6 @@ private void RefreshTextBox_KeyPress(object sender, KeyPressEventArgs e) private void PauseRefreshCheckBox_CheckedChanged(object sender, EventArgs e) { Main.Instance.configuration.RefreshPaused = PauseRefreshCheckBox.Checked; - Main.Instance.configuration.Save(); if (Main.Instance.configuration.RefreshPaused) Main.Instance.refreshTimer.Stop(); diff --git a/GUI/Main/Main.cs b/GUI/Main/Main.cs index 675e32acb3..c97002ea6d 100644 --- a/GUI/Main/Main.cs +++ b/GUI/Main/Main.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; using Timer = System.Windows.Forms.Timer; @@ -16,45 +17,54 @@ using CKAN.Extensions; using CKAN.Versioning; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { public partial class Main : Form, IMessageFilter { private static readonly ILog log = LogManager.GetLogger(typeof(Main)); - public GUIConfiguration configuration; - - public ControlFactory controlFactory; - - public TabController tabController; + // Stuff we set in the constructor and never change + public readonly GUIUser currentUser; + [Obsolete("Main.tabController should be private. Find a better way to access this object.")] + public readonly TabController tabController; + private readonly GameInstanceManager manager; + public GameInstanceManager Manager => manager; + public GameInstance CurrentInstance => Manager.CurrentInstance; + private string focusIdent; + // Stuff we set when the game instance changes + public GUIConfiguration configuration; public PluginController pluginController; - public volatile GameInstanceManager manager; - - public GameInstance CurrentInstance - { - get { return manager.CurrentInstance; } - } - - public GameInstanceManager Manager - { - get { return manager; } - set { manager = value; } - } - private bool needRegistrySave = false; - public string[] commandLineArgs; - - public GUIUser currentUser; - + [Obsolete("Main.Instance is a global singleton. Find a better way to access this object.")] public static Main Instance { get; private set; } - public Main(string[] cmdlineArgs, GameInstanceManager mgr, bool showConsole) + /// + /// Set up the main form's core properties quickly. + /// This should have NO UI interactions! + /// A constructor just initializes the object, it doesn't ask the user questions. + /// That's the job of OnLoad or OnShown. + /// + /// The strings from the command line that launched us + /// Game instance manager created by the cmdline handler + public Main(string[] cmdlineArgs, GameInstanceManager mgr) { log.Info("Starting the GUI"); - commandLineArgs = cmdlineArgs; + if (cmdlineArgs.Length >= 2) + { + focusIdent = cmdlineArgs[1]; + if (focusIdent.StartsWith("//")) + focusIdent = focusIdent.Substring(2); + else if (focusIdent.StartsWith("ckan://")) + focusIdent = focusIdent.Substring(7); + if (focusIdent.EndsWith("/")) + focusIdent = focusIdent.Substring(0, focusIdent.Length - 1); + } Configuration.IConfiguration mainConfig = ServiceLocator.Container.Resolve(); @@ -75,26 +85,11 @@ public Main(string[] cmdlineArgs, GameInstanceManager mgr, bool showConsole) Application.AddMessageFilter(this); 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; + Instance = this; + // Replace mono's broken, ugly toolstrip renderer if (Platform.IsMono) { @@ -108,76 +103,17 @@ public Main(string[] cmdlineArgs, GameInstanceManager mgr, bool showConsole) // 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(); }; + var timer = new Timer + { + Interval = 2 + }; + timer.Tick += (sender, e) => Thread.Yield();; timer.Start(); } @@ -187,44 +123,216 @@ public Main(string[] cmdlineArgs, GameInstanceManager mgr, bool showConsole) HandleCreated += (sender, e) => X11.SetWMClass("CKAN", "CKAN", Handle); } - Application.Run(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); + } + + tabController = new TabController(MainTabControl); + tabController.ShowTab("ManageModsTabPage"); - if (CurrentInstance != null) + // Disable the modinfo controls until a mod has been choosen. This has an effect if the modlist is empty. + ActiveModInfo = null; + } + + protected override void OnLoad(EventArgs e) + { + // Try to get an instance + if (CurrentInstance == null) { - var registry = RegistryManager.Instance(Manager.CurrentInstance); - registry?.Dispose(); + // Maybe we can find an instance automatically (e.g., portable, only, default) + manager.GetPreferredInstance(); } + + // We need a config object to get the window geometry, but we don't need the registry lock yet + configuration = CurrentInstance != null + ? GUIConfiguration.LoadOrCreateConfiguration( + Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml"), + CurrentInstance.game) + // No instance, just get the defaults + : new GUIConfiguration(); + + // This must happen before Shown, and it depends on the configuration + SetStartPosition(); + Size = configuration.WindowSize; + WindowState = configuration.IsWindowMaximised ? FormWindowState.Maximized : FormWindowState.Normal; + + URLHandlers.RegisterURLHandler(configuration, currentUser); + + 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. + } + + log.Info("GUI started"); + base.OnLoad(e); + } + + /// + /// Form.Visible says true even when the form hasn't shown yet. + /// This value will tell the truth. + /// + public bool actuallyVisible { get; private set; } = false; + + protected override void OnShown(EventArgs e) + { + actuallyVisible = true; + + tabController.RenameTab("WaitTabPage", Properties.Resources.MainLoadingGameInstance); + ShowWaitDialog(); + DisableMainWindow(); + Wait.StartWaiting( + (sender, evt) => + { + Wait.AddLogMessage(Properties.Resources.MainModListLoadingRegistry); + // Make sure we have a lockable instance + do + { + if (CurrentInstance == null && !InstancePromptAtStart()) + { + // User cancelled, give up + evt.Result = false; + return; + } + for (RegistryManager regMgr = null; + CurrentInstance != null && regMgr == null;) + { + // We now have a tentative instance. Check if it's locked. + try + { + // This will throw RegistryInUseKraken if locked by another process + 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) + { + if (Main.Instance.YesNoDialog( + kraken.ToString(), + Properties.Resources.MainDeleteLockfileYes, + Properties.Resources.MainDeleteLockfileNo)) + { + // Delete it + File.Delete(kraken.lockfilePath); + // Loop back around to re-acquire the lock + } + else + { + // Couldn't get the lock, there is no current instance + manager.CurrentInstance = null; + if (manager.Instances.Values.All(inst => !inst.Valid || inst.IsMaybeLocked)) + { + // Everything's invalid or locked, give up + evt.Result = false; + return; + } + } + } + } + } while (CurrentInstance == null); + // We can only reach this point if CurrentInstance is not null + // AND we acquired the lock for it successfully + if (!configuration.CheckForUpdatesOnLaunchNoNag && AutoUpdate.CanUpdate) + { + log.Debug("Asking user if they wish for auto-updates"); + if (new AskUserForAutoUpdatesDialog().ShowDialog(this) == DialogResult.OK) + configuration.CheckForUpdatesOnLaunch = true; + configuration.CheckForUpdatesOnLaunchNoNag = true; + } + evt.Result = true; + }, + (sender, evt) => + { + // Application.Exit doesn't work if the window is disabled! + EnableMainWindow(); + if ((bool)evt.Result) + { + HideWaitDialog(); + CheckTrayState(); + bool autoUpdating = CheckForCKANUpdate(); + Console.CancelKeyPress += (sender2, evt2) => + { + // Hide tray icon on Ctrl-C + minimizeNotifyIcon.Visible = false; + }; + InitRefreshTimer(); + CurrentInstanceUpdated(!autoUpdating); + } + else + { + Application.Exit(); + } + }, + false, + null); + + base.OnShown(e); } private bool InstancePromptAtStart() { - Hide(); - var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(); - if (result != DialogResult.OK) + bool gotInstance = false; + Util.Invoke(this, () => { - Application.Exit(); - return false; - } - return true; + var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(this); + gotInstance = result == DialogResult.OK; + }); + return gotInstance; } private void manageGameInstancesMenuItem_Click(object sender, EventArgs e) { var old_instance = CurrentInstance; - var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(); + var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(this); if (result == DialogResult.OK && !Equals(old_instance, CurrentInstance)) { - try - { - ManageMods.ModGrid.ClearSelection(); - CurrentInstanceUpdated(true); - } - catch (RegistryInUseKraken kraken) + for (bool done = false; !done;) { - // Couldn't get the lock, revert to previous instance - errorDialog.ShowErrorDialog(kraken.ToString()); - manager.CurrentInstance = old_instance; - CurrentInstanceUpdated(false); + try + { + ManageMods.ModGrid.ClearSelection(); + CurrentInstanceUpdated(true); + done = true; + } + catch (RegistryInUseKraken kraken) + { + if (Main.Instance.YesNoDialog( + kraken.ToString(), + Properties.Resources.MainDeleteLockfileYes, + Properties.Resources.MainDeleteLockfileNo)) + { + // Delete it + File.Delete(kraken.lockfilePath); + } + else + { + // Couldn't get the lock, revert to previous instance + manager.CurrentInstance = old_instance; + CurrentInstanceUpdated(false); + done = true; + } + } } } } @@ -247,8 +355,10 @@ private void UpdateStatusBar() /// true if a repo update is allowed if needed (e.g. on initial load), false otherwise private void CurrentInstanceUpdated(bool allowRepoUpdate) { + // This will throw RegistryInUseKraken if locked by another process + var regMgr = RegistryManager.Instance(CurrentInstance); 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)}"; @@ -258,14 +368,12 @@ private void CurrentInstanceUpdated(bool allowRepoUpdate) if (CurrentInstance.CompatibleVersionsAreFromDifferentGameVersion) { new CompatibleGameVersionsDialog(CurrentInstance, !actuallyVisible) - .ShowDialog(); + .ShowDialog(this); } - // 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)) + && !string.IsNullOrEmpty(regMgr.previousCorruptedPath)) { errorDialog.ShowErrorDialog(Properties.Resources.MainCorruptedRegistry, regMgr.previousCorruptedPath, regMgr.previousCorruptedMessage, @@ -275,11 +383,19 @@ private void CurrentInstanceUpdated(bool allowRepoUpdate) } registry.BuildTagIndex(ManageMods.mainModList.ModuleTags); + configuration?.Save(); configuration = GUIConfiguration.LoadOrCreateConfiguration( - Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml")); + Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml"), + CurrentInstance.game); - bool repoUpdateNeeded = configuration.RefreshOnStartup - || !RegistryManager.Instance(CurrentInstance).registry.HasAnyAvailable(); + var pluginsPath = Path.Combine(CurrentInstance.CkanDir(), "Plugins"); + if (!Directory.Exists(pluginsPath)) + Directory.CreateDirectory(pluginsPath); + pluginController = new PluginController(pluginsPath, true); + + CurrentInstance.game.RebuildSubdirectories(CurrentInstance.GameDir()); + + bool repoUpdateNeeded = configuration.RefreshOnStartup || !registry.HasAnyAvailable(); if (allowRepoUpdate) { // If not allowing, don't do anything @@ -297,29 +413,6 @@ private void CurrentInstanceUpdated(bool allowRepoUpdate) ManageMods.InstanceUpdated(CurrentInstance); } - /// - /// Form.Visible says true even when the form hasn't shown yet. - /// This value will tell the truth. - /// - public bool actuallyVisible { get; private set; } = false; - - protected override void OnShown(EventArgs e) - { - actuallyVisible = true; - - 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. - } - - base.OnShown(e); - } - /// /// Open the user guide when the user presses F1 /// @@ -330,6 +423,12 @@ protected override void OnHelpRequested(HelpEventArgs evt) protected override void OnFormClosed(FormClosedEventArgs e) { + if (CurrentInstance != null) + { + var registry = RegistryManager.Instance(Manager.CurrentInstance); + registry?.Dispose(); + } + // Stop all running play time timers foreach (var inst in manager.Instances.Values) { @@ -373,70 +472,6 @@ private void SetStartPosition() } } - 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(); - Console.CancelKeyPress += (sender, evt) => - { - // Hide tray icon on Ctrl-C - minimizeNotifyIcon.Visible = false; - }; - InitRefreshTimer(); - - 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.GameDir()); - } - - log.Info("GUI started"); - base.OnLoad(e); - } - protected override void OnFormClosing(FormClosingEventArgs e) { // Only close the window, when the user has access to the "Exit" of the menu. @@ -515,7 +550,7 @@ private void ExitToolButton_Click(object sender, EventArgs e) private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { - new AboutDialog().ShowDialog(); + new AboutDialog().ShowDialog(this); } private void GameCommandlineToolStripMenuItem_Click(object sender, EventArgs e) @@ -524,7 +559,6 @@ private void GameCommandlineToolStripMenuItem_Click(object sender, EventArgs e) if (dialog.ShowGameCommandLineOptionsDialog(configuration.CommandLineArguments) == DialogResult.OK) { configuration.CommandLineArguments = dialog.GetResult(); - configuration.Save(); } } @@ -539,7 +573,7 @@ private void CKANSettingsToolStripMenuItem_Click(object sender, EventArgs e) private void pluginsToolStripMenuItem_Click(object sender, EventArgs e) { Enabled = false; - pluginsDialog.ShowDialog(); + pluginsDialog.ShowDialog(this); Enabled = true; } @@ -559,7 +593,7 @@ private void installFromckanToolStripMenuItem_Click(object sender, EventArgs e) Multiselect = true, }; - if (open_file_dialog.ShowDialog() == DialogResult.OK) + if (open_file_dialog.ShowDialog(this) == DialogResult.OK) { // We'll need to make some registry changes to do this. RegistryManager registry_manager = RegistryManager.Instance(CurrentInstance); @@ -636,7 +670,7 @@ private void CompatibleGameVersionsToolStripMenuItem_Click(object sender, EventA Instance.manager.CurrentInstance, !actuallyVisible ); - if (dialog.ShowDialog() != DialogResult.Cancel) + if (dialog.ShowDialog(this) != DialogResult.Cancel) { // This takes a while, so don't do it if they cancel out RefreshModList(); @@ -777,7 +811,7 @@ private void Main_Resize(object sender, EventArgs e) private void openGameDirectoryToolStripMenuItem_Click(object sender, EventArgs e) { - Utilities.ProcessStartURL(Instance.manager.CurrentInstance.GameDir()); + Utilities.ProcessStartURL(manager.CurrentInstance.GameDir()); } private void openGameToolStripMenuItem_Click(object sender, EventArgs e) @@ -875,11 +909,19 @@ private void RefreshModList(Dictionary oldModules = null) DisableMainWindow(); Wait.StartWaiting( ManageMods.Update, - (sender, e) => { + (sender, e) => + { UpdateTrayInfo(); HideWaitDialog(); EnableMainWindow(); SetupDefaultSearch(); + if (!string.IsNullOrEmpty(focusIdent)) + { + log.Debug("Attempting to select mod from startup parameters"); + ManageMods.FocusMod(focusIdent, true, true); + // Only do it the first time + focusIdent = null; + } }, false, oldModules); diff --git a/GUI/Main/MainAutoUpdate.cs b/GUI/Main/MainAutoUpdate.cs index 5e8e4f2948..26405234b5 100644 --- a/GUI/Main/MainAutoUpdate.cs +++ b/GUI/Main/MainAutoUpdate.cs @@ -1,8 +1,12 @@ using System; using System.ComponentModel; using System.Windows.Forms; + using CKAN.Versioning; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { public partial class Main @@ -30,7 +34,7 @@ private bool CheckForCKANUpdate() 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) + if (dialog.ShowDialog(this) == DialogResult.OK) { UpdateCKAN(); return true; diff --git a/GUI/Main/MainChangeset.cs b/GUI/Main/MainChangeset.cs index c66006a1e9..35a84852bd 100644 --- a/GUI/Main/MainChangeset.cs +++ b/GUI/Main/MainChangeset.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.Windows.Forms; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { public partial class Main diff --git a/GUI/Main/MainDialogs.cs b/GUI/Main/MainDialogs.cs index 294e207e7a..60eff2cd16 100644 --- a/GUI/Main/MainDialogs.cs +++ b/GUI/Main/MainDialogs.cs @@ -9,9 +9,14 @@ public partial class Main private PluginsDialog pluginsDialog; private YesNoDialog yesNoDialog; private SelectionDialog selectionDialog; + public ControlFactory controlFactory; public void RecreateDialogs() { + if (controlFactory == null) + { + controlFactory = new ControlFactory(); + } errorDialog = controlFactory.CreateControl(); pluginsDialog = controlFactory.CreateControl(); yesNoDialog = controlFactory.CreateControl(); diff --git a/GUI/Main/MainExport.cs b/GUI/Main/MainExport.cs index b4f7954bcc..c3f29c4515 100644 --- a/GUI/Main/MainExport.cs +++ b/GUI/Main/MainExport.cs @@ -4,9 +4,13 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; + using CKAN.Exporters; using CKAN.Types; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { public partial class Main @@ -65,7 +69,7 @@ private void exportModListToolStripMenuItem_Click(object sender, EventArgs e) Filter = string.Join("|", specialExportOptions.Select(i => i.ToString()).ToArray()), Title = Properties.Resources.ExportInstalledModsDialogTitle }; - if (dlg.ShowDialog() == DialogResult.OK) + if (dlg.ShowDialog(this) == DialogResult.OK) { var fileMode = File.Exists(dlg.FileName) ? FileMode.Truncate : FileMode.CreateNew; using (var stream = new FileStream(dlg.FileName, fileMode)) diff --git a/GUI/Main/MainImport.cs b/GUI/Main/MainImport.cs index 4845c72b48..fa37b6416b 100644 --- a/GUI/Main/MainImport.cs +++ b/GUI/Main/MainImport.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.Windows.Forms; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { public partial class Main @@ -26,7 +29,7 @@ private void ImportModules() Filter = Properties.Resources.MainImportFilter, Multiselect = true }; - if (dlg.ShowDialog() == DialogResult.OK + if (dlg.ShowDialog(this) == DialogResult.OK && dlg.FileNames.Length > 0) { // Show WaitTabPage (status page) and lock it. diff --git a/GUI/Main/MainInstall.cs b/GUI/Main/MainInstall.cs index 6e3566aab4..6eb7981593 100644 --- a/GUI/Main/MainInstall.cs +++ b/GUI/Main/MainInstall.cs @@ -7,6 +7,9 @@ using CKAN.Extensions; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { using ModChanges = List; diff --git a/GUI/Main/MainRecommendations.cs b/GUI/Main/MainRecommendations.cs index 2393dba06a..8ba916fb2a 100644 --- a/GUI/Main/MainRecommendations.cs +++ b/GUI/Main/MainRecommendations.cs @@ -3,9 +3,13 @@ using System.Windows.Forms; using System.Threading.Tasks; using System.Linq; + using CKAN.Extensions; using CKAN.Versioning; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { using ModChanges = List; diff --git a/GUI/Main/MainRepo.cs b/GUI/Main/MainRepo.cs index e7afeee212..f09906028b 100644 --- a/GUI/Main/MainRepo.cs +++ b/GUI/Main/MainRepo.cs @@ -12,6 +12,9 @@ using CKAN.Versioning; using CKAN.Configuration; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { public partial class Main @@ -208,7 +211,6 @@ private void ShowRefreshQuestion() { configuration.RefreshOnStartup = false; } - configuration.Save(); } } diff --git a/GUI/Main/MainTime.cs b/GUI/Main/MainTime.cs index 522e3e4d25..59539da69c 100644 --- a/GUI/Main/MainTime.cs +++ b/GUI/Main/MainTime.cs @@ -2,6 +2,9 @@ using System.Diagnostics; using System.Windows.Forms; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { public partial class Main diff --git a/GUI/Main/MainTrayIcon.cs b/GUI/Main/MainTrayIcon.cs index aaae5876a2..d1129d4402 100644 --- a/GUI/Main/MainTrayIcon.cs +++ b/GUI/Main/MainTrayIcon.cs @@ -46,7 +46,6 @@ private void UpdateTrayState() { // Save the window state configuration.IsWindowMaximised = WindowState == FormWindowState.Maximized; - configuration.Save(); } } else diff --git a/GUI/Main/MainWait.cs b/GUI/Main/MainWait.cs index 70d3331a68..7e75504169 100644 --- a/GUI/Main/MainWait.cs +++ b/GUI/Main/MainWait.cs @@ -1,6 +1,9 @@ using System; using System.Windows.Forms; +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + namespace CKAN.GUI { public partial class Main diff --git a/GUI/Model/GUIConfiguration.cs b/GUI/Model/GUIConfiguration.cs index ebf15cf29a..520378efcb 100644 --- a/GUI/Model/GUIConfiguration.cs +++ b/GUI/Model/GUIConfiguration.cs @@ -5,6 +5,8 @@ using System.IO; using System.Xml.Serialization; +using CKAN.Games; + namespace CKAN.GUI { [XmlRootAttribute("Configuration")] @@ -100,14 +102,14 @@ public void Save() SaveConfiguration(this); } - public static GUIConfiguration LoadOrCreateConfiguration(string path) + public static GUIConfiguration LoadOrCreateConfiguration(string path, IGame game) { if (!File.Exists(path) || new FileInfo(path).Length == 0) { var configuration = new GUIConfiguration { path = path, - CommandLineArguments = Main.Instance.CurrentInstance.game.DefaultCommandLine + CommandLineArguments = game.DefaultCommandLine }; SaveConfiguration(configuration); diff --git a/GUI/Program.cs b/GUI/Program.cs index 5ce4eae41c..ae8fbe285a 100644 --- a/GUI/Program.cs +++ b/GUI/Program.cs @@ -32,7 +32,12 @@ public static void Main_(string[] args, GameInstanceManager manager = null, bool } else { - new Main(args, manager, showConsole); + var main = new Main(args, manager); + if (!showConsole) + { + Util.HideConsoleWindow(); + } + Application.Run(main); } } diff --git a/GUI/Properties/Resources.Designer.cs b/GUI/Properties/Resources.Designer.cs index 9a2781f298..0c02c1f262 100644 --- a/GUI/Properties/Resources.Designer.cs +++ b/GUI/Properties/Resources.Designer.cs @@ -494,9 +494,18 @@ internal static string MainReinstallConfirm { internal static string MainCantInstallDLC { get { return (string)(ResourceManager.GetObject("MainCantInstallDLC", resourceCulture)); } } + internal static string MainLoadingGameInstance { + get { return (string)(ResourceManager.GetObject("MainLoadingGameInstance", resourceCulture)); } + } internal static string MainCorruptedRegistry { get { return (string)(ResourceManager.GetObject("MainCorruptedRegistry", resourceCulture)); } } + internal static string MainDeleteLockfileYes { + get { return (string)(ResourceManager.GetObject("MainDeleteLockfileYes", resourceCulture)); } + } + internal static string MainDeleteLockfileNo { + get { return (string)(ResourceManager.GetObject("MainDeleteLockfileNo", resourceCulture)); } + } internal static string AllModVersionsInstallPrompt { get { return (string)(ResourceManager.GetObject("AllModVersionsInstallPrompt", resourceCulture)); } diff --git a/GUI/Properties/Resources.fr-FR.resx b/GUI/Properties/Resources.fr-FR.resx index a2b731dc71..46b649b2a5 100644 --- a/GUI/Properties/Resources.fr-FR.resx +++ b/GUI/Properties/Resources.fr-FR.resx @@ -386,6 +386,8 @@ Essayez de déplacer {2} en dehors de {3} et redémarrez CKAN. Cela veut dire que CKAN a oublié tous les mods que vous avez installé, mais ceux-ci sont toujours présents dans le dossier GameData. Vous pouvez les réinstaller en important le fichier {2} + Forcer + Annuler {0} n'est pas supporté par vos versions de jeu compatibles ({1}) et pourrait ne pas marcher du tout. Si vous avez des problèmes avec, vous NE devez PAS demander de l'aide à ses développeurs. diff --git a/GUI/Properties/Resources.it-IT.resx b/GUI/Properties/Resources.it-IT.resx index 1eec2883dd..caa94b40e6 100644 --- a/GUI/Properties/Resources.it-IT.resx +++ b/GUI/Properties/Resources.it-IT.resx @@ -386,6 +386,8 @@ Prova a spostare {2} da {3} e a riavviare CKAN. Questo significa che CKAN si è dimenticato di tutte le tue mod installate, ma sono ancora presenti in GameData. Puoi reinstallarle importando il file {2}. + Forza + Annulla {0} non è supportato dalle versioni del gioco attualmente compatibili ({1}) e potrebbe non funzionare affatto. Se hai qualche problema, NON devi chiedere aiuto ai suoi manutentori. diff --git a/GUI/Properties/Resources.pl-PL.resx b/GUI/Properties/Resources.pl-PL.resx index eacd149c7c..3cdfb64bae 100644 --- a/GUI/Properties/Resources.pl-PL.resx +++ b/GUI/Properties/Resources.pl-PL.resx @@ -386,6 +386,8 @@ Spróbuj przenieść {2} z {3} i uruchomić ponownie CKAN. Oznacza to, że CKAN zapomniał o wszystkich zainstalowanych modyfikacjach, ale wciąż znajdują się w GameData. Możesz je ponownie zainstalować importując plik {2}. + Wymuś + Anuluj {0} nie jest obsługiwany w bieżącej wersji gry i może w ogóle nie działać. Jeśli masz jakieś problemy z nim, NIE powinieneś poprosić twórców o pomoc. diff --git a/GUI/Properties/Resources.resx b/GUI/Properties/Resources.resx index 64e79e4fe9..313e758510 100644 --- a/GUI/Properties/Resources.resx +++ b/GUI/Properties/Resources.resx @@ -211,9 +211,12 @@ Try to move {2} out of {3} and restart CKAN. Not found. Do you want to reinstall {0}? CKAN can't install expansion {0}! + Loading game instance Corrupted registry archived to {0}: {1} This means that CKAN forgot about all your installed mods, but they are still in GameData. You can reinstall them by importing the {2} file. + Force + Cancel {0} is not supported on your current compatible game versions ({1}) and may not work at all. If you have any problems with it, you should NOT ask its maintainers for help. Do you really want to install it? diff --git a/GUI/Properties/Resources.ru-RU.resx b/GUI/Properties/Resources.ru-RU.resx index d21dfbf131..115cf1646b 100644 --- a/GUI/Properties/Resources.ru-RU.resx +++ b/GUI/Properties/Resources.ru-RU.resx @@ -185,6 +185,8 @@ Повреждение реестра, архивированного в {0}: {1} Это означает, что CKAN «забыл» о всех установленных модификациях, но сами они продолжают находиться в GameData. Вы можете переустановить их, импортировав файлы {2}. + Принуд. + Отмена {0} не поддерживается установленной версией игры и может не заработать. Вы действительно хотите установить его? diff --git a/Tests/GUI/GUIConfiguration.cs b/Tests/GUI/GUIConfiguration.cs index a1623688cc..3d87d94db6 100644 --- a/Tests/GUI/GUIConfiguration.cs +++ b/Tests/GUI/GUIConfiguration.cs @@ -1,9 +1,12 @@ using System.IO; -using CKAN; -using CKAN.GUI; + using NUnit.Framework; using Tests.Data; +using CKAN; +using CKAN.GUI; +using CKAN.Games; + namespace Tests.GUI { [TestFixture] @@ -33,7 +36,7 @@ public void LoadOrCreateConfiguration_MalformedXMLFile_ThrowsKraken() stream.Write("This is not a valid XML file."); } - Assert.Throws(() => GUIConfiguration.LoadOrCreateConfiguration(tempFile)); + Assert.Throws(() => GUIConfiguration.LoadOrCreateConfiguration(tempFile, new KerbalSpaceProgram())); } [Test] @@ -46,7 +49,7 @@ public void LoadOrCreateConfiguration_CorrectConfigurationFile_Loaded() stream.Write(TestData.ConfigurationFile()); } - var result = GUIConfiguration.LoadOrCreateConfiguration(tempFile); + var result = GUIConfiguration.LoadOrCreateConfiguration(tempFile, new KerbalSpaceProgram()); Assert.IsNotNull(result); }