Пример #1
0
static void test_parsing(FmPathFunc func, const char* str, const char** expected, int n_expected)
{
    GSList* elements = NULL, *l;
    int i;
    FmPath *path, *element;
    g_print("\ntry to parse \'%s\':\n[", str);
    path = func(str);

    for(element = path; element; element = fm_path_get_parent(element))
        elements = g_slist_prepend(elements, element);

    for(i = 0, l = elements; l; l=l->next, ++i)
    {
        g_assert_cmpint(i, <, n_expected);
        element = (FmPath*)l->data;
        g_print("\'%s\'", fm_path_get_basename(element));
        if(l->next)
            g_print(", ");
        g_assert_cmpstr(fm_path_get_basename(element), ==, expected[i]);
    }
    g_slist_free(elements);
    g_print("]\n");

    g_assert_cmpint(i, ==, n_expected);

    fm_path_unref(path);
}
Пример #2
0
static void on_browse_btn_clicked(GtkButton* btn, AppChooserData* data)
{
    FmPath* file;
    GtkFileFilter* filter = gtk_file_filter_new();
    char* binary;
    gtk_file_filter_add_custom(filter,
        GTK_FILE_FILTER_FILENAME|GTK_FILE_FILTER_MIME_TYPE, exec_filter_func, NULL, NULL);
    /* gtk_file_filter_set_name(filter, _("Executable files")); */
    file = fm_select_file(GTK_WINDOW(data->dlg), NULL, "/usr/bin", TRUE, FALSE, filter, NULL);

    if (file == NULL)
        return;
    binary = fm_path_to_str(file);
    if (g_str_has_suffix(fm_path_get_basename(file), ".desktop"))
    {
        GKeyFile *kf = g_key_file_new();
        GDesktopAppInfo *info;
        if (g_key_file_load_from_file(kf, binary, 0, NULL) &&
            (info = g_desktop_app_info_new_from_keyfile(kf)) != NULL)
            /* it is a valid desktop entry */
        {
            /* FIXME: it will duplicate the file, how to avoid that? */
            gtk_entry_set_text(data->cmdline,
                               g_app_info_get_commandline(G_APP_INFO(info)));
            gtk_entry_set_text(data->app_name,
                               g_app_info_get_name(G_APP_INFO(info)));
            gtk_toggle_button_set_active(data->use_terminal,
                                         g_key_file_get_boolean(kf, G_KEY_FILE_DESKTOP_GROUP,
                                                                G_KEY_FILE_DESKTOP_KEY_TERMINAL,
                                                                NULL));
            gtk_toggle_button_set_active(data->keep_open,
                                         g_key_file_get_boolean(kf, G_KEY_FILE_DESKTOP_GROUP,
                                                                "X-KeepTerminal",
                                                                NULL));
            g_object_unref(info);
            g_key_file_free(kf);
            fm_path_unref(file);
            return;
        }
        g_key_file_free(kf);
    }
    gtk_entry_set_text(data->cmdline, binary);
    g_free(binary);
    fm_path_unref(file);
}
Пример #3
0
void renameFile(FmFileInfo *file, QWidget *parent) {
  FmPath* path = fm_file_info_get_path(file);
  FilenameDialog dlg(parent);
  dlg.setWindowTitle(QObject::tr("Rename File"));
  dlg.setLabelText(QObject::tr("Please enter a new name:"));
  // FIXME: what's the best way to handle non-UTF8 filename encoding here?
  QString old_name = QString::fromLocal8Bit(fm_path_get_basename(path));
  dlg.setTextValue(old_name);

  if(fm_file_info_is_dir(file)) // select filename extension for directories
    dlg.setSelectExtension(true);

  if(dlg.exec() != QDialog::Accepted)
    return;

  QString new_name = dlg.textValue();

  if(new_name == old_name)
    return;

  GFile* gf = fm_path_to_gfile(path);
  GFile* parent_gf = g_file_get_parent(gf);
  GFile* dest = g_file_get_child(G_FILE(parent_gf), new_name.toLocal8Bit().data());
  g_object_unref(parent_gf);

  GError* err = NULL;
  if(!g_file_move(gf, dest,
                  GFileCopyFlags(G_FILE_COPY_ALL_METADATA |
                                 G_FILE_COPY_NO_FALLBACK_FOR_MOVE |
                                 G_FILE_COPY_NOFOLLOW_SYMLINKS),
                  NULL, /* make this cancellable later. */
                  NULL, NULL, &err)) {
    QMessageBox::critical(parent, QObject::tr("Error"), err->message);
    g_error_free(err);
  }

  g_object_unref(dest);
  g_object_unref(gf);
}
Пример #4
0
static gboolean fm_file_info_job_run(FmJob* fmjob)
{
    GList* l;
    FmFileInfoJob* job = (FmFileInfoJob*)fmjob;
    GError* err = NULL;

    if(job->file_infos == NULL)
        return FALSE;

    for(l = fm_file_info_list_peek_head_link(job->file_infos); !fm_job_is_cancelled(fmjob) && l;)
    {
        FmFileInfo* fi = (FmFileInfo*)l->data;
        GList* next = l->next;
        FmPath* path = fm_file_info_get_path(fi);

        if(job->current)
            fm_path_unref(job->current);
        job->current = fm_path_ref(path);

        if(fm_path_is_native(path))
        {
            char* path_str = fm_path_to_str(path);
            if(!_fm_file_info_job_get_info_for_native_file(fmjob, fi, path_str, &err))
            {
                FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
                g_error_free(err);
                err = NULL;
                if(act == FM_JOB_RETRY)
                {
                    g_free(path_str);
                    continue; /* retry */
                }

                fm_file_info_list_delete_link(job->file_infos, l); /* also calls unref */
            }
            else if(G_UNLIKELY(job->flags & FM_FILE_INFO_JOB_EMIT_FOR_EACH_FILE))
                fm_job_call_main_thread(fmjob, _emit_current_file, fi);
            g_free(path_str);
            /* recursively set display names for path parents */
            _check_native_display_names(fm_path_get_parent(path));
        }
        else
        {
            GFile* gf;

            gf = fm_path_to_gfile(path);
            if(!_fm_file_info_job_get_info_for_gfile(fmjob, fi, gf, &err))
            {
              if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_NOT_MOUNTED)
              {
                GFileInfo *inf;
                /* location by link isn't mounted; unfortunately we cannot
                   launch a target if we don't know what kind of target we
                   have; lets make a simplest directory-kind GFIleInfo */
                /* FIXME: this may be dirty a bit */
                g_error_free(err);
                err = NULL;
                inf = g_file_info_new();
                g_file_info_set_file_type(inf, G_FILE_TYPE_DIRECTORY);
                g_file_info_set_name(inf, fm_path_get_basename(path));
                g_file_info_set_display_name(inf, fm_path_get_basename(path));
                fm_file_info_set_from_g_file_data(fi, gf, inf);
                g_object_unref(inf);
              }
              else
              {
                FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
                g_error_free(err);
                err = NULL;
                if(act == FM_JOB_RETRY)
                {
                    g_object_unref(gf);
                    continue; /* retry */
                }

                fm_file_info_list_delete_link(job->file_infos, l); /* also calls unref */
                goto _next;
              }
            }
            else if(G_UNLIKELY(job->flags & FM_FILE_INFO_JOB_EMIT_FOR_EACH_FILE))
                    fm_job_call_main_thread(fmjob, _emit_current_file, fi);
            /* recursively set display names for path parents */
            _check_gfile_display_names(fm_path_get_parent(path), gf);
_next:
            g_object_unref(gf);
        }
        l = next;
    }
    return TRUE;
}
Пример #5
0
static gint on_ask_rename(FmFileOpsJob* job, FmFileInfo* src, FmFileInfo* dest, char** new_name, FmProgressDisplay* data)
{
    int res;
    GtkBuilder* builder;
    GtkDialog *dlg;
    GtkImage *src_icon, *dest_icon;
    GtkLabel *src_fi, *dest_fi;
    GtkEntry *filename;
    GtkToggleButton *apply_all;
    char* tmp;
    const char* disp_size;
    FmPath* path;
    FmIcon* icon;

    /* return default operation if the user has set it */
    if(data->default_opt)
        return data->default_opt;

    builder = gtk_builder_new();
    path = fm_file_info_get_path(dest);
    icon = fm_file_info_get_icon(src);

    if(data->timer)
        g_timer_stop(data->timer);

    gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE);
    ensure_dlg(data);

    gtk_builder_add_from_file(builder, PACKAGE_UI_DIR "/ask-rename.ui", NULL);
    dlg = GTK_DIALOG(gtk_builder_get_object(builder, "dlg"));
    src_icon = GTK_IMAGE(gtk_builder_get_object(builder, "src_icon"));
    src_fi = GTK_LABEL(gtk_builder_get_object(builder, "src_fi"));
    dest_icon = GTK_IMAGE(gtk_builder_get_object(builder, "dest_icon"));
    dest_fi = GTK_LABEL(gtk_builder_get_object(builder, "dest_fi"));
    filename = GTK_ENTRY(gtk_builder_get_object(builder, "filename"));
    apply_all = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "apply_all"));
    gtk_window_set_transient_for(GTK_WINDOW(dlg), GTK_WINDOW(data->dlg));

    gtk_image_set_from_gicon(src_icon, icon->gicon, GTK_ICON_SIZE_DIALOG);
    disp_size = fm_file_info_get_disp_size(src);
    if(disp_size)
    {
        tmp = g_strdup_printf(_("Type: %s\nSize: %s\nModified: %s"),
                              fm_file_info_get_desc(src),
                              disp_size,
                              fm_file_info_get_disp_mtime(src));
    }
    else
    {
        tmp = g_strdup_printf(_("Type: %s\nModified: %s"),
                              fm_file_info_get_desc(src),
                              fm_file_info_get_disp_mtime(src));
    }

    gtk_label_set_text(src_fi, tmp);
    g_free(tmp);

    gtk_image_set_from_gicon(dest_icon, icon->gicon, GTK_ICON_SIZE_DIALOG);
    disp_size = fm_file_info_get_disp_size(dest);
    if(disp_size)
    {
        tmp = g_strdup_printf(_("Type: %s\nSize: %s\nModified: %s"),
                              fm_file_info_get_desc(dest),
                              fm_file_info_get_disp_size(dest),
                              fm_file_info_get_disp_mtime(dest));
    }
    else
    {
        tmp = g_strdup_printf(_("Type: %s\nModified: %s"),
                              fm_file_info_get_desc(dest),
                              fm_file_info_get_disp_mtime(dest));
    }

    gtk_label_set_text(dest_fi, tmp);
    g_free(tmp);

    tmp = g_filename_display_name(fm_path_get_basename(path));
    gtk_entry_set_text(filename, tmp);
    g_free(tmp);
    tmp = (char*)fm_file_info_get_disp_name(dest); /* FIXME: cast const to char */
    g_object_set_data(G_OBJECT(filename), "old_name", tmp);
    g_signal_connect(filename, "changed", G_CALLBACK(on_filename_changed), gtk_builder_get_object(builder, "rename"));

    g_object_unref(builder);

    res = gtk_dialog_run(dlg);
    switch(res)
    {
    case RESPONSE_RENAME:
        *new_name = g_strdup(gtk_entry_get_text(filename));
        res = FM_FILE_OP_RENAME;
        break;
    case RESPONSE_OVERWRITE:
        res = FM_FILE_OP_OVERWRITE;
        break;
    case RESPONSE_SKIP:
        res = FM_FILE_OP_SKIP;
        break;
    default:
        res = FM_FILE_OP_CANCEL;
    }

    if(gtk_toggle_button_get_active(apply_all))
    {
        if(res == RESPONSE_OVERWRITE || res == FM_FILE_OP_SKIP)
            data->default_opt = res;
    }

    gtk_widget_destroy(GTK_WIDGET(dlg));

    if(data->timer)
        g_timer_continue(data->timer);

    return res;
}
Пример #6
0
gboolean _fm_file_ops_job_move_run(FmFileOpsJob* job)
{
    GFile *dest_dir;
    GFileInfo* inf;
    GList* l;
    GError* err = NULL;
    FmJob* fmjob = FM_JOB(job);
    dev_t dest_dev = 0;
    gboolean ret = TRUE;
    FmDeepCountJob* dc;
    FmPath *parent = NULL;
    FmFolder *df, *sf = NULL;

    /* get information of destination folder */
    g_return_val_if_fail(job->dest, FALSE);
    dest_dir = fm_path_to_gfile(job->dest);
_retry_query_dest_info:
    inf = g_file_query_info(dest_dir, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL","
                                  G_FILE_ATTRIBUTE_UNIX_DEVICE","
                                  G_FILE_ATTRIBUTE_ID_FILESYSTEM","
                                  G_FILE_ATTRIBUTE_UNIX_DEVICE, 0,
                                  fm_job_get_cancellable(fmjob), &err);
    if(inf)
    {
        job->dest_fs_id = g_intern_string(g_file_info_get_attribute_string(inf, G_FILE_ATTRIBUTE_ID_FILESYSTEM));
        dest_dev = g_file_info_get_attribute_uint32(inf, G_FILE_ATTRIBUTE_UNIX_DEVICE); /* needed by deep count */
        g_object_unref(inf);
    }
    else
    {
        FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MODERATE);
        g_error_free(err);
        err = NULL;
        if(act == FM_JOB_RETRY)
            goto _retry_query_dest_info;
        else
        {
            g_object_unref(dest_dir);
            return FALSE;
        }
    }

    /* prepare the job, count total work needed with FmDeepCountJob */
    dc = fm_deep_count_job_new(job->srcs, FM_DC_JOB_PREPARE_MOVE);
    fm_deep_count_job_set_dest(dc, dest_dev, job->dest_fs_id);
    fm_job_run_sync(FM_JOB(dc));
    job->total = dc->total_size;

    if( fm_job_is_cancelled(FM_JOB(dc)) )
    {
        g_object_unref(dest_dir);
        g_object_unref(dc);
        return FALSE;
    }
    g_object_unref(dc);
    g_debug("total size to move: %llu, dest_fs: %s",
            (long long unsigned int)job->total, job->dest_fs_id);

    fm_file_ops_job_emit_prepared(job);
    /* suspend updates for destination */
    df = fm_folder_find_by_path(job->dest);
    if (df)
        fm_folder_block_updates(df);

    for(l = fm_path_list_peek_head_link(job->srcs); !fm_job_is_cancelled(fmjob) && l; l=l->next)
    {
        FmPath* path = FM_PATH(l->data);
        GFile* src = fm_path_to_gfile(path);
        GFile* dest;
        char* tmp_basename;

        /* do with updates for source */
        if (fm_path_get_parent(path) != parent && fm_path_get_parent(path) != NULL)
        {
            FmFolder *pf;

            pf = fm_folder_find_by_path(fm_path_get_parent(path));
            if (pf != sf)
            {
                if (sf)
                {
                    fm_folder_unblock_updates(sf);
                    g_object_unref(sf);
                }
                if (pf)
                    fm_folder_block_updates(pf);
                sf = pf;
            }
            else if (pf)
                g_object_unref(pf);
        }
        parent = fm_path_get_parent(path);
        if(g_file_is_native(src) && g_file_is_native(dest_dir))
            /* both are native */
            tmp_basename = NULL;
        else if(g_file_is_native(src)) /* move from native to virtual */
            tmp_basename = g_filename_to_utf8(fm_path_get_basename(path),
                                              -1, NULL, NULL, NULL);
            /* gvfs escapes it itself */
        else /* move from virtual to native/virtual */
            tmp_basename = fm_uri_subpath_to_native_subpath(fm_path_get_basename(path), NULL);
        dest = g_file_get_child(dest_dir,
                        tmp_basename ? tmp_basename : fm_path_get_basename(path));
        g_free(tmp_basename);

        if(!_fm_file_ops_job_move_file(job, src, NULL, dest, path, sf, df))
            ret = FALSE;
        g_object_unref(src);
        g_object_unref(dest);

        if(!ret)
            break;
    }
    /* restore updates for destination and source */
    if (df)
    {
        fm_folder_unblock_updates(df);
        g_object_unref(df);
    }
    if (sf)
    {
        fm_folder_unblock_updates(sf);
        g_object_unref(sf);
    }

    g_object_unref(dest_dir);
    return ret;
}
Пример #7
0
gboolean _fm_file_ops_job_copy_run(FmFileOpsJob* job)
{
    gboolean ret = TRUE;
    GFile *dest_dir;
    GList* l;
    FmJob* fmjob = FM_JOB(job);
    /* prepare the job, count total work needed with FmDeepCountJob */
    FmDeepCountJob* dc = fm_deep_count_job_new(job->srcs, FM_DC_JOB_DEFAULT);
    FmFolder *df;

    /* let the deep count job share the same cancellable object. */
    fm_job_set_cancellable(FM_JOB(dc), fm_job_get_cancellable(fmjob));
    fm_job_run_sync(FM_JOB(dc));
    job->total = dc->total_size;
    if(fm_job_is_cancelled(fmjob))
    {
        g_object_unref(dc);
        return FALSE;
    }
    g_object_unref(dc);
    g_debug("total size to copy: %llu", (long long unsigned int)job->total);

    dest_dir = fm_path_to_gfile(job->dest);
    /* suspend updates for destination */
    df = fm_folder_find_by_path(job->dest);
    if (df)
        fm_folder_block_updates(df);

    fm_file_ops_job_emit_prepared(job);

    for(l = fm_path_list_peek_head_link(job->srcs); !fm_job_is_cancelled(fmjob) && l; l=l->next)
    {
        FmPath* path = FM_PATH(l->data);
        GFile* src = fm_path_to_gfile(path);
        GFile* dest;
        char* tmp_basename;

        if(g_file_is_native(src) && g_file_is_native(dest_dir))
            /* both are native */
            tmp_basename = NULL;
        else if(g_file_is_native(src)) /* copy from native to virtual */
            tmp_basename = g_filename_to_utf8(fm_path_get_basename(path),
                                              -1, NULL, NULL, NULL);
            /* gvfs escapes it itself */
        else /* copy from virtual to native/virtual */
        {
            /* if we drop URI query onto native filesystem, omit query part */
            const char *basename = fm_path_get_basename(path);
            char *sub_name;

            sub_name = strchr(basename, '?');
            if (sub_name)
            {
                sub_name = g_strndup(basename, sub_name - basename);
                basename = strrchr(sub_name, G_DIR_SEPARATOR);
                if (basename)
                    basename++;
                else
                    basename = sub_name;
            }
            tmp_basename = fm_uri_subpath_to_native_subpath(basename, NULL);
            g_free(sub_name);
        }
        dest = g_file_get_child(dest_dir,
                        tmp_basename ? tmp_basename : fm_path_get_basename(path));
        g_free(tmp_basename);
        if(!_fm_file_ops_job_copy_file(job, src, NULL, dest, NULL, df))
            ret = FALSE;
        g_object_unref(src);
        g_object_unref(dest);
    }

    /* g_debug("finished: %llu, total: %llu", job->finished, job->total); */
    fm_file_ops_job_emit_percent(job);

    /* restore updates for destination */
    if (df)
    {
        fm_folder_unblock_updates(df);
        g_object_unref(df);
    }
    g_object_unref(dest_dir);
    return ret;
}
Пример #8
0
static void test_path_child()
{
    FmPath* parent = fm_path_get_home();
    FmPath* path;
    g_print("\n");
    path = fm_path_new_child(parent, "child");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "child");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "child/");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "child");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "child///");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "child");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "..");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert(path == fm_path_get_parent(parent));
    fm_path_unref(path);

    path = fm_path_new_child(parent, "../");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert(path == fm_path_get_parent(parent));
    fm_path_unref(path);

    path = fm_path_new_child(parent, "/");
    g_assert(path == parent);
    fm_path_unref(path);

    parent = fm_path_get_root();

    path = fm_path_new_child(parent, "..");
    g_assert(path == parent);
    fm_path_unref(path);

    path = fm_path_new_child(parent, "../");
    g_assert(path == parent);
    fm_path_unref(path);

    parent = NULL;
    path = fm_path_new_child(parent, "/");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "/");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "//");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "/");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "///");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "/");
    fm_path_unref(path);

/*  FIXME: how to handle this case?
    path = fm_path_new_child(parent, "/test");
    g_printf("path->name = %s\n", path->name);
    g_assert_cmpstr(path->name, ==, "/test/");
    fm_path_unref(path);
*/

    path = fm_path_new_child(parent, "trash:");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "trash:///");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "trash:/");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "trash:///");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "trash:////");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "trash:///");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "..");
    g_printf("path->name = %s\n", fm_path_get_basename(path));
    g_assert_cmpstr(fm_path_get_basename(path), ==, "/");
    fm_path_unref(path);

    path = fm_path_new_child(parent, "../");
    g_assert_cmpstr(fm_path_get_basename(path), ==, "/");
    fm_path_unref(path);

/*
    path = fm_path_new_child(parent, "..");
    g_assert(path == NULL);

    path = fm_path_new_child(parent, ".");
    g_assert(path == NULL);
*/
}