void View::prepareFileMenu(Fm::FileMenu* menu) { Application* app = static_cast<Application*>(qApp); menu->setConfirmDelete(app->settings().confirmDelete()); menu->setConfirmTrash(app->settings().confirmTrash()); menu->setUseTrash(app->settings().useTrash()); // add some more menu items for dirs bool all_native = true; bool all_directory = true; FmFileInfoList* files = menu->files(); for(GList* l = fm_file_info_list_peek_head_link(files); l; l = l->next) { FmFileInfo* fi = FM_FILE_INFO(l->data); if(!fm_file_info_is_dir(fi)) all_directory = false; else if(fm_file_info_is_dir(fi) && !fm_file_info_is_native(fi)) all_native = false; } if (all_directory) { QAction* action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New T&ab"), menu); connect(action, &QAction::triggered, this, &View::onNewTab); menu->insertAction(menu->separator1(), action); action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New Win&dow"), menu); connect(action, &QAction::triggered, this, &View::onNewWindow); menu->insertAction(menu->separator1(), action); // TODO: add search // action = menu->addAction(_("Search")); if(all_native) { action = new QAction(QIcon::fromTheme("utilities-terminal"), tr("Open in Termina&l"), menu); connect(action, &QAction::triggered, this, &View::onOpenInTerminal); menu->insertAction(menu->separator1(), action); } } else { if(menu->pasteAction()) // NULL for trash menu->pasteAction()->setVisible(false); if(menu->createAction()) menu->createAction()->setVisible(false); } }
static gpointer _dentry_ui_init(GtkBuilder *ui, gpointer uidata, FmFileInfoList *files) { GObject *widget; GtkWidget *new_widget; FmFilePropertiesDEntryData *data; GtkTable *table; GtkLabel *label; GError *err = NULL; FmFileInfo *fi; GFile *gf; gchar *txt; gsize length; const gchar * const *langs; gboolean tmp_bool; /* disable permissions tab and open_with in any case */ #define HIDE_WIDGET(x) widget = gtk_builder_get_object(ui, x); \ gtk_widget_hide(GTK_WIDGET(widget)) /* HIDE_WIDGET("permissions_tab"); TODO: made visibility of permissions_tab configurable */ table = GTK_TABLE(gtk_builder_get_object(ui, "general_table")); HIDE_WIDGET("open_with"); HIDE_WIDGET("open_with_label"); gtk_table_set_row_spacing(table, 5, 0); /* we will do the thing only for single file! */ if (fm_file_info_list_get_length(files) != 1) return NULL; fi = fm_file_info_list_peek_head(files); gf = fm_path_to_gfile(fm_file_info_get_path(fi)); if (!g_file_load_contents(gf, NULL, &txt, &length, NULL, NULL)) { g_warning("file properties dialog: cannot access desktop entry file"); g_object_unref(gf); return NULL; } data = g_slice_new(FmFilePropertiesDEntryData); data->changed = FALSE; data->file = gf; data->kf = g_key_file_new(); g_key_file_load_from_data(data->kf, txt, length, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, NULL); g_free(txt); /* FIXME: handle errors, also do g_key_file_has_group() */ /* get locale name */ data->lang = NULL; langs = g_get_language_names(); if (strcmp(langs[0], "C") != 0) { /* remove encoding from locale name */ char *sep = strchr(langs[0], '.'); if (sep) data->lang = g_strndup(langs[0], sep - langs[0]); else data->lang = g_strdup(langs[0]); } /* enable events for icon */ widget = gtk_builder_get_object(ui, "icon_eventbox"); data->icon = gtk_builder_get_object(ui, "icon"); gtk_widget_set_can_focus(GTK_WIDGET(widget), TRUE); /* disable Name event handler in the widget */ widget = gtk_builder_get_object(ui, "name"); g_signal_handlers_block_matched(widget, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, uidata); g_signal_connect(widget, "changed", G_CALLBACK(_dentry_name_changed), data); data->name = GTK_ENTRY(widget); data->saved_name = g_strdup(gtk_entry_get_text(data->name)); /* FIXME: two lines below is temporary workaround on FIXME in widget */ gtk_widget_set_can_focus(GTK_WIDGET(widget), TRUE); gtk_editable_set_editable(GTK_EDITABLE(widget), TRUE); /* Name is set from "Name" by libfm already so don't touch it */ /* support 'hidden' option */ data->hidden = NULL; widget = gtk_builder_get_object(ui, "hidden"); if (widget && GTK_IS_TOGGLE_BUTTON(widget) && fm_file_info_is_native(fi)) { data->hidden = (GtkToggleButton*)widget; data->was_hidden = fm_file_info_is_hidden(fi); g_signal_connect(widget, "toggled", G_CALLBACK(_dentry_hidden_toggled), data); gtk_widget_set_can_focus(GTK_WIDGET(data->hidden), TRUE); /* set sensitive since it can be toggled for desktop entry */ gtk_widget_set_sensitive(GTK_WIDGET(widget), TRUE); gtk_widget_show(GTK_WIDGET(data->hidden)); } #undef HIDE_WIDGET /* FIXME: migrate to GtkGrid */ table = GTK_TABLE(gtk_table_new(8, 2, FALSE)); gtk_table_set_row_spacings(table, 4); gtk_table_set_col_spacings(table, 12); gtk_container_set_border_width(GTK_CONTAINER(table), 4); /* row 0: "Exec" GtkHBox: GtkEntry+GtkButton */ new_widget = gtk_label_new(NULL); label = GTK_LABEL(new_widget); gtk_misc_set_alignment(GTK_MISC(new_widget), 0.0, 0.0); gtk_label_set_markup_with_mnemonic(label, _("<b>Co_mmand:</b>")); gtk_table_attach(table, new_widget, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); #if GTK_CHECK_VERSION(3, 2, 0) /* FIXME: migrate to GtkGrid */ widget = G_OBJECT(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6)); #else widget = G_OBJECT(gtk_hbox_new(FALSE, 6)); #endif new_widget = gtk_button_new_with_mnemonic(_("_Browse...")); gtk_box_pack_end(GTK_BOX(widget), new_widget, FALSE, FALSE, 0); g_signal_connect(new_widget, "clicked", G_CALLBACK(_dentry_browse_exec_event), data); new_widget = gtk_entry_new(); data->exec = GTK_ENTRY(new_widget); txt = g_key_file_get_locale_string(data->kf, GRP_NAME, "Exec", NULL, NULL); if (txt) { gtk_entry_set_text(data->exec, txt); g_free(txt); } gtk_widget_set_tooltip_text(new_widget, _("Command to execute when the application icon is activated")); gtk_box_pack_start(GTK_BOX(widget), new_widget, TRUE, TRUE, 0); g_signal_connect(new_widget, "changed", G_CALLBACK(_dentry_exec_changed), data); gtk_table_attach(table, GTK_WIDGET(widget), 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0); gtk_label_set_mnemonic_widget(label, new_widget); /* row 1: "Terminal" GtkCheckButton */ new_widget = gtk_check_button_new_with_mnemonic(_("_Execute in terminal emulator")); data->terminal = GTK_TOGGLE_BUTTON(new_widget); tmp_bool = g_key_file_get_boolean(data->kf, GRP_NAME, "Terminal", &err); if (err) /* no such key present */ { tmp_bool = FALSE; g_clear_error(&err); } gtk_toggle_button_set_active(data->terminal, tmp_bool); g_signal_connect(new_widget, "toggled", G_CALLBACK(_dentry_terminal_toggled), data); gtk_table_attach(table, new_widget, 0, 2, 1, 2, GTK_FILL, 0, 18, 0); /* row 2: "X-KeepTerminal" GtkCheckButton */ new_widget = gtk_check_button_new_with_mnemonic(_("_Keep terminal window open after command execution")); data->keep_open = GTK_TOGGLE_BUTTON(new_widget); gtk_widget_set_sensitive(new_widget, tmp_bool); /* disable if not in terminal */ tmp_bool = g_key_file_get_boolean(data->kf, GRP_NAME, "X-KeepTerminal", &err); if (err) /* no such key present */ { tmp_bool = FALSE; g_clear_error(&err); } gtk_toggle_button_set_active(data->keep_open, tmp_bool); g_signal_connect(new_widget, "toggled", G_CALLBACK(_dentry_keepterm_toggled), data); gtk_table_attach(table, new_widget, 0, 2, 2, 3, GTK_FILL, 0, 27, 0); /* row 4: "GenericName" GtkEntry */ new_widget = gtk_label_new(NULL); label = GTK_LABEL(new_widget); gtk_misc_set_alignment(GTK_MISC(new_widget), 0.0, 0.0); gtk_label_set_markup_with_mnemonic(label, _("<b>D_escription:</b>")); gtk_table_attach(table, new_widget, 0, 1, 4, 5, GTK_FILL, 0, 0, 0); new_widget = gtk_entry_new(); data->generic_name = GTK_ENTRY(new_widget); txt = g_key_file_get_locale_string(data->kf, GRP_NAME, "GenericName", NULL, NULL); if (txt) { gtk_entry_set_text(data->generic_name, txt); g_free(txt); } gtk_widget_set_tooltip_text(new_widget, _("Generic name of the application")); g_signal_connect(new_widget, "changed", G_CALLBACK(_dentry_genname_changed), data); gtk_table_attach(table, new_widget, 1, 2, 4, 5, GTK_FILL|GTK_EXPAND, 0, 0, 0); gtk_label_set_mnemonic_widget(label, new_widget); /* row 3: "Path" GtkEntry */ new_widget = gtk_label_new(NULL); label = GTK_LABEL(new_widget); gtk_misc_set_alignment(GTK_MISC(new_widget), 0.0, 0.0); gtk_label_set_markup_with_mnemonic(label, _("<b>_Working directory:</b>")); gtk_table_attach(table, new_widget, 0, 1, 3, 4, GTK_FILL, 0, 0, 0); new_widget = gtk_entry_new(); data->path = GTK_ENTRY(new_widget); txt = g_key_file_get_locale_string(data->kf, GRP_NAME, "Path", NULL, NULL); if (txt) { gtk_entry_set_text(data->path, txt); g_free(txt); } gtk_widget_set_tooltip_text(new_widget, _("The working directory to run the program in")); g_signal_connect(new_widget, "changed", G_CALLBACK(_dentry_path_changed), data); gtk_table_attach(table, new_widget, 1, 2, 3, 4, GTK_FILL|GTK_EXPAND, 0, 0, 0); gtk_label_set_mnemonic_widget(label, new_widget); /* row 5: "Comment" GtkEntry */ new_widget = gtk_label_new(NULL); label = GTK_LABEL(new_widget); gtk_misc_set_alignment(GTK_MISC(new_widget), 0.0, 0.0); gtk_label_set_markup_with_mnemonic(label, _("<b>_Tooltip:</b>")); gtk_table_attach(table, new_widget, 0, 1, 5, 6, GTK_FILL, 0, 0, 0); new_widget = gtk_entry_new(); data->comment = GTK_ENTRY(new_widget); txt = g_key_file_get_locale_string(data->kf, GRP_NAME, "Comment", NULL, NULL); if (txt) { gtk_entry_set_text(data->comment, txt); g_free(txt); } gtk_widget_set_tooltip_text(new_widget, _("Tooltip to show on application")); g_signal_connect(new_widget, "changed", G_CALLBACK(_dentry_tooltip_changed), data); gtk_table_attach(table, new_widget, 1, 2, 5, 6, GTK_FILL|GTK_EXPAND, 0, 0, 0); gtk_label_set_mnemonic_widget(label, new_widget); /* TODO: handle "TryExec" field ? */ /* row 7: "StartupNotify" GtkCheckButton */ new_widget = gtk_check_button_new_with_mnemonic(_("_Use startup notification")); data->notification = GTK_TOGGLE_BUTTON(new_widget); tmp_bool = g_key_file_get_boolean(data->kf, GRP_NAME, "StartupNotify", &err); if (err) /* no such key present */ { tmp_bool = FALSE; g_clear_error(&err); } gtk_toggle_button_set_active(data->notification, tmp_bool); g_signal_connect(new_widget, "toggled", G_CALLBACK(_dentry_notification_toggled), data); gtk_table_attach(table, new_widget, 0, 2, 7, 8, GTK_FILL, 0, 0, 0); /* put the table into third tab and enable it */ widget = gtk_builder_get_object(ui, "extra_tab_label"); gtk_label_set_markup_with_mnemonic(GTK_LABEL(widget), _("_Desktop Entry")); widget = gtk_builder_get_object(ui, "extra_tab"); gtk_container_add(GTK_CONTAINER(widget), GTK_WIDGET(table)); gtk_widget_show_all(GTK_WIDGET(widget)); return data; }
void FilePropsDialog::initPermissionsPage() { // ownership handling // get owner/group and mode of the first file in the list uid = fm_file_info_get_uid(fileInfo); gid = fm_file_info_get_gid(fileInfo); mode_t mode = fm_file_info_get_mode(fileInfo); ownerPerm = (mode & (S_IRUSR|S_IWUSR|S_IXUSR)); groupPerm = (mode & (S_IRGRP|S_IWGRP|S_IXGRP)); otherPerm = (mode & (S_IROTH|S_IWOTH|S_IXOTH)); execPerm = (mode & (S_IXUSR|S_IXGRP|S_IXOTH)); allNative = fm_file_info_is_native(fileInfo); hasDir = S_ISDIR(mode); // check if all selected files belongs to the same owner/group or have the same mode // at the same time, check if all files are on native unix filesystems GList* l; for(l = fm_file_info_list_peek_head_link(fileInfos_)->next; l; l = l->next) { FmFileInfo* fi = FM_FILE_INFO(l->data); if(allNative && !fm_file_info_is_native(fi)) allNative = false; // not all of the files are native mode_t fi_mode = fm_file_info_get_mode(fi); if(S_ISDIR(fi_mode)) hasDir = true; // the files list contains dir(s) if(uid != DIFFERENT_UIDS && uid != fm_file_info_get_uid(fi)) uid = DIFFERENT_UIDS; // not all files have the same owner if(gid != DIFFERENT_GIDS && gid != fm_file_info_get_gid(fi)) gid = DIFFERENT_GIDS; // not all files have the same owner group if(ownerPerm != DIFFERENT_PERMS && ownerPerm != (fi_mode & (S_IRUSR|S_IWUSR|S_IXUSR))) ownerPerm = DIFFERENT_PERMS; // not all files have the same permission for owner if(groupPerm != DIFFERENT_PERMS && groupPerm != (fi_mode & (S_IRGRP|S_IWGRP|S_IXGRP))) groupPerm = DIFFERENT_PERMS; // not all files have the same permission for grop if(otherPerm != DIFFERENT_PERMS && otherPerm != (fi_mode & (S_IROTH|S_IWOTH|S_IXOTH))) otherPerm = DIFFERENT_PERMS; // not all files have the same permission for other if(execPerm != DIFFERENT_PERMS && execPerm != (fi_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) execPerm = DIFFERENT_PERMS; // not all files have the same executable permission } // init owner/group initOwner(); // if all files are of the same type, and some of them are dirs => all of the items are dirs // rwx values have different meanings for dirs // Let's make it clear for the users // init combo boxes for file permissions here QStringList comboItems; comboItems.append("---"); // no change if(singleType && hasDir) { // all files are dirs comboItems.append(tr("View folder content")); comboItems.append(tr("View and modify folder content")); ui->executable->hide(); } else { //not all of the files are dirs comboItems.append(tr("Read")); comboItems.append(tr("Read and write")); } comboItems.append(tr("Forbidden")); QStringListModel* comboModel = new QStringListModel(comboItems, this); ui->ownerPerm->setModel(comboModel); ui->groupPerm->setModel(comboModel); ui->otherPerm->setModel(comboModel); // owner ownerPermSel = ACCESS_NO_CHANGE; if(ownerPerm != DIFFERENT_PERMS) { // permissions for owner are the same among all files if(ownerPerm & S_IRUSR) { // can read if(ownerPerm & S_IWUSR) // can write ownerPermSel = ACCESS_READ_WRITE; else ownerPermSel = ACCESS_READ_ONLY; } else { if((ownerPerm & S_IWUSR) == 0) // cannot read or write ownerPermSel = ACCESS_FORBID; } } ui->ownerPerm->setCurrentIndex(ownerPermSel); // owner and group groupPermSel = ACCESS_NO_CHANGE; if(groupPerm != DIFFERENT_PERMS) { // permissions for owner are the same among all files if(groupPerm & S_IRGRP) { // can read if(groupPerm & S_IWGRP) // can write groupPermSel = ACCESS_READ_WRITE; else groupPermSel = ACCESS_READ_ONLY; } else { if((groupPerm & S_IWGRP) == 0) // cannot read or write groupPermSel = ACCESS_FORBID; } } ui->groupPerm->setCurrentIndex(groupPermSel); // other otherPermSel = ACCESS_NO_CHANGE; if(otherPerm != DIFFERENT_PERMS) { // permissions for owner are the same among all files if(otherPerm & S_IROTH) { // can read if(otherPerm & S_IWOTH) // can write otherPermSel = ACCESS_READ_WRITE; else otherPermSel = ACCESS_READ_ONLY; } else { if((otherPerm & S_IWOTH) == 0) // cannot read or write otherPermSel = ACCESS_FORBID; } } ui->otherPerm->setCurrentIndex(otherPermSel); // set the checkbox to partially checked state // when owner, group, and other have different executable flags set. // some of them have exec, and others do not have. execCheckState = Qt::PartiallyChecked; if(execPerm != DIFFERENT_PERMS) { // if all files have the same executable permission // check if the files are all executable if((mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == (S_IXUSR|S_IXGRP|S_IXOTH)) { // owner, group, and other all have exec permission. ui->executable->setTristate(false); execCheckState = Qt::Checked; } else if((mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) { // owner, group, and other all have no exec permission ui->executable->setTristate(false); execCheckState = Qt::Unchecked; } } ui->executable->setCheckState(execCheckState); }