[gtranslator] codeview: Recover codeview plugin



commit d38b6256023f656dd0ad8361a3174848d691eb00
Author: Daniel GarcĂ­a Moreno <danigm wadobo com>
Date:   Sat Dec 29 11:35:55 2018 +0100

    codeview: Recover codeview plugin
    
    The codeview plugin shows the current string file and line in the
    original source code. So I recover this plugin as a builtin
    functionality.
    
    Close #39

 plugins/codeview/Makefile.am                       |  52 --
 plugins/codeview/gtr-codeview-dialog.ui            | 171 -----
 plugins/codeview/gtr-codeview-plugin.c             | 805 ---------------------
 plugins/codeview/gtr-codeview-plugin.h             |  58 --
 plugins/codeview/gtr-codeview.plugin.desktop.in    |   8 -
 ...ome.gtranslator.plugins.codeview.gschema.xml.in |  19 -
 src/codeview/gtr-codeview.c                        | 586 +++++++++++++++
 .../codeview/gtr-codeview.gresource.xml            |   1 -
 src/codeview/gtr-codeview.h                        |  34 +
 {plugins => src}/codeview/gtr-viewer.c             |  77 +-
 {plugins => src}/codeview/gtr-viewer.h             |  30 +-
 {plugins => src}/codeview/gtr-viewer.ui            |   0
 src/codeview/meson.build                           |  15 +
 src/gtr-window.c                                   |   8 +
 src/meson.build                                    |   6 +-
 15 files changed, 683 insertions(+), 1187 deletions(-)
---
diff --git a/src/codeview/gtr-codeview.c b/src/codeview/gtr-codeview.c
new file mode 100644
index 00000000..94229418
--- /dev/null
+++ b/src/codeview/gtr-codeview.c
@@ -0,0 +1,586 @@
+/*
+ * Copyright (C) 2018  Daniel Garcia Moreno <danigm gnome org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gtr-codeview.h"
+#include "gtr-context.h"
+#include "gtr-dirs.h"
+#include "gtr-utils.h"
+#include "gtr-viewer.h"
+#include "gtr-window.h"
+#include "gtr-window-activatable.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <string.h>
+#include <gio/gio.h>
+#include <ctype.h>
+
+typedef struct
+{
+  GtrWindow *window;
+  GSList *tags;
+} GtrCodeViewPrivate;
+
+struct _GtrCodeView
+{
+  GObject parent_instance;
+};
+
+enum
+{
+  PROP_0,
+  PROP_WINDOW
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtrCodeView, gtr_code_view, G_TYPE_OBJECT)
+
+static void
+insert_link (GtkTextBuffer *buffer,
+             GtkTextIter   *iter,
+             const gchar   *path,
+             gint          *line,
+             GtrCodeView   *codeview,
+             const gchar   *msgid)
+{
+  GtkTextTag *tag;
+  gchar *text;
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (codeview);
+
+  tag = gtk_text_buffer_create_tag (buffer, NULL,
+                                    "foreground", "blue",
+                                    "underline", PANGO_UNDERLINE_SINGLE,
+                                    NULL);
+
+  g_object_set_data (G_OBJECT (tag), "line", line);
+  g_object_set_data_full (G_OBJECT (tag), "path", g_strdup (path), g_free);
+  g_object_set_data_full (G_OBJECT (tag), "msgid", g_strdup (msgid), g_free);
+
+  text = g_strdup_printf ("%s:%d\n", path, GPOINTER_TO_INT (line));
+  gtk_text_buffer_insert_with_tags (buffer, iter, text, -1, tag, NULL);
+  g_free (text);
+
+  priv->tags = g_slist_prepend (priv->tags, tag);
+}
+
+static void
+show_source (GtrCodeView *codeview, const gchar *path, gint line)
+{
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (codeview);
+  gtr_show_viewer (priv->window, path, line);
+}
+
+static gboolean
+path_is_fake (const gchar *path)
+{
+  return g_str_has_suffix (path, ".h")
+    && !g_file_test (path, G_FILE_TEST_EXISTS);
+}
+
+static gchar *
+real_path (const gchar *path)
+{
+  gchar *result = g_strdup (path);
+
+  if (path_is_fake (path))
+    result[strlen (result) - 2] = '\0';
+
+  return result;
+}
+
+static int
+get_line_for_text (const gchar *path, const gchar *msgid)
+{
+  gchar *content, *str_found, *i, *escaped;
+  int result;
+
+  content = NULL;
+  result = 1;
+  escaped = g_markup_escape_text (msgid, -1);
+
+  if (!g_file_get_contents (path, &content, NULL, NULL))
+    goto out;
+
+  i = content;
+  while ((str_found = g_strstr_len (i, -1, escaped)))
+    {
+      gchar c;
+
+      i = str_found + strlen (escaped);
+      c = *i;
+      if (!isalpha (c) &&
+          !isalpha (*(str_found - 1)) && !(c == ':') && !(c == '_'))
+        break;
+    }
+  if (!str_found)
+    goto out;
+
+  for (i = content; i < str_found; i++)
+    if (*i == '\n')
+      result++;
+
+out:
+  g_free (content);
+  g_free (escaped);
+
+  return result;
+}
+
+static void
+follow_if_link (GtrCodeView *codeview, GtkWidget *text_view, GtkTextIter *iter)
+{
+  GSList *tags = NULL, *tagp = NULL;
+  GtrTab *tab;
+  GtrPo *po;
+  gchar *fullpath;
+  gchar *dirname;
+  GFile *location, *parent;
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (codeview);
+
+  tab = gtr_window_get_active_tab (priv->window);
+
+  if (!tab)
+    return;
+  po = gtr_tab_get_po (tab);
+
+  location = gtr_po_get_location (po);
+  parent = g_file_get_parent (location);
+  g_object_unref (location);
+
+  dirname = g_file_get_path (parent);
+  g_object_unref (parent);
+
+  tags = gtk_text_iter_get_tags (iter);
+  for (tagp = tags; tagp != NULL; tagp = tagp->next)
+    {
+      GtkTextTag *tag = tagp->data;
+      gchar *path = g_object_get_data (G_OBJECT (tag), "path");
+      gint line = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "line"));
+
+      fullpath = g_build_filename (dirname, path, NULL);
+
+      if (path_is_fake (fullpath))
+        {
+          gchar *msgid = g_object_get_data (G_OBJECT (tag), "msgid");
+
+          path = g_strdup (fullpath);
+          g_free (fullpath);
+          fullpath = real_path (path);
+          g_free (path);
+
+          line = get_line_for_text (fullpath, msgid);
+        }
+
+      show_source (codeview, fullpath, line);
+
+      g_free (fullpath);
+    }
+
+  if (tags)
+    g_slist_free (tags);
+
+  g_free (dirname);
+}
+
+static gboolean
+event_after (GtkWidget *text_view, GdkEvent *ev, GtrCodeView *codeview)
+{
+  GtkTextIter start, end, iter;
+  GtkTextBuffer *buffer;
+  GdkEventButton *event;
+  gint x, y;
+
+  if (ev->type != GDK_BUTTON_RELEASE)
+    return FALSE;
+
+  event = (GdkEventButton *) ev;
+
+  if (event->button != 1)
+    return FALSE;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+
+  /* we shouldn't follow a link if the user has selected something */
+  gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+  if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
+    return FALSE;
+
+  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+                                         GTK_TEXT_WINDOW_WIDGET,
+                                         event->x, event->y, &x, &y);
+
+  gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y);
+
+  follow_if_link (codeview, text_view, &iter);
+
+  return FALSE;
+}
+
+static gboolean hovering_over_link = FALSE;
+static GdkCursor *hand_cursor = NULL;
+static GdkCursor *regular_cursor = NULL;
+
+/* Looks at all tags covering the position (x, y) in the text view,
+ * and if one of them is a link, change the cursor to the "hands" cursor
+ * typically used by web browsers.
+ */
+static void
+set_cursor_if_appropriate (GtkTextView *text_view, gint x, gint y)
+{
+  GSList *tags = NULL, *tagp = NULL;
+  GtkTextIter iter;
+  gboolean hovering = FALSE;
+
+  gtk_text_view_get_iter_at_location (text_view, &iter, x, y);
+
+  tags = gtk_text_iter_get_tags (&iter);
+  for (tagp = tags; tagp != NULL; tagp = tagp->next)
+    {
+      GtkTextTag *tag = tagp->data;
+      gchar *path = g_object_get_data (G_OBJECT (tag), "path");
+
+      if (path)
+        {
+          hovering = TRUE;
+          break;
+        }
+    }
+
+  if (hovering != hovering_over_link)
+    {
+      hovering_over_link = hovering;
+
+      if (hovering_over_link)
+        gdk_window_set_cursor (gtk_text_view_get_window (text_view,
+                                                         GTK_TEXT_WINDOW_TEXT),
+                               hand_cursor);
+      else
+        gdk_window_set_cursor (gtk_text_view_get_window (text_view,
+                                                         GTK_TEXT_WINDOW_TEXT),
+                               regular_cursor);
+    }
+
+  if (tags)
+    g_slist_free (tags);
+}
+
+/*
+ * Update the cursor image if the pointer moved.
+ */
+static gboolean
+motion_notify_event (GtkWidget *text_view, GdkEventMotion *event)
+{
+  gint x, y;
+
+  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+                                         GTK_TEXT_WINDOW_WIDGET,
+                                         event->x, event->y, &x, &y);
+
+  set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), x, y);
+
+  return FALSE;
+}
+
+/* Also update the cursor image if the window becomes visible
+ * (e.g. when a window covering it got iconified).
+ */
+static gboolean
+visibility_notify_event (GtkWidget *text_view, GdkEventVisibility *event)
+{
+  GdkDevice *pointer;
+  GdkSeat *seat;
+  gint wx, wy, bx, by;
+
+  seat = gdk_display_get_default_seat (gtk_widget_get_display (text_view));
+  pointer = gdk_seat_get_pointer (seat);
+  gdk_window_get_device_position (gtk_widget_get_window (text_view), pointer,
+                                  &wx, &wy, NULL);
+
+  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+                                         GTK_TEXT_WINDOW_WIDGET,
+                                         wx, wy, &bx, &by);
+
+  set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), bx, by);
+
+  return FALSE;
+}
+
+static void
+showed_message_cb (GtrTab *tab, GtrMsg *msg, GtrCodeView *codeview)
+{
+  const gchar *filename = NULL;
+  gint i = 0;
+  gint *line = NULL;
+  GtkTextIter iter;
+  GtkTextBuffer *buffer;
+  GtkTextView *view;
+  GtrContextPanel *panel;
+  GtkTextTag *bold;
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (codeview);
+
+  panel = gtr_tab_get_context_panel (tab);
+  view = gtr_context_panel_get_context_text_view (panel);
+
+  buffer = gtk_text_view_get_buffer (view);
+
+  gtk_text_buffer_get_end_iter (buffer, &iter);
+
+  /* Create the bold tag for header */
+  bold =
+    gtk_text_buffer_create_tag (buffer, NULL, "weight", PANGO_WEIGHT_BOLD,
+                                "weight-set", TRUE, NULL);
+
+  gtk_text_buffer_insert (buffer, &iter, "\n", 1);
+  gtk_text_buffer_insert_with_tags (buffer, &iter, _("Paths:"), -1, bold,
+                                    NULL);
+  gtk_text_buffer_insert (buffer, &iter, "\n", 1);
+
+  filename = gtr_msg_get_filename (msg, i);
+  while (filename)
+    {
+      line = gtr_msg_get_file_line (msg, i);
+      insert_link (buffer, &iter, filename, line, codeview,
+                   gtr_msg_get_msgid (msg));
+      i++;
+      filename = gtr_msg_get_filename (msg, i);
+    }
+
+  /*
+   * The tags are managed by buffer, so lets add a reference in the buffer
+   */
+  g_object_set_data (G_OBJECT (buffer), "link_tags", priv->tags);
+  priv->tags = NULL;
+}
+
+static void
+delete_text_and_tags (GtrTab *tab, GtrCodeView *codeview)
+{
+  GSList *tagp = NULL, *tags;
+  GtkTextBuffer *buffer;
+  GtrContextPanel *panel;
+  GtkTextView *view;
+  GtkTextIter start, end;
+  GtkTextMark *path_start, *path_end;
+
+  panel = gtr_tab_get_context_panel (tab);
+  view = gtr_context_panel_get_context_text_view (panel);
+
+  buffer = gtk_text_view_get_buffer (view);
+  path_start = gtk_text_buffer_get_mark (buffer, "path_start");
+
+  if (path_start == NULL)
+    return;
+
+  path_end = gtk_text_buffer_get_mark (buffer, "path_end");
+  tags = g_object_get_data (G_OBJECT (buffer), "link_tags");
+
+  for (tagp = tags; tagp != NULL; tagp = tagp->next)
+    {
+      GtkTextTag *tag = tagp->data;
+
+      g_object_set_data (G_OBJECT (tag), "path", NULL);
+      g_object_set_data (G_OBJECT (tag), "msgid", NULL);
+    }
+  g_slist_free (tags);
+
+  /*
+   * Deleting the text
+   */
+  gtk_text_buffer_get_iter_at_mark (buffer, &start, path_start);
+  gtk_text_buffer_get_iter_at_mark (buffer, &end, path_end);
+  gtk_text_buffer_delete (buffer, &start, &end);
+
+  /*
+   * Deleting the marks
+   */
+  gtk_text_buffer_delete_mark (buffer, path_start);
+  gtk_text_buffer_delete_mark (buffer, path_end);
+}
+
+static void
+message_edition_finished_cb (GtrTab      *tab,
+                             GtrMsg      *msg,
+                             GtrCodeView *codeview)
+{
+  delete_text_and_tags (tab, codeview);
+}
+
+static void
+on_context_panel_reloaded (GtrContextPanel *panel,
+                           GtrMsg          *msg,
+                           GtrCodeView     *codeview)
+{
+  GtrTab *tab;
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (codeview);
+
+  tab = gtr_window_get_active_tab (priv->window);
+
+  showed_message_cb (tab, msg, codeview);
+}
+
+static void
+page_added_cb (GtkNotebook *notebook,
+               GtkWidget   *child,
+               guint        page_num,
+               GtrCodeView *codeview)
+{
+  GtrContextPanel *panel;
+  GtkTextView *view;
+
+  panel = gtr_tab_get_context_panel (GTR_TAB (child));
+  view = gtr_context_panel_get_context_text_view (panel);
+
+  g_return_if_fail (GTK_IS_TEXT_VIEW (view));
+
+  g_signal_connect_after (child, "showed-message",
+                          G_CALLBACK (showed_message_cb), codeview);
+  g_signal_connect (child, "message-edition-finished",
+                    G_CALLBACK (message_edition_finished_cb), codeview);
+
+  g_signal_connect (view, "event-after", G_CALLBACK (event_after), codeview);
+  g_signal_connect (view, "motion-notify-event",
+                    G_CALLBACK (motion_notify_event), NULL);
+  g_signal_connect (view, "visibility-notify-event",
+                    G_CALLBACK (visibility_notify_event), NULL);
+  g_signal_connect (panel, "reloaded",
+                    G_CALLBACK (on_context_panel_reloaded), codeview);
+}
+
+static void
+gtr_code_view_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  GtrCodeView *code_view = GTR_CODE_VIEW (object);
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (code_view);
+
+  switch (prop_id)
+    {
+    case PROP_WINDOW:
+      priv->window = GTR_WINDOW (g_value_dup_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtr_code_view_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  GtrCodeView *code_view = GTR_CODE_VIEW (object);
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (code_view);
+
+  switch (prop_id)
+    {
+    case PROP_WINDOW:
+      g_value_set_object (value, priv->window);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtr_code_view_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (gtr_code_view_parent_class)->dispose (object);
+}
+
+static void
+gtr_code_view_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtr_code_view_parent_class)->finalize (object);
+}
+
+static void
+gtr_code_view_class_init (GtrCodeViewClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GParamSpec *param;
+
+  object_class->finalize = gtr_code_view_finalize;
+  object_class->dispose = gtr_code_view_dispose;
+  object_class->get_property = gtr_code_view_get_property;
+  object_class->set_property = gtr_code_view_set_property;
+
+  param = g_param_spec_object ("window", "WINDOW", "The window",
+                               GTR_TYPE_WINDOW,
+                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  g_object_class_install_property (object_class, PROP_WINDOW, param);
+}
+
+static void
+gtr_code_view_init (GtrCodeView *self)
+{
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (self);
+  priv->window = NULL;
+}
+
+GtrCodeView *
+gtr_code_view_new (GtrWindow *window)
+{
+  GtrCodeView *self = g_object_new (GTR_TYPE_CODE_VIEW,
+                                    "window", window, NULL);
+  GtrCodeViewPrivate *priv = gtr_code_view_get_instance_private (self);
+  GtkWidget *notebook;
+  GdkDisplay *display;
+  GList *tabs, *l;
+
+  notebook = GTK_WIDGET (gtr_window_get_notebook (priv->window));
+  display = gtk_widget_get_display (notebook);
+
+  /*
+   * Cursors
+   */
+  hand_cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
+  regular_cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
+
+  g_signal_connect (notebook, "page-added", G_CALLBACK (page_added_cb), self);
+
+  /*
+   * If we already have tabs opened we have to add them
+   */
+  tabs = gtr_window_get_all_tabs (priv->window);
+  for (l = tabs; l != NULL; l = g_list_next (l))
+    {
+      GtrPo *po;
+      GList *msg;
+
+      page_added_cb (GTK_NOTEBOOK (notebook), l->data, 0, self);
+
+      po = gtr_tab_get_po (GTR_TAB (l->data));
+      msg = gtr_po_get_current_message (po);
+
+      showed_message_cb (GTR_TAB (l->data), msg->data, self);
+    }
+
+  return self;
+}
diff --git a/plugins/codeview/gtr-codeview.gresource.xml b/src/codeview/gtr-codeview.gresource.xml
similarity index 75%
rename from plugins/codeview/gtr-codeview.gresource.xml
rename to src/codeview/gtr-codeview.gresource.xml
index 2f54a1c4..3393b1e9 100644
--- a/plugins/codeview/gtr-codeview.gresource.xml
+++ b/src/codeview/gtr-codeview.gresource.xml
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
  <gresource prefix="/org/gnome/gtranslator/plugins/codeview/ui">
-  <file preprocess="xml-stripblanks">gtr-codeview-dialog.ui</file>
   <file preprocess="xml-stripblanks">gtr-viewer.ui</file>
  </gresource>
 </gresources>
diff --git a/src/codeview/gtr-codeview.h b/src/codeview/gtr-codeview.h
new file mode 100644
index 00000000..02e82737
--- /dev/null
+++ b/src/codeview/gtr-codeview.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018  Daniel Garcia Moreno <danigm gnome org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <glib-object.h>
+#include "gtr-window.h"
+
+G_BEGIN_DECLS
+
+#define GTR_TYPE_CODE_VIEW (gtr_code_view_get_type())
+
+G_DECLARE_FINAL_TYPE (GtrCodeView, gtr_code_view, GTR, CODE_VIEW, GObject)
+
+GtrCodeView*  gtr_code_view_new (GtrWindow *window);
+
+G_END_DECLS
+
diff --git a/plugins/codeview/gtr-viewer.c b/src/codeview/gtr-viewer.c
similarity index 85%
rename from plugins/codeview/gtr-viewer.c
rename to src/codeview/gtr-viewer.c
index 6566e6b4..101b3282 100644
--- a/plugins/codeview/gtr-viewer.c
+++ b/src/codeview/gtr-viewer.c
@@ -33,23 +33,22 @@
 #include <string.h>
 #include <gtksourceview/gtksource.h>
 
-#define GTR_VIEWER_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ( \
-                                                       (object),       \
-                                                       GTR_TYPE_VIEWER,     \
-                                                       GtrViewerPrivate))
-
-
-G_DEFINE_TYPE (GtrViewer, gtr_viewer, GTK_TYPE_DIALOG)
-
-struct _GtrViewerPrivate
+typedef struct
 {
   GtkWidget *main_box;
   GtkWidget *view;
   GtkWidget *filename_label;
+} GtrViewerPrivate;
+
+struct _GtrViewer
+{
+  GtkDialog parent_instance;
 };
 
+G_DEFINE_TYPE_WITH_PRIVATE (GtrViewer, gtr_viewer, GTK_TYPE_DIALOG)
+
 static void
-dialog_response_handler (GtkDialog * dlg, gint res_id)
+dialog_response_handler (GtkDialog *dlg, gint res_id)
 {
   switch (res_id)
     {
@@ -59,10 +58,8 @@ dialog_response_handler (GtkDialog * dlg, gint res_id)
 }
 
 static void
-gtr_viewer_init (GtrViewer * dlg)
+gtr_viewer_init (GtrViewer *dlg)
 {
-  GtrViewerPrivate *priv;
-  GtkWidget *action_area;
   GtkBox *content_area;
   GtkWidget *sw;
   GtkBuilder *builder;
@@ -70,27 +67,18 @@ gtr_viewer_init (GtrViewer * dlg)
     "main_box",
     NULL
   };
-
-  dlg->priv = GTR_VIEWER_GET_PRIVATE (dlg);
-  priv = dlg->priv;
+  GtrViewerPrivate *priv = gtr_viewer_get_instance_private (dlg);
 
   gtk_dialog_add_buttons (GTK_DIALOG (dlg),
-                          GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
+                          _("_Close"), GTK_RESPONSE_CLOSE, NULL);
 
   gtk_window_set_title (GTK_WINDOW (dlg), _("Source Viewer"));
   gtk_window_set_default_size (GTK_WINDOW (dlg), 800, 600);
   gtk_window_set_resizable (GTK_WINDOW (dlg), TRUE);
   gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
 
-  action_area = gtk_dialog_get_action_area (GTK_DIALOG (dlg));
   content_area = GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg)));
 
-  /* HIG defaults */
-  gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
-  gtk_box_set_spacing (content_area, 2);    /* 2 * 5 + 2 = 12 */
-  gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
-  gtk_box_set_spacing (GTK_BOX (action_area), 4);
-
   g_signal_connect (dlg,
                     "response", G_CALLBACK (dialog_response_handler), NULL);
 
@@ -98,7 +86,7 @@ gtr_viewer_init (GtrViewer * dlg)
   builder = gtk_builder_new ();
   gtk_builder_add_objects_from_resource (builder, "/org/gnome/gtranslator/plugins/codeview/ui/gtr-viewer.ui",
   root_objects, NULL);
- 
+
   priv->main_box = GTK_WIDGET (gtk_builder_get_object (builder, "main_box"));
   g_object_ref (priv->main_box);
   sw = GTK_WIDGET (gtk_builder_get_object (builder, "scrolledwindow"));
@@ -110,7 +98,7 @@ gtr_viewer_init (GtrViewer * dlg)
   gtk_container_set_border_width (GTK_CONTAINER (priv->main_box), 5);
 
   /* Source view */
-  dlg->priv->view = gtk_source_view_new ();
+  priv->view = gtk_source_view_new ();
   gtk_text_view_set_editable (GTK_TEXT_VIEW (priv->view), FALSE);
   gtk_widget_show (priv->view);
   gtk_container_add (GTK_CONTAINER (sw), priv->view);
@@ -126,25 +114,23 @@ gtr_viewer_init (GtrViewer * dlg)
 }
 
 static void
-gtr_viewer_finalize (GObject * object)
+gtr_viewer_finalize (GObject *object)
 {
   G_OBJECT_CLASS (gtr_viewer_parent_class)->finalize (object);
 }
 
 static void
-gtr_viewer_class_init (GtrViewerClass * klass)
+gtr_viewer_class_init (GtrViewerClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  g_type_class_add_private (klass, sizeof (GtrViewerPrivate));
-
   object_class->finalize = gtr_viewer_finalize;
 }
 
 /***************** File loading *****************/
 
 static void
-error_dialog (GtkWindow * parent, const gchar * msg, ...)
+error_dialog (GtkWindow *parent, const gchar *msg, ...)
 {
   va_list ap;
   gchar *tmp;
@@ -165,8 +151,9 @@ error_dialog (GtkWindow * parent, const gchar * msg, ...)
 }
 
 static gboolean
-gtk_source_buffer_load_file (GtkSourceBuffer * source_buffer,
-                             const gchar * filename, GError ** error)
+gtk_source_buffer_load_file (GtkSourceBuffer *source_buffer,
+                             const gchar     *filename,
+                             GError         **error)
 {
   GtkTextIter iter;
   gchar *buffer;
@@ -208,7 +195,7 @@ gtk_source_buffer_load_file (GtkSourceBuffer * source_buffer,
 }
 
 static void
-remove_all_marks (GtkSourceBuffer * buffer)
+remove_all_marks (GtkSourceBuffer *buffer)
 {
   GtkTextIter s, e;
 
@@ -220,7 +207,7 @@ remove_all_marks (GtkSourceBuffer * buffer)
 /* Note this is wrong for several reasons, e.g. g_pattern_match is broken
  * for glob matching. */
 static GtkSourceLanguage *
-get_language_for_filename (const gchar * filename)
+get_language_for_filename (const gchar *filename)
 {
   const gchar *const *languages;
   gchar *filename_utf8;
@@ -264,7 +251,7 @@ get_language_for_filename (const gchar * filename)
 }
 
 static GtkSourceLanguage *
-get_language_for_file (const gchar * filename)
+get_language_for_file (const gchar *filename)
 {
   GtkSourceLanguage *language = NULL;
 
@@ -275,7 +262,7 @@ get_language_for_file (const gchar * filename)
 }
 
 static GtkSourceLanguage *
-get_language_by_id (const gchar * id)
+get_language_by_id (const gchar *id)
 {
   GtkSourceLanguageManager *manager;
   manager = gtk_source_language_manager_get_default ();
@@ -283,7 +270,7 @@ get_language_by_id (const gchar * id)
 }
 
 static GtkSourceLanguage *
-get_language (GtkTextBuffer * buffer, const gchar * filename)
+get_language (GtkTextBuffer *buffer, const gchar *filename)
 {
   GtkSourceLanguage *language = NULL;
   GtkTextIter start, end;
@@ -320,7 +307,7 @@ get_language (GtkTextBuffer * buffer, const gchar * filename)
 }
 
 static gboolean
-open_file (GtkSourceBuffer * buffer, const gchar * filename)
+open_file (GtkSourceBuffer *buffer, const gchar *filename)
 {
   GtkSourceLanguage *language = NULL;
   gchar *freeme = NULL;
@@ -388,7 +375,7 @@ out:
 }
 
 static void
-jump_to_line (GtkTextView * view, gint line)
+jump_to_line (GtkTextView *view, gint line)
 {
   GtkTextBuffer *buffer;
   GtkTextIter iter;
@@ -411,9 +398,10 @@ jump_to_line (GtkTextView * view, gint line)
 }
 
 void
-gtr_show_viewer (GtrWindow * window, const gchar * path, gint line)
+gtr_show_viewer (GtrWindow *window, const gchar *path, gint line)
 {
   static GtrViewer *dlg = NULL;
+  GtrViewerPrivate *priv;
 
   g_return_if_fail (GTR_IS_WINDOW (window));
 
@@ -423,16 +411,17 @@ gtr_show_viewer (GtrWindow * window, const gchar * path, gint line)
       gchar *label;
 
       dlg = g_object_new (GTR_TYPE_VIEWER, NULL);
+      priv = gtr_viewer_get_instance_private (dlg);
 
       buffer =
         GTK_SOURCE_BUFFER (gtk_text_view_get_buffer
-                           (GTK_TEXT_VIEW (dlg->priv->view)));
+                           (GTK_TEXT_VIEW (priv->view)));
 
       open_file (buffer, path);
-      jump_to_line (GTK_TEXT_VIEW (dlg->priv->view), line);
+      jump_to_line (GTK_TEXT_VIEW (priv->view), line);
 
       label = g_strdup_printf ("<b>%s</b>", g_path_get_basename (path));
-      gtk_label_set_markup (GTK_LABEL (dlg->priv->filename_label), label);
+      gtk_label_set_markup (GTK_LABEL (priv->filename_label), label);
       g_free (label);
 
       g_signal_connect (dlg,
diff --git a/plugins/codeview/gtr-viewer.h b/src/codeview/gtr-viewer.h
similarity index 55%
rename from plugins/codeview/gtr-viewer.h
rename to src/codeview/gtr-viewer.h
index b709fe89..5b5d6a7e 100644
--- a/plugins/codeview/gtr-viewer.h
+++ b/src/codeview/gtr-viewer.h
@@ -16,8 +16,7 @@
  *
  */
 
-#ifndef __VIEWER_H__
-#define __VIEWER_H__
+#pragma once
 
 #include <glib.h>
 #include <glib-object.h>
@@ -27,31 +26,9 @@
 
 G_BEGIN_DECLS
 
-#define GTR_TYPE_VIEWER                (gtr_viewer_get_type ())
-#define GTR_VIEWER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_VIEWER, GtrViewer))
-#define GTR_VIEWER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_VIEWER, GtrViewerClass))
-#define GTR_IS_VIEWER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_VIEWER))
-#define GTR_IS_VIEWER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_VIEWER))
-#define GTR_VIEWER_GET_CLASS(o)        (G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_VIEWER, GtrViewerClass))
+#define GTR_TYPE_VIEWER (gtr_viewer_get_type())
 
-typedef struct _GtrViewer        GtrViewer;
-typedef struct _GtrViewerPrivate GtrViewerPrivate;
-typedef struct _GtrViewerClass   GtrViewerClass;
-
-struct _GtrViewer
-{
-  GtkDialog parent_instance;
-
-  /*< private > */
-  GtrViewerPrivate *priv;
-};
-
-struct _GtrViewerClass
-{
-  GtkDialogClass parent_class;
-};
-
-GType   gtr_viewer_get_type           (void) G_GNUC_CONST;
+G_DECLARE_FINAL_TYPE (GtrViewer, gtr_viewer, GTR, VIEWER, GtkDialog)
 
 GType   gtr_viewer_register_type      (GTypeModule  *module);
 
@@ -60,4 +37,3 @@ void    gtr_show_viewer               (GtrWindow    *window,
                                        gint          line);
 
 G_END_DECLS
-#endif /* __VIEWER_H__ */
diff --git a/plugins/codeview/gtr-viewer.ui b/src/codeview/gtr-viewer.ui
similarity index 100%
rename from plugins/codeview/gtr-viewer.ui
rename to src/codeview/gtr-viewer.ui
diff --git a/src/codeview/meson.build b/src/codeview/meson.build
new file mode 100644
index 00000000..d4c38889
--- /dev/null
+++ b/src/codeview/meson.build
@@ -0,0 +1,15 @@
+codeview_inc = include_directories('.')
+
+codeview_sources = files(
+  'gtr-codeview.c',
+  'gtr-viewer.c',
+)
+
+resource_data = files('gtr-viewer.ui')
+
+codeview_sources += gnome.compile_resources(
+  'gtr-codeview-resources',
+  'gtr-codeview.gresource.xml',
+  dependencies: resource_data,
+  export: true,
+)
diff --git a/src/gtr-window.c b/src/gtr-window.c
index df9a78f0..c704e7c0 100644
--- a/src/gtr-window.c
+++ b/src/gtr-window.c
@@ -46,6 +46,8 @@
 #include "translation-memory/gtr-translation-memory-dialog.h"
 #include "translation-memory/gda/gtr-gda.h"
 
+#include "codeview/gtr-codeview.h"
+
 #include <glib.h>
 #include <glib-object.h>
 #include <glib/gi18n.h>
@@ -67,6 +69,8 @@ typedef struct
   GSettings *tm_settings;
   GtrTranslationMemory *translation_memory;
 
+  GtrCodeView *codeview;
+
   GtkWidget *header_bar;
   GtkWidget *main_box;
 
@@ -782,6 +786,9 @@ gtr_window_init (GtrWindow *window)
                                                             "max-length-diff"));
   gtr_translation_memory_set_max_items (priv->translation_memory, 10);
 
+  // code view
+  priv->codeview = gtr_code_view_new (window);
+
   gtr_window_show_projects (window);
 }
 
@@ -813,6 +820,7 @@ gtr_window_dispose (GObject * object)
   g_clear_object (&priv->prof_manager);
   g_clear_object (&priv->translation_memory);
   g_clear_object (&priv->tm_settings);
+  g_clear_object (&priv->codeview);
 
   G_OBJECT_CLASS (gtr_window_parent_class)->dispose (object);
 }
diff --git a/src/meson.build b/src/meson.build
index 7274aa66..d47e25c9 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,6 +1,7 @@
 src_inc = include_directories('.')
 
 subdir('translation-memory')
+subdir('codeview')
 
 enum_headers = files(
   'gtr-application.h',
@@ -122,11 +123,12 @@ sources += gnome.compile_resources(
 incs = [
   top_inc,
   translation_mem_inc,
+  codeview_inc,
 ]
 
 libgtranslator = shared_library(
   meson.project_name(),
-  sources: sources + translation_mem_sources,
+  sources: sources + translation_mem_sources + codeview_sources,
   include_directories: incs,
   dependencies: gtr_deps,
 )
@@ -147,4 +149,4 @@ executable(
   dependencies: gtr_deps,
   objects: libgtranslator.extract_all_objects(),
   install: true,
-)
\ No newline at end of file
+)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]