diff --git a/po/POTFILES b/po/POTFILES index 5b5c70006..044533f59 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -5,6 +5,7 @@ src/Dialogs/GlobalSearchDialog.vala src/Dialogs/NewBranchDialog.vala src/Dialogs/PreferencesDialog.vala src/Dialogs/RestoreConfirmationDialog.vala +src/Dialogs/CloseProjectsConfirmationDialog.vala src/FolderManager/File.vala src/FolderManager/FileItem.vala src/FolderManager/FileView.vala diff --git a/src/Dialogs/CloseProjectsConfirmationDialog.vala b/src/Dialogs/CloseProjectsConfirmationDialog.vala new file mode 100644 index 000000000..fde88a5a0 --- /dev/null +++ b/src/Dialogs/CloseProjectsConfirmationDialog.vala @@ -0,0 +1,67 @@ +/* +* Copyright 2024 elementary, Inc. (https://elementary.io) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License version 3 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301 USA +*/ + +public class Scratch.Dialogs.CloseProjectsConfirmationDialog : Granite.MessageDialog { + + public uint n_parents { get; construct; } + public uint n_children { get; construct; } + + public CloseProjectsConfirmationDialog (MainWindow parent, uint n_parents, uint n_children) { + Object ( + buttons: Gtk.ButtonsType.NONE, + transient_for: parent, + n_parents: n_parents, + n_children: n_children + ); + } + + construct { + image_icon = new ThemedIcon ("dialog-warning"); + var button_label = ""; + // We can assume that either n_parents or n_children is zero (but not both). + // We can assume n_parents is either zero or one + if (n_children > 0) { + primary_text = ngettext ( + _("This folder is the parent of an open project"), + _("This folder is the parent of %u open projects").printf (n_children), + (ulong) n_children + ); + ; + secondary_text = ngettext ( + _("Opening this folder will close the child project"), + _("Opening this folder will close all child projects"), + (ulong) n_children + ); + + button_label = ngettext ( + _("Close Child Project"), + _("Close Child Projects"), + (ulong) n_children + ); + } else { + primary_text = _("This folder is a child of an open project"); + secondary_text = _("Opening this folder will close the parent project"); + button_label = _("Close Parent Project"); + } + + add_button (_("Don't Open"), Gtk.ResponseType.REJECT); + + var ignore_button = (Gtk.Button) add_button (button_label, Gtk.ResponseType.ACCEPT); + ignore_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); + } +} diff --git a/src/FolderManager/FileView.vala b/src/FolderManager/FileView.vala index c9efd85bb..98aaf3574 100644 --- a/src/FolderManager/FileView.vala +++ b/src/FolderManager/FileView.vala @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017 - 2022 elementary LLC. (https://elementary.io), + * Copyright (c) 2017 - 2024 elementary LLC. (https://elementary.io), * 2013 Julien Spautz * * This program is free software: you can redistribute it and/or modify @@ -514,25 +514,77 @@ public class Scratch.FolderManager.FileView : Code.Widgets.SourceList, Code.Pane return; } - var folder_root = new ProjectFolderItem (folder, this); // Constructor adds project to GitManager - this.root.add (folder_root); - rename_items_with_same_name (folder_root); + var add_file = folder.file; + // Need to deal with case where folder is parent or child of an existing project + var parents = new List (); + var children = new List (); - folder_root.expanded = expand; - folder_root.closed.connect (() => { - toplevel_action_group.activate_action (MainWindow.ACTION_CLOSE_PROJECT_DOCS, new Variant.string (folder_root.path)); - root.remove (folder_root); - foreach (var child in root.children) { - var child_folder = (ProjectFolderItem) child; - if (child_folder.name != child_folder.file.name) { - rename_items_with_same_name (child_folder); + foreach (var child in root.children) { + var item = (ProjectFolderItem) child; + if (add_file.get_relative_path (item.file.file) != null) { + debug ("Trying to add parent of existing project"); + children.append (item); + } else if (item.file.file.get_relative_path (add_file) != null) { + debug ("Trying to add child of existing project"); + parents.append (item); + } + } + + if (parents.length () > 0 || children.length () > 0) { + assert (parents.length () <= 1); + assert (parents.length () == 0 || children.length () == 0); + var dialog = new Scratch.Dialogs.CloseProjectsConfirmationDialog ( + (MainWindow) get_toplevel (), + parents.length (), + children.length () + ); + + var close_projects = false; + dialog.response.connect ((res) => { + dialog.destroy (); + if (res == Gtk.ResponseType.ACCEPT) { + close_projects = true; + } + }); + + dialog.run (); + + if (close_projects) { + foreach (var item in parents) { + item.closed (); + } + + foreach (var item in children) { + item.closed (); } + } else { + return; } - Scratch.Services.GitManager.get_instance ().remove_project (folder_root); + } + + // Process any closed signals emitted before proceeding + Idle.add (() => { + var folder_root = new ProjectFolderItem (folder, this); // Constructor adds project to GitManager + this.root.add (folder_root); + rename_items_with_same_name (folder_root); + + folder_root.expanded = expand; + folder_root.closed.connect (() => { + toplevel_action_group.activate_action (MainWindow.ACTION_CLOSE_PROJECT_DOCS, new Variant.string (folder_root.path)); + root.remove (folder_root); + foreach (var child in root.children) { + var child_folder = (ProjectFolderItem) child; + if (child_folder.name != child_folder.file.name) { + rename_items_with_same_name (child_folder); + } + } + Scratch.Services.GitManager.get_instance ().remove_project (folder_root); + write_settings (); + }); + write_settings (); + return Source.REMOVE; }); - - write_settings (); } private bool is_open (File folder) { diff --git a/src/meson.build b/src/meson.build index 08497a110..b9778607f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,6 +20,7 @@ code_files = files( 'Utils.vala', 'Dialogs/PreferencesDialog.vala', 'Dialogs/RestoreConfirmationDialog.vala', + 'Dialogs/CloseProjectsConfirmationDialog.vala', 'Dialogs/GlobalSearchDialog.vala', 'Dialogs/NewBranchDialog.vala', 'FolderManager/File.vala',