latexila-build-tools-personal.c 11.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * This file is part of LaTeXila.
 *
 * Copyright (C) 2014 - Sébastien Wilmet <swilmet@gnome.org>
 *
 * LaTeXila is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LaTeXila is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * SECTION:build-tools-personal
 * @title: LatexilaBuildToolsPersonal
 * @short_description: Personal build tools
 *
 * The #LatexilaBuildToolsPersonal singleton class represents the personal build
 * tools. The personal build tools can be entirely modified. The XML file can be
 * saved with latexila_build_tools_personal_save().
 */

#include "latexila-build-tools-personal.h"
#include <gio/gio.h>
32
#include "latexila-build-tool.h"
33
#include "latexila-utils.h"
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

static LatexilaBuildToolsPersonal *instance = NULL;

struct _LatexilaBuildToolsPersonalPrivate
{
  /* Used for saving */
  GString *xml_file_contents;

  guint modified : 1;
};

G_DEFINE_TYPE_WITH_PRIVATE (LatexilaBuildToolsPersonal, latexila_build_tools_personal, LATEXILA_TYPE_BUILD_TOOLS)

static void
latexila_build_tools_personal_finalize (GObject *object)
{
  LatexilaBuildToolsPersonal *build_tools = LATEXILA_BUILD_TOOLS_PERSONAL (object);

  if (build_tools->priv->xml_file_contents != NULL)
    {
      g_string_free (build_tools->priv->xml_file_contents, TRUE);
      build_tools->priv->xml_file_contents = NULL;
    }

  G_OBJECT_CLASS (latexila_build_tools_personal_parent_class)->finalize (object);
}

static void
latexila_build_tools_personal_class_init (LatexilaBuildToolsPersonalClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->finalize = latexila_build_tools_personal_finalize;
}

static GFile *
get_xml_file (void)
{
  gchar *path;
  GFile *file;

  path = g_build_filename (g_get_user_config_dir (),
                           "latexila",
                           "build_tools.xml",
                           NULL);

  file = g_file_new_for_path (path);
  g_free (path);

  return file;
}

static void
modified_cb (LatexilaBuildToolsPersonal *build_tools)
{
  build_tools->priv->modified = TRUE;
}

static void
latexila_build_tools_personal_init (LatexilaBuildToolsPersonal *build_tools)
{
  GFile *xml_file;

  build_tools->priv = latexila_build_tools_personal_get_instance_private (build_tools);

  g_signal_connect (build_tools,
                    "modified",
                    G_CALLBACK (modified_cb),
                    NULL);

  xml_file = get_xml_file ();
  latexila_build_tools_load (LATEXILA_BUILD_TOOLS (build_tools), xml_file);
  g_object_unref (xml_file);
}

/**
 * latexila_build_tools_personal_get_instance:
 *
 * Gets the instance of the #LatexilaBuildToolsPersonal singleton.
 *
114
 * Returns: (transfer none): the instance of #LatexilaBuildToolsPersonal.
115 116 117 118 119
 */
LatexilaBuildToolsPersonal *
latexila_build_tools_personal_get_instance (void)
{
  if (instance == NULL)
120
    instance = g_object_new (LATEXILA_TYPE_BUILD_TOOLS_PERSONAL, NULL);
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148

  return instance;
}

static void
save_cb (GFile                      *xml_file,
         GAsyncResult               *result,
         LatexilaBuildToolsPersonal *build_tools)
{
  GError *error = NULL;

  g_file_replace_contents_finish (xml_file, result, NULL, &error);

  if (error != NULL)
    {
      g_warning ("Error while saving the personal build tools: %s",
                 error->message);
      g_error_free (error);
    }
  else
    {
      build_tools->priv->modified = FALSE;
    }

  g_string_free (build_tools->priv->xml_file_contents, TRUE);
  build_tools->priv->xml_file_contents = NULL;

  g_object_unref (build_tools);
149
  g_application_release (g_application_get_default ());
150 151 152 153
}

/**
 * latexila_build_tools_personal_save:
Sébastien Wilmet's avatar
Sébastien Wilmet committed
154
 * @build_tools: the #LatexilaBuildToolsPersonal instance.
155
 *
156
 * Saves asynchronously the personal build tools into the XML file.
157 158 159 160 161 162 163 164
 */
void
latexila_build_tools_personal_save (LatexilaBuildToolsPersonal *build_tools)
{
  LatexilaBuildTools *build_tools_parent = LATEXILA_BUILD_TOOLS (build_tools);
  GString *contents;
  GList *cur_build_tool;
  GFile *xml_file;
165
  GError *error = NULL;
166 167 168

  g_return_if_fail (LATEXILA_IS_BUILD_TOOLS_PERSONAL (build_tools));

169 170
  if (!build_tools->priv->modified ||
      build_tools->priv->xml_file_contents != NULL)
171
    return;
172 173 174 175 176 177 178 179 180

  contents = g_string_new ("<tools>");
  build_tools->priv->xml_file_contents = contents;

  for (cur_build_tool = build_tools_parent->build_tools;
       cur_build_tool != NULL;
       cur_build_tool = cur_build_tool->next)
    {
      LatexilaBuildTool *build_tool = cur_build_tool->data;
181 182 183 184
      gchar *build_tool_xml = latexila_build_tool_to_xml (build_tool);

      g_string_append (contents, build_tool_xml);
      g_free (build_tool_xml);
185 186 187 188 189 190
    }

  g_string_append (contents, "</tools>\n");

  xml_file = get_xml_file ();

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
  latexila_utils_create_parent_directories (xml_file, &error);

  if (error == NULL)
    {
      /* Avoid finalization of build_tools during the async operation. And keep the
       * application running.
       */
      g_object_ref (build_tools);
      g_application_hold (g_application_get_default ());

      g_file_replace_contents_async (xml_file,
                                     contents->str,
                                     contents->len,
                                     NULL,
                                     TRUE, /* make a backup */
                                     G_FILE_CREATE_NONE,
                                     NULL,
                                     (GAsyncReadyCallback) save_cb,
                                     build_tools);
    }
  else
    {
      g_warning ("Error while saving the personal build tools: %s",
                 error->message);
      g_error_free (error);
    }
217 218 219 220 221 222

  g_object_unref (xml_file);
}

/**
 * latexila_build_tools_personal_move_up:
Sébastien Wilmet's avatar
Sébastien Wilmet committed
223 224
 * @build_tools: the #LatexilaBuildToolsPersonal instance.
 * @tool_num: the build tool position in the list.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
 *
 * Move a build tool up. The first build tool is at the top.
 */
void
latexila_build_tools_personal_move_up (LatexilaBuildToolsPersonal *build_tools,
                                       guint                       tool_num)
{
  LatexilaBuildTools *build_tools_parent = LATEXILA_BUILD_TOOLS (build_tools);
  GList *node;
  GList *prev_node;

  g_return_if_fail (LATEXILA_IS_BUILD_TOOLS_PERSONAL (build_tools));

  node = g_list_nth (build_tools_parent->build_tools, tool_num);
  g_return_if_fail (node != NULL);

  prev_node = node->prev;
  g_return_if_fail (prev_node != NULL);

  build_tools_parent->build_tools = g_list_remove_link (build_tools_parent->build_tools, node);

  build_tools_parent->build_tools = g_list_insert_before (build_tools_parent->build_tools,
                                                          prev_node,
                                                          node->data);

  g_list_free (node);

  g_signal_emit_by_name (build_tools, "modified");
}

/**
 * latexila_build_tools_personal_move_down:
Sébastien Wilmet's avatar
Sébastien Wilmet committed
257 258
 * @build_tools: the #LatexilaBuildToolsPersonal instance.
 * @tool_num: the build tool position in the list.
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
 *
 * Move a build tool down. The first build tool is at the top.
 */
void
latexila_build_tools_personal_move_down (LatexilaBuildToolsPersonal *build_tools,
                                         guint                       tool_num)
{
  LatexilaBuildTools *build_tools_parent = LATEXILA_BUILD_TOOLS (build_tools);
  GList *node;
  GList *next_node;

  g_return_if_fail (LATEXILA_IS_BUILD_TOOLS_PERSONAL (build_tools));

  node = g_list_nth (build_tools_parent->build_tools, tool_num);
  g_return_if_fail (node != NULL);

  next_node = node->next;
  g_return_if_fail (next_node != NULL);

  build_tools_parent->build_tools = g_list_remove_link (build_tools_parent->build_tools, node);

  build_tools_parent->build_tools = g_list_insert_before (build_tools_parent->build_tools,
                                                          next_node->next,
                                                          node->data);

  g_list_free (node);

  g_signal_emit_by_name (build_tools, "modified");
}

/**
 * latexila_build_tools_personal_delete:
291 292 293 294
 * @build_tools: the #LatexilaBuildToolsPersonal instance.
 * @tool_num: the build tool position in the list.
 *
 * Deletes a build tool.
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
 */
void
latexila_build_tools_personal_delete (LatexilaBuildToolsPersonal *build_tools,
                                      guint                       tool_num)
{
  LatexilaBuildTools *build_tools_parent = LATEXILA_BUILD_TOOLS (build_tools);
  GList *node;

  g_return_if_fail (LATEXILA_IS_BUILD_TOOLS_PERSONAL (build_tools));

  node = g_list_nth (build_tools_parent->build_tools, tool_num);
  g_return_if_fail (node != NULL);

  build_tools_parent->build_tools = g_list_remove_link (build_tools_parent->build_tools, node);

310
  g_list_free_full (node, g_object_unref);
311 312 313 314 315 316

  g_signal_emit_by_name (build_tools, "modified");
}

/**
 * latexila_build_tools_personal_add:
Sébastien Wilmet's avatar
Sébastien Wilmet committed
317
 * @build_tools: the #LatexilaBuildToolsPersonal instance.
318
 * @new_build_tool: the new build tool object.
319
 *
Sébastien Wilmet's avatar
Sébastien Wilmet committed
320
 * Append the new build tool at the end of the list.
321 322 323 324 325 326 327 328 329 330 331 332
 */
void
latexila_build_tools_personal_add (LatexilaBuildToolsPersonal *build_tools,
                                   LatexilaBuildTool          *new_build_tool)
{
  LatexilaBuildTools *build_tools_parent = LATEXILA_BUILD_TOOLS (build_tools);

  g_return_if_fail (LATEXILA_IS_BUILD_TOOLS_PERSONAL (build_tools));

  build_tools_parent->build_tools = g_list_append (build_tools_parent->build_tools,
                                                   new_build_tool);

333 334
  g_object_ref (new_build_tool);

335 336 337 338 339
  g_signal_emit_by_name (build_tools, "modified");
}

/**
 * latexila_build_tools_personal_insert:
Sébastien Wilmet's avatar
Sébastien Wilmet committed
340
 * @build_tools: the #LatexilaBuildToolsPersonal instance.
341
 * @new_build_tool: the new build tool object.
Sébastien Wilmet's avatar
Sébastien Wilmet committed
342
 * @position: the position in the list where to insert the new build tool.
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
 *
 * Inserts a new build tool at a given position.
 */
void
latexila_build_tools_personal_insert (LatexilaBuildToolsPersonal *build_tools,
                                      LatexilaBuildTool          *new_build_tool,
                                      guint                       position)
{
  LatexilaBuildTools *build_tools_parent = LATEXILA_BUILD_TOOLS (build_tools);

  g_return_if_fail (LATEXILA_IS_BUILD_TOOLS_PERSONAL (build_tools));

  build_tools_parent->build_tools = g_list_insert (build_tools_parent->build_tools,
                                                   new_build_tool,
                                                   position);

359 360
  g_object_ref (new_build_tool);

361 362 363 364 365
  g_signal_emit_by_name (build_tools, "modified");
}

/**
 * latexila_build_tools_personal_replace:
Sébastien Wilmet's avatar
Sébastien Wilmet committed
366
 * @build_tools: the #LatexilaBuildToolsPersonal instance.
367
 * @new_build_tool: the new build tool object.
Sébastien Wilmet's avatar
Sébastien Wilmet committed
368
 * @position: the position in the list where to replace the build tool. The old
369
 * build tool located at @position will be unreffed.
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
 *
 * Replaces a build tool.
 */
void
latexila_build_tools_personal_replace (LatexilaBuildToolsPersonal *build_tools,
                                       LatexilaBuildTool          *new_build_tool,
                                       guint                       position)
{
  LatexilaBuildTools *build_tools_parent = LATEXILA_BUILD_TOOLS (build_tools);
  GList *node;

  g_return_if_fail (LATEXILA_IS_BUILD_TOOLS_PERSONAL (build_tools));

  node = g_list_nth (build_tools_parent->build_tools, position);
  g_return_if_fail (node != NULL);

  if (node->data != new_build_tool)
    {
388 389
      g_object_unref (node->data);
      node->data = g_object_ref (new_build_tool);
390 391 392 393

      g_signal_emit_by_name (build_tools, "modified");
    }
}