22
22
public class CustomFileChooserDialog : Object {
23
private static Gtk.FileChooser chooser;
25
private static Gtk.FileChooserDialog d;
23
private static Gtk.FileChooserDialog chooser_dialog;
26
24
private static Gtk.Widget rootwidget;
28
26
private static Gtk.Box container_box;
29
27
private static Gtk.Button? gtk_folder_button = null;
31
29
/* Response to get parent of the bottom box */
32
private const int BUTTON_RESPONSE = -6;
30
private const int BUTTON_RESPONSE = -6;
34
32
/* Paths to widgets */
35
private const string[] GTK_PATHBAR_PATH = { "widget", "browse_widgets_box", "browse_files_box", "browse_header_box" };
33
private const string[] GTK_PATHBAR_PATH = { "widget", "browse_widgets_box", "browse_files_box", "browse_header_revealer" };
36
34
private const string[] GTK_FILTERCHOOSER_PATH = { "extra_and_filters", "filter_combo_hbox" };
37
private const string[] GTK_CREATEFOLDER_BUTTON_PATH = { "browse_header_stack", "browse_path_bar_hbox", "browse_new_folder_button" };
38
35
private const string PLACES_SIDEBAR_PATH = "places_sidebar";
40
private const string FILE_PREFIX = "file://";
42
private GenericArray<string> forward_path_list = new GenericArray<string> ();
43
private Gee.ArrayList<string> history = new Gee.ArrayList<string> ();
45
private static bool filters_available = false;
47
private static string open_path;
48
private string previous_path = "";
50
public CustomFileChooserDialog (Gtk.FileChooserDialog _dialog) {
51
/* The "d" variable is the main dialog */
55
/* Main FileChooser interface */
56
chooser = (d as Gtk.FileChooser);
37
private GLib.Queue<string> previous_paths;
38
private GLib.Queue<string> next_paths;
40
private bool filters_available = false;
42
private string current_path = null;
43
private bool is_previous = false;
44
private bool is_button_next = false;
46
public CustomFileChooserDialog (Gtk.FileChooserDialog dialog) {
47
previous_paths = new GLib.Queue<string> ();
48
next_paths = new GLib.Queue<string> ();
49
/* The "chooser_dialog" variable is the main dialog */
50
chooser_dialog = dialog;
51
chooser_dialog.can_focus = true;
52
chooser_dialog.deletable = false;
59
54
assign_container_box ();
55
remove_gtk_widgets ();
60
56
setup_filter_box ();
61
remove_gtk_widgets ();
63
58
var header_bar = new Gtk.HeaderBar ();
65
60
var button_back = new Gtk.Button.from_icon_name ("go-previous-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
66
61
button_back.tooltip_text = _("Previous");
67
62
button_back.sensitive = false;
69
64
var button_forward = new Gtk.Button.from_icon_name ("go-next-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
70
65
button_forward.tooltip_text = _("Next");
71
66
button_forward.sensitive = false;
73
68
var location_bar = new Marlin.View.Chrome.BasicLocationBar ();
74
location_bar.set_display_path (FILE_PREFIX + chooser.get_current_folder ());
69
location_bar.set_display_path (chooser_dialog.get_current_folder_uri ());
75
70
location_bar.hexpand = true;
77
72
header_bar.pack_start (button_back);
78
73
header_bar.pack_start (button_forward);
79
74
header_bar.pack_start (location_bar);
80
if ((gtk_folder_button != null) && (chooser.get_action () != Gtk.FileChooserAction.OPEN)) {
81
var create_folder_button = new Gtk.Button.from_icon_name ("folder-new", Gtk.IconSize.LARGE_TOOLBAR);
82
create_folder_button.set_tooltip_text (_("Create folder"));
83
create_folder_button.clicked.connect (() => {
84
gtk_folder_button.clicked ();
87
header_bar.pack_end (create_folder_button);
75
if ((gtk_folder_button != null) && (chooser_dialog.get_action () != Gtk.FileChooserAction.OPEN)) {
76
gtk_folder_button.image = new Gtk.Image.from_icon_name ("folder-new", Gtk.IconSize.LARGE_TOOLBAR);
77
((Gtk.Container) gtk_folder_button.get_parent ()).remove (gtk_folder_button);
78
header_bar.pack_end (gtk_folder_button);
90
d.set_titlebar (header_bar);
81
chooser_dialog.set_titlebar (header_bar);
82
chooser_dialog.show_all ();
93
84
button_back.clicked.connect (() => {
94
forward_path_list.add (chooser.get_current_folder ());
96
history.remove (history.last ());
97
chooser.set_current_folder (history.last ());
98
history.remove (history.last ());
86
chooser_dialog.set_current_folder_uri (previous_paths.pop_head ());
101
89
button_forward.clicked.connect (() => {
102
if (forward_path_list.length > 0) {
103
int length = forward_path_list.length - 1;
105
location_bar.set_display_path (FILE_PREFIX + forward_path_list.@get (length));
106
chooser.set_current_folder (forward_path_list.@get (length));
107
forward_path_list.remove (forward_path_list.@get (length));
111
chooser.current_folder_changed.connect (() => {
112
if (history.size > 0)
113
previous_path = history.last ();
114
else if (open_path != chooser.get_current_folder ()) {
116
history.add (open_path);
119
button_back.sensitive = (history.size > 0);
120
button_forward.sensitive = (forward_path_list.length > 0);
122
if (chooser.get_current_folder () != previous_path)
123
history.add (chooser.get_current_folder ());
125
location_bar.set_display_path (FILE_PREFIX + chooser.get_current_folder ());
90
is_button_next = true;
91
chooser_dialog.set_current_folder_uri (next_paths.pop_head ());
94
chooser_dialog.current_folder_changed.connect (() => {
95
var previous_path = current_path;
96
current_path = chooser_dialog.get_current_folder_uri ();
97
if (previous_path == null || previous_path == current_path) {
98
location_bar.set_display_path (current_path);
103
next_paths.push_head (previous_path);
106
previous_paths.push_head (previous_path);
107
if (!is_button_next) {
110
is_button_next = false;
114
button_back.sensitive = !previous_paths.is_empty ();
115
button_forward.sensitive = !next_paths.is_empty ();
116
location_bar.set_display_path (current_path);
128
119
location_bar.path_change_request.connect ((uri) => {
129
chooser.set_current_folder (uri);
120
chooser_dialog.set_current_folder (uri);
133
public void set_open_path (string _open_path) {
134
open_path = _open_path;
135
previous_path = open_path;
136
chooser.set_current_folder (open_path);
125
* Playing with the native Gtk dialog.
139
128
/* Remove GTK's native path bar and FileFilter chooser by widgets names */
140
private static void remove_gtk_widgets () {
141
foreach (var root in d.get_children ()) {
142
foreach (var w0 in (root as Gtk.Container).get_children ()) {
129
private void remove_gtk_widgets () {
130
chooser_dialog.get_children ().foreach ((root) => {
131
(root as Gtk.Container).get_children ().foreach ((w0) => {
143
132
if (w0.get_name () == GTK_PATHBAR_PATH[0]) {
144
133
/* Add top separator between headerbar and filechooser when is not Save action */
145
134
var chooserwidget = w0 as Gtk.Container;
150
139
root_box.add (new Gtk.Separator (Gtk.Orientation.HORIZONTAL));
151
140
root_box.add (chooserwidget);
153
if (chooser.get_extra_widget () == null)
154
root_box.add (new Gtk.Separator (Gtk.Orientation.HORIZONTAL));
142
if (chooser_dialog.get_extra_widget () == null) {
143
root_box.add (new Gtk.Separator (Gtk.Orientation.HORIZONTAL));
156
146
(root as Gtk.Container).add (root_box);
157
147
rootwidget = chooserwidget;
159
149
rootwidget.can_focus = true;
160
150
transform_rootwidget_container (rootwidget, w0);
166
private static void transform_rootwidget_container (Gtk.Widget rootwidget, Gtk.Widget w0) {
167
foreach (var w1 in (rootwidget as Gtk.Container).get_children ()) {
156
private void transform_rootwidget_container (Gtk.Widget rootwidget, Gtk.Widget w0) {
157
(rootwidget as Gtk.Container).get_children ().foreach ((w1) => {
168
158
if (w1.name == "GtkBox" && w1.get_name () != GTK_PATHBAR_PATH[1]) {
169
var new_w1 = w1.@ref ();
170
160
(rootwidget as Gtk.Container).remove (w1);
172
foreach (var grid in (new_w1 as Gtk.Container).get_children ()) {
174
var new_grid = grid.@ref ();
175
(new_grid as Gtk.Widget).margin = 0;
176
(new_w1 as Gtk.Container).remove (grid);
177
container_box.add (new_grid as Gtk.Widget);
162
(w1 as Gtk.Container).get_children ().foreach ((grid) => {
165
grid.valign = Gtk.Align.CENTER;
166
((Gtk.Container) grid).border_width = 0;
167
(w1 as Gtk.Container).remove (grid);
168
container_box.pack_start (grid);
169
((Gtk.ButtonBox) container_box).set_child_secondary (grid, true);
181
174
container_box.show_all ();
182
} else if (w1.get_name () == GTK_PATHBAR_PATH[1])
175
} else if (w1.get_name () == GTK_PATHBAR_PATH[1]) {
183
176
transform_w1_container (w1);
185
178
if (w1.get_name () == GTK_FILTERCHOOSER_PATH[0]) {
186
179
/* Remove extra_and_filters if there is no extra widget */
187
if (chooser.get_extra_widget () == null)
180
if (chooser_dialog.get_extra_widget () == null) {
188
181
(w0 as Gtk.Container).remove (w1);
190
foreach (var w5 in (w1 as Gtk.Container).get_children ()) {
183
(w1 as Gtk.Container).get_children ().foreach ((w5) => {
191
184
if (w5.get_name () == GTK_FILTERCHOOSER_PATH[1])
192
185
(w1 as Gtk.Container).remove (w5);
200
private static void transform_w1_container (Gtk.Widget w1) {
201
foreach (var paned in (w1 as Gtk.Container).get_children ()) {
202
foreach (var w2 in (paned as Gtk.Container).get_children ()) {
203
if (w2.get_name () == PLACES_SIDEBAR_PATH) {
193
private void transform_w1_container (Gtk.Widget w1) {
194
(w1 as Gtk.Container).get_children ().foreach ((paned) => {
195
(paned as Gtk.Container).get_children ().foreach ((w2) => {
196
if (w2 is Gtk.PlacesSidebar) {
204
197
(w2 as Gtk.PlacesSidebar).show_desktop = false;
205
198
(w2 as Gtk.PlacesSidebar).show_enter_location = false;
206
} else if (w2.get_name () == GTK_PATHBAR_PATH[2])
207
transform_w2_container (w2);
200
transform_w2_container (w2);
212
private static void transform_w2_container (Gtk.Widget w2) {
213
foreach (var w3 in (w2 as Gtk.Container).get_children ()) {
206
private void transform_w2_container (Gtk.Widget w2) {
207
(w2 as Gtk.Container).get_children ().foreach ((w3) => {
214
208
if (w3.get_name () == GTK_PATHBAR_PATH[3]) {
215
foreach (var w4 in (w3 as Gtk.Container).get_children ()) {
216
if (w4.get_name () == GTK_CREATEFOLDER_BUTTON_PATH[0]) {
217
foreach (var w5 in (w4 as Gtk.Container).get_children ()) {
218
if (w5.get_name () == GTK_CREATEFOLDER_BUTTON_PATH[1]) {
219
foreach (var w6 in (w5 as Gtk.Container).get_children ()) {
220
if (w6.get_name () == GTK_CREATEFOLDER_BUTTON_PATH[2])
209
(w3 as Gtk.Container).get_children ().foreach ((w4) => {
210
(w4 as Gtk.Container).get_children ().foreach ((w5) => {
211
(w5 as Gtk.Container).get_children ().foreach ((w6) => {
213
(w6 as Gtk.Container).get_children ().foreach ((w7) => {
214
if (w7 is Gtk.Button) {
221
215
/* Register the button so we can use it's signal */
222
gtk_folder_button = w6.@ref () as Gtk.Button;
216
gtk_folder_button = w7 as Gtk.Button;
229
224
(w2 as Gtk.Container).remove (w3);
234
private static void assign_container_box () {
235
var tmp = d.get_widget_for_response (BUTTON_RESPONSE);
237
var container = tmp.get_parent ();
238
container_box = container.get_parent () as Gtk.Box;
241
private static void setup_filter_box () {
242
var filters = chooser.list_filters ();
243
var current_filter_name = chooser.get_filter ().get_filter_name ();
229
private void assign_container_box () {
230
container_box = chooser_dialog.get_action_area () as Gtk.Box;
231
container_box.valign = Gtk.Align.CENTER;
232
container_box.get_children ().foreach ((child) => {
233
child.valign = Gtk.Align.CENTER;
237
private void setup_filter_box () {
238
var filters = chooser_dialog.list_filters ();
239
var current_filter_name = chooser_dialog.get_filter ().get_filter_name ();
245
241
if (filters.length () > 0) {
246
242
filters_available = true;
247
243
var combo_box = new Gtk.ComboBoxText ();
249
if (chooser.get_action () == Gtk.FileChooserAction.SAVE)
250
combo_box.margin_top = 8;
252
combo_box.margin_top = 4;
254
244
combo_box.changed.connect (() => {
255
chooser.list_filters ().@foreach ((filter) => {
245
chooser_dialog.list_filters ().foreach ((filter) => {
256
246
if (filter.get_filter_name () == combo_box.get_active_text ())
257
chooser.set_filter (filter);
247
chooser_dialog.set_filter (filter);