time_t time;
} Device;
+typedef struct sGuiContext
+{
+ int manager;
+ GtkWidget *list;
+ GtkWidget *button;
+ char *post_mount_command;
+} GuiContext;
+
int verbosity = 0;
-char *post_mount_command = NULL;
/**
Parses a string of the form name=value and places the components in a Property
return 0;
}
+/**
+Callback for selection in the device list changing. Updates the action button
+label according to device status.
+*/
+void selection_changed(GtkTreeSelection *selection, gpointer user_data)
+{
+ GuiContext *context = (GuiContext *)user_data;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ Device *device;
+
+ gtk_tree_selection_get_selected(selection, &model, &iter);
+ gtk_tree_model_get(model, &iter, 1, &device, -1);
+ gtk_button_set_label(GTK_BUTTON(context->button), (device->mount_point ? "Unmount" : "Mount"));
+}
+
/**
Callback for activating a row in the device list. Mounts or unmounts the
device depending on operating mode.
*/
void row_activated(GtkTreeView *list, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
{
+ GuiContext *context = (GuiContext *)user_data;
GtkTreeModel *model;
GtkTreeIter iter;
Device *device;
/* Pmount terminated with nonzero status or a signal. Display an
error to the user. */
dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", output);
- g_signal_connect(dialog, "response", >k_main_quit, NULL);
+ if(context->manager)
+ g_signal_connect(dialog, "response", G_CALLBACK(>k_widget_destroy), dialog);
+ else
+ g_signal_connect(dialog, "response", G_CALLBACK(>k_main_quit), NULL);
gtk_widget_show_all(dialog);
return;
}
- gtk_main_quit();
+ if(context->manager)
+ {
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+ 2, !!device->mount_point,
+ 3, device->mount_point,
+ -1);
+
+ gtk_button_set_label(GTK_BUTTON(context->button), (device->mount_point ? "Unmount" : "Mount"));
+ }
+ else
+ gtk_main_quit();
- if(post_mount_command && device->mount_point)
+ if(context->post_mount_command && device->mount_point)
{
if(verbosity>=1)
- printf("Running %s in %s\n", post_mount_command, device->mount_point);
+ printf("Running %s in %s\n", context->post_mount_command, device->mount_point);
pid = fork();
if(pid==0)
{
chdir(device->mount_point);
- execlp(post_mount_command, post_mount_command, NULL);
+ execlp(context->post_mount_command, context->post_mount_command, NULL);
_exit(1);
}
}
*/
void button_clicked(GtkButton *button, gpointer user_data)
{
- GtkWidget *list = (GtkWidget *)user_data;
+ GuiContext *context = (GuiContext *)user_data;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreePath *path;
+ GtkTreeViewColumn *column;
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(context->list));
gtk_tree_selection_get_selected(selection, &model, &iter);
path = gtk_tree_model_get_path(model, &iter);
- gtk_tree_view_row_activated(GTK_TREE_VIEW(list), path, gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0));
+ column = gtk_tree_view_get_column(GTK_TREE_VIEW(context->list), 0);
+ gtk_tree_view_row_activated(GTK_TREE_VIEW(context->list), path, column);
gtk_tree_path_free(path);
(void)button;
" -v Increase verbosity\n"
" -u Unmount a device (default is mount)\n"
" -r Run a command after mounting\n"
+ " -m Start a persistent mount manager\n"
" -h Display this help\n");
}
int main(int argc, char **argv)
{
+ GuiContext context;
GtkWidget *window;
GtkWidget *box;
GtkWidget *viewport;
- GtkWidget *list;
GtkListStore *store;
GtkTreeSelection *selection;
- GtkWidget *button;
+ GtkCellRenderer *mounted_toggle;
GtkTreeIter iter;
Device *devices;
int i;
int umount = 0;
int n_listed;
+ context.manager = 0;
+ context.post_mount_command = NULL;
+
gtk_init(&argc, &argv);
- while((opt = getopt(argc, argv, "vur:h"))!=-1) switch(opt)
+ while((opt = getopt(argc, argv, "vur:mh"))!=-1) switch(opt)
{
case 'v':
++verbosity;
umount = 1;
break;
case 'r':
- post_mount_command = optarg;
+ context.post_mount_command = optarg;
+ break;
+ case 'm':
+ context.manager = 1;
break;
case 'h':
show_help();
gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_IN);
gtk_box_pack_start(GTK_BOX(box), viewport, TRUE, TRUE, 0);
- list = gtk_tree_view_new();
- gtk_container_add(GTK_CONTAINER(viewport), list);
- g_signal_connect(list, "row-activated", G_CALLBACK(&row_activated), NULL);
+ context.list = gtk_tree_view_new();
+ gtk_container_add(GTK_CONTAINER(viewport), context.list);
+ g_signal_connect(context.list, "row-activated", G_CALLBACK(&row_activated), &context);
- store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
- gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));
- gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(list),
+ store = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_STRING);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(context.list), GTK_TREE_MODEL(store));
+ gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context.list),
-1, "Device", gtk_cell_renderer_text_new(), "text", 0, NULL);
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
+ if(context.manager)
+ {
+ GtkTreeViewColumn *mounted_column;
+ GtkCellRenderer *mount_point_renderer;
+
+ mounted_column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(mounted_column, "Mounted");
+
+ mounted_toggle = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_column_pack_start(mounted_column, mounted_toggle, FALSE);
+ gtk_tree_view_column_add_attribute(mounted_column, mounted_toggle, "active", 2);
+
+ mount_point_renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(mounted_column, mount_point_renderer, TRUE);
+ gtk_tree_view_column_add_attribute(mounted_column, mount_point_renderer, "text", 3);
+
+ gtk_tree_view_insert_column(GTK_TREE_VIEW(context.list), mounted_column, -1);
+ }
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(context.list));
+ g_signal_connect(selection, "changed", G_CALLBACK(&selection_changed), &context);
- button = gtk_button_new_with_label(umount ? "Unmount" : "Mount");
- g_signal_connect(button, "clicked", G_CALLBACK(&button_clicked), list);
- gtk_box_pack_start(GTK_BOX(box), button, FALSE, TRUE, 0);
+ context.button = gtk_button_new_with_label(umount ? "Unmount" : "Mount");
+ g_signal_connect(context.button, "clicked", G_CALLBACK(&button_clicked), &context);
+ gtk_box_pack_start(GTK_BOX(box), context.button, FALSE, TRUE, 0);
devices = get_devices();
n_listed = 0;
/* Populate the list with devices in appropriate state. */
latest = 0;
for(i=0; devices[i].node; ++i)
- if(!devices[i].mount_point==!umount)
+ if(!devices[i].mount_point==!umount || context.manager)
{
gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, devices[i].description, 1, &devices[i], -1);
+ gtk_list_store_set(store, &iter,
+ 0, devices[i].description,
+ 1, &devices[i],
+ 2, !!devices[i].mount_point,
+ 3, devices[i].mount_point,
+ -1);
if(devices[i].time>latest)
{
/* Pre-select the device that appeared on the system most recently. */
}
- if(n_listed)
+ if(n_listed || context.manager)
gtk_widget_show_all(window);
else
{