1 /******************************* LICENCE **************************************
2 * Any code in this file may be redistributed or modified under the terms of
3 * the GNU General Public Licence as published by the Free Software
4 * Foundation; version 2 of the licence.
5 ****************************** END LICENCE ***********************************/
6
7 /******************************************************************************
8 * Author:
9 * Andrew Smith, http://littlesvr.ca/misc/contactandrew.php
10 *
11 * Contributors:
12 *
13 ******************************************************************************/
14
15 #include <gtk/gtk.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <libintl.h>
19
20 #include "isomaster.h"
21
22 /* this file has thigs shared by the fs and the iso browser */
23
24 /* menu-sized pixbufs of a directory and a file */
25 GdkPixbuf* GBLdirPixbuf;
26 GdkPixbuf* GBLfilePixbuf;
27 //~ GdkPixbuf* GBLsymlinkPixbuf;
28
29 /* text box for showing the path and name of the current directory on the fs */
30 GtkWidget* GBLfsCurrentDirField;
31 /* the view used for the contents of the fs browser */
32 GtkWidget* GBLfsTreeView;
33 /* the list store used for the contents of the fs browser */
34 GtkListStore* GBLfsListStore;
35 /* slash-terminated, the dir being displayed in the fs browser */
36 char* GBLfsCurrentDir = NULL;
37
38 /* text box for showing the path and name of the current directory on the iso */
39 GtkWidget* GBLisoCurrentDirField;
40 /* the view used for the contents of the fs browser */
41 GtkWidget* GBLisoTreeView;
42 /* the list store used for the contents of the fs browser */
43 GtkListStore* GBLisoListStore;
44 /* slash-terminated, the dir being displayed in the iso browser */
45 char* GBLisoCurrentDir = NULL;
46
47 extern GtkWidget* GBLmainWindow;
48 extern VolInfo GBLvolInfo;
49 extern bool GBLisoPaneActive;
50 extern AppSettings GBLappSettings;
51
52 /* connected to the activate signal of a text entry in a dialog */
acceptDialogCbk(GtkEntry * entry,GtkDialog * dialog)53 void acceptDialogCbk(GtkEntry *entry, GtkDialog* dialog)
54 {
55 gtk_dialog_response(dialog, GTK_RESPONSE_ACCEPT);
56 }
57
createDirCbk(GtkButton * button,gpointer onFs)58 void createDirCbk(GtkButton *button, gpointer onFs)
59 {
60 GtkWidget* dialog;
61 GtkWidget* warningDialog;
62 int response;
63 GtkWidget* textEntry;
64 const char* newDirName;
65 int rc;
66
67 if(!onFs && !GBLisoPaneActive)
68 /* asked to create dir on iso but no iso is open */
69 return;
70
71 dialog = gtk_dialog_new_with_buttons(_("Enter name for new directory"),
72 GTK_WINDOW(GBLmainWindow),
73 GTK_DIALOG_DESTROY_WITH_PARENT,
74 GTK_STOCK_OK,
75 GTK_RESPONSE_ACCEPT,
76 GTK_STOCK_CANCEL,
77 GTK_RESPONSE_REJECT,
78 NULL);
79
80 textEntry = gtk_entry_new();
81 gtk_entry_set_width_chars(GTK_ENTRY(textEntry), 40);
82 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), textEntry);
83 gtk_widget_show(textEntry);
84 g_signal_connect(textEntry, "activate", (GCallback)acceptDialogCbk, dialog);
85 g_signal_connect(dialog, "close", G_CALLBACK(rejectDialogCbk), NULL);
86
87 response = gtk_dialog_run(GTK_DIALOG(dialog));
88
89 if(response == GTK_RESPONSE_ACCEPT)
90 {
91 newDirName = gtk_entry_get_text(GTK_ENTRY(textEntry));
92
93 if(onFs)
94 {
95 char* pathAndName;
96
97 pathAndName = malloc(strlen(GBLfsCurrentDir) + strlen(newDirName) + 1);
98 if(pathAndName == NULL)
99 fatalError("createDirCbk(): malloc(strlen(GBLfsCurrentDir) + "
100 "strlen(newDirName) + 1) failed");
101
102 strcpy(pathAndName, GBLfsCurrentDir);
103 strcat(pathAndName, newDirName);
104
105 rc = mkdir(pathAndName, 0755);
106 if(rc == -1)
107 {
108 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
109 GTK_DIALOG_DESTROY_WITH_PARENT,
110 GTK_MESSAGE_ERROR,
111 GTK_BUTTONS_CLOSE,
112 _("Failed to create directory %s"),
113 pathAndName);
114 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
115 gtk_dialog_run(GTK_DIALOG(warningDialog));
116 gtk_widget_destroy(warningDialog);
117 gtk_widget_destroy(dialog);
118 return;
119 }
120
121 free(pathAndName);
122
123 refreshFsView();
124 }
125 else
126 /* on iso */
127 {
128 rc = bk_create_dir(&GBLvolInfo, GBLisoCurrentDir, newDirName);
129 if(rc <= 0)
130 {
131 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
132 GTK_DIALOG_DESTROY_WITH_PARENT,
133 GTK_MESSAGE_ERROR,
134 GTK_BUTTONS_CLOSE,
135 _("Failed to create directory %s: '%s'"),
136 newDirName,
137 bk_get_error_string(rc));
138 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
139 gtk_dialog_run(GTK_DIALOG(warningDialog));
140 gtk_widget_destroy(warningDialog);
141 gtk_widget_destroy(dialog);
142 return;
143 }
144
145 refreshIsoView();
146 }
147 fflush(NULL);
148 }
149
150 gtk_widget_destroy(dialog);
151 }
152
formatSize(bk_off_t sizeInt,char * sizeStr,int sizeStrLen)153 void formatSize(bk_off_t sizeInt, char* sizeStr, int sizeStrLen)
154 {
155 if(sizeInt > 1073741824)
156 /* print gibibytes */
157 snprintf(sizeStr, sizeStrLen, "%.1f GB", (double)sizeInt / 1073741824);
158 else if(sizeInt > 1048576)
159 /* print mebibytes */
160 snprintf(sizeStr, sizeStrLen, "%.1f MB", (double)sizeInt / 1048576);
161 else if(sizeInt > 1024)
162 /* print kibibytes */
163 snprintf(sizeStr, sizeStrLen, "%.1f KB", (double)sizeInt / 1024);
164 else
165 /* print bytes */
166 snprintf(sizeStr, sizeStrLen, "%llu B", (long long unsigned)sizeInt);
167
168 sizeStr[sizeStrLen - 1] = '\0';
169 }
170
refreshBothViewsCbk(GtkWidget * widget,GdkEvent * event)171 void refreshBothViewsCbk(GtkWidget *widget, GdkEvent *event)
172 {
173 refreshFsView();
174 if(GBLisoPaneActive)
175 refreshIsoView();
176 }
177
178 /* formats the file size text for displaying */
sizeCellDataFunc32(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)179 void sizeCellDataFunc32(GtkTreeViewColumn *col, GtkCellRenderer *renderer,
180 GtkTreeModel *model, GtkTreeIter *iter,
181 gpointer data)
182 {
183 unsigned sizeInt;
184 unsigned long long sizeLlInt;
185 int fileType;
186 char sizeStr[20];
187
188 gtk_tree_model_get(model, iter, COLUMN_SIZE, &sizeInt,
189 COLUMN_HIDDEN_TYPE, &fileType, -1);
190
191 sizeLlInt = sizeInt;
192
193 if(fileType == FILE_TYPE_DIRECTORY)
194 {
195 snprintf(sizeStr, sizeof(sizeStr), "dir");
196 sizeStr[sizeof(sizeStr) - 1] = '\0';
197 }
198 else if(fileType == FILE_TYPE_SYMLINK)
199 {
200 snprintf(sizeStr, sizeof(sizeStr), "link");
201 sizeStr[sizeof(sizeStr) - 1] = '\0';
202 }
203 else
204 formatSize(sizeLlInt, sizeStr, sizeof(sizeStr));
205
206 g_object_set(renderer, "text", sizeStr, NULL);
207 }
208
209 /* formats the file size text for displaying */
sizeCellDataFunc64(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)210 void sizeCellDataFunc64(GtkTreeViewColumn *col, GtkCellRenderer *renderer,
211 GtkTreeModel *model, GtkTreeIter *iter,
212 gpointer data)
213 {
214 unsigned long long sizeInt;
215 int fileType;
216 char sizeStr[20];
217
218 gtk_tree_model_get(model, iter, COLUMN_SIZE, &sizeInt,
219 COLUMN_HIDDEN_TYPE, &fileType, -1);
220
221 if(fileType == FILE_TYPE_DIRECTORY)
222 {
223 snprintf(sizeStr, sizeof(sizeStr), "dir");
224 sizeStr[sizeof(sizeStr) - 1] = '\0';
225 }
226 else if(fileType == FILE_TYPE_SYMLINK)
227 {
228 snprintf(sizeStr, sizeof(sizeStr), "link");
229 sizeStr[sizeof(sizeStr) - 1] = '\0';
230 }
231 else
232 formatSize(sizeInt, sizeStr, sizeof(sizeStr));
233
234 g_object_set(renderer, "text", sizeStr, NULL);
235 }
236
sortByName(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)237 gint sortByName(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
238 {
239 if(GBLappSettings.sortDirectoriesFirst)
240 /* directories before files */
241 {
242 int aFileType;
243 int bFileType;
244 gint unused;
245 GtkSortType order;
246
247 gtk_tree_model_get(model, a, COLUMN_HIDDEN_TYPE, &aFileType, -1);
248 gtk_tree_model_get(model, b, COLUMN_HIDDEN_TYPE, &bFileType, -1);
249
250 /* have to make sure directories come first regardless of sort order,
251 * that's why all the fancyness in the rest of this block */
252 gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model), &unused, &order);
253
254 if(aFileType == FILE_TYPE_DIRECTORY && bFileType != FILE_TYPE_DIRECTORY)
255 {
256 if(order == GTK_SORT_ASCENDING)
257 return -1;
258 else
259 return 1;
260 }
261 else if(aFileType != FILE_TYPE_DIRECTORY && bFileType == FILE_TYPE_DIRECTORY)
262 {
263 if(order == GTK_SORT_ASCENDING)
264 return 1;
265 else
266 return -1;
267 }
268 }
269
270 char* aName;
271 char* bName;
272 gint toReturn;
273
274 gtk_tree_model_get(model, a, COLUMN_FILENAME, &aName, -1);
275 gtk_tree_model_get(model, b, COLUMN_FILENAME, &bName, -1);
276
277 if(GBLappSettings.caseSensitiveSort)
278 toReturn = strcmp(aName, bName);
279 else
280 toReturn = strcasecmp(aName, bName);
281
282 g_free(aName);
283 g_free(bName);
284
285 return toReturn;
286 }
287
sortBySize(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)288 gint sortBySize(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
289 {
290 if(GBLappSettings.sortDirectoriesFirst)
291 /* directories before files */
292 {
293 int aFileType;
294 int bFileType;
295 gint unused;
296 GtkSortType order;
297
298 gtk_tree_model_get(model, a, COLUMN_HIDDEN_TYPE, &aFileType, -1);
299 gtk_tree_model_get(model, b, COLUMN_HIDDEN_TYPE, &bFileType, -1);
300
301 /* have to make sure directories come first regardless of sort order,
302 * that's why all the fancyness below */
303 gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model), &unused, &order);
304
305 if(aFileType == FILE_TYPE_DIRECTORY && bFileType != FILE_TYPE_DIRECTORY)
306 {
307 if(order == GTK_SORT_ASCENDING)
308 return -1;
309 else
310 return 1;
311 }
312 else if(aFileType != FILE_TYPE_DIRECTORY && bFileType == FILE_TYPE_DIRECTORY)
313 {
314 if(order == GTK_SORT_ASCENDING)
315 return 1;
316 else
317 return -1;
318 }
319 }
320
321 guint64 aSize;
322 guint64 bSize;
323
324 gtk_tree_model_get(model, a, COLUMN_SIZE, &aSize, -1);
325 gtk_tree_model_get(model, b, COLUMN_SIZE, &bSize, -1);
326
327 if(aSize < bSize)
328 return -1;
329 else
330 return 1;
331 }
332
333 /* this function exists to deal with the gtk stupidity that sorting can't be disabled */
sortVoid(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)334 gint sortVoid(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
335 {
336 return 0;
337 }
338