[latexila] Cleanup Build Files: take into account projects



commit 275d68b9b99355663c77f8e71a6a6182810c12fd
Author: SÃbastien Wilmet <swilmet src gnome org>
Date:   Wed Jun 22 03:48:45 2011 +0200

    Cleanup Build Files: take into account projects
    
    If a project is defined, there were some remaining *.aux files.
    
    So in this case, instead of replacing the extension of the main file
    to see if the file exist and remove it, search directly all files
    which have the extension (in all sub-directories), and remove them.
    
    The code has been moved to a new class, so it's cleaner.

 TODO                       |    5 -
 src/clean_build_files.vala |  291 ++++++++++++++++++++++++++++++++++++++++++++
 src/dialogs.vala           |  137 ---------------------
 src/document.vala          |   41 ------
 src/document_tab.vala      |   62 +---------
 src/documents_panel.vala   |    6 +-
 src/file_browser.vala      |    1 +
 src/main_window.vala       |   12 ++-
 src/utils.vala             |   68 ++++++++++
 9 files changed, 378 insertions(+), 245 deletions(-)
---
diff --git a/TODO b/TODO
index 24a3cc9..0622eab 100644
--- a/TODO
+++ b/TODO
@@ -23,11 +23,6 @@ LaTeXila 2.2
 	  so we can modify the copy and keep the original
 	- right click menu in bottom panel: copy the line to the clipboard
 
-- Cleanup Build Files: if a project is defined, some *.aux files are not removed
-  => If a project is defined, instead of replacing the extension of the main
-     file to see if the file exist and remove it, search directly all files
-     which have the extension (in all sub-directories), and remove them.
-
 - Write some documentation:
 	- explain the build tools, how to create a new one, etc.
 	- the difference between Latexmk and Rubber
diff --git a/src/clean_build_files.vala b/src/clean_build_files.vala
new file mode 100644
index 0000000..f58a157
--- /dev/null
+++ b/src/clean_build_files.vala
@@ -0,0 +1,291 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright  2011 SÃbastien Wilmet
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila 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 General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Gtk;
+
+public class CleanBuildFiles : GLib.Object
+{
+    private unowned MainWindow  _main_window;
+    private Document            _doc;
+    private string[]            _extensions;
+    private bool                _no_confirm;
+
+    public CleanBuildFiles (MainWindow main_window, Document doc)
+    {
+        _main_window = main_window;
+        _doc = doc;
+
+        GLib.Settings settings =
+            new GLib.Settings ("org.gnome.latexila.preferences.latex");
+        string exts = settings.get_string ("clean-extensions");
+        _extensions = exts.split (" ");
+
+        _no_confirm = settings.get_boolean ("no-confirm-clean");
+    }
+
+    // return true if some files have been deleted
+    public bool clean ()
+    {
+        if (! _doc.is_main_file_a_tex_file ())
+            return false;
+
+        Gee.ArrayList<File> files_to_delete;
+        File directory;
+
+        // the document is part of a project
+        if (_doc.project_id != -1)
+        {
+            Project? project = Projects.get_default ().get (_doc.project_id);
+            return_val_if_fail (project != null, false);
+
+            directory = project.directory;
+
+            files_to_delete = get_build_files_in_directory (directory);
+        }
+        else
+        {
+            directory = _doc.location.get_parent ();
+            files_to_delete = get_build_files_simple ();
+        }
+
+        if (files_to_delete.size == 0)
+            return false;
+
+        if (_no_confirm)
+        {
+            foreach (File file_to_delete in files_to_delete)
+                Utils.delete_file (file_to_delete);
+
+            return true;
+        }
+
+        return confirm_cleanup (files_to_delete, directory);
+    }
+
+    private Gee.ArrayList<File> get_build_files_simple ()
+    {
+        File location = _doc.location;
+        File directory = location.get_parent ();
+        string shortname = Utils.get_shortname (location.get_basename ());
+
+        Gee.ArrayList<File> files_to_delete = new Gee.ArrayList<File> ();
+
+        foreach (string extension in _extensions)
+        {
+            string basename = shortname + extension;
+            File file = directory.get_child (basename);
+            if (file.query_exists ())
+                files_to_delete.add (file);
+        }
+
+        return files_to_delete;
+    }
+
+    private Gee.ArrayList<File> get_build_files_in_directory (File directory)
+    {
+        Gee.ArrayList<File> files_to_delete = new Gee.ArrayList<File> ();
+        FileEnumerator enumerator;
+
+        try
+        {
+            enumerator = directory.enumerate_children ("standard::type,standard::name",
+                FileQueryInfoFlags.NONE);
+        }
+        catch (Error e)
+        {
+            stderr.printf ("Error: clean build files: %s\n", e.message);
+            return files_to_delete;
+        }
+
+        while (true)
+        {
+            FileInfo? info = null;
+
+            try
+            {
+                info = enumerator.next_file ();
+            }
+            catch (Error e)
+            {
+                stderr.printf ("Error: clean build files: %s\n", e.message);
+                break;
+            }
+
+            if (info == null)
+                break;
+
+            string name = info.get_name ();
+            File file = directory.get_child (name);
+
+            FileType type = info.get_file_type ();
+            if (type == FileType.DIRECTORY)
+            {
+                var files_to_delete_in_dir = get_build_files_in_directory (file);
+                files_to_delete.add_all (files_to_delete_in_dir);
+                continue;
+            }
+
+            string extension = Utils.get_extension (name);
+            if (extension in _extensions)
+                files_to_delete.add (file);
+        }
+
+        return files_to_delete;
+    }
+
+    private enum CleanFileColumn
+    {
+        DELETE,
+        NAME,
+        FILE,
+        N_COLUMNS
+    }
+
+    private bool confirm_cleanup (Gee.ArrayList<File> files_to_delete, File directory)
+    {
+        return_val_if_fail (0 < files_to_delete.size, false);
+
+        Dialog dialog = new Dialog.with_buttons (null,
+            _main_window,
+            DialogFlags.DESTROY_WITH_PARENT,
+            Stock.CANCEL, ResponseType.CANCEL,
+            Stock.DELETE, ResponseType.ACCEPT,
+            null);
+
+        dialog.has_separator = false;
+
+        HBox hbox = new HBox (false, 12);
+        hbox.border_width = 5;
+        VBox content_area = dialog.get_content_area () as VBox;
+        content_area.pack_start (hbox);
+
+        /* image */
+        Image image = new Image.from_stock (Stock.DIALOG_WARNING, IconSize.DIALOG);
+        image.set_alignment ((float) 0.5, (float) 0.0);
+        hbox.pack_start (image, false, false, 0);
+
+        VBox vbox = new VBox (false, 12);
+        hbox.pack_start (vbox);
+
+        /* primary label */
+        Label primary_label = new Label (null);
+        primary_label.set_line_wrap (true);
+        primary_label.set_use_markup (true);
+        primary_label.set_alignment ((float) 0.0, (float) 0.5);
+        primary_label.set_selectable (true);
+        primary_label.set_markup ("<span weight=\"bold\" size=\"larger\">"
+            + _("Do you really want to delete these files?") + "</span>");
+
+        vbox.pack_start (primary_label, false, false, 0);
+
+        VBox vbox2 = new VBox (false, 8);
+        vbox.pack_start (vbox2, false, false);
+
+        Label select_label = new Label (_("Select the files you want to delete:"));
+        select_label.set_line_wrap (true);
+        select_label.set_alignment ((float) 0.0, (float) 0.5);
+        vbox2.pack_start (select_label, false, false, 0);
+
+        /* files list with checkboxes */
+        TreeView treeview = new TreeView ();
+        treeview.set_size_request (260, 120);
+        treeview.headers_visible = false;
+        treeview.enable_search = false;
+
+        ListStore store = new ListStore (CleanFileColumn.N_COLUMNS,
+            typeof (bool), typeof (string), typeof (File));
+
+        // fill the list
+        foreach (File file_to_delete in files_to_delete)
+        {
+            string relative_path = Utils.get_relative_path (directory, file_to_delete,
+                directory);
+            TreeIter iter;
+            store.append (out iter);
+            store.set (iter,
+                CleanFileColumn.DELETE, true,
+                CleanFileColumn.NAME, relative_path,
+                CleanFileColumn.FILE, file_to_delete,
+                -1);
+        }
+
+        treeview.set_model (store);
+        CellRendererToggle toggle_renderer = new CellRendererToggle ();
+
+        toggle_renderer.toggled.connect ((path_str) =>
+        {
+            TreePath path = new TreePath.from_string (path_str);
+            TreeIter iter;
+            bool active;
+            store.get_iter (out iter, path);
+            store.get (iter, CleanFileColumn.DELETE, out active, -1);
+            // inverse the value
+            store.set (iter, CleanFileColumn.DELETE, ! active, -1);
+        });
+
+        TreeViewColumn column = new TreeViewColumn.with_attributes ("Delete?",
+            toggle_renderer, "active", CleanFileColumn.DELETE, null);
+        treeview.append_column (column);
+
+        CellRendererText text_renderer = new CellRendererText ();
+        column = new TreeViewColumn.with_attributes ("Name", text_renderer,
+            "text", CleanFileColumn.NAME, null);
+        treeview.append_column (column);
+
+        // with a scrollbar
+        ScrolledWindow sw = Utils.add_scrollbar (treeview) as ScrolledWindow;
+        sw.set_shadow_type (ShadowType.IN);
+        vbox2.pack_start (sw);
+
+        hbox.show_all ();
+
+        /* run */
+        bool ret = false;
+        if (dialog.run () == ResponseType.ACCEPT)
+        {
+            // get files to delete
+            File[] selected_files = {};
+            TreeIter iter;
+            bool valid = store.get_iter_first (out iter);
+            while (valid)
+            {
+                bool selected;
+                File file_to_delete;
+
+                store.get (iter,
+                    CleanFileColumn.DELETE, out selected,
+                    CleanFileColumn.FILE, out file_to_delete,
+                    -1);
+
+                if (selected)
+                    selected_files += file_to_delete;
+
+                valid = store.iter_next (ref iter);
+            }
+
+            ret = 0 < selected_files.length;
+
+            foreach (File file_to_delete in selected_files)
+                Utils.delete_file (file_to_delete);
+        }
+
+        dialog.destroy ();
+        return ret;
+    }
+}
diff --git a/src/dialogs.vala b/src/dialogs.vala
index 691680a..d696e97 100644
--- a/src/dialogs.vala
+++ b/src/dialogs.vala
@@ -185,141 +185,4 @@ namespace Dialogs
 
         dialog.destroy ();
     }
-
-    private enum CleanFileColumn
-    {
-        DELETE,
-        NAME,
-        N_COLUMNS
-    }
-
-    public bool
-    confirm_clean_build_files (MainWindow window, File directory, string[] basenames)
-    {
-        return_if_fail (basenames.length > 0);
-
-        Dialog dialog = new Dialog.with_buttons (null,
-            window,
-            DialogFlags.DESTROY_WITH_PARENT,
-            Stock.CANCEL, ResponseType.CANCEL,
-            Stock.DELETE, ResponseType.ACCEPT,
-            null);
-
-        dialog.has_separator = false;
-
-        HBox hbox = new HBox (false, 12);
-        hbox.border_width = 5;
-        VBox content_area = (VBox) dialog.get_content_area ();
-        content_area.pack_start (hbox, true, true, 0);
-
-        /* image */
-        Image image = new Image.from_stock (Stock.DIALOG_WARNING, IconSize.DIALOG);
-        image.set_alignment ((float) 0.5, (float) 0.0);
-        hbox.pack_start (image, false, false, 0);
-
-        VBox vbox = new VBox (false, 12);
-        hbox.pack_start (vbox, true, true, 0);
-
-        /* primary label */
-        Label primary_label = new Label (null);
-        primary_label.set_line_wrap (true);
-        primary_label.set_use_markup (true);
-        primary_label.set_alignment ((float) 0.0, (float) 0.5);
-        primary_label.set_selectable (true);
-        primary_label.set_markup ("<span weight=\"bold\" size=\"larger\">"
-            + _("Do you really want to delete these files?") + "</span>");
-
-        vbox.pack_start (primary_label, false, false, 0);
-
-        VBox vbox2 = new VBox (false, 8);
-        vbox.pack_start (vbox2, false, false);
-
-        Label select_label = new Label (_("Select the files you want to delete:"));
-        select_label.set_line_wrap (true);
-        select_label.set_alignment ((float) 0.0, (float) 0.5);
-        vbox2.pack_start (select_label, false, false, 0);
-
-        /* files list with checkboxes */
-        TreeView treeview = new TreeView ();
-        treeview.set_size_request (260, 120);
-        treeview.headers_visible = false;
-        treeview.enable_search = false;
-
-        ListStore store = new ListStore (CleanFileColumn.N_COLUMNS, typeof (bool),
-            typeof (string));
-
-        // fill the list
-        foreach (string basename in basenames)
-        {
-            TreeIter iter;
-            store.append (out iter);
-            store.set (iter,
-                CleanFileColumn.DELETE, true,
-                CleanFileColumn.NAME, basename,
-                -1);
-        }
-
-        treeview.set_model (store);
-        CellRendererToggle renderer1 = new CellRendererToggle ();
-
-        renderer1.toggled.connect ((path_str) =>
-        {
-            TreePath path = new TreePath.from_string (path_str);
-            TreeIter iter;
-            bool active;
-            store.get_iter (out iter, path);
-            store.get (iter, CleanFileColumn.DELETE, out active, -1);
-            // inverse the value
-            store.set (iter, CleanFileColumn.DELETE, ! active, -1);
-        });
-
-        TreeViewColumn column = new TreeViewColumn.with_attributes ("Delete?", renderer1,
-            "active", CleanFileColumn.DELETE, null);
-        treeview.append_column (column);
-
-        CellRendererText renderer2 = new CellRendererText ();
-        column = new TreeViewColumn.with_attributes ("Name", renderer2,
-            "text", CleanFileColumn.NAME, null);
-        treeview.append_column (column);
-
-        // with a scrollbar
-        ScrolledWindow sw = (ScrolledWindow) Utils.add_scrollbar (treeview);
-        sw.set_shadow_type (ShadowType.IN);
-        vbox2.pack_start (sw, true, true, 0);
-
-        hbox.show_all ();
-
-        /* run */
-        bool ret = false;
-        if (dialog.run () == ResponseType.ACCEPT)
-        {
-            // get files to delete
-            string[] selected_files = {};
-            TreeIter iter;
-            bool valid = store.get_iter_first (out iter);
-            while (valid)
-            {
-                bool selected;
-                string basename;
-                store.get (iter,
-                    CleanFileColumn.DELETE, out selected,
-                    CleanFileColumn.NAME, out basename,
-                    -1);
-                if (selected)
-                    selected_files += basename;
-
-                valid = store.iter_next (ref iter);
-            }
-
-            foreach (string selected_file in selected_files)
-            {
-                ret = true;
-                File file = directory.get_child (selected_file);
-                Utils.delete_file (file);
-            }
-        }
-
-        dialog.destroy ();
-        return ret;
-    }
 }
diff --git a/src/document.vala b/src/document.vala
index 7565eb2..45e8f4a 100644
--- a/src/document.vala
+++ b/src/document.vala
@@ -481,47 +481,6 @@ public class Document : Gtk.SourceBuffer
         return SelectionType.MULTIPLE_LINES;
     }
 
-    public bool clean_build_files (MainWindow window)
-    {
-        if (! is_main_file_a_tex_file ())
-            return false;
-
-        bool ret = false;
-
-        GLib.Settings settings =
-            new GLib.Settings ("org.gnome.latexila.preferences.latex");
-        string exts = settings.get_string ("clean-extensions");
-        string[] extensions = exts.split (" ");
-
-        bool no_confirm = settings.get_boolean ("no-confirm-clean");
-
-        File mainfile = get_main_file ();
-        File directory = mainfile.get_parent ();
-        string shortname = Utils.get_shortname (mainfile.get_basename ());
-        string[] basenames = {};
-        foreach (string extension in extensions)
-        {
-            string basename = shortname + extension;
-            File file = directory.get_child (basename);
-            if (file.query_exists ())
-            {
-                ret = true;
-                if (no_confirm)
-                    Utils.delete_file (file);
-                else
-                    basenames += basename;
-            }
-        }
-
-        if (no_confirm)
-            return ret;
-
-        else if (basenames.length > 0)
-            return Dialogs.confirm_clean_build_files (window, directory, basenames);
-
-        return false;
-    }
-
     // If line is bigger than the number of lines of the document, the cursor is moved
     // to the last line and false is returned.
     public bool goto_line (int line)
diff --git a/src/document_tab.vala b/src/document_tab.vala
index 9aa7bfb..4c08713 100644
--- a/src/document_tab.vala
+++ b/src/document_tab.vala
@@ -247,65 +247,11 @@ public class DocumentTab : VBox
         if (project == null)
             return null;
 
-        File main_file = project.main_file;
-        File project_dir = project.directory;
-        File doc_file = document.location;
+        File origin = document.location;
+        File target = project.main_file;
+        File common_dir = project.directory;
 
-        File main_parent = main_file.get_parent ();
-        File doc_parent = doc_file.get_parent ();
-
-        // The document is in the same directory as the main file.
-        if (main_parent.equal (doc_parent))
-            return main_file.get_basename ();
-
-        // Get a list of parent directories. Stop at the project dir.
-        List<File> main_dirs = new List<File> ();
-        List<File> doc_dirs = new List<File> ();
-
-        while (main_parent != null && ! main_parent.equal (project_dir))
-        {
-            main_dirs.prepend (main_parent);
-            main_parent = main_parent.get_parent ();
-        }
-
-        while (doc_parent != null && ! doc_parent.equal (project_dir))
-        {
-            doc_dirs.prepend (doc_parent);
-            doc_parent = doc_parent.get_parent ();
-        }
-
-        // Get number of common dirs
-        uint dir_index = 0;
-        while (dir_index < main_dirs.length () && dir_index < doc_dirs.length ())
-        {
-            File cur_main_dir = main_dirs.nth_data (dir_index);
-            File cur_doc_dir = doc_dirs.nth_data (dir_index);
-            if (! cur_main_dir.equal (cur_doc_dir))
-                break;
-
-            dir_index++;
-        }
-
-        uint nb_common_dirs = dir_index;
-
-        /* Build the relative path */
-        string relative_path = "";
-
-        // go to the common dir
-        uint nb_remaining_doc_dirs = doc_dirs.length () - nb_common_dirs;
-        for (uint i = 0 ; i < nb_remaining_doc_dirs ; i++)
-            relative_path += "../";
-
-        // go to the main file dir
-        for (uint i = nb_common_dirs ; i < main_dirs.length () ; i++)
-        {
-            File cur_main_dir = main_dirs.nth_data (i);
-            relative_path += cur_main_dir.get_basename () + "/";
-        }
-
-        // add the main file basename
-        relative_path += main_file.get_basename ();
-        return relative_path;
+        return Utils.get_relative_path (origin, target, common_dir);
     }
 
     public string get_name ()
diff --git a/src/documents_panel.vala b/src/documents_panel.vala
index 489d2f2..2152e44 100644
--- a/src/documents_panel.vala
+++ b/src/documents_panel.vala
@@ -65,9 +65,13 @@ public class DocumentsPanel : Notebook
         // automatic clean-up build files
         GLib.Settings settings =
             new GLib.Settings ("org.gnome.latexila.preferences.latex");
+
         if (settings.get_boolean ("no-confirm-clean")
             && settings.get_boolean ("automatic-clean"))
-            tab.document.clean_build_files (main_window);
+        {
+            CleanBuildFiles build_files = new CleanBuildFiles (main_window, tab.document);
+            build_files.clean ();
+        }
 
         int pos = page_num (tab);
         remove_page (pos);
diff --git a/src/file_browser.vala b/src/file_browser.vala
index 71f5166..e2299b3 100644
--- a/src/file_browser.vala
+++ b/src/file_browser.vala
@@ -320,6 +320,7 @@ public class FileBrowser : VBox
                 directory = File.new_for_path (Environment.get_home_dir ());
         }
 
+        // TODO try (haha) to put the minimum code in the try
         try
         {
             FileEnumerator enumerator = directory.enumerate_children (
diff --git a/src/main_window.vala b/src/main_window.vala
index e58c32d..a65c56a 100644
--- a/src/main_window.vala
+++ b/src/main_window.vala
@@ -1701,9 +1701,15 @@ public class MainWindow : Window
     public void on_build_clean ()
     {
         return_if_fail (active_tab != null);
-        if (active_document.clean_build_files (this))
-            file_browser.refresh_if_in_dir (
-                active_document.get_main_file ().get_parent ());
+
+        CleanBuildFiles build_files = new CleanBuildFiles (this, active_document);
+
+        if (build_files.clean ())
+        {
+            File? main_file = active_document.get_main_file ();
+            if (main_file != null)
+                file_browser.refresh_if_in_dir (main_file.get_parent ());
+        }
     }
 
     public void on_build_view_log ()
diff --git a/src/utils.vala b/src/utils.vala
index db18389..078440e 100644
--- a/src/utils.vala
+++ b/src/utils.vala
@@ -280,4 +280,72 @@ namespace Utils
         }
         return escaped;
     }
+
+    // origin can be equal to common_dir, but target must be different
+    public string? get_relative_path (File origin, File target, File common_dir)
+    {
+        File? origin_dir;
+        if (origin.equal (common_dir))
+            origin_dir = origin;
+        else
+            origin_dir = origin.get_parent ();
+
+        File? target_parent = target.get_parent ();
+
+        return_val_if_fail (origin_dir != null, null);
+        return_val_if_fail (target_parent != null, null);
+
+        // The origin is in the same directory as the target.
+        if (target_parent.equal (origin_dir))
+            return target.get_basename ();
+
+        // Get a list of parent directories. Stop at the common dir.
+        List<File> target_dirs = new List<File> ();
+        List<File> origin_dirs = new List<File> ();
+
+        while (target_parent != null && ! target_parent.equal (common_dir))
+        {
+            target_dirs.prepend (target_parent);
+            target_parent = target_parent.get_parent ();
+        }
+
+        while (origin_dir != null && ! origin_dir.equal (common_dir))
+        {
+            origin_dirs.prepend (origin_dir);
+            origin_dir = origin_dir.get_parent ();
+        }
+
+        // Get number of common dirs
+        uint dir_index = 0;
+        while (dir_index < target_dirs.length () && dir_index < origin_dirs.length ())
+        {
+            File cur_target_dir = target_dirs.nth_data (dir_index);
+            File cur_origin_dir = origin_dirs.nth_data (dir_index);
+            if (! cur_target_dir.equal (cur_origin_dir))
+                break;
+
+            dir_index++;
+        }
+
+        uint nb_common_dirs = dir_index;
+
+        /* Build the relative path */
+        string relative_path = "";
+
+        // go to the common dir
+        uint nb_remaining_origin_dirs = origin_dirs.length () - nb_common_dirs;
+        for (uint i = 0 ; i < nb_remaining_origin_dirs ; i++)
+            relative_path += "../";
+
+        // go to the target dir
+        for (uint i = nb_common_dirs ; i < target_dirs.length () ; i++)
+        {
+            File cur_target_dir = target_dirs.nth_data (i);
+            relative_path += cur_target_dir.get_basename () + "/";
+        }
+
+        // add the target basename
+        relative_path += target.get_basename ();
+        return relative_path;
+    }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]