Пример #1
0
        public void SetUp()
        {
            _testModule = TestData.DogeCoinFlag_101_module();

            _instance        = new DisposableKSP();
            _nullUser        = new NullUser();
            _config          = new FakeConfiguration(_instance.KSP, _instance.KSP.Name);
            _manager         = new GameInstanceManager(_nullUser, _config);
            _registryManager = CKAN.RegistryManager.Instance(_instance.KSP);
            _registry        = _registryManager.registry;
            _installer       = CKAN.ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _nullUser);

            _gameDir     = _instance.KSP.GameDir();
            _gameDataDir = _instance.KSP.game.PrimaryModDirectory(_instance.KSP);
            _registry.AddAvailable(_testModule);
            var testModFile = TestData.DogeCoinFlagZip();

            _manager.Cache.Store(_testModule, testModFile);
            HashSet <string> possibleConfigOnlyDirs = null;

            _installer.InstallList(
                new List <string>()
            {
                _testModule.identifier
            },
                new RelationshipResolverOptions(),
                _registryManager,
                ref possibleConfigOnlyDirs
                );
        }
Пример #2
0
 // Constructor
 private ModuleInstaller(KSP ksp, IUser user)
 {
     User = user;
     this.ksp = ksp;
     registry_manager = RegistryManager.Instance(ksp);
     log.DebugFormat("Creating ModuleInstaller for {0}", ksp.GameDir());
 }
Пример #3
0
        public void SetUp()
        {
            _testModule = TestData.DogeCoinFlag_101_module();

            _nullUser = new NullUser();

            _manager         = new KSPManager(_nullUser);
            _instance        = new DisposableKSP();
            _registryManager = CKAN.RegistryManager.Instance(_instance.KSP);
            _registry        = _registryManager.registry;
            _installer       = CKAN.ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _nullUser);

            _gameDataDir = _instance.KSP.GameData();
            _registry.AddAvailable(_testModule);
            var testModFile = TestData.DogeCoinFlagZip();

            _manager.Cache.Store(_testModule, testModFile);
            _installer.InstallList(
                new List <string>()
            {
                _testModule.identifier
            },
                new RelationshipResolverOptions(),
                _registryManager
                );
        }
Пример #4
0
 public void Setup()
 {
     ksp      = new DisposableKSP();
     manager  = CKAN.RegistryManager.Instance(ksp.KSP);
     registry = manager.registry;
     registry.ClearDlls();
     registry.Installed().Clear();
 }
Пример #5
0
        public static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, string repo = null)
        {
            if (repo == null)
            {
                return Update(registry_manager, ksp, user, clear, (Uri)null);
            }

            return Update(registry_manager, ksp, user, clear, new Uri(repo));
        }
Пример #6
0
        public void Setup()
        {
            ksp = new DisposableKSP();

            manager  = CKAN.RegistryManager.Instance(ksp.KSP);
            registry = manager.registry;
            registry.ClearDlls();
            registry.Installed().Clear();
            CKAN.Repo.Update(manager, ksp.KSP, new NullUser(), TestData.TestKANZip());
        }
Пример #7
0
        /// <summary>
        /// Returns an instance of the registry manager for the KSP install.
        /// The file `registry.json` is assumed.
        /// </summary>
        public static RegistryManager Instance(KSP ksp)
        {
            string directory = ksp.CkanDir();
            if (!singleton.ContainsKey(directory))
            {
                log.DebugFormat("Preparing to load registry at {0}", directory);
                singleton[directory] = new RegistryManager(directory, ksp);
            }

            return singleton[directory];
        }
Пример #8
0
        public static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, Uri repo = null)
        {
            // Use our default repo, unless we've been told otherwise.
            if (repo == null)
            {
                repo = default_ckan_repo;
            }

            UpdateRegistry(repo, registry_manager.registry, ksp, user, clear);

            // Save our changes!
            registry_manager.Save();

            // Return how many we got!
            return registry_manager.registry.Available(ksp.Version()).Count;
        }
Пример #9
0
        /// <summary>
        ///     Download and update the local CKAN meta-info.
        ///     Optionally takes a URL to the zipfile repo to download.
        ///     Returns the number of unique modules updated.
        /// </summary>
        public static int UpdateAllRepositories(RegistryManager registry_manager, KSP ksp, IUser user)
        {
            // If we handle multiple repositories, we will call ClearRegistry() ourselves...
            registry_manager.registry.ClearAvailable();
            // TODO this should already give us a pre-sorted list
            SortedDictionary<string, Repository> sortedRepositories = registry_manager.registry.Repositories;
            foreach (KeyValuePair<string, Repository> repository in sortedRepositories)
            {
                log.InfoFormat("About to update {0}", repository.Value.name);
                UpdateRegistry(repository.Value.uri, registry_manager.registry, ksp, user, false);
            }

            // Save our changes.
            registry_manager.Save();

            // Return how many we got!
            return registry_manager.registry.Available(ksp.Version()).Count;
        }
Пример #10
0
        public void Setup()
        {
            manager = new KSPManager(new NullUser());
            // Give us a registry to play with.
            ksp = new DisposableKSP();
            registry_manager = CKAN.RegistryManager.Instance(ksp.KSP);
            registry         = registry_manager.registry;
            registry.ClearDlls();
            registry.Installed().Clear();
            // Make sure we have a registry we can use.
            CKAN.Repo.Update(registry_manager, ksp.KSP, new NullUser(), TestData.TestKANZip());

            // Ready our downloader.
            async = new CKAN.NetAsyncModulesDownloader(new NullUser(), manager.Cache);

            // General shortcuts
            cache = manager.Cache;
        }
Пример #11
0
        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))
                );
            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);

            //TODO Consider using smart enumeration pattern so stuff like this is easier
            Util.Invoke(menuStrip2, () =>
            {
                FilterToolButton.DropDownItems[0].Text = String.Format(Properties.Resources.MainModListCompatible,
                                                                       mainModList.CountModsByFilter(GUIModFilter.Compatible));
                FilterToolButton.DropDownItems[1].Text = String.Format(Properties.Resources.MainModListInstalled,
                                                                       mainModList.CountModsByFilter(GUIModFilter.Installed));
                FilterToolButton.DropDownItems[2].Text = String.Format(Properties.Resources.MainModListUpgradeable,
                                                                       mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable));
                FilterToolButton.DropDownItems[3].Text = String.Format(Properties.Resources.MainModListReplaceable,
                                                                       mainModList.CountModsByFilter(GUIModFilter.Replaceable));
                FilterToolButton.DropDownItems[4].Text = String.Format(Properties.Resources.MainModListCached,
                                                                       mainModList.CountModsByFilter(GUIModFilter.Cached));
                FilterToolButton.DropDownItems[5].Text = String.Format(Properties.Resources.MainModListNewlyCompatible,
                                                                       mainModList.CountModsByFilter(GUIModFilter.NewInRepository));
                FilterToolButton.DropDownItems[6].Text = String.Format(Properties.Resources.MainModListNotInstalled,
                                                                       mainModList.CountModsByFilter(GUIModFilter.NotInstalled));
                FilterToolButton.DropDownItems[7].Text = String.Format(Properties.Resources.MainModListIncompatible,
                                                                       mainModList.CountModsByFilter(GUIModFilter.Incompatible));
                FilterToolButton.DropDownItems[8].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());
        }
Пример #12
0
        /// <summary>
        /// Download and update the local CKAN meta-info.
        /// Optionally takes a URL to the zipfile repo to download.
        /// </summary>
        public static RepoUpdateResult UpdateAllRepositories(RegistryManager registry_manager, GameInstance ksp, NetModuleCache cache, IUser user)
        {
            SortedDictionary <string, Repository> sortedRepositories = registry_manager.registry.Repositories;

            user.RaiseProgress("Checking for updates", 0);
            if (sortedRepositories.Values.All(repo => !string.IsNullOrEmpty(repo.last_server_etag) && repo.last_server_etag == Net.CurrentETag(repo.uri)))
            {
                user.RaiseProgress("Already up to date", 100);
                user.RaiseMessage("No changes since last update");
                return(RepoUpdateResult.NoChanges);
            }
            List <CkanModule> allAvail = new List <CkanModule>();
            int index = 0;

            foreach (KeyValuePair <string, Repository> repository in sortedRepositories)
            {
                user.RaiseProgress($"Updating {repository.Value.name}",
                                   10 + 80 * index / sortedRepositories.Count);
                SortedDictionary <string, int> downloadCounts;
                string            newETag;
                List <CkanModule> avail = UpdateRegistry(repository.Value.uri, ksp, user, out downloadCounts, out newETag);
                registry_manager.registry.SetDownloadCounts(downloadCounts);
                if (avail == null)
                {
                    // Report failure if any repo fails, rather than losing half the list.
                    // UpdateRegistry will have alerted the user to specific errors already.
                    return(RepoUpdateResult.Failed);
                }
                else
                {
                    // Merge all the lists
                    allAvail.AddRange(avail);
                    repository.Value.last_server_etag = newETag;
                    user.RaiseMessage("Updated {0}", repository.Value.name);
                }
                ++index;
            }
            // Save allAvail to the registry if we found anything
            if (allAvail.Count > 0)
            {
                user.RaiseProgress("Saving modules to registry", 90);
                using (var transaction = CkanTransaction.CreateTransactionScope())
                {
                    // Save our changes.
                    registry_manager.registry.SetAllAvailable(allAvail);
                    registry_manager.Save(enforce_consistency: false);
                    transaction.Complete();
                }

                ShowUserInconsistencies(registry_manager.registry, user);

                List <CkanModule> metadataChanges = GetChangedInstalledModules(registry_manager.registry);
                if (metadataChanges.Count > 0)
                {
                    HandleModuleChanges(metadataChanges, user, ksp, cache, registry_manager);
                }

                // Registry.CompatibleModules is slow, just return success,
                // caller can check it if it's really needed
                user.RaiseProgress("Registry saved", 100);
                user.RaiseMessage("Repositories updated");
                return(RepoUpdateResult.Updated);
            }
            else
            {
                // Return failure
                return(RepoUpdateResult.Failed);
            }
        }
Пример #13
0
        public Main(string[] cmdlineArgs, KSPManager mgr, GUIUser user, bool showConsole)
        {
            log.Info("Starting the GUI");
            commandLineArgs = cmdlineArgs;

            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
            if (Platform.IsMono)
            {
                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();
                minimizedContextMenuStrip.Renderer          = new FlatToolStripRenderer();
                ModListContextMenuStrip.Renderer            = new FlatToolStripRenderer();
                ModListHeaderContextMenuStrip.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 ManageKspInstances(!actuallyVisible).ShowDialog();
                if (result == DialogResult.Cancel || result == DialogResult.Abort)
                {
                    Application.Exit();
                    return;
                }
            }

            configuration = Configuration.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;
            }

            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");

            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();
        }
Пример #14
0
        private TreeNode UpdateModDependencyGraphRecursively(TreeNode parentNode, CkanModule module, RelationshipType relationship, int depth, bool virtualProvides = false)
        {
            if (module == null ||
                (depth > 0 && dependencyGraphRootModule == module) ||
                (alreadyVisited.Contains(module)))
            {
                return(null);
            }

            alreadyVisited.Add(module);

            string nodeText = module.name;

            if (virtualProvides)
            {
                nodeText = String.Format("provided by - {0}", module.name);
            }

            var node = parentNode == null ? new TreeNode(nodeText) : parentNode.Nodes.Add(nodeText);

            IEnumerable <RelationshipDescriptor> relationships = null;

            switch (relationship)
            {
            case RelationshipType.Depends:
                relationships = module.depends;
                break;

            case RelationshipType.Recommends:
                relationships = module.recommends;
                break;

            case RelationshipType.Suggests:
                relationships = module.suggests;
                break;

            case RelationshipType.Supports:
                relationships = module.supports;
                break;
            }

            if (relationships == null)
            {
                return(node);
            }

            foreach (RelationshipDescriptor dependency in relationships)
            {
                Registry registry = RegistryManager.Instance(manager.CurrentInstance).registry;

                try
                {
                    try
                    {
                        var dependencyModule = registry.LatestAvailable
                                                   (dependency.name, manager.CurrentInstance.Version());
                        UpdateModDependencyGraphRecursively(node, dependencyModule, relationship, depth + 1);
                    }
                    catch (ModuleNotFoundKraken)
                    {
                        List <CkanModule> dependencyModules = registry.LatestAvailableWithProvides
                                                                  (dependency.name, manager.CurrentInstance.Version());

                        if (dependencyModules == null)
                        {
                            continue;
                        }

                        var newNode = node.Nodes.Add(dependency.name + " (virtual)");
                        newNode.ForeColor = Color.Gray;

                        foreach (var dep in dependencyModules)
                        {
                            UpdateModDependencyGraphRecursively(newNode, dep, relationship, depth + 1, true);
                        }
                    }
                }
                catch (Exception)
                {
                }
            }

            if (virtualProvides)
            {
                node.Collapse(true);
            }
            else
            {
                node.ExpandAll();
            }

            return(node);
        }
Пример #15
0
        /// <summary>
        /// Resolve differences between installed and available metadata for given ModuleInstaller
        /// </summary>
        /// <param name="metadataChanges">List of modules that changed</param>
        /// <param name="user">Object for user interaction callbacks</param>
        /// <param name="ksp">Game instance</param>
        /// <param name="cache">Cacne object for mod downloads</param>
        /// <param name="registry_manager">Manager that holds our game instances</param>
        private static void HandleModuleChanges(List <CkanModule> metadataChanges, IUser user, GameInstance ksp, NetModuleCache cache, RegistryManager registry_manager)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < metadataChanges.Count; i++)
            {
                CkanModule module = metadataChanges[i];
                sb.AppendLine(string.Format("- {0} {1}", module.identifier, module.version));
            }

            if (user.RaiseYesNoDialog(string.Format(@"The following mods have had their metadata changed since last update:

{0}
You should reinstall them in order to preserve consistency with the repository.

Do you wish to reinstall now?", sb)))
            {
                ModuleInstaller installer = ModuleInstaller.GetInstance(ksp, cache, new NullUser());
                // New upstream metadata may break the consistency of already installed modules
                // e.g. if user installs modules A and B and then later up A is made to conflict with B
                // This is perfectly normal and shouldn't produce an error, therefore we skip enforcing
                // consistency. However, we will show the user any inconsistencies later on.

                // Do each changed module one at a time so a failure of one doesn't cause all the others to fail
                foreach (CkanModule mod in metadataChanges)
                {
                    try
                    {
                        HashSet <string> possibleConfigOnlyDirs = null;
                        installer.Upgrade(
                            new CkanModule[] { mod },
                            new NetAsyncModulesDownloader(new NullUser(), cache),
                            ref possibleConfigOnlyDirs,
                            registry_manager,
                            enforceConsistency: false,
                            resolveRelationships: true
                            );
                    }
                    // Thrown when a dependency couldn't be satisfied
                    catch (ModuleNotFoundKraken)
                    {
                        log.WarnFormat("Skipping installation of {0} due to relationship error.", mod.identifier);
                        user.RaiseMessage("Skipping installation of {0} due to relationship error.", mod.identifier);
                    }
                    // Thrown when a conflicts relationship is violated
                    catch (InconsistentKraken)
                    {
                        log.WarnFormat("Skipping installation of {0} due to relationship error.", mod.identifier);
                        user.RaiseMessage("Skipping installation of {0} due to relationship error.", mod.identifier);
                    }
                }
            }
        }
Пример #16
0
        private void InstallMods(object sender, DoWorkEventArgs e) // this probably needs to be refactored
        {
            installCanceled = false;

            ClearLog();

            var opts =
                (KeyValuePair <List <KeyValuePair <CkanModule, GUIModChangeType> >, RelationshipResolverOptions>)e.Argument;

            var installer = ModuleInstaller.Instance;

            // setup progress callback
            installer.onReportProgress += InstallModsReportProgress;

            // first we uninstall whatever the user wanted to plus the mods we want to update
            foreach (var change in opts.Key)
            {
                if (change.Value == GUIModChangeType.Remove)
                {
                    SetDescription(String.Format("Uninstalling mod \"{0}\"", change.Key.name));
                    installer.UninstallList(change.Key.identifier);
                }
                else if (change.Value == GUIModChangeType.Update)
                {
                    // TODO: Proper upgrades when ckan.dll supports them.
                    installer.UninstallList(change.Key.identifier);
                }
            }

            toInstall = new HashSet <string>();

            foreach (var change in opts.Key)
            {
                if (change.Value == GUIModChangeType.Install)
                {
                    toInstall.Add(change.Key.identifier);
                }
            }

            var recommended = new Dictionary <string, List <string> >();
            var suggested   = new Dictionary <string, List <string> >();

            foreach (var change in opts.Key)
            {
                if (change.Value == GUIModChangeType.Install)
                {
                    if (change.Key.recommends != null)
                    {
                        foreach (RelationshipDescriptor mod in change.Key.recommends)
                        {
                            try
                            {
                                // if the mod is available for the current KSP version _and_
                                // the mod is not installed _and_
                                // the mod is not already in the install list
                                if (
                                    RegistryManager.Instance(KSPManager.CurrentInstance)
                                    .registry.LatestAvailable(mod.name.ToString(), KSPManager.CurrentInstance.Version()) != null &&
                                    !RegistryManager.Instance(KSPManager.CurrentInstance).registry.IsInstalled(mod.name.ToString()) &&
                                    !toInstall.Contains(mod.name.ToString()))
                                {
                                    // add it to the list of recommended mods we display to the user
                                    if (recommended.ContainsKey(mod.name))
                                    {
                                        recommended[mod.name].Add(change.Key.identifier);
                                    }
                                    else
                                    {
                                        recommended.Add(mod.name, new List <string> {
                                            change.Key.identifier
                                        });
                                    }
                                }
                            }
                            catch (Kraken)
                            {
                            }
                        }
                    }

                    if (change.Key.suggests != null)
                    {
                        foreach (RelationshipDescriptor mod in change.Key.suggests)
                        {
                            try
                            {
                                if (
                                    RegistryManager.Instance(KSPManager.CurrentInstance)
                                    .registry.LatestAvailable(mod.name.ToString(), KSPManager.CurrentInstance.Version()) != null &&
                                    !RegistryManager.Instance(KSPManager.CurrentInstance).registry.IsInstalled(mod.name.ToString()) &&
                                    !toInstall.Contains(mod.name.ToString()))
                                {
                                    if (suggested.ContainsKey(mod.name))
                                    {
                                        suggested[mod.name].Add(change.Key.identifier);
                                    }
                                    else
                                    {
                                        suggested.Add(mod.name, new List <string> {
                                            change.Key.identifier
                                        });
                                    }
                                }
                            }
                            catch (Kraken)
                            {
                            }
                        }
                    }
                }
                else if (change.Value == GUIModChangeType.Update)
                {
                    // any mods for update we just put in the install list
                    toInstall.Add(change.Key.identifier);
                }
            }

            if (recommended.Any())
            {
                Util.Invoke(this, () => UpdateRecommendedDialog(recommended));

                m_TabController.ShowTab("ChooseRecommendedModsTabPage", 3);
                m_TabController.SetTabLock(true);

                lock (this)
                {
                    Monitor.Wait(this);
                }

                m_TabController.SetTabLock(false);
            }

            m_TabController.HideTab("ChooseRecommendedModsTabPage");

            if (installCanceled)
            {
                m_TabController.HideTab("WaitTabPage");
                m_TabController.ShowTab("ManageModsTabPage");
                return;
            }

            m_TabController.RenameTab("WaitTabPage", "Installing mods");
            m_TabController.ShowTab("WaitTabPage");

            bool resolvedAllProvidedMods = false;

            while (!resolvedAllProvidedMods)
            {
                try
                {
                    InstallList(toInstall, opts.Value);
                    resolvedAllProvidedMods = true;
                }
                catch (TooManyModsProvideKraken tooManyProvides)
                {
                    Util.Invoke(this, () => UpdateProvidedModsDialog(tooManyProvides));

                    m_TabController.ShowTab("ChooseProvidedModsTabPage", 3);
                    m_TabController.SetTabLock(true);

                    lock (this)
                    {
                        Monitor.Wait(this);
                    }

                    m_TabController.SetTabLock(false);

                    m_TabController.HideTab("ChooseProvidedModsTabPage");

                    if (installCanceled)
                    {
                        m_TabController.HideTab("WaitTabPage");
                        m_TabController.ShowTab("ManageModsTabPage");
                        return;
                    }

                    m_TabController.ShowTab("WaitTabPage");
                }
            }
        }
Пример #17
0
        private void InstallMods(object sender, DoWorkEventArgs e) // this probably needs to be refactored
        {
            installCanceled = false;

            ClearLog();

            var opts =
                (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument;

            IRegistryQuerier registry  = RegistryManager.Instance(manager.CurrentInstance).registry;
            ModuleInstaller  installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user);

            // setup progress callback

            toInstall = new HashSet <string>();
            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.Identifier);
                    break;
                }
            }

            // Now work on satisifying dependencies.

            var recommended = new Dictionary <string, List <string> >();
            var suggested   = new Dictionary <string, List <string> >();

            foreach (var change in opts.Key)
            {
                if (change.ChangeType == GUIModChangeType.Install)
                {
                    AddMod(change.Mod.ToModule().recommends, recommended, change.Mod.Identifier, registry);
                    AddMod(change.Mod.ToModule().suggests, suggested, change.Mod.Identifier, registry);
                }
            }

            ShowSelection(recommended);
            ShowSelection(suggested, true);

            tabController.HideTab("ChooseRecommendedModsTabPage");

            if (installCanceled)
            {
                tabController.HideTab("WaitTabPage");
                tabController.ShowTab("ManageModsTabPage");
                e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                return;
            }

            // Now let's make all our changes.

            tabController.RenameTab("WaitTabPage", "Status log");
            tabController.ShowTab("WaitTabPage");
            tabController.SetTabLock(true);


            var downloader = new NetAsyncModulesDownloader(GUI.user);

            cancelCallback = () =>
            {
                downloader.CancelDownload();
                installCanceled = true;
            };

            //Transaction is needed here to revert changes when an installation is cancelled
            //TODO: Cancellation should be handelt in the ModuleInstaller
            using (var transaction = CkanTransaction.CreateTransactionScope())
            {
                //Set the result to false/failed in case we return
                e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                SetDescription("Uninstalling selected mods");
                if (!WasSuccessful(() => installer.UninstallList(toUninstall)))
                {
                    return;
                }
                if (installCanceled)
                {
                    return;
                }

                SetDescription("Updating selected mods");
                if (!WasSuccessful(() => installer.Upgrade(toUpgrade, downloader)))
                {
                    return;
                }
                if (installCanceled)
                {
                    return;
                }

                // TODO: We should be able to resolve all our provisioning conflicts
                // before we start installing anything. CKAN.SanityChecker can be used to
                // pre-check if our changes are going to be consistent.

                bool resolvedAllProvidedMods = false;

                while (!resolvedAllProvidedMods)
                {
                    if (installCanceled)
                    {
                        e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                        return;
                    }
                    var ret = InstallList(toInstall, opts.Value, downloader);
                    if (!ret)
                    {
                        // install failed for some reason, error message is already displayed to the user
                        e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                        return;
                    }
                    resolvedAllProvidedMods = true;
                }

                if (!installCanceled)
                {
                    transaction.Complete();
                }
            }

            e.Result = new KeyValuePair <bool, ModChanges>(!installCanceled, opts.Key);
        }
Пример #18
0
        private void _UpdateModsList(bool repo_updated, IEnumerable <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))
                );

            if (mc != null)
            {
                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);
                }
            }

            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
            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());

            //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);
            UpdateTrayInfo();
        }
Пример #19
0
        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);
        }
Пример #20
0
        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);
        }
Пример #21
0
        public Main(string[] cmdlineArgs, GUIUser user, bool showConsole)
        {
            log.Info("Starting the GUI");
            commandLineArgs = cmdlineArgs;
            currentUser     = user;

            user.displayMessage = AddStatusMessage;
            user.displayError   = ErrorDialog;

            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();

            // 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.
            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;
                }
            }

            configuration = Configuration.LoadOrCreateConfiguration
                            (
                Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml"),
                Repo.default_ckan_repo.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.
            ModInfoTabControl.SelectedModule = 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();
            }

            Application.Run(this);

            var registry = RegistryManager.Instance(Manager.CurrentInstance);
            registry?.Dispose();
        }
Пример #22
0
        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);
        }
Пример #23
0
        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:";
            }
            else
            {
                RecommendedDialogLabel.Text =
                    "The following modules have been suggested by one or more of the chosen modules:";
                RecommendedModsListView.Columns[1].Text = "Suggested by:";
            }


            RecommendedModsListView.Items.Clear();

            foreach (var pair in mods)
            {
                CkanModule module;

                try
                {
                    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);
            }
        }
Пример #24
0
        // this probably needs to be refactored
        private void InstallMods(object sender, DoWorkEventArgs e)
        {
            installCanceled = false;
            ClearLog();

            var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument;

            IRegistryQuerier registry  = RegistryManager.Instance(manager.CurrentInstance).registry;
            ModuleInstaller  installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user);

            // 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
            var recRows = getRecSugRows(
                opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install)
                .Select(ch => ch.Mod),
                registry, toInstall
                );

            if (recRows.Any())
            {
                ShowRecSugDialog(recRows, toInstall);
            }

            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.
            tabController.RenameTab("WaitTabPage", Properties.Resources.MainInstallWaitTitle);
            ShowWaitDialog();
            tabController.SetTabLock(true);

            IDownloader downloader = new NetAsyncModulesDownloader(GUI.user, Manager.Cache);

            cancelCallback = () =>
            {
                downloader.CancelDownload();
                installCanceled = true;
            };

            // 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, false, toInstall.Select(m => m.identifier));
                            processSuccessful = true;
                        }
                    }
                    if (toUpgrade.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.Upgrade(toUpgrade, downloader);
                            processSuccessful = true;
                        }
                    }
                    if (toInstall.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.InstallList(toInstall, opts.Value, downloader, false);
                            processSuccessful = true;
                        }
                    }
                    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
                    CkanModule chosen = TooManyModsProvideCore(k).Result;
                    // Close the selection prompt
                    Util.Invoke(this, () =>
                    {
                        tabController.ShowTab("WaitTabPage");
                        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
                    }
                    else
                    {
                        // User cancelled, get out
                        tabController.ShowTab("ManageModsTabPage");
                        e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                        return;
                    }
                }
                catch (DependencyNotSatisfiedKraken ex)
                {
                    GUI.user.RaiseMessage(Properties.Resources.MainInstallDepNotSatisfied, ex.parent, ex.module);
                    return;
                }
                catch (ModuleNotFoundKraken ex)
                {
                    GUI.user.RaiseMessage(Properties.Resources.MainInstallNotFound, ex.module);
                    return;
                }
                catch (BadMetadataKraken ex)
                {
                    GUI.user.RaiseMessage(Properties.Resources.MainInstallBadMetadata, ex.module, ex.Message);
                    return;
                }
                catch (FileExistsKraken ex)
                {
                    if (ex.owningModule != null)
                    {
                        GUI.user.RaiseMessage(
                            Properties.Resources.MainInstallFileExists,
                            ex.filename, ex.installingModule, ex.owningModule,
                            Meta.GetVersion()
                            );
                    }
                    else
                    {
                        GUI.user.RaiseMessage(
                            Properties.Resources.MainInstallUnownedFileExists,
                            ex.installingModule, ex.filename
                            );
                    }
                    GUI.user.RaiseMessage(Properties.Resources.MainInstallGameDataReverted);
                    return;
                }
                catch (InconsistentKraken ex)
                {
                    // The prettiest Kraken formats itself for us.
                    GUI.user.RaiseMessage(ex.InconsistenciesPretty);
                    return;
                }
                catch (CancelledActionKraken)
                {
                    return;
                }
                catch (MissingCertificateKraken kraken)
                {
                    // Another very pretty kraken.
                    GUI.user.RaiseMessage(kraken.ToString());
                    return;
                }
                catch (DownloadThrottledKraken kraken)
                {
                    string msg = kraken.ToString();
                    GUI.user.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)
                        {
                            Process.Start(new ProcessStartInfo()
                            {
                                UseShellExecute = true,
                                FileName        = kraken.infoUrl.ToString()
                            });
                        }
                        // Now pretend they clicked the menu option for the settings
                        Enabled = false;
                        settingsDialog.ShowDialog();
                        Enabled = true;
                    }
                    return;
                }
                catch (ModuleDownloadErrorsKraken kraken)
                {
                    GUI.user.RaiseMessage(kraken.ToString());
                    GUI.user.RaiseError(kraken.ToString());
                    return;
                }
                catch (DirectoryNotFoundKraken kraken)
                {
                    GUI.user.RaiseMessage("\r\n{0}", kraken.Message);
                    return;
                }
                catch (DllNotFoundException)
                {
                    if (GUI.user.RaiseYesNoDialog(Properties.Resources.MainInstallLibCurlMissing))
                    {
                        Process.Start(new ProcessStartInfo()
                        {
                            UseShellExecute = true,
                            FileName        = "https://github.com/KSP-CKAN/CKAN/wiki/libcurl"
                        });
                    }
                    throw;
                }
            }
        }
Пример #25
0
        private void InstallMods(object sender, DoWorkEventArgs e) // this probably needs to be refactored
        {
            installCanceled = false;

            ClearLog();

            var opts =
                (KeyValuePair <List <KeyValuePair <CkanModule, GUIModChangeType> >, RelationshipResolverOptions>)e.Argument;

            ModuleInstaller installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user);

            // setup progress callback

            toInstall = new HashSet <string>();
            var toUninstall = new HashSet <string>();
            var toUpgrade   = new HashSet <string>();

            // First compose sets of what the user wants installed, upgraded, and removed.
            foreach (KeyValuePair <CkanModule, GUIModChangeType> change in opts.Key)
            {
                switch (change.Value)
                {
                case GUIModChangeType.Remove:
                    toUninstall.Add(change.Key.identifier);
                    break;

                case GUIModChangeType.Update:
                    toUpgrade.Add(change.Key.identifier);
                    break;

                case GUIModChangeType.Install:
                    toInstall.Add(change.Key.identifier);
                    break;
                }
            }

            // Now work on satisifying dependencies.

            var recommended = new Dictionary <string, List <string> >();
            var suggested   = new Dictionary <string, List <string> >();

            foreach (var change in opts.Key)
            {
                if (change.Value == GUIModChangeType.Install)
                {
                    if (change.Key.recommends != null)
                    {
                        foreach (RelationshipDescriptor mod in change.Key.recommends)
                        {
                            try
                            {
                                // if the mod is available for the current KSP version _and_
                                // the mod is not installed _and_
                                // the mod is not already in the install list
                                if (
                                    RegistryManager.Instance(manager.CurrentInstance)
                                    .registry.LatestAvailable(mod.name, manager.CurrentInstance.Version()) !=
                                    null &&
                                    !RegistryManager.Instance(manager.CurrentInstance)
                                    .registry.IsInstalled(mod.name) &&
                                    !toInstall.Contains(mod.name))
                                {
                                    // add it to the list of recommended mods we display to the user
                                    if (recommended.ContainsKey(mod.name))
                                    {
                                        recommended[mod.name].Add(change.Key.identifier);
                                    }
                                    else
                                    {
                                        recommended.Add(mod.name, new List <string> {
                                            change.Key.identifier
                                        });
                                    }
                                }
                            }
                            // XXX - Don't ignore all krakens! Those things are important!
                            catch (Kraken)
                            {
                            }
                        }
                    }

                    if (change.Key.suggests != null)
                    {
                        foreach (RelationshipDescriptor mod in change.Key.suggests)
                        {
                            try
                            {
                                if (
                                    RegistryManager.Instance(manager.CurrentInstance).registry.LatestAvailable(mod.name, manager.CurrentInstance.Version()) != null &&
                                    !RegistryManager.Instance(manager.CurrentInstance).registry.IsInstalled(mod.name) &&
                                    !toInstall.Contains(mod.name))
                                {
                                    if (suggested.ContainsKey(mod.name))
                                    {
                                        suggested[mod.name].Add(change.Key.identifier);
                                    }
                                    else
                                    {
                                        suggested.Add(mod.name, new List <string> {
                                            change.Key.identifier
                                        });
                                    }
                                }
                            }
                            // XXX - Don't ignore all krakens! Those things are important!
                            catch (Kraken)
                            {
                            }
                        }
                    }
                }
            }

            // If we're going to install something anyway, then don't list it in the
            // recommended list, since they can't de-select it anyway.
            foreach (var item in toInstall)
            {
                recommended.Remove(item);
            }

            // If there are any mods that would be recommended, prompt the user to make
            // selections.
            if (recommended.Any())
            {
                Util.Invoke(this, () => UpdateRecommendedDialog(recommended));

                m_TabController.ShowTab("ChooseRecommendedModsTabPage", 3);
                m_TabController.RenameTab("ChooseRecommendedModsTabPage", "Choose recommended mods");
                m_TabController.SetTabLock(true);

                lock (this)
                {
                    Monitor.Wait(this);
                }

                m_TabController.SetTabLock(false);
            }

            m_TabController.HideTab("ChooseRecommendedModsTabPage");

            // And now on to suggestions. Again, we don't show anything that's scheduled to
            // be installed on our suggest list.
            foreach (var item in toInstall)
            {
                suggested.Remove(item);
            }

            if (suggested.Any())
            {
                Util.Invoke(this, () => UpdateRecommendedDialog(suggested, true));

                m_TabController.ShowTab("ChooseRecommendedModsTabPage", 3);
                m_TabController.RenameTab("ChooseRecommendedModsTabPage", "Choose suggested mods");
                m_TabController.SetTabLock(true);

                lock (this)
                {
                    Monitor.Wait(this);
                }

                m_TabController.SetTabLock(false);
            }

            m_TabController.HideTab("ChooseRecommendedModsTabPage");

            if (installCanceled)
            {
                m_TabController.HideTab("WaitTabPage");
                m_TabController.ShowTab("ManageModsTabPage");
                e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(false, opts.Key);
                return;
            }

            // Now let's make all our changes.

            m_TabController.RenameTab("WaitTabPage", "Installing mods");
            m_TabController.ShowTab("WaitTabPage");
            m_TabController.SetTabLock(true);

            using (var transaction = new CkanTransaction())
            {
                var downloader = new NetAsyncDownloader(GUI.user);
                cancelCallback = () =>
                {
                    downloader.CancelDownload();
                    installCanceled = true;
                };


                SetDescription("Uninstalling selected mods");
                installer.UninstallList(toUninstall);
                if (installCanceled)
                {
                    return;
                }

                SetDescription("Updating selected mods");
                installer.Upgrade(toUpgrade, downloader);


                // TODO: We should be able to resolve all our provisioning conflicts
                // before we start installing anything. CKAN.SanityChecker can be used to
                // pre-check if our changes are going to be consistent.

                bool resolvedAllProvidedMods = false;

                while (!resolvedAllProvidedMods)
                {
                    if (installCanceled)
                    {
                        e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(false,
                                                                                                                 opts.Key);
                        return;
                    }
                    try
                    {
                        var ret = InstallList(toInstall, opts.Value, downloader);
                        if (!ret)
                        {
                            // install failed for some reason, error message is already displayed to the user
                            e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(false,
                                                                                                                     opts.Key);
                            return;
                        }
                        resolvedAllProvidedMods = true;
                    }
                    catch (TooManyModsProvideKraken tooManyProvides)
                    {
                        Util.Invoke(this, () => UpdateProvidedModsDialog(tooManyProvides));

                        m_TabController.ShowTab("ChooseProvidedModsTabPage", 3);
                        m_TabController.SetTabLock(true);

                        lock (this)
                        {
                            Monitor.Wait(this);
                        }

                        m_TabController.SetTabLock(false);

                        m_TabController.HideTab("ChooseProvidedModsTabPage");

                        if (installCanceled)
                        {
                            m_TabController.HideTab("WaitTabPage");
                            m_TabController.ShowTab("ManageModsTabPage");
                            e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(false,
                                                                                                                     opts.Key);
                            return;
                        }

                        m_TabController.ShowTab("WaitTabPage");
                    }
                }
                if (!installCanceled)
                {
                    transaction.Complete();
                }
            }
            e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(true, opts.Key);
        }
Пример #26
0
        private void InstallMods(object sender, DoWorkEventArgs e) // this probably needs to be refactored
        {
            installCanceled = false;
            ClearLog();

            var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument;

            IRegistryQuerier registry  = RegistryManager.Instance(manager.CurrentInstance).registry;
            ModuleInstaller  installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user);

            // Avoid accumulating multiple event handlers
            installer.onReportModInstalled -= OnModInstalled;
            installer.onReportModInstalled += OnModInstalled;
            // setup progress callback

            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.ToModule());
                    break;
                }
            }

            // Now work on satisifying dependencies.

            var recommended = new Dictionary <CkanModule, List <string> >();
            var suggested   = new Dictionary <CkanModule, List <string> >();

            foreach (var change in opts.Key)
            {
                if (change.ChangeType == GUIModChangeType.Install)
                {
                    AddMod(change.Mod.ToModule().recommends, recommended, change.Mod.Identifier, registry);
                    AddMod(change.Mod.ToModule().suggests, suggested, change.Mod.Identifier, registry);
                }
            }

            ShowSelection(recommended);
            ShowSelection(suggested, true);

            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.
            tabController.RenameTab("WaitTabPage", "Status log");
            ShowWaitDialog();
            tabController.SetTabLock(true);

            IDownloader downloader = new NetAsyncModulesDownloader(GUI.user);

            cancelCallback = () =>
            {
                downloader.CancelDownload();
                installCanceled = true;
            };

            bool resolvedAllProvidedMods = false;

            while (!resolvedAllProvidedMods)
            {
                try
                {
                    e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                    if (!installCanceled && toUninstall.Count > 0)
                    {
                        installer.UninstallList(toUninstall);
                    }
                    if (!installCanceled && toUpgrade.Count > 0)
                    {
                        installer.Upgrade(toUpgrade, downloader);
                    }
                    if (!installCanceled && toInstall.Count > 0)
                    {
                        installer.InstallList(toInstall, opts.Value, downloader);
                    }
                    e.Result = new KeyValuePair <bool, ModChanges>(!installCanceled, opts.Key);
                    if (installCanceled)
                    {
                        return;
                    }
                    resolvedAllProvidedMods = true;
                }
                catch (DependencyNotSatisfiedKraken ex)
                {
                    GUI.user.RaiseMessage(
                        "{0} requires {1} but it is not listed in the index, or not available for your version of KSP.",
                        ex.parent, ex.module);
                    return;
                }
                catch (ModuleNotFoundKraken ex)
                {
                    GUI.user.RaiseMessage(
                        "Module {0} required but it is not listed in the index, or not available for your version of KSP.",
                        ex.module);
                    return;
                }
                catch (BadMetadataKraken ex)
                {
                    GUI.user.RaiseMessage("Bad metadata detected for module {0}: {1}", ex.module, ex.Message);
                    return;
                }
                catch (FileExistsKraken ex)
                {
                    if (ex.owningModule != null)
                    {
                        GUI.user.RaiseMessage(
                            "\r\nOh no! We tried to overwrite a file owned by another mod!\r\n" +
                            "Please try a `ckan update` and try again.\r\n\r\n" +
                            "If this problem re-occurs, then it maybe a packaging bug.\r\n" +
                            "Please report it at:\r\n\r\n" +
                            "https://github.com/KSP-CKAN/NetKAN/issues/new\r\n\r\n" +
                            "Please including the following information in your report:\r\n\r\n" +
                            "File           : {0}\r\n" +
                            "Installing Mod : {1}\r\n" +
                            "Owning Mod     : {2}\r\n" +
                            "CKAN Version   : {3}\r\n",
                            ex.filename, ex.installingModule, ex.owningModule,
                            Meta.GetVersion()
                            );
                    }
                    else
                    {
                        GUI.user.RaiseMessage(
                            "\r\n\r\nOh no!\r\n\r\n" +
                            "It looks like you're trying to install a mod which is already installed,\r\n" +
                            "or which conflicts with another mod which is already installed.\r\n\r\n" +
                            "As a safety feature, the CKAN will *never* overwrite or alter a file\r\n" +
                            "that it did not install itself.\r\n\r\n" +
                            "If you wish to install {0} via the CKAN,\r\n" +
                            "then please manually uninstall the mod which owns:\r\n\r\n" +
                            "{1}\r\n\r\n" + "and try again.\r\n",
                            ex.installingModule, ex.filename
                            );
                    }

                    GUI.user.RaiseMessage("Your GameData has been returned to its original state.\r\n");
                    return;
                }
                catch (InconsistentKraken ex)
                {
                    // The prettiest Kraken formats itself for us.
                    GUI.user.RaiseMessage(ex.InconsistenciesPretty);
                    return;
                }
                catch (CancelledActionKraken)
                {
                    return;
                }
                catch (MissingCertificateKraken kraken)
                {
                    // Another very pretty kraken.
                    GUI.user.RaiseMessage(kraken.ToString());
                    return;
                }
                catch (DownloadThrottledKraken kraken)
                {
                    string msg = kraken.ToString();
                    GUI.user.RaiseMessage(msg);
                    if (YesNoDialog($"{msg}\r\n\r\nOpen settings now?"))
                    {
                        // Launch the URL describing this host's throttling practices, if any
                        if (kraken.infoUrl != null)
                        {
                            Process.Start(new ProcessStartInfo()
                            {
                                UseShellExecute = true,
                                FileName        = kraken.infoUrl.ToString()
                            });
                        }
                        // Now pretend they clicked the menu option for the settings
                        Enabled = false;
                        settingsDialog.ShowDialog();
                        Enabled = true;
                    }
                    return;
                }
                catch (ModuleDownloadErrorsKraken kraken)
                {
                    GUI.user.RaiseMessage(kraken.ToString());
                    GUI.user.RaiseError(kraken.ToString());
                    return;
                }
                catch (DirectoryNotFoundKraken kraken)
                {
                    GUI.user.RaiseMessage("\r\n{0}", kraken.Message);
                    return;
                }
                catch (DllNotFoundException)
                {
                    if (GUI.user.RaiseYesNoDialog("libcurl installation not found. Open wiki page for help?"))
                    {
                        Process.Start(new ProcessStartInfo()
                        {
                            UseShellExecute = true,
                            FileName        = "https://github.com/KSP-CKAN/CKAN/wiki/libcurl"
                        });
                    }
                    throw;
                }
            }
        }
Пример #27
0
        private static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, Uri repo = null)
        {
            // Use our default repo, unless we've been told otherwise.
            if (repo == null)
            {
                repo = default_ckan_repo;
            }

            UpdateRegistry(repo, registry_manager.registry, ksp, user, clear);

            // Save our changes!
            registry_manager.Save(enforce_consistency: false);

            ShowUserInconsistencies(registry_manager.registry, user);

            // Return how many we got!
            return registry_manager.registry.Available(ksp.VersionCriteria()).Count;
        }
Пример #28
0
        // 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;
                    }
                }
            }
        }
Пример #29
0
        /// <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)
        {
            Util.Invoke(this, () =>
            {
                Text = $"CKAN {Meta.GetVersion()} - KSP {CurrentInstance.Version()}    --    {CurrentInstance.GameDir().Replace('/', Path.DirectorySeparatorChar)}";
                StatusInstanceLabel.Text = string.Format(
                    Properties.Resources.StatusInstanceLabelText,
                    CurrentInstance.Name,
                    CurrentInstance.Version()?.ToString()
                    );
            });

            configuration = GUIConfiguration.LoadOrCreateConfiguration(
                Path.Combine(CurrentInstance.CkanDir(), "GUIConfig.xml")
                );

            if (CurrentInstance.CompatibleVersionsAreFromDifferentKsp)
            {
                new CompatibleKspVersionsDialog(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);
        }
Пример #30
0
        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);
        }
Пример #31
0
        public Main(string[] cmdlineArgs, KSPManager 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 KSPManager(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 ManageKspInstancesDialog(!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();
        }
Пример #32
0
        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 (KeyValuePair <string, List <string> > pair in mods)
            {
                CfanModule module;

                try
                {
                    var opts = new RelationshipResolverOptions
                    {
                        with_all_suggests              = false,
                        with_recommends                = false,
                        with_suggests                  = false,
                        without_enforce_consistency    = false,
                        without_toomanyprovides_kraken = true
                    };

                    CfanModuleIdAndVersion[] arrayWithOneModName = new[] { new CfanModuleIdAndVersion(pair.Key) };
                    RelationshipResolver     resolver            = new RelationshipResolver(arrayWithOneModName, 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);
            }
        }