1 /*
2  * Copyright (c) 2002-2007  Daniel Elstner  <daniel.kitta@gmail.com>
3  *
4  * This file is part of regexxer.
5  *
6  * regexxer is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * regexxer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with regexxer; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #ifndef REGEXXER_FILETREE_H_INCLUDED
22 #define REGEXXER_FILETREE_H_INCLUDED
23 
24 #include "filebuffer.h"
25 #include "fileio.h"
26 #include "signalutils.h"
27 #include "undostack.h"
28 
29 #include <gdkmm/color.h>
30 #include <gdkmm/pixbuf.h>
31 #include <gtkmm/treemodel.h>
32 #include <gtkmm/treeview.h>
33 #include <list>
34 
35 namespace Gtk   { class TreeStore; }
36 namespace Glib  { class Regex; }
37 
38 namespace Regexxer
39 {
40 
41 class FileTree : public Gtk::TreeView
42 {
43 public:
44   class Error; // exception class
45 
46   FileTree();
47   virtual ~FileTree();
48 
49   void find_files(const std::string& dirname, const Glib::RefPtr<Glib::Regex>& pattern,
50                   bool recursive, bool hidden);
51 
52   int  get_file_count() const;
53 
54   void save_current_file();
55   void save_all_files();
56 
57   void select_first_file();
58   bool select_next_file(bool move_forward);
59 
60   BoundState get_bound_state();
61 
62   void find_matches(const Glib::RefPtr<Glib::Regex>& pattern, bool multiple);
63   long get_match_count() const;
64   void replace_all_matches(const Glib::ustring& substitution);
65 
66   int get_modified_count() const;
67 
68   sigc::signal<void, FileInfoPtr, int>  signal_switch_buffer;
69   sigc::signal<void>                    signal_bound_state_changed;
70   sigc::signal<void>                    signal_file_count_changed;
71   sigc::signal<void>                    signal_match_count_changed;
72   sigc::signal<void>                    signal_modified_count_changed;
73   sigc::signal<bool>                    signal_pulse;
74   sigc::signal<void, UndoActionPtr>     signal_undo_stack_push;
75 
76   // Provide line number, subject and file info for match location output.
77   sigc::signal<void, int, const Glib::ustring&, FileInfoPtr> signal_feedback;
78 
79 protected:
80   virtual void on_style_updated();
81 
82 private:
83   class  TreeRowRef;
84   class  MessageList;
85   class  ScopedBlockSorting;
86   class  BufferActionShell;
87   struct FindData;
88   struct FindMatchesData;
89   struct ReplaceMatchesData;
90 
91   typedef Util::SharedPtr<TreeRowRef>        TreeRowRefPtr;
92   typedef Util::SharedPtr<BufferActionShell> BufferActionShellPtr;
93 
94   Glib::RefPtr<Gtk::TreeStore>  treestore_;
95 
96   Glib::RefPtr<Gdk::Pixbuf>     pixbuf_directory_;
97   Glib::RefPtr<Gdk::Pixbuf>     pixbuf_file_;
98   Glib::RefPtr<Gdk::Pixbuf>     pixbuf_load_failed_;
99 
100   Gdk::Color                    color_modified_;
101   Gdk::Color                    color_load_failed_;
102 
103   TreeRowRefPtr                 last_selected_rowref_;
104   FileInfoPtr                   last_selected_;
105 
106   DirInfo                       toplevel_;
107   long                          sum_matches_;
108 
109   Util::AutoConnection          conn_match_count_;
110   Util::AutoConnection          conn_modified_changed_;
111   Util::AutoConnection          conn_undo_stack_push_;
112 
113   Gtk::TreeModel::Path          path_match_first_;
114   Gtk::TreeModel::Path          path_match_last_;
115 
116   std::string                   fallback_encoding_;
117 
118   void icon_cell_data_func(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter);
119   void text_cell_data_func(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter);
120 
121   static bool select_func(const Glib::RefPtr<Gtk::TreeModel>& model,
122                           const Gtk::TreeModel::Path& path, bool currently_selected);
123 
124   void find_recursively(const std::string& dirname, FindData& find_data);
125   void find_add_file(const Glib::ustring& basename, const std::string& fullname,
126                      FindData& find_data);
127   void find_fill_dirstack(FindData& find_data);
128   void find_increment_file_count(FindData& find_data, int file_count);
129 
130   bool save_file_at_iter(const Gtk::TreeModel::iterator& iter,
131                          const Util::SharedPtr<MessageList>& error_list);
132 
133   bool find_matches_at_path_iter(const Gtk::TreeModel::Path& path,
134                                  const Gtk::TreeModel::iterator& iter,
135                                  FindMatchesData& find_data);
136 
137   bool replace_matches_at_path_iter(const Gtk::TreeModel::Path& path,
138                                     const Gtk::TreeModel::iterator& iter,
139                                     ReplaceMatchesData& replace_data);
140 
141   void expand_and_select(const Gtk::TreeModel::Path& path);
142 
143   void on_treestore_rows_reordered(const Gtk::TreeModel::Path& path,
144                                    const Gtk::TreeModel::iterator& iter, int* order);
145   void on_selection_changed();
146   void on_buffer_match_count_changed();
147   void on_buffer_modified_changed();
148   void on_buffer_undo_stack_push(UndoActionPtr undo_action);
149 
150   int calculate_file_index(const Gtk::TreeModel::iterator& pos);
151 
152   void propagate_match_count_change(const Gtk::TreeModel::iterator& pos, int difference);
153   void propagate_modified_change(const Gtk::TreeModel::iterator& pos, bool modified);
154 
155   void load_file_with_fallback(const Gtk::TreeModel::iterator& iter, const FileInfoPtr& fileinfo);
156 
157   void on_conf_value_changed(const Glib::ustring& key);
158 };
159 
160 class FileTree::Error
161 {
162 public:
163   explicit Error(const Util::SharedPtr<FileTree::MessageList>& error_list);
164   virtual ~Error();
165 
166   Error(const FileTree::Error& other);
167   FileTree::Error& operator=(const FileTree::Error& other);
168 
169   const std::list<Glib::ustring>& get_error_list() const;
170 
171 private:
172   Util::SharedPtr<FileTree::MessageList> error_list_;
173 };
174 
175 } // namespace Regexxer
176 
177 #endif /* REGEXXER_FILETREE_H_INCLUDED */
178