bool Launcher::openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err) { GList* l = folder_infos; FmFileInfo* fi = FM_FILE_INFO(l->data); Application* app = static_cast<Application*>(qApp); MainWindow* mainWindow = mainWindow_; Fm::FilePath path{fm_path_to_gfile(fm_file_info_get_path(fi)), false}; if(!mainWindow) { mainWindow = new MainWindow(std::move(path)); mainWindow->resize(app->settings().windowWidth(), app->settings().windowHeight()); if(app->settings().windowMaximized()) { mainWindow->setWindowState(mainWindow->windowState() | Qt::WindowMaximized); } } else { mainWindow->chdir(std::move(path)); } l = l->next; for(; l; l = l->next) { fi = FM_FILE_INFO(l->data); path = Fm::FilePath{fm_path_to_gfile(fm_file_info_get_path(fi)), false}; mainWindow->addTab(std::move(path)); } mainWindow->show(); mainWindow->raise(); return true; }
static void on_file_info_job_finished(FmFileInfoJob* job, gpointer user_data) { FmPlacesModel* model = FM_PLACES_MODEL(user_data); GList* l; GtkTreeIter it; FmPlaceItem* item; FmFileInfo* fi; /* g_debug("file info job finished"); */ model->jobs = g_slist_remove(model->jobs, job); if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &it)) return; if(fm_list_is_empty(job->file_infos)) return; /* optimize for one file case */ if(fm_list_get_length(job->file_infos) == 1) { fi = FM_FILE_INFO(fm_list_peek_head(job->file_infos)); do { item = NULL; gtk_tree_model_get(GTK_TREE_MODEL(model), &it, FM_PLACES_MODEL_COL_INFO, &item, -1); if( item && item->fi && item->fi->path && fm_path_equal(item->fi->path, fi->path) ) { fm_file_info_unref(item->fi); item->fi = fm_file_info_ref(fi); break; } }while(gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &it)); } else { do { item = NULL; gtk_tree_model_get(GTK_TREE_MODEL(model), &it, FM_PLACES_MODEL_COL_INFO, &item, -1); if( item && item->fi && item->fi->path ) { for(l = fm_list_peek_head_link(job->file_infos); l; l = l->next ) { fi = FM_FILE_INFO(l->data); if(fm_path_equal(item->fi->path, fi->path)) { fm_file_info_unref(item->fi); item->fi = fm_file_info_ref(fi); /* remove the file from list to speed up further loading. * This won't cause problem since nobody else if using the list. */ fm_list_delete_link(job->file_infos, l); break; } } } }while(gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &it)); } }
// when the current selection in the folder view is changed void TabPage::onSelChanged(int numSel) { QString msg; if(numSel > 0) { /* FIXME: display total size of all selected files. */ if(numSel == 1) { /* only one file is selected */ FmFileInfoList* files = folderView_->selectedFiles(); FmFileInfo* fi = fm_file_info_list_peek_head(files); const char* size_str = fm_file_info_get_disp_size(fi); if(size_str) { msg = QString("\"%1\" (%2) %3") .arg(QString::fromUtf8(fm_file_info_get_disp_name(fi))) .arg(QString::fromUtf8(size_str ? size_str : "")) .arg(QString::fromUtf8(fm_file_info_get_desc(fi))); } else { msg = QString("\"%1\" %2") .arg(QString::fromUtf8(fm_file_info_get_disp_name(fi))) .arg(QString::fromUtf8(fm_file_info_get_desc(fi))); } /* FIXME: should we support statusbar plugins as in the gtk+ version? */ fm_file_info_list_unref(files); } else { goffset sum; GList* l; msg = tr("%1 item(s) selected", NULL, numSel).arg(numSel); /* don't count if too many files are selected, that isn't lightweight */ if(numSel < 1000) { sum = 0; FmFileInfoList* files = folderView_->selectedFiles(); for(l = fm_file_info_list_peek_head_link(files); l; l = l->next) { if(fm_file_info_is_dir(FM_FILE_INFO(l->data))) { /* if we got a directory then we cannot tell it's size unless we do deep count but we cannot afford it */ sum = -1; break; } sum += fm_file_info_get_size(FM_FILE_INFO(l->data)); } if(sum >= 0) { char size_str[128]; fm_file_size_to_str(size_str, sizeof(size_str), sum, fm_config->si_unit); msg += QString(" (%1)").arg(QString::fromUtf8(size_str)); } /* FIXME: should we support statusbar plugins as in the gtk+ version? */ fm_file_info_list_unref(files); } /* FIXME: can we show some more info on selection? that isn't lightweight if a lot of files are selected */ } } statusText_[StatusTextSelectedFiles] = msg; Q_EMIT statusChanged(StatusTextSelectedFiles, msg); }
void View::onNewTab() { Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent()); for(GList* l = fm_file_info_list_peek_head_link(menu->files()); l; l = l->next) { FmFileInfo* file = FM_FILE_INFO(l->data); Q_EMIT openDirRequested(fm_file_info_get_path(file), OpenInNewTab); } }
bool FileLauncher::openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err) { for(GList* l = folder_infos; l; l = l->next) { FmFileInfo* fi = FM_FILE_INFO(l->data); qDebug() << " folder:" << QString::fromUtf8(fm_file_info_get_disp_name(fi)); } return false; }
void View::onOpenInTerminal() { Application* app = static_cast<Application*>(qApp); Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent()); for(GList* l = fm_file_info_list_peek_head_link(menu->files()); l; l = l->next) { FmFileInfo* file = FM_FILE_INFO(l->data); app->openFolderInTerminal(fm_file_info_get_path(file)); } }
void DesktopWindow::onRenameActivated() { if(FmFileInfoList* files = selectedFiles()) { for(GList* l = fm_file_info_list_peek_head_link(files); l; l = l->next) { FmFileInfo* info = FM_FILE_INFO(l->data); Fm::renameFile(info, NULL); fm_file_info_list_unref(files); } } }
static void on_files_added(FmFolder* folder, GSList* files, gpointer user_data) { GSList* l; for(l = files; l; l = l->next) { FmFileInfo* file = FM_FILE_INFO(l->data); FmPath* path = fm_file_info_get_path(file); char* path_str = fm_path_display_name(path, FALSE); g_printf("file found: %s\n", path_str); } }
static gpointer queue_add_file(FmJob* fmjob, gpointer user_data) { FmDirListJob* job = FM_DIR_LIST_JOB(fmjob); FmFileInfo* file = FM_FILE_INFO(user_data); /* this callback is called from the main thread */ /* g_print("queue_add_file: %s\n", fm_file_info_get_disp_name(file)); */ job->files_to_add = g_slist_prepend(job->files_to_add, fm_file_info_ref(file)); if(job->delay_add_files_handler == 0) job->delay_add_files_handler = g_timeout_add_seconds_full(G_PRIORITY_LOW, 1, emit_found_files, g_object_ref(job), g_object_unref); return NULL; }
bool Launcher::openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err) { GList* l = folder_infos; FmFileInfo* fi = FM_FILE_INFO(l->data); // TODO: Use services to resolve application settings // Application* app = Application::instance(); MainWindow* mainWindow = mainWindow_; if(!mainWindow) { mainWindow = new MainWindow(fm_file_info_get_path(fi)); // mainWindow->resize(app->settings().windowWidth(), app->settings().windowHeight()); } else mainWindow->chdir(fm_file_info_get_path(fi)); l = l->next; for(; l; l = l->next) { fi = FM_FILE_INFO(l->data); mainWindow->addTab(fm_file_info_get_path(fi)); } mainWindow->show(); mainWindow->raise(); return true; }
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); } }
void SidePane::initDirTree() { // TODO DirTreeModel* model = new DirTreeModel(view_); FmFileInfoJob* job = fm_file_info_job_new(NULL, FM_FILE_INFO_JOB_NONE); model->setShowHidden(showHidden_); GList* l; /* query FmFileInfo for home dir and root dir, and then, * add them to dir tree model */ fm_file_info_job_add(job, fm_path_get_home()); fm_file_info_job_add(job, fm_path_get_root()); /* FIXME: maybe it's cleaner to use run_async here? */ fm_job_run_sync_with_mainloop(FM_JOB(job)); for(l = fm_file_info_list_peek_head_link(job->file_infos); l; l = l->next) { FmFileInfo* fi = FM_FILE_INFO(l->data); model->addRoot(fi); } g_object_unref(job); static_cast<DirTreeView*>(view_)->setModel(model); }
gboolean on_dnd_dest_files_dropped(FmDndDest* dd, GdkDragAction action, int info_type, FmFileInfoList* files, FmPlacesView* view) { FmPath* dest; GList* l; gboolean ret = FALSE; dest = fm_dnd_dest_get_dest_path(dd); /* g_debug("action= %d, %d files-dropped!, info_type: %d", action, fm_list_get_length(files), info_type); */ if(!dest && action == GDK_ACTION_LINK) /* add bookmarks */ { GtkTreePath* tp = view->dest_row; if(tp) { const GtkTreePath* sep = fm_places_model_get_separator_path(FM_PLACES_MODEL(model)); int idx = gtk_tree_path_get_indices(tp)[0] - gtk_tree_path_get_indices(sep)[0]; if(view->dest_pos == GTK_TREE_VIEW_DROP_BEFORE) --idx; for( l=fm_list_peek_head_link(files); l; l=l->next, ++idx ) { FmBookmarkItem* item; FmFileInfo* fi = FM_FILE_INFO(l->data); if(fm_file_info_is_dir(fi)) item = fm_bookmarks_insert( FM_PLACES_MODEL(model)->bookmarks, fi->path, fi->disp_name, idx); /* we don't need to add item to places view. Later the bookmarks will be reloaded. */ } } ret = TRUE; } if(view->dest_row) { gtk_tree_path_free(view->dest_row); view->dest_row = NULL; } return ret; }
gboolean fm_dnd_dest_drag_data_received(FmDndDest* dd, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *sel_data, guint info, guint time) { FmList* files = NULL; GtkWidget *dest_widget = dd->widget; if(info == FM_DND_DEST_TARGET_FM_LIST) { if((sel_data->length >= 0) && (sel_data->format==8)) { /* get the pointer */ memcpy(&files, sel_data->data, sel_data->length); if(files) fm_list_ref(files); if(files) { FmFileInfo* fi = FM_FILE_INFO(fm_list_peek_head(files)); /* get the device of the first dragged source file */ if(fm_path_is_native(fi->path)) dd->src_dev = fi->dev; else dd->src_fs_id = fi->fs_id; } } } else if(info == FM_DND_DEST_TARGET_URI_LIST) { if((sel_data->length >= 0) && (sel_data->format==8)) { gchar **uris; uris = gtk_selection_data_get_uris( sel_data ); files = fm_path_list_new_from_uris((const char **)uris); g_free(uris); if(files) { GFileInfo* inf; FmPath* path = FM_PATH(fm_list_peek_head(files)); GFile* gf = fm_path_to_gfile(path); const char* attr = fm_path_is_native(path) ? G_FILE_ATTRIBUTE_UNIX_DEVICE : G_FILE_ATTRIBUTE_ID_FILESYSTEM; inf = g_file_query_info(gf, attr, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); g_object_unref(gf); if(fm_path_is_native(path)) dd->src_dev = g_file_info_get_attribute_uint32(inf, G_FILE_ATTRIBUTE_UNIX_DEVICE); else dd->src_fs_id = g_intern_string(g_file_info_get_attribute_string(inf, G_FILE_ATTRIBUTE_ID_FILESYSTEM)); g_object_unref(inf); } } } else if(info == FM_DND_DEST_TARGET_XDS) /* X direct save */ { if( sel_data->format == 8 && sel_data->length == 1 && sel_data->data[0] == 'F') { gdk_property_change(GDK_DRAWABLE(drag_context->source_window), xds_target_atom, gdk_atom_intern_static_string("text/plain"), 8, GDK_PROP_MODE_REPLACE, (const guchar *)"", 0); } else if(sel_data->format == 8 && sel_data->length == 1 && sel_data->data[0] == 'S') { /* XDS succeeds */ } gtk_drag_finish(drag_context, TRUE, FALSE, time); return TRUE; } else return FALSE; /* remove previously cached source files. */ if(G_UNLIKELY(dd->src_files)) { fm_list_unref(dd->src_files); dd->src_files = NULL; } dd->src_files = files; dd->waiting_data = FALSE; dd->info_type = info; return TRUE; }
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); }