static void
gb_rename_file_popover_set_file (GbRenameFilePopover *self,
                                 GFile               *file)
{
  g_return_if_fail (GB_IS_RENAME_FILE_POPOVER (self));
  g_return_if_fail (G_IS_FILE (file));

  if (g_set_object (&self->file, file))
    {
      if (file != NULL)
        {
          gchar *name;
          gchar *label;

          name = g_file_get_basename (file);
          label = g_strdup_printf (_("Rename %s"), name);

          gtk_label_set_label (self->label, label);

          g_free (name);
          g_free (label);
        }

      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FILE]);
    }
}
GFile *
gb_rename_file_popover_get_file (GbRenameFilePopover *self)
{
  g_return_val_if_fail (GB_IS_RENAME_FILE_POPOVER (self), NULL);

  return self->file;
}
static void
gb_rename_file_popover__button_clicked (GbRenameFilePopover *self,
                                        GtkButton           *button)
{
  g_autoptr(GFile) file = NULL;
  g_autoptr(GFile) parent = NULL;
  const gchar *path;

  g_assert (GB_IS_RENAME_FILE_POPOVER (self));
  g_assert (GTK_IS_BUTTON (button));
  g_assert (self->file != NULL);
  g_assert (G_IS_FILE (self->file));

  path = gtk_entry_get_text (self->entry);
  if (ide_str_empty0 (path))
    return;

  parent = g_file_get_parent (self->file);
  file = g_file_get_child (parent, path);

  /* only activate once */
  gtk_widget_set_sensitive (GTK_WIDGET (self->button), FALSE);

  g_signal_emit (self, signals [RENAME_FILE], 0, self->file, file);
}
static void
gb_rename_file_popover__entry_activate (GbRenameFilePopover *self,
                                        GtkEntry            *entry)
{
  g_assert (GB_IS_RENAME_FILE_POPOVER (self));
  g_assert (GTK_IS_ENTRY (entry));

  if (gtk_widget_get_sensitive (GTK_WIDGET (self->button)))
    gtk_widget_activate (GTK_WIDGET (self->button));
}
static void
gb_project_tree_actions__project_rename_file_cb (GObject      *object,
                                                 GAsyncResult *result,
                                                 gpointer      user_data)
{
  IdeProject *project = (IdeProject *)object;
  g_autoptr(GbRenameFilePopover) popover = user_data;
  g_autoptr(GError) error = NULL;
  GbTreeNode *node;
  GFile *file;
  GbTree *tree;
  gboolean expanded = FALSE;

  g_assert (IDE_IS_PROJECT (project));
  g_assert (GB_IS_RENAME_FILE_POPOVER (popover));

  if (!ide_project_rename_file_finish (project, result, &error))
    {
      /* todo: display error */
      g_warning ("%s", error->message);
      return;
    }

  file = g_object_get_data (G_OBJECT (popover), "G_FILE");
  tree = GB_TREE (gtk_popover_get_relative_to (GTK_POPOVER (popover)));

  g_assert (G_IS_FILE (file));
  g_assert (GB_IS_TREE (tree));

  if ((node = gb_tree_get_selected (tree)))
    expanded = gb_tree_node_get_expanded (node);

  gb_tree_rebuild (tree);

  node = gb_tree_find_custom (tree,
                              (GEqualFunc)project_item_equal_func,
                              file);

  if (node != NULL)
    {
      gb_tree_node_expand (node, TRUE);
      if (!expanded)
        gb_tree_node_collapse (node);
      gb_tree_node_select (node);
      gb_tree_scroll_to_node (tree, node);
    }

  gtk_widget_hide (GTK_WIDGET (popover));
  gtk_widget_destroy (GTK_WIDGET (popover));
}
static void
gb_rename_file_popover_set_is_directory (GbRenameFilePopover *self,
                                         gboolean             is_directory)
{
  g_return_if_fail (GB_IS_RENAME_FILE_POPOVER (self));

  is_directory = !!is_directory;

  if (is_directory != self->is_directory)
    {
      self->is_directory = is_directory;
      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_DIRECTORY]);
    }
}
static void
gb_rename_file_popover__entry_changed (GbRenameFilePopover *self,
                                       GtkEntry            *entry)
{
  g_autoptr(GFile) parent = NULL;
  g_autoptr(GFile) file = NULL;
  const gchar *text;

  g_assert (GB_IS_RENAME_FILE_POPOVER (self));
  g_assert (GTK_IS_ENTRY (entry));
  g_assert (self->file != NULL);
  g_assert (G_IS_FILE (self->file));

  gtk_widget_set_sensitive (GTK_WIDGET (self->button), FALSE);
  gtk_label_set_label (self->message, NULL);

  text = gtk_entry_get_text (entry);
  if (ide_str_empty0 (text))
    return;

  if (strchr (text, G_DIR_SEPARATOR) != NULL)
    {
      gtk_label_set_label (self->message,
                           _("File name must not contain subdirectories."));
      return;
    }

  if (self->cancellable)
    {
      g_cancellable_cancel (self->cancellable);
      g_clear_object (&self->cancellable);
    }

  self->cancellable = g_cancellable_new ();

  parent = g_file_get_parent (self->file);
  file = g_file_get_child (parent, text);

  g_file_query_info_async (file,
                           G_FILE_ATTRIBUTE_STANDARD_TYPE,
                           G_FILE_QUERY_INFO_NONE,
                           G_PRIORITY_DEFAULT,
                           self->cancellable,
                           gb_rename_file_popover__file_query_info,
                           g_object_ref (self));
}