[gedit/zbrown/deteplification: 1/3] deteplification: the mega commit
- From: Zander Brown <zbrown src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit/zbrown/deteplification: 1/3] deteplification: the mega commit
- Date: Sat, 10 Apr 2021 12:20:08 +0000 (UTC)
commit a2fb7158e6506cdeb91c82cebc29e342a460c04f
Author: Zander Brown <zbrown gnome org>
Date: Sat Apr 10 06:06:32 2021 +0100
deteplification: the mega commit
TODO: Explain this
build-aux/flatpak/org.gnome.gedit.yml | 15 +-
build-aux/snap/snapcraft.yaml | 27 +-
data/org.gnome.gedit.gschema.xml.in | 5 +
docs/gedit-development-getting-started.md | 8 +-
docs/reference/api-breaks.xml | 7 -
docs/reference/gedit-docs.xml | 1 +
docs/reference/gedit-sections.txt | 36 +
docs/reference/meson.build | 6 +-
docs/roadmap.md | 3 +-
gedit/Gedit-3.0.metadata | 1 +
gedit/gedit-app-osx.m | 4 +-
gedit/gedit-app-private.h | 3 +
gedit/gedit-app.c | 54 +-
gedit/gedit-commands-edit.c | 28 +-
gedit/gedit-commands-file.c | 26 +-
gedit/gedit-commands-search.c | 7 +-
gedit/gedit-commands-view.c | 42 +-
gedit/gedit-debug.c | 4 +
gedit/gedit-debug.h | 2 +
gedit/gedit-document-private.h | 12 +-
gedit/gedit-document.c | 534 +++++++-
gedit/gedit-document.h | 18 +-
gedit/gedit-documents-panel.c | 3 +-
gedit/gedit-factory.c | 50 -
gedit/gedit-factory.h | 53 -
gedit/gedit-file-chooser-dialog-gtk.c | 72 +-
gedit/gedit-file-chooser-dialog-gtk.h | 9 +-
gedit/gedit-file-chooser-dialog.c | 40 +-
gedit/gedit-file-chooser-dialog.h | 17 +
gedit/gedit-highlight-mode-dialog.c | 102 ++
gedit/gedit-highlight-mode-dialog.h | 41 +
gedit/gedit-highlight-mode-selector.c | 375 ++++++
gedit/gedit-highlight-mode-selector.h | 44 +
gedit/gedit-io-error-info-bar.c | 362 +++++-
gedit/gedit-io-error-info-bar.h | 10 +
gedit/gedit-metadata-manager.c | 650 ++++++++++
gedit/gedit-metadata-manager.h | 49 +
gedit/gedit-open-document-selector-helper.c | 103 ++
gedit/gedit-open-document-selector-helper.h | 103 ++
gedit/gedit-open-document-selector-store.c | 820 ++++++++++++
gedit/gedit-open-document-selector-store.h | 68 +
gedit/gedit-open-document-selector.c | 1304 ++++++++++++++++++++
gedit/gedit-open-document-selector.h | 44 +
gedit/gedit-pango.c | 230 ++++
gedit/gedit-pango.h | 28 +
gedit/gedit-preferences-dialog.c | 447 ++++---
gedit/gedit-print-job.c | 4 +-
gedit/gedit-progress-info-bar.c | 177 +++
gedit/gedit-progress-info-bar.h | 53 +
gedit/gedit-recent-osx.c | 249 ----
gedit/gedit-recent-osx.h | 54 -
gedit/gedit-recent.c | 231 +++-
gedit/gedit-recent.h | 23 +-
gedit/gedit-settings.c | 177 +--
gedit/gedit-settings.h | 7 +-
gedit/gedit-tab.c | 115 +-
gedit/gedit-utils.c | 333 ++++-
gedit/gedit-utils.h | 21 +-
gedit/gedit-view-centering.c | 495 ++++++++
gedit/gedit-view-centering.h | 67 +
gedit/gedit-view-frame.c | 37 +-
gedit/gedit-view-frame.h | 4 +
gedit/gedit-view.c | 322 ++++-
gedit/gedit-view.h | 24 +-
gedit/gedit-window-private.h | 15 +-
gedit/gedit-window.c | 380 +++---
gedit/gedit.c | 8 +-
gedit/meson.build | 23 +-
gedit/resources/css/gedit-style.css | 12 +
gedit/resources/css/gedit.adwaita.css | 25 +
gedit/resources/gedit.gresource.xml.in | 4 +
gedit/resources/ui/gedit-highlight-mode-dialog.ui | 87 ++
.../resources/ui/gedit-highlight-mode-selector.ui | 83 ++
gedit/resources/ui/gedit-open-document-selector.ui | 115 ++
gedit/resources/ui/gedit-preferences-dialog.ui | 30 +-
gedit/resources/ui/gedit-progress-info-bar.ui | 88 ++
gedit/resources/ui/gedit-view-frame.ui | 30 +-
gedit/resources/ui/gedit-window.ui | 87 +-
help/C/gedit-tab-groups.page | 4 +-
meson.build | 34 +-
meson_options.txt | 7 +
plugins/snippets/snippets/document.py | 10 +-
plugins/spell/gedit-spell-plugin.c | 9 +-
po/POTFILES.in | 8 +-
84 files changed, 8099 insertions(+), 1220 deletions(-)
---
diff --git a/build-aux/flatpak/org.gnome.gedit.yml b/build-aux/flatpak/org.gnome.gedit.yml
index 1438abd07..d3b535176 100644
--- a/build-aux/flatpak/org.gnome.gedit.yml
+++ b/build-aux/flatpak/org.gnome.gedit.yml
@@ -59,17 +59,12 @@ modules:
url: https://download.gnome.org/sources/gspell/1.9/gspell-1.9.1.tar.xz
sha256: dcbb769dfdde8e3c0a8ed3102ce7e661abbf7ddf85df08b29915e92cd723abdd
- - name: amtk
- buildsystem: meson
+ - name: uchardet
+ buildsystem: cmake-ninja
sources:
- - type: git
- url: https://gitlab.gnome.org/GNOME/amtk.git
-
- - name: tepl
- buildsystem: meson
- sources:
- - type: git
- url: https://gitlab.gnome.org/GNOME/tepl.git
+ - type: archive
+ url: https://www.freedesktop.org/software/uchardet/releases/uchardet-0.0.6.tar.xz
+ sha256: 8351328cdfbcb2432e63938721dd781eb8c11ebc56e3a89d0f84576b96002c61
- name: gedit
buildsystem: meson
diff --git a/build-aux/snap/snapcraft.yaml b/build-aux/snap/snapcraft.yaml
index fc49c3949..43db5e027 100644
--- a/build-aux/snap/snapcraft.yaml
+++ b/build-aux/snap/snapcraft.yaml
@@ -41,30 +41,6 @@ apps:
GTK_USE_PORTAL: 1
parts:
- amtk:
- source: https://gitlab.gnome.org/GNOME/amtk.git
- source-type: git
- plugin: autotools
- configflags:
- - --prefix=/usr
- - --enable-introspection=no
- organize:
- snap/gedit/current/usr: usr
-
- tepl:
- after: [amtk, gtksourceview]
- source: https://gitlab.gnome.org/GNOME/tepl.git
- source-type: git
- plugin: meson
- meson-parameters:
- - --prefix=/usr
- organize:
- snap/gedit/current/usr: usr
- build-packages:
- - libuchardet-dev
- stage-packages:
- - libuchardet0
-
gtksourceview:
source: https://gitlab.gnome.org/GNOME/gtksourceview.git
source-type: git
@@ -94,7 +70,7 @@ parts:
cp $SNAPCRAFT_PART_INSTALL/usr/share/vala/vapi/gtksource* /usr/share/vala/vapi
gedit:
- after: [gtksourceview, tepl]
+ after: [gtksourceview]
source: .
source-type: git
parse-info: [usr/share/metainfo/org.gnome.gedit.appdata.xml]
@@ -102,6 +78,7 @@ parts:
meson-parameters:
- --prefix=/usr
- -Dvala_args="--vapidir=$SNAPCRAFT_STAGE/usr/share/vala/vapi"
+
build-environment:
- C_INCLUDE_PATH: $SNAPCRAFT_STAGE/usr/include/gtksourceview-4
override-build: |
diff --git a/data/org.gnome.gedit.gschema.xml.in b/data/org.gnome.gedit.gschema.xml.in
index b797d843c..59325f4ef 100644
--- a/data/org.gnome.gedit.gschema.xml.in
+++ b/data/org.gnome.gedit.gschema.xml.in
@@ -126,6 +126,11 @@
<summary>Right Margin Position</summary>
<description>Specifies the position of the right margin.</description>
</key>
+ <key name="display-overview-map" type="b">
+ <default>false</default>
+ <summary>Display Overview Map</summary>
+ <description>Whether gedit should display the overview map for the document.</description>
+ </key>
<key name="background-pattern" enum="org.gnome.gedit.BackgroundPatternType">
<default>'none'</default>
<summary>Document background pattern type</summary>
diff --git a/docs/gedit-development-getting-started.md b/docs/gedit-development-getting-started.md
index 4f930afc7..774bc180f 100644
--- a/docs/gedit-development-getting-started.md
+++ b/docs/gedit-development-getting-started.md
@@ -31,11 +31,9 @@ editor. To learn that widget API, read the excellent
mostly valid). But GtkTextView is not enough for source code edition. gedit
actually uses the
[GtkSourceView](https://wiki.gnome.org/Projects/GtkSourceView) library, which
-contains a subclass of GtkTextView with many features useful for a text editor
-or an IDE. But GtkSourceView is not enough to have a full-blown text editor,
-gedit is actually in the process of using more features from the
-[Tepl](https://wiki.gnome.org/Projects/Tepl) library, and to further develop
-Tepl alongside gedit.
+contains a subclass of GtkTextView with syntax highlighting, a completion
+framework, the search and replace, and many other features useful for a text
+editor or an IDE.
For its plugin system, gedit uses the
[libpeas](https://wiki.gnome.org/Projects/Libpeas) library.
diff --git a/docs/reference/api-breaks.xml b/docs/reference/api-breaks.xml
index f631761a6..a239cc443 100644
--- a/docs/reference/api-breaks.xml
+++ b/docs/reference/api-breaks.xml
@@ -96,13 +96,6 @@
<code>gedit_app_get_lockdown()</code> function has been removed.
</para>
</listitem>
- <listitem>
- <para>
- The <code>GBOOLEAN_TO_POINTER()</code> and
- <code>GPOINTER_TO_BOOLEAN()</code> macros have been removed from
- <code>gedit-utils.h</code>.
- </para>
- </listitem>
<listitem>
<para>
The <code>gedit_utils_get_current_workspace()</code>,
diff --git a/docs/reference/gedit-docs.xml b/docs/reference/gedit-docs.xml
index a0dc624cf..9e32e5469 100644
--- a/docs/reference/gedit-docs.xml
+++ b/docs/reference/gedit-docs.xml
@@ -16,6 +16,7 @@
<xi:include href="xml/gedit-menu-extension.xml"/>
<xi:include href="xml/gedit-message-bus.xml"/>
<xi:include href="xml/gedit-message.xml"/>
+ <xi:include href="xml/gedit-progress-info-bar.xml"/>
<xi:include href="xml/gedit-statusbar.xml"/>
<xi:include href="xml/gedit-tab.xml"/>
<xi:include href="xml/gedit-view.xml"/>
diff --git a/docs/reference/gedit-sections.txt b/docs/reference/gedit-sections.txt
index cec055fce..a71e00faa 100644
--- a/docs/reference/gedit-sections.txt
+++ b/docs/reference/gedit-sections.txt
@@ -54,7 +54,10 @@ gedit_document_new
gedit_document_get_file
gedit_document_get_short_name_for_display
gedit_document_get_mime_type
+gedit_document_is_untouched
gedit_document_is_untitled
+gedit_document_goto_line
+gedit_document_goto_line_offset
gedit_document_set_language
gedit_document_get_content_type
gedit_document_get_metadata
@@ -148,6 +151,26 @@ GEDIT_MESSAGE_GET_CLASS
GeditMessagePrivate
</SECTION>
+<SECTION>
+<FILE>gedit-progress-info-bar</FILE>
+<TITLE>GeditProgressInfoBar</TITLE>
+GeditProgressInfoBar
+gedit_progress_info_bar_new
+gedit_progress_info_bar_set_icon_name
+gedit_progress_info_bar_set_markup
+gedit_progress_info_bar_set_text
+gedit_progress_info_bar_set_fraction
+gedit_progress_info_bar_pulse
+<SUBSECTION Standard>
+GEDIT_PROGRESS_INFO_BAR
+GEDIT_IS_PROGRESS_INFO_BAR
+GEDIT_TYPE_PROGRESS_INFO_BAR
+gedit_progress_info_bar_get_type
+GEDIT_PROGRESS_INFO_BAR_CLASS
+GEDIT_IS_PROGRESS_INFO_BAR_CLASS
+GEDIT_PROGRESS_INFO_BAR_GET_CLASS
+</SECTION>
+
<SECTION>
<FILE>gedit-statusbar</FILE>
<TITLE>GeditStatusbar</TITLE>
@@ -199,6 +222,13 @@ GeditViewPrivate
<TITLE>GeditView</TITLE>
GeditView
gedit_view_new
+gedit_view_cut_clipboard
+gedit_view_copy_clipboard
+gedit_view_paste_clipboard
+gedit_view_delete_selection
+gedit_view_select_all
+gedit_view_scroll_to_cursor
+gedit_view_set_font
<SUBSECTION Standard>
GEDIT_VIEW
GEDIT_IS_VIEW
@@ -291,6 +321,7 @@ DEBUG_DOCUMENT
DEBUG_COMMANDS
DEBUG_APP
DEBUG_UTILS
+DEBUG_METADATA
gedit_debug_init
gedit_debug
gedit_debug_message
@@ -321,9 +352,14 @@ gedit_menu_extension_get_type
<SECTION>
<FILE>gedit-utils</FILE>
+GBOOLEAN_TO_POINTER
+GPOINTER_TO_BOOLEAN
gedit_utils_menu_position_under_tree_view
gedit_utils_set_atk_name_description
+gedit_warning
+gedit_utils_replace_home_dir_with_tilde
gedit_utils_basename_for_display
+gedit_utils_decode_uri
gedit_utils_drop_get_uris
gedit_utils_get_compression_type_from_content_type
gedit_utils_is_valid_location
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index 9a9c414dc..ed85f9cec 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -6,14 +6,12 @@ gio_docpath = dependency('gio-2.0').get_pkgconfig_variable('prefix') / 'share/gt
gdk_docpath = dependency('gdk-3.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/gdk3'
gtk_docpath = dependency('gtk+-3.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/gtk3'
gsv_docpath = dependency('gtksourceview-4').get_pkgconfig_variable('prefix') /
'share/gtk-doc/html/gtksourceview-4.0'
-amtk_docpath = dependency('amtk-5').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/amtk-5'
-tepl_docpath = dependency('tepl-6').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/tepl-6'
libpeas_docpath = dependency('libpeas-1.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/libpeas'
gedit_doc_dep = declare_dependency(
link_with: libgedit_shared_lib,
include_directories: root_include_dir,
- dependencies: deps_basic_list,
+ dependencies: deps_basic_list + [libxml_dep],
)
gnome.gtkdoc(
@@ -30,8 +28,6 @@ gnome.gtkdoc(
'--extra-dir=@0@'.format(gdk_docpath),
'--extra-dir=@0@'.format(gtk_docpath),
'--extra-dir=@0@'.format(gsv_docpath),
- '--extra-dir=@0@'.format(amtk_docpath),
- '--extra-dir=@0@'.format(tepl_docpath),
'--extra-dir=@0@'.format(libpeas_docpath),
],
content_files: [
diff --git a/docs/roadmap.md b/docs/roadmap.md
index 44a2f00b7..8199749b4 100644
--- a/docs/roadmap.md
+++ b/docs/roadmap.md
@@ -4,7 +4,8 @@ gedit roadmap
This page contains the plans for major code changes we hope to get done in the
future.
-See the [roadmap-done.md](roadmap-done.md) file for done tasks.
+See also the
+[GtkSourceView and Tepl roadmap](https://wiki.gnome.org/Projects/GtkSourceView/RoadMap).
See the [NEWS file](../NEWS) for a detailed history.
diff --git a/gedit/Gedit-3.0.metadata b/gedit/Gedit-3.0.metadata
index e36d7cb30..1a5b45a3a 100644
--- a/gedit/Gedit-3.0.metadata
+++ b/gedit/Gedit-3.0.metadata
@@ -6,6 +6,7 @@ EncodingsComboBox cheader_filename="gedit/gedit-encodings-combo-box.h"
MenuExtension cheader_filename="gedit/gedit-menu-extension.h"
Message cheader_filename="gedit/gedit-message.h"
MessageBus cheader_filename="gedit/gedit-message-bus.h"
+ProgressInfoBar cheader_filename="gedit/gedit-progress-info-bar.h"
Statusbar cheader_filename="gedit/gedit-statusbar.h"
Tab cheader_filename="gedit/gedit-tab.h"
TabState cheader_filename="gedit/gedit-tab.h"
diff --git a/gedit/gedit-app-osx.m b/gedit/gedit-app-osx.m
index b02e9a28b..5df1b94da 100644
--- a/gedit/gedit-app-osx.m
+++ b/gedit/gedit-app-osx.m
@@ -31,7 +31,7 @@
#include "gedit-debug.h"
#include "gedit-commands.h"
#include "gedit-commands-private.h"
-#include "gedit-recent-osx.h"
+#include "gedit-recent.h"
#import <AppKit/AppKit.h>
NSWindow *gdk_quartz_window_get_nswindow(GdkWindow *window);
@@ -286,7 +286,7 @@ gedit_app_osx_set_window_title_impl (GeditApp *app,
g_free (uri);
}
- ismodified = !tepl_buffer_is_untouched (TEPL_BUFFER (document));
+ ismodified = !gedit_document_is_untouched (document);
[native setDocumentEdited:ismodified];
}
else
diff --git a/gedit/gedit-app-private.h b/gedit/gedit-app-private.h
index 6e1278a3b..e9c58cc27 100644
--- a/gedit/gedit-app-private.h
+++ b/gedit/gedit-app-private.h
@@ -22,6 +22,7 @@
#define GEDIT_APP_PRIVATE_H
#include "gedit-app.h"
+#include "gedit-metadata-manager.h"
#include "gedit-menu-extension.h"
G_BEGIN_DECLS
@@ -34,6 +35,8 @@ GtkPrintSettings *_gedit_app_get_default_print_settings (GeditApp *app);
void _gedit_app_set_default_print_settings (GeditApp *app,
GtkPrintSettings *settings);
+GeditMetadataManager *_gedit_app_get_metadata_manager (GeditApp *app);
+
GMenuModel *_gedit_app_get_hamburger_menu (GeditApp *app);
GMenuModel *_gedit_app_get_notebook_menu (GeditApp *app);
diff --git a/gedit/gedit-app.c b/gedit/gedit-app.c
index 5532d5975..27d71a87a 100644
--- a/gedit/gedit-app.c
+++ b/gedit/gedit-app.c
@@ -28,8 +28,9 @@
#include <stdlib.h>
#include <glib/gi18n.h>
+#include <gio/gio.h>
#include <libpeas/peas-extension-set.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
#include "gedit-commands-private.h"
#include "gedit-notebook.h"
@@ -44,6 +45,10 @@
#include "gedit-preferences-dialog.h"
#include "gedit-tab.h"
+#ifndef ENABLE_GVFS_METADATA
+#include "gedit-metadata-manager.h"
+#endif
+
#define GEDIT_PAGE_SETUP_FILE "gedit-page-setup"
#define GEDIT_PRINT_SETTINGS_FILE "gedit-print-settings"
@@ -51,6 +56,10 @@ typedef struct
{
GeditPluginsEngine *engine;
+#ifndef ENABLE_GVFS_METADATA
+ GeditMetadataManager *metadata_manager;
+#endif
+
GtkCssProvider *theme_provider;
GtkPageSetup *page_setup;
@@ -145,6 +154,10 @@ gedit_app_dispose (GObject *object)
priv = gedit_app_get_instance_private (GEDIT_APP (object));
+#ifndef ENABLE_GVFS_METADATA
+ g_clear_object (&priv->metadata_manager);
+#endif
+
g_clear_object (&priv->ui_settings);
g_clear_object (&priv->window_settings);
@@ -643,6 +656,10 @@ gedit_app_startup (GApplication *application)
GeditAppPrivate *priv;
GtkCssProvider *css_provider;
GtkSourceStyleSchemeManager *manager;
+#ifndef ENABLE_GVFS_METADATA
+ const gchar *cache_dir;
+ gchar *metadata_filename;
+#endif
priv = gedit_app_get_instance_private (GEDIT_APP (application));
@@ -654,6 +671,13 @@ gedit_app_startup (GApplication *application)
setup_theme_extensions (GEDIT_APP (application));
+#ifndef ENABLE_GVFS_METADATA
+ cache_dir = gedit_dirs_get_user_cache_dir ();
+ metadata_filename = g_build_filename (cache_dir, "gedit-metadata.xml", NULL);
+ priv->metadata_manager = gedit_metadata_manager_new (metadata_filename);
+ g_free (metadata_filename);
+#endif
+
/* Load/init settings */
_gedit_settings_get_singleton ();
priv->ui_settings = g_settings_new ("org.gnome.gedit.preferences.ui");
@@ -1114,6 +1138,10 @@ gedit_app_shutdown (GApplication *app)
save_page_setup (GEDIT_APP (app));
save_print_settings (GEDIT_APP (app));
+ /* GTK+ can still hold references to some gedit objects, for example
+ * GeditDocument for the clipboard. So the metadata-manager should be
+ * shutdown after.
+ */
G_APPLICATION_CLASS (gedit_app_parent_class)->shutdown (app);
}
@@ -1253,15 +1281,10 @@ load_print_settings (GeditApp *app)
static void
gedit_app_init (GeditApp *app)
{
- TeplApplication *tepl_app;
-
g_set_application_name ("gedit");
gtk_window_set_default_icon_name ("org.gnome.gedit");
g_application_add_main_option_entries (G_APPLICATION (app), options);
-
- tepl_app = tepl_application_get_from_gtk_application (GTK_APPLICATION (app));
- tepl_application_handle_metadata (tepl_app);
}
/**
@@ -1571,6 +1594,25 @@ _gedit_app_set_default_print_settings (GeditApp *app,
priv->print_settings = g_object_ref (settings);
}
+
+GeditMetadataManager *
+_gedit_app_get_metadata_manager (GeditApp *app)
+{
+#ifndef ENABLE_GVFS_METADATA
+ GeditAppPrivate *priv;
+
+ g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
+
+ priv = gedit_app_get_instance_private (app);
+
+ return priv->metadata_manager;
+#else
+ g_assert_not_reached ();
+ return NULL;
+#endif
+}
+
+
GMenuModel *
_gedit_app_get_hamburger_menu (GeditApp *app)
{
diff --git a/gedit/gedit-commands-edit.c b/gedit/gedit-commands-edit.c
index 66ea0174b..978440150 100644
--- a/gedit/gedit-commands-edit.c
+++ b/gedit/gedit-commands-edit.c
@@ -44,13 +44,13 @@ _gedit_cmd_edit_undo (GSimpleAction *action,
gedit_debug (DEBUG_COMMANDS);
active_view = gedit_window_get_active_view (window);
- g_return_if_fail (active_view != NULL);
+ g_return_if_fail (active_view);
active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
gtk_source_buffer_undo (active_document);
- tepl_view_scroll_to_cursor (TEPL_VIEW (active_view));
+ gedit_view_scroll_to_cursor (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
@@ -67,13 +67,13 @@ _gedit_cmd_edit_redo (GSimpleAction *action,
gedit_debug (DEBUG_COMMANDS);
active_view = gedit_window_get_active_view (window);
- g_return_if_fail (active_view != NULL);
+ g_return_if_fail (active_view);
active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
gtk_source_buffer_redo (active_document);
- tepl_view_scroll_to_cursor (TEPL_VIEW (active_view));
+ gedit_view_scroll_to_cursor (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
@@ -89,9 +89,9 @@ _gedit_cmd_edit_cut (GSimpleAction *action,
gedit_debug (DEBUG_COMMANDS);
active_view = gedit_window_get_active_view (window);
- g_return_if_fail (active_view != NULL);
+ g_return_if_fail (active_view);
- tepl_view_cut_clipboard (TEPL_VIEW (active_view));
+ gedit_view_cut_clipboard (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
@@ -107,9 +107,9 @@ _gedit_cmd_edit_copy (GSimpleAction *action,
gedit_debug (DEBUG_COMMANDS);
active_view = gedit_window_get_active_view (window);
- g_return_if_fail (active_view != NULL);
+ g_return_if_fail (active_view);
- tepl_view_copy_clipboard (TEPL_VIEW (active_view));
+ gedit_view_copy_clipboard (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
@@ -125,9 +125,9 @@ _gedit_cmd_edit_paste (GSimpleAction *action,
gedit_debug (DEBUG_COMMANDS);
active_view = gedit_window_get_active_view (window);
- g_return_if_fail (active_view != NULL);
+ g_return_if_fail (active_view);
- tepl_view_paste_clipboard (TEPL_VIEW (active_view));
+ gedit_view_paste_clipboard (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
@@ -143,9 +143,9 @@ _gedit_cmd_edit_delete (GSimpleAction *action,
gedit_debug (DEBUG_COMMANDS);
active_view = gedit_window_get_active_view (window);
- g_return_if_fail (active_view != NULL);
+ g_return_if_fail (active_view);
- tepl_view_delete_selection (TEPL_VIEW (active_view));
+ gedit_view_delete_selection (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
@@ -161,9 +161,9 @@ _gedit_cmd_edit_select_all (GSimpleAction *action,
gedit_debug (DEBUG_COMMANDS);
active_view = gedit_window_get_active_view (window);
- g_return_if_fail (active_view != NULL);
+ g_return_if_fail (active_view);
- tepl_view_select_all (TEPL_VIEW (active_view));
+ gedit_view_select_all (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
diff --git a/gedit/gedit-commands-file.c b/gedit/gedit-commands-file.c
index 91798b95f..001899b0c 100644
--- a/gedit/gedit-commands-file.c
+++ b/gedit/gedit-commands-file.c
@@ -27,7 +27,6 @@
#include "gedit-commands-private.h"
#include <glib/gi18n.h>
-#include <tepl/tepl.h>
#include "gedit-app.h"
#include "gedit-debug.h"
@@ -44,10 +43,6 @@
#include "gedit-file-chooser-open.h"
#include "gedit-close-confirmation-dialog.h"
-/* useful macro */
-#define GBOOLEAN_TO_POINTER(i) (GINT_TO_POINTER ((i) ? 2 : 1))
-#define GPOINTER_TO_BOOLEAN(i) ((gboolean) ((GPOINTER_TO_INT(i) == 2) ? TRUE : FALSE))
-
#define GEDIT_IS_CLOSING_ALL "gedit-is-closing-all"
#define GEDIT_NOTEBOOK_TO_CLOSE "gedit-notebook-to-close"
#define GEDIT_IS_QUITTING "gedit-is-quitting"
@@ -150,24 +145,26 @@ load_file_list (GeditWindow *window,
{
if (l == files)
{
- TeplView *view;
+ GeditDocument *doc;
gedit_window_set_active_tab (window, tab);
jump_to = FALSE;
- view = TEPL_VIEW (gedit_tab_get_view (tab));
+ doc = gedit_tab_get_document (tab);
if (line_pos > 0)
{
if (column_pos > 0)
{
- tepl_view_goto_line_offset (view,
- line_pos - 1,
- column_pos - 1);
+ gedit_document_goto_line_offset (doc,
+ line_pos - 1,
+ column_pos - 1);
}
else
{
- tepl_view_goto_line (view, line_pos - 1);
+ gedit_document_goto_line (doc, line_pos - 1);
}
+
+ gedit_view_scroll_to_cursor (gedit_tab_get_view (tab));
}
}
@@ -194,7 +191,7 @@ load_file_list (GeditWindow *window,
doc = gedit_tab_get_document (tab);
- if (tepl_buffer_is_untouched (TEPL_BUFFER (doc)) &&
+ if (gedit_document_is_untouched (doc) &&
gedit_tab_get_state (tab) == GEDIT_TAB_STATE_NORMAL)
{
_gedit_tab_load (tab,
@@ -513,7 +510,7 @@ replace_read_only_file (GtkWindow *parent,
* though the dialog uses wrapped text, if the name doesn't contain
* white space then the text-wrapping code is too stupid to wrap it.
*/
- name_for_display = tepl_utils_str_middle_truncate (parse_name, 50);
+ name_for_display = gedit_utils_str_middle_truncate (parse_name, 50);
g_free (parse_name);
dialog = gtk_message_dialog_new (parent,
@@ -565,7 +562,7 @@ change_compression (GtkWindow *parent,
* though the dialog uses wrapped text, if the name doesn't contain
* white space then the text-wrapping code is too stupid to wrap it.
*/
- name_for_display = tepl_utils_str_middle_truncate (parse_name, 50);
+ name_for_display = gedit_utils_str_middle_truncate (parse_name, 50);
g_free (parse_name);
if (compressed)
@@ -827,6 +824,7 @@ save_as_tab_async (GeditTab *tab,
/* Translators: "Save As" is the title of the file chooser window. */
save_dialog = gedit_file_chooser_dialog_create (C_("window title", "Save As"),
GTK_WINDOW (window),
+ GEDIT_FILE_CHOOSER_FLAG_SAVE,
_("_Save"),
_("_Cancel"));
diff --git a/gedit/gedit-commands-search.c b/gedit/gedit-commands-search.c
index 22703985e..f120b8bad 100644
--- a/gedit/gedit-commands-search.c
+++ b/gedit/gedit-commands-search.c
@@ -29,7 +29,6 @@
#include <string.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
-#include <tepl/tepl.h>
#include "gedit-debug.h"
#include "gedit-statusbar.h"
@@ -132,7 +131,7 @@ text_not_found (GeditWindow *window,
gchar *truncated_text;
search_text = gedit_replace_dialog_get_search_text (replace_dialog);
- truncated_text = tepl_utils_str_end_truncate (search_text, MAX_MSG_LENGTH);
+ truncated_text = gedit_utils_str_end_truncate (search_text, MAX_MSG_LENGTH);
gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
window->priv->generic_message_cid,
@@ -188,7 +187,7 @@ forward_search_finished (GtkSourceSearchContext *search_context,
&match_start,
&match_end);
- tepl_view_scroll_to_cursor (TEPL_VIEW (view));
+ gedit_view_scroll_to_cursor (view);
}
else
{
@@ -294,7 +293,7 @@ backward_search_finished (GtkSourceSearchContext *search_context,
&match_start,
&match_end);
- tepl_view_scroll_to_cursor (TEPL_VIEW (view));
+ gedit_view_scroll_to_cursor (view);
}
else
{
diff --git a/gedit/gedit-commands-view.c b/gedit/gedit-commands-view.c
index 71785b78f..369bc93b0 100644
--- a/gedit/gedit-commands-view.c
+++ b/gedit/gedit-commands-view.c
@@ -21,11 +21,16 @@
*/
#include "config.h"
+
#include "gedit-commands.h"
#include "gedit-commands-private.h"
-#include <tepl/tepl.h>
+
+#include <gtk/gtk.h>
+
#include "gedit-debug.h"
#include "gedit-window.h"
+#include "gedit-highlight-mode-dialog.h"
+#include "gedit-highlight-mode-selector.h"
void
_gedit_cmd_view_focus_active (GSimpleAction *action,
@@ -121,9 +126,9 @@ _gedit_cmd_view_leave_fullscreen_mode (GSimpleAction *action,
}
static void
-language_activated_cb (TeplLanguageChooserDialog *dialog,
- GtkSourceLanguage *language,
- GeditWindow *window)
+language_selected_cb (GeditHighlightModeSelector *selector,
+ GtkSourceLanguage *language,
+ GeditWindow *window)
{
GeditDocument *active_document;
@@ -132,16 +137,6 @@ language_activated_cb (TeplLanguageChooserDialog *dialog,
{
gedit_document_set_language (active_document, language);
}
-
- gtk_widget_destroy (GTK_WIDGET (dialog));
-}
-
-static void
-language_chooser_dialog_response_after_cb (TeplLanguageChooserDialog *dialog,
- gint response_id,
- gpointer user_data)
-{
- gtk_widget_destroy (GTK_WIDGET (dialog));
}
void
@@ -150,10 +145,12 @@ _gedit_cmd_view_highlight_mode (GSimpleAction *action,
gpointer user_data)
{
GeditWindow *window = GEDIT_WINDOW (user_data);
- TeplLanguageChooserDialog *dialog;
+ GeditHighlightModeDialog *dialog;
+ GeditHighlightModeSelector *selector;
GeditDocument *active_document;
- dialog = tepl_language_chooser_dialog_new (GTK_WINDOW (window));
+ dialog = GEDIT_HIGHLIGHT_MODE_DIALOG (gedit_highlight_mode_dialog_new (GTK_WINDOW (window)));
+ selector = gedit_highlight_mode_dialog_get_selector (dialog);
active_document = gedit_window_get_active_document (window);
if (active_document != NULL)
@@ -161,20 +158,15 @@ _gedit_cmd_view_highlight_mode (GSimpleAction *action,
GtkSourceLanguage *language;
language = gedit_document_get_language (active_document);
- tepl_language_chooser_select_language (TEPL_LANGUAGE_CHOOSER (dialog), language);
+ gedit_highlight_mode_selector_select_language (selector, language);
}
- g_signal_connect_object (dialog,
- "language-activated",
- G_CALLBACK (language_activated_cb),
+ g_signal_connect_object (selector,
+ "language-selected",
+ G_CALLBACK (language_selected_cb),
window,
0);
- g_signal_connect_after (dialog,
- "response",
- G_CALLBACK (language_chooser_dialog_response_after_cb),
- NULL);
-
gtk_widget_show (GTK_WIDGET (dialog));
}
diff --git a/gedit/gedit-debug.c b/gedit/gedit-debug.c
index 5aa82fa51..396dc140f 100644
--- a/gedit/gedit-debug.c
+++ b/gedit/gedit-debug.c
@@ -100,6 +100,10 @@ gedit_debug_init (void)
{
enabled_sections |= GEDIT_DEBUG_UTILS;
}
+ if (g_getenv ("GEDIT_DEBUG_METADATA") != NULL)
+ {
+ enabled_sections |= GEDIT_DEBUG_METADATA;
+ }
out:
diff --git a/gedit/gedit-debug.h b/gedit/gedit-debug.h
index a9d7caf37..49e5127e1 100644
--- a/gedit/gedit-debug.h
+++ b/gedit/gedit-debug.h
@@ -48,6 +48,7 @@ typedef enum {
GEDIT_DEBUG_COMMANDS = 1 << 7,
GEDIT_DEBUG_APP = 1 << 8,
GEDIT_DEBUG_UTILS = 1 << 9,
+ GEDIT_DEBUG_METADATA = 1 << 10,
} GeditDebugSection;
#define DEBUG_VIEW GEDIT_DEBUG_VIEW, __FILE__, __LINE__, G_STRFUNC
@@ -60,6 +61,7 @@ typedef enum {
#define DEBUG_COMMANDS GEDIT_DEBUG_COMMANDS,__FILE__, __LINE__, G_STRFUNC
#define DEBUG_APP GEDIT_DEBUG_APP, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_UTILS GEDIT_DEBUG_UTILS, __FILE__, __LINE__, G_STRFUNC
+#define DEBUG_METADATA GEDIT_DEBUG_METADATA,__FILE__, __LINE__, G_STRFUNC
void gedit_debug_init (void);
diff --git a/gedit/gedit-document-private.h b/gedit/gedit-document-private.h
index 62444cc76..574c0bb89 100644
--- a/gedit/gedit-document-private.h
+++ b/gedit/gedit-document-private.h
@@ -28,9 +28,15 @@
G_BEGIN_DECLS
-#define GEDIT_METADATA_ATTRIBUTE_POSITION "gedit-position"
-#define GEDIT_METADATA_ATTRIBUTE_ENCODING "gedit-encoding"
-#define GEDIT_METADATA_ATTRIBUTE_LANGUAGE "gedit-language"
+#ifdef G_OS_WIN32
+#define GEDIT_METADATA_ATTRIBUTE_POSITION "position"
+#define GEDIT_METADATA_ATTRIBUTE_ENCODING "encoding"
+#define GEDIT_METADATA_ATTRIBUTE_LANGUAGE "language"
+#else
+#define GEDIT_METADATA_ATTRIBUTE_POSITION "metadata::gedit-position"
+#define GEDIT_METADATA_ATTRIBUTE_ENCODING "metadata::gedit-encoding"
+#define GEDIT_METADATA_ATTRIBUTE_LANGUAGE "metadata::gedit-language"
+#endif
G_GNUC_INTERNAL
glong _gedit_document_get_seconds_since_last_save_or_load (GeditDocument *doc);
diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c
index 54c11a96c..4cb08ee03 100644
--- a/gedit/gedit-document.c
+++ b/gedit/gedit-document.c
@@ -5,7 +5,7 @@
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
- * Copyright (C) 2014-2020 Sébastien Wilmet
+ * Copyright (C) 2014-2015 Sébastien Wilmet
*
* 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
@@ -22,13 +22,21 @@
*/
#include "config.h"
+
#include "gedit-document.h"
#include "gedit-document-private.h"
+
#include <string.h>
#include <glib/gi18n.h>
+
+#include "gedit-app.h"
+#include "gedit-app-private.h"
#include "gedit-settings.h"
#include "gedit-debug.h"
#include "gedit-utils.h"
+#include "gedit-metadata-manager.h"
+
+#define METADATA_QUERY "metadata::*"
#define NO_LANGUAGE_NAME "_NORMAL_"
@@ -43,7 +51,11 @@ typedef struct
{
GtkSourceFile *file;
- TeplMetadata *metadata;
+ GSettings *editor_settings;
+
+ gint untitled_number;
+
+ GFileInfo *metadata_info;
gchar *content_type;
@@ -54,7 +66,12 @@ typedef struct
*/
GtkSourceSearchContext *search_context;
+ GeditMetadataManager *metadata_manager;
+
+ guint user_action;
+
guint language_set_by_user : 1;
+ guint use_gvfs_metadata : 1;
/* The search is empty if there is no search context, or if the
* search text is empty. It is used for the sensitivity of some menu
@@ -71,9 +88,11 @@ typedef struct
enum
{
PROP_0,
+ PROP_SHORTNAME,
PROP_CONTENT_TYPE,
PROP_MIME_TYPE,
PROP_EMPTY_SEARCH,
+ PROP_USE_GVFS_METADATA,
LAST_PROP
};
@@ -81,6 +100,7 @@ static GParamSpec *properties[LAST_PROP];
enum
{
+ CURSOR_MOVED,
LOAD,
LOADED,
SAVE,
@@ -90,40 +110,41 @@ enum
static guint document_signals[LAST_SIGNAL];
-G_DEFINE_TYPE_WITH_PRIVATE (GeditDocument, gedit_document, TEPL_TYPE_BUFFER)
+static GHashTable *allocated_untitled_numbers = NULL;
-static void
-load_metadata_from_metadata_manager (GeditDocument *doc)
+G_DEFINE_TYPE_WITH_PRIVATE (GeditDocument, gedit_document, GTK_SOURCE_TYPE_BUFFER)
+
+static gint
+get_untitled_number (void)
{
- GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
- GFile *location;
+ gint i = 1;
- location = gtk_source_file_get_location (priv->file);
+ if (allocated_untitled_numbers == NULL)
+ allocated_untitled_numbers = g_hash_table_new (NULL, NULL);
- if (location != NULL)
+ g_return_val_if_fail (allocated_untitled_numbers != NULL, -1);
+
+ while (TRUE)
{
- TeplMetadataManager *manager;
+ if (g_hash_table_lookup (allocated_untitled_numbers, GINT_TO_POINTER (i)) == NULL)
+ {
+ g_hash_table_insert (allocated_untitled_numbers,
+ GINT_TO_POINTER (i),
+ GINT_TO_POINTER (i));
- manager = tepl_metadata_manager_get_singleton ();
- tepl_metadata_manager_copy_from (manager, location, priv->metadata);
+ return i;
+ }
+
+ ++i;
}
}
static void
-save_metadata_into_metadata_manager (GeditDocument *doc)
+release_untitled_number (gint n)
{
- GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
- GFile *location;
-
- location = gtk_source_file_get_location (priv->file);
-
- if (location != NULL)
- {
- TeplMetadataManager *manager;
+ g_return_if_fail (allocated_untitled_numbers != NULL);
- manager = tepl_metadata_manager_get_singleton ();
- tepl_metadata_manager_merge_into (manager, location, priv->metadata);
- }
+ g_hash_table_remove (allocated_untitled_numbers, GINT_TO_POINTER (n));
}
static void
@@ -195,16 +216,17 @@ gedit_document_dispose (GObject *object)
/* Metadata must be saved here and not in finalize because the language
* is gone by the time finalize runs.
*/
- if (priv->metadata != NULL)
+ if (priv->file != NULL)
{
save_metadata (doc);
- g_object_unref (priv->metadata);
- priv->metadata = NULL;
+ g_object_unref (priv->file);
+ priv->file = NULL;
}
- g_clear_object (&priv->file);
+ g_clear_object (&priv->metadata_info);
g_clear_object (&priv->search_context);
+ g_clear_object (&priv->metadata_manager);
G_OBJECT_CLASS (gedit_document_parent_class)->dispose (object);
}
@@ -212,10 +234,17 @@ gedit_document_dispose (GObject *object)
static void
gedit_document_finalize (GObject *object)
{
- GeditDocumentPrivate *priv = gedit_document_get_instance_private (GEDIT_DOCUMENT (object));
+ GeditDocumentPrivate *priv;
gedit_debug (DEBUG_DOCUMENT);
+ priv = gedit_document_get_instance_private (GEDIT_DOCUMENT (object));
+
+ if (priv->untitled_number > 0)
+ {
+ release_untitled_number (priv->untitled_number);
+ }
+
g_free (priv->content_type);
if (priv->time_of_last_save_or_load != NULL)
@@ -239,6 +268,10 @@ gedit_document_get_property (GObject *object,
switch (prop_id)
{
+ case PROP_SHORTNAME:
+ g_value_take_string (value, gedit_document_get_short_name_for_display (doc));
+ break;
+
case PROP_CONTENT_TYPE:
g_value_take_string (value, gedit_document_get_content_type (doc));
break;
@@ -251,6 +284,10 @@ gedit_document_get_property (GObject *object,
g_value_set_boolean (value, priv->empty_search);
break;
+ case PROP_USE_GVFS_METADATA:
+ g_value_set_boolean (value, priv->use_gvfs_metadata);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -264,6 +301,7 @@ gedit_document_set_property (GObject *object,
GParamSpec *pspec)
{
GeditDocument *doc = GEDIT_DOCUMENT (object);
+ GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
switch (prop_id)
{
@@ -271,22 +309,97 @@ gedit_document_set_property (GObject *object,
set_content_type (doc, g_value_get_string (value));
break;
+ case PROP_USE_GVFS_METADATA:
+ priv->use_gvfs_metadata = g_value_get_boolean (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
+static void
+gedit_document_begin_user_action (GtkTextBuffer *buffer)
+{
+ GeditDocumentPrivate *priv;
+
+ priv = gedit_document_get_instance_private (GEDIT_DOCUMENT (buffer));
+
+ ++priv->user_action;
+
+ if (GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->begin_user_action != NULL)
+ {
+ GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->begin_user_action (buffer);
+ }
+}
+
+static void
+gedit_document_end_user_action (GtkTextBuffer *buffer)
+{
+ GeditDocumentPrivate *priv;
+
+ priv = gedit_document_get_instance_private (GEDIT_DOCUMENT (buffer));
+
+ --priv->user_action;
+
+ if (GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->end_user_action != NULL)
+ {
+ GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->end_user_action (buffer);
+ }
+}
+
+static void
+gedit_document_mark_set (GtkTextBuffer *buffer,
+ const GtkTextIter *iter,
+ GtkTextMark *mark)
+{
+ GeditDocument *doc = GEDIT_DOCUMENT (buffer);
+ GeditDocumentPrivate *priv;
+
+ priv = gedit_document_get_instance_private (doc);
+
+ if (GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->mark_set != NULL)
+ {
+ GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->mark_set (buffer, iter, mark);
+ }
+
+ if (mark == gtk_text_buffer_get_insert (buffer) && (priv->user_action == 0))
+ {
+ g_signal_emit (doc, document_signals[CURSOR_MOVED], 0);
+ }
+}
+
+static void
+gedit_document_changed (GtkTextBuffer *buffer)
+{
+ g_signal_emit (GEDIT_DOCUMENT (buffer), document_signals[CURSOR_MOVED], 0);
+
+ GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->changed (buffer);
+}
+
static void
gedit_document_constructed (GObject *object)
{
GeditDocument *doc = GEDIT_DOCUMENT (object);
+ GeditDocumentPrivate *priv;
GeditSettings *settings;
GSettings *editor_settings;
+ priv = gedit_document_get_instance_private (doc);
+
settings = _gedit_settings_get_singleton ();
editor_settings = _gedit_settings_peek_editor_settings (settings);
+ if (!priv->use_gvfs_metadata)
+ {
+ GeditMetadataManager *metadata_manager;
+
+ metadata_manager = _gedit_app_get_metadata_manager (GEDIT_APP (g_application_get_default ()));
+ g_assert (GEDIT_IS_METADATA_MANAGER (metadata_manager));
+ priv->metadata_manager = g_object_ref (metadata_manager);
+ }
+
/* Bind construct properties. */
g_settings_bind (editor_settings, GEDIT_SETTINGS_ENSURE_TRAILING_NEWLINE,
doc, "implicit-trailing-newline",
@@ -299,6 +412,7 @@ static void
gedit_document_class_init (GeditDocumentClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkTextBufferClass *buf_class = GTK_TEXT_BUFFER_CLASS (klass);
object_class->dispose = gedit_document_dispose;
object_class->finalize = gedit_document_finalize;
@@ -306,9 +420,26 @@ gedit_document_class_init (GeditDocumentClass *klass)
object_class->set_property = gedit_document_set_property;
object_class->constructed = gedit_document_constructed;
+ buf_class->begin_user_action = gedit_document_begin_user_action;
+ buf_class->end_user_action = gedit_document_end_user_action;
+ buf_class->mark_set = gedit_document_mark_set;
+ buf_class->changed = gedit_document_changed;
+
klass->loaded = gedit_document_loaded_real;
klass->saved = gedit_document_saved_real;
+ /**
+ * GeditDocument:shortname:
+ *
+ * The document's short name.
+ */
+ properties[PROP_SHORTNAME] =
+ g_param_spec_string ("shortname",
+ "Short Name",
+ "The document's short name",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
/**
* GeditDocument:content-type:
*
@@ -348,8 +479,44 @@ gedit_document_class_init (GeditDocumentClass *klass)
TRUE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ /**
+ * GeditDocument:use-gvfs-metadata:
+ *
+ * Whether to use GVFS metadata. If %FALSE, use the gedit metadata
+ * manager that stores the metadata in an XML file in the user cache
+ * directory.
+ *
+ * <warning>
+ * The property is used internally by gedit. It must not be used in a
+ * gedit plugin. The property can be modified or removed at any time.
+ * </warning>
+ */
+ properties[PROP_USE_GVFS_METADATA] =
+ g_param_spec_boolean ("use-gvfs-metadata",
+ "Use GVFS metadata",
+ "",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties (object_class, LAST_PROP, properties);
+ /* This signal is used to update the cursor position in the statusbar,
+ * it's emitted either when the insert mark is moved explicitely or
+ * when the buffer changes (insert/delete).
+ * FIXME When the replace_all was implemented in gedit, this signal was
+ * not emitted during the replace_all to improve performance. Now the
+ * replace_all is implemented in GtkSourceView, so the signal is
+ * emitted.
+ */
+ document_signals[CURSOR_MOVED] =
+ g_signal_new ("cursor-moved",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GeditDocumentClass, cursor_moved),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 0);
+
/**
* GeditDocument::load:
* @document: the #GeditDocument.
@@ -632,20 +799,79 @@ on_location_changed (GtkSourceFile *file,
GParamSpec *pspec,
GeditDocument *doc)
{
+ GeditDocumentPrivate *priv;
+ GFile *location;
+
gedit_debug (DEBUG_DOCUMENT);
- load_metadata_from_metadata_manager (doc);
+
+ priv = gedit_document_get_instance_private (doc);
+
+ location = gtk_source_file_get_location (file);
+
+ if (location != NULL && priv->untitled_number > 0)
+ {
+ release_untitled_number (priv->untitled_number);
+ priv->untitled_number = 0;
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_SHORTNAME]);
+
+ /* Load metadata for this location: we load sync since metadata is
+ * always local so it should be fast and we need the information
+ * right after the location was set.
+ * TODO: do async I/O for the metadata.
+ */
+ if (priv->use_gvfs_metadata && location != NULL)
+ {
+ GError *error = NULL;
+
+ if (priv->metadata_info != NULL)
+ {
+ g_object_unref (priv->metadata_info);
+ }
+
+ priv->metadata_info = g_file_query_info (location,
+ METADATA_QUERY,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+
+ if (error != NULL)
+ {
+ /* Do not complain about metadata if we are opening a
+ * non existing file.
+ */
+ if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_ISDIR) &&
+ !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR) &&
+ !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ g_warning ("%s", error->message);
+ }
+
+ g_error_free (error);
+ }
+
+ if (priv->metadata_info == NULL)
+ {
+ priv->metadata_info = g_file_info_new ();
+ }
+ }
}
static void
gedit_document_init (GeditDocument *doc)
{
GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
- TeplFile *tepl_file;
GeditSettings *settings;
GSettings *editor_settings;
gedit_debug (DEBUG_DOCUMENT);
+ settings = _gedit_settings_get_singleton ();
+ editor_settings = _gedit_settings_peek_editor_settings (settings);
+
+ priv->untitled_number = get_untitled_number ();
priv->content_type = get_default_content_type ();
priv->language_set_by_user = FALSE;
priv->empty_search = TRUE;
@@ -653,13 +879,7 @@ gedit_document_init (GeditDocument *doc)
update_time_of_last_save_or_load (doc);
priv->file = gtk_source_file_new ();
- tepl_file = tepl_buffer_get_file (TEPL_BUFFER (doc));
-
- g_object_bind_property (priv->file, "location",
- tepl_file, "location",
- G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
-
- priv->metadata = tepl_metadata_new ();
+ priv->metadata_info = g_file_info_new ();
g_signal_connect_object (priv->file,
"notify::location",
@@ -667,9 +887,6 @@ gedit_document_init (GeditDocument *doc)
doc,
0);
- settings = _gedit_settings_get_singleton ();
- editor_settings = _gedit_settings_peek_editor_settings (settings);
-
g_settings_bind (editor_settings, GEDIT_SETTINGS_MAX_UNDO_ACTIONS,
doc, "max-undo-levels",
G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
@@ -699,7 +916,17 @@ gedit_document_init (GeditDocument *doc)
GeditDocument *
gedit_document_new (void)
{
- return g_object_new (GEDIT_TYPE_DOCUMENT, NULL);
+ gboolean use_gvfs_metadata;
+
+#ifdef ENABLE_GVFS_METADATA
+ use_gvfs_metadata = TRUE;
+#else
+ use_gvfs_metadata = FALSE;
+#endif
+
+ return g_object_new (GEDIT_TYPE_DOCUMENT,
+ "use-gvfs-metadata", use_gvfs_metadata,
+ NULL);
}
static gchar *
@@ -814,17 +1041,19 @@ set_content_type (GeditDocument *doc,
gchar *
_gedit_document_get_uri_for_display (GeditDocument *doc)
{
- TeplFile *file;
+ GeditDocumentPrivate *priv;
GFile *location;
g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), g_strdup (""));
- file = tepl_buffer_get_file (TEPL_BUFFER (doc));
- location = tepl_file_get_location (file);
+ priv = gedit_document_get_instance_private (doc);
+
+ location = gtk_source_file_get_location (priv->file);
if (location == NULL)
{
- return tepl_file_get_short_name (file);
+ return g_strdup_printf (_("Untitled Document %d"),
+ priv->untitled_number);
}
else
{
@@ -841,12 +1070,24 @@ _gedit_document_get_uri_for_display (GeditDocument *doc)
gchar *
gedit_document_get_short_name_for_display (GeditDocument *doc)
{
- TeplFile *file;
+ GeditDocumentPrivate *priv;
+ GFile *location;
g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), g_strdup (""));
- file = tepl_buffer_get_file (TEPL_BUFFER (doc));
- return tepl_file_get_short_name (file);
+ priv = gedit_document_get_instance_private (doc);
+
+ location = gtk_source_file_get_location (priv->file);
+
+ if (location == NULL)
+ {
+ return g_strdup_printf (_("Untitled Document %d"),
+ priv->untitled_number);
+ }
+ else
+ {
+ return gedit_utils_basename_for_display (location);
+ }
}
gchar *
@@ -1032,15 +1273,31 @@ gedit_document_saved_real (GeditDocument *doc)
doc);
}
+gboolean
+gedit_document_is_untouched (GeditDocument *doc)
+{
+ GeditDocumentPrivate *priv;
+ GFile *location;
+
+ g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), TRUE);
+
+ priv = gedit_document_get_instance_private (doc);
+
+ location = gtk_source_file_get_location (priv->file);
+
+ return location == NULL && !gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc));
+}
+
gboolean
gedit_document_is_untitled (GeditDocument *doc)
{
- TeplFile *file;
+ GeditDocumentPrivate *priv;
g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), TRUE);
- file = tepl_buffer_get_file (TEPL_BUFFER (doc));
- return tepl_file_get_location (file) == NULL;
+ priv = gedit_document_get_instance_private (doc);
+
+ return gtk_source_file_get_location (priv->file) == NULL;
}
/*
@@ -1072,6 +1329,51 @@ _gedit_document_needs_saving (GeditDocument *doc)
return (externally_modified || deleted) && !priv->create;
}
+/* If @line is bigger than the lines of the document, the cursor is moved
+ * to the last line and FALSE is returned.
+ */
+gboolean
+gedit_document_goto_line (GeditDocument *doc,
+ gint line)
+{
+ GtkTextIter iter;
+
+ gedit_debug (DEBUG_DOCUMENT);
+
+ g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
+ g_return_val_if_fail (line >= -1, FALSE);
+
+ gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc),
+ &iter,
+ line);
+
+ gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
+
+ return gtk_text_iter_get_line (&iter) == line;
+}
+
+gboolean
+gedit_document_goto_line_offset (GeditDocument *doc,
+ gint line,
+ gint line_offset)
+{
+ GtkTextIter iter;
+
+ g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
+ g_return_val_if_fail (line >= -1, FALSE);
+ g_return_val_if_fail (line_offset >= -1, FALSE);
+
+ gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER (doc),
+ &iter,
+ line,
+ line_offset);
+
+ gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
+
+ return (gtk_text_iter_get_line (&iter) == line &&
+ gtk_text_iter_get_line_offset (&iter) == line_offset);
+}
+
/**
* gedit_document_set_language:
* @doc:
@@ -1130,6 +1432,64 @@ _gedit_document_get_seconds_since_last_save_or_load (GeditDocument *doc)
return n_microseconds / (1000 * 1000);
}
+static gchar *
+get_metadata_from_metadata_manager (GeditDocument *doc,
+ const gchar *key)
+{
+ GeditDocumentPrivate *priv;
+ GFile *location;
+
+ priv = gedit_document_get_instance_private (doc);
+
+ location = gtk_source_file_get_location (priv->file);
+
+ if (location != NULL)
+ {
+ return gedit_metadata_manager_get (priv->metadata_manager, location, key);
+ }
+
+ return NULL;
+}
+
+static gchar *
+get_metadata_from_gvfs (GeditDocument *doc,
+ const gchar *key)
+{
+ GeditDocumentPrivate *priv;
+
+ priv = gedit_document_get_instance_private (doc);
+
+ if (priv->metadata_info != NULL &&
+ g_file_info_has_attribute (priv->metadata_info, key) &&
+ g_file_info_get_attribute_type (priv->metadata_info, key) == G_FILE_ATTRIBUTE_TYPE_STRING)
+ {
+ return g_strdup (g_file_info_get_attribute_string (priv->metadata_info, key));
+ }
+
+ return NULL;
+}
+
+static void
+set_gvfs_metadata (GFileInfo *info,
+ const gchar *key,
+ const gchar *value)
+{
+ g_return_if_fail (G_IS_FILE_INFO (info));
+
+ if (value != NULL)
+ {
+ g_file_info_set_attribute_string (info, key, value);
+ }
+ else
+ {
+ /* Unset the key */
+ g_file_info_set_attribute (info,
+ key,
+ G_FILE_ATTRIBUTE_TYPE_INVALID,
+ NULL);
+ }
+}
+
/**
* gedit_document_get_metadata:
* @doc: a #GeditDocument
@@ -1150,12 +1510,12 @@ gedit_document_get_metadata (GeditDocument *doc,
priv = gedit_document_get_instance_private (doc);
- if (priv->metadata == NULL)
+ if (priv->use_gvfs_metadata)
{
- return NULL;
+ return get_metadata_from_gvfs (doc, key);
}
- return tepl_metadata_get (priv->metadata, key);
+ return get_metadata_from_metadata_manager (doc, key);
}
/**
@@ -1173,30 +1533,84 @@ gedit_document_set_metadata (GeditDocument *doc,
...)
{
GeditDocumentPrivate *priv;
- va_list var_args;
+ GFile *location;
const gchar *key;
+ va_list var_args;
+ GFileInfo *info = NULL;
g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
g_return_if_fail (first_key != NULL);
priv = gedit_document_get_instance_private (doc);
- if (priv->metadata == NULL)
+ location = gtk_source_file_get_location (priv->file);
+
+ /* With the metadata manager, can't set metadata for untitled documents.
+ * With GVFS metadata, if the location is NULL the metadata is stored in
+ * priv->metadata_info, so that it can be saved later if the document is
+ * saved.
+ */
+ if (!priv->use_gvfs_metadata && location == NULL)
{
return;
}
+ if (priv->use_gvfs_metadata)
+ {
+ info = g_file_info_new ();
+ }
+
va_start (var_args, first_key);
- for (key = first_key; key != NULL; key = va_arg (var_args, const gchar *))
+ for (key = first_key; key; key = va_arg (var_args, const gchar *))
{
const gchar *value = va_arg (var_args, const gchar *);
- tepl_metadata_set (priv->metadata, key, value);
+
+ if (priv->use_gvfs_metadata)
+ {
+ set_gvfs_metadata (info, key, value);
+ set_gvfs_metadata (priv->metadata_info, key, value);
+ }
+ else
+ {
+ gedit_metadata_manager_set (priv->metadata_manager, location, key, value);
+ }
}
va_end (var_args);
- save_metadata_into_metadata_manager (doc);
+ if (priv->use_gvfs_metadata && location != NULL)
+ {
+ GError *error = NULL;
+
+ /* We save synchronously since metadata is always local so it
+ * should be fast. Moreover this function can be called on
+ * application shutdown, when the main loop has already exited,
+ * so an async operation would not terminate.
+ * https://bugzilla.gnome.org/show_bug.cgi?id=736591
+ */
+ g_file_set_attributes_from_info (location,
+ info,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+
+ if (error != NULL)
+ {
+ /* Do not complain about metadata if we are closing a
+ * document for a non existing file.
+ */
+ if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ g_warning ("Set document metadata failed: %s", error->message);
+ }
+
+ g_error_free (error);
+ }
+ }
+
+ g_clear_object (&info);
}
static void
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index 901d02dc0..ed52a42fb 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -5,7 +5,7 @@
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
- * Copyright (C) 2014-2020 Sébastien Wilmet
+ * Copyright (C) 2014 Sébastien Wilmet
*
* 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
@@ -24,19 +24,20 @@
#ifndef GEDIT_DOCUMENT_H
#define GEDIT_DOCUMENT_H
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
G_BEGIN_DECLS
#define GEDIT_TYPE_DOCUMENT (gedit_document_get_type())
-G_DECLARE_DERIVABLE_TYPE (GeditDocument, gedit_document, GEDIT, DOCUMENT, TeplBuffer)
+G_DECLARE_DERIVABLE_TYPE (GeditDocument, gedit_document, GEDIT, DOCUMENT, GtkSourceBuffer)
struct _GeditDocumentClass
{
- TeplBufferClass parent_class;
+ GtkSourceBufferClass parent_class;
/* Signals */
+ void (* cursor_moved) (GeditDocument *document);
void (* load) (GeditDocument *document);
@@ -57,8 +58,17 @@ gchar *gedit_document_get_content_type (GeditDocument
*doc);
gchar *gedit_document_get_mime_type (GeditDocument *doc);
+gboolean gedit_document_is_untouched (GeditDocument *doc);
+
gboolean gedit_document_is_untitled (GeditDocument *doc);
+gboolean gedit_document_goto_line (GeditDocument *doc,
+ gint line);
+
+gboolean gedit_document_goto_line_offset (GeditDocument *doc,
+ gint line,
+ gint line_offset);
+
void gedit_document_set_language (GeditDocument *doc,
GtkSourceLanguage *lang);
GtkSourceLanguage
diff --git a/gedit/gedit-documents-panel.c b/gedit/gedit-documents-panel.c
index 98d84a98f..8033f944e 100644
--- a/gedit/gedit-documents-panel.c
+++ b/gedit/gedit-documents-panel.c
@@ -23,7 +23,6 @@
#include "gedit-documents-panel.h"
#include <glib/gi18n.h>
-#include <tepl/tepl.h>
#include "gedit-debug.h"
#include "gedit-document.h"
@@ -447,7 +446,7 @@ doc_get_name (GeditDocument *doc)
name = gedit_document_get_short_name_for_display (doc);
/* Truncate the name so it doesn't get insanely wide. */
- docname = tepl_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
+ docname = gedit_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
g_free (name);
diff --git a/gedit/gedit-file-chooser-dialog-gtk.c b/gedit/gedit-file-chooser-dialog-gtk.c
index 4b8b4dbb0..17671ff3e 100644
--- a/gedit/gedit-file-chooser-dialog-gtk.c
+++ b/gedit/gedit-file-chooser-dialog-gtk.c
@@ -192,6 +192,12 @@ chooser_show (GeditFileChooserDialog *dialog)
gtk_widget_grab_focus (GTK_WIDGET (dialog));
}
+static void
+chooser_hide (GeditFileChooserDialog *dialog)
+{
+ gtk_widget_hide (GTK_WIDGET (dialog));
+}
+
static void
chooser_destroy (GeditFileChooserDialog *dialog)
{
@@ -211,6 +217,26 @@ chooser_get_window (GeditFileChooserDialog *dialog)
return GTK_WINDOW (dialog);
}
+static void
+chooser_add_pattern_filter (GeditFileChooserDialog *dialog,
+ const gchar *name,
+ const gchar *pattern)
+{
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new ();
+
+ gtk_file_filter_set_name (filter, name);
+ gtk_file_filter_add_pattern (filter, pattern);
+
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+ if (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == NULL)
+ {
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
+ }
+}
+
static void
gedit_file_chooser_dialog_gtk_chooser_init (gpointer g_iface,
gpointer iface_data)
@@ -229,9 +255,11 @@ gedit_file_chooser_dialog_gtk_chooser_init (gpointer g_iface,
iface->get_file = chooser_get_file;
iface->set_do_overwrite_confirmation = chooser_set_do_overwrite_confirmation;
iface->show = chooser_show;
+ iface->hide = chooser_hide;
iface->destroy = chooser_destroy;
iface->set_modal = chooser_set_modal;
iface->get_window = chooser_get_window;
+ iface->add_pattern_filter = chooser_add_pattern_filter;
}
static void
@@ -253,7 +281,8 @@ gedit_file_chooser_dialog_gtk_class_init (GeditFileChooserDialogGtkClass *klass)
}
static void
-create_option_menu (GeditFileChooserDialogGtk *dialog)
+create_option_menu (GeditFileChooserDialogGtk *dialog,
+ GeditFileChooserFlags flags)
{
GtkWidget *label;
GtkWidget *menu;
@@ -262,7 +291,7 @@ create_option_menu (GeditFileChooserDialogGtk *dialog)
label = gtk_label_new_with_mnemonic (_("C_haracter Encoding:"));
gtk_widget_set_halign (label, GTK_ALIGN_START);
- save_mode = TRUE;
+ save_mode = (flags & GEDIT_FILE_CHOOSER_FLAG_SAVE) != 0;
menu = gedit_encodings_combo_box_new (save_mode);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu);
@@ -374,13 +403,18 @@ create_newline_combo (GeditFileChooserDialogGtk *dialog)
}
static void
-create_extra_widget (GeditFileChooserDialogGtk *dialog)
+create_extra_widget (GeditFileChooserDialogGtk *dialog,
+ GeditFileChooserFlags flags)
{
dialog->extra_widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_show (dialog->extra_widget);
- create_option_menu (dialog);
- create_newline_combo (dialog);
+ create_option_menu (dialog, flags);
+
+ if ((flags & GEDIT_FILE_CHOOSER_FLAG_SAVE) != 0)
+ {
+ create_newline_combo (dialog);
+ }
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), dialog->extra_widget);
}
@@ -421,21 +455,35 @@ gedit_file_chooser_dialog_gtk_init (GeditFileChooserDialogGtk *dialog)
}
GeditFileChooserDialog *
-gedit_file_chooser_dialog_gtk_create (const gchar *title,
- GtkWindow *parent,
- const gchar *accept_label,
- const gchar *cancel_label)
+gedit_file_chooser_dialog_gtk_create (const gchar *title,
+ GtkWindow *parent,
+ GeditFileChooserFlags flags,
+ const gchar *accept_label,
+ const gchar *cancel_label)
{
GeditFileChooserDialogGtk *result;
+ GtkFileChooserAction action;
+ gboolean select_multiple;
+
+ if ((flags & GEDIT_FILE_CHOOSER_FLAG_SAVE) != 0)
+ {
+ action = GTK_FILE_CHOOSER_ACTION_SAVE;
+ select_multiple = FALSE;
+ }
+ else
+ {
+ action = GTK_FILE_CHOOSER_ACTION_OPEN;
+ select_multiple = TRUE;
+ }
result = g_object_new (GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK,
"title", title,
"local-only", FALSE,
- "action", GTK_FILE_CHOOSER_ACTION_SAVE,
- "select-multiple", FALSE,
+ "action", action,
+ "select-multiple", select_multiple,
NULL);
- create_extra_widget (result);
+ create_extra_widget (result, flags);
g_signal_connect (result,
"notify::action",
diff --git a/gedit/gedit-file-chooser-dialog-gtk.h b/gedit/gedit-file-chooser-dialog-gtk.h
index 0bf6a0d41..40726af54 100644
--- a/gedit/gedit-file-chooser-dialog-gtk.h
+++ b/gedit/gedit-file-chooser-dialog-gtk.h
@@ -33,10 +33,11 @@ G_DECLARE_FINAL_TYPE (GeditFileChooserDialogGtk, gedit_file_chooser_dialog_gtk,
GEDIT, FILE_CHOOSER_DIALOG_GTK,
GtkFileChooserDialog)
-GeditFileChooserDialog * gedit_file_chooser_dialog_gtk_create (const gchar *title,
- GtkWindow *parent,
- const gchar *accept_label,
- const gchar *cancel_label);
+GeditFileChooserDialog * gedit_file_chooser_dialog_gtk_create (const gchar *title,
+ GtkWindow *parent,
+ GeditFileChooserFlags flags,
+ const gchar *accept_label,
+ const gchar *cancel_label);
G_END_DECLS
diff --git a/gedit/gedit-file-chooser-dialog.c b/gedit/gedit-file-chooser-dialog.c
index 56edbae3b..b4ce2fd9e 100644
--- a/gedit/gedit-file-chooser-dialog.c
+++ b/gedit/gedit-file-chooser-dialog.c
@@ -62,13 +62,15 @@ gedit_file_chooser_dialog_default_init (GeditFileChooserDialogInterface *iface)
}
GeditFileChooserDialog *
-gedit_file_chooser_dialog_create (const gchar *title,
- GtkWindow *parent,
- const gchar *accept_label,
- const gchar *cancel_label)
+gedit_file_chooser_dialog_create (const gchar *title,
+ GtkWindow *parent,
+ GeditFileChooserFlags flags,
+ const gchar *accept_label,
+ const gchar *cancel_label)
{
return gedit_file_chooser_dialog_gtk_create (title,
parent,
+ flags,
accept_label,
cancel_label);
}
@@ -211,6 +213,19 @@ gedit_file_chooser_dialog_show (GeditFileChooserDialog *dialog)
iface->show (dialog);
}
+void
+gedit_file_chooser_dialog_hide (GeditFileChooserDialog *dialog)
+{
+ GeditFileChooserDialogInterface *iface;
+
+ g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
+
+ iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+ g_return_if_fail (iface->hide != NULL);
+
+ iface->hide (dialog);
+}
+
void
gedit_file_chooser_dialog_destroy (GeditFileChooserDialog *dialog)
{
@@ -255,4 +270,21 @@ gedit_file_chooser_dialog_get_window (GeditFileChooserDialog *dialog)
return NULL;
}
+void
+gedit_file_chooser_dialog_add_pattern_filter (GeditFileChooserDialog *dialog,
+ const gchar *name,
+ const gchar *pattern)
+{
+ GeditFileChooserDialogInterface *iface;
+
+ g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
+
+ iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+
+ if (iface->add_pattern_filter)
+ {
+ iface->add_pattern_filter (dialog, name, pattern);
+ }
+}
+
/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-file-chooser-dialog.h b/gedit/gedit-file-chooser-dialog.h
index b759c6566..633950e05 100644
--- a/gedit/gedit-file-chooser-dialog.h
+++ b/gedit/gedit-file-chooser-dialog.h
@@ -64,6 +64,7 @@ struct _GeditFileChooserDialogInterface
gboolean overwrite_confirmation);
void (*show) (GeditFileChooserDialog *dialog);
+ void (*hide) (GeditFileChooserDialog *dialog);
void (*destroy) (GeditFileChooserDialog *dialog);
@@ -72,11 +73,22 @@ struct _GeditFileChooserDialogInterface
GtkWindow *
(*get_window) (GeditFileChooserDialog *dialog);
+
+ void (*add_pattern_filter) (GeditFileChooserDialog *dilaog,
+ const gchar *name,
+ const gchar *pattern);
};
+typedef enum
+{
+ GEDIT_FILE_CHOOSER_FLAG_SAVE = 1 << 0,
+ GEDIT_FILE_CHOOSER_FLAG_OPEN = 1 << 1
+} GeditFileChooserFlags;
+
GeditFileChooserDialog *
gedit_file_chooser_dialog_create (const gchar *title,
GtkWindow *parent,
+ GeditFileChooserFlags flags,
const gchar *accept_label,
const gchar *cancel_label);
@@ -110,12 +122,17 @@ void gedit_file_chooser_dialog_set_do_overwrite_confirmation (
gboolean
overwrite_confirmation);
void gedit_file_chooser_dialog_show (GeditFileChooserDialog *dialog);
+void gedit_file_chooser_dialog_hide (GeditFileChooserDialog *dialog);
void gedit_file_chooser_dialog_set_modal (GeditFileChooserDialog *dialog,
gboolean is_modal);
GtkWindow *gedit_file_chooser_dialog_get_window (GeditFileChooserDialog *dialog);
+void gedit_file_chooser_dialog_add_pattern_filter (GeditFileChooserDialog *dialog,
+ const gchar *name,
+ const gchar *pattern);
+
G_END_DECLS
#endif /* GEDIT_FILE_CHOOSER_DIALOG_H */
diff --git a/gedit/gedit-highlight-mode-dialog.c b/gedit/gedit-highlight-mode-dialog.c
new file mode 100644
index 000000000..a0661bfc3
--- /dev/null
+++ b/gedit/gedit-highlight-mode-dialog.c
@@ -0,0 +1,102 @@
+/*
+ * gedit-highlight-mode-dialog.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2013 - Ignacio Casal Quinteiro
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-highlight-mode-dialog.h"
+
+struct _GeditHighlightModeDialog
+{
+ GtkDialog parent_instance;
+
+ GeditHighlightModeSelector *selector;
+ gulong on_language_selected_id;
+};
+
+G_DEFINE_TYPE (GeditHighlightModeDialog, gedit_highlight_mode_dialog, GTK_TYPE_DIALOG)
+
+static void
+gedit_highlight_mode_dialog_response (GtkDialog *dialog,
+ gint response_id)
+{
+ GeditHighlightModeDialog *dlg = GEDIT_HIGHLIGHT_MODE_DIALOG (dialog);
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ g_signal_handler_block (dlg->selector, dlg->on_language_selected_id);
+ gedit_highlight_mode_selector_activate_selected_language (dlg->selector);
+ g_signal_handler_unblock (dlg->selector, dlg->on_language_selected_id);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+on_language_selected (GeditHighlightModeSelector *sel,
+ GtkSourceLanguage *language,
+ GeditHighlightModeDialog *dlg)
+{
+ g_signal_handler_block (dlg->selector, dlg->on_language_selected_id);
+ gedit_highlight_mode_selector_activate_selected_language (dlg->selector);
+ g_signal_handler_unblock (dlg->selector, dlg->on_language_selected_id);
+
+ gtk_widget_destroy (GTK_WIDGET (dlg));
+}
+
+static void
+gedit_highlight_mode_dialog_class_init (GeditHighlightModeDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+
+ dialog_class->response = gedit_highlight_mode_dialog_response;
+
+ /* Bind class to template */
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/gedit/ui/gedit-highlight-mode-dialog.ui");
+ gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeDialog, selector);
+}
+
+static void
+gedit_highlight_mode_dialog_init (GeditHighlightModeDialog *dlg)
+{
+ gtk_widget_init_template (GTK_WIDGET (dlg));
+ gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK);
+
+ dlg->on_language_selected_id = g_signal_connect (dlg->selector, "language-selected",
+ G_CALLBACK (on_language_selected), dlg);
+}
+
+GtkWidget *
+gedit_highlight_mode_dialog_new (GtkWindow *parent)
+{
+ return GTK_WIDGET (g_object_new (GEDIT_TYPE_HIGHLIGHT_MODE_DIALOG,
+ "transient-for", parent,
+ "use-header-bar", TRUE,
+ NULL));
+}
+
+GeditHighlightModeSelector *
+gedit_highlight_mode_dialog_get_selector (GeditHighlightModeDialog *dlg)
+{
+ g_return_val_if_fail (GEDIT_IS_HIGHLIGHT_MODE_DIALOG (dlg), NULL);
+
+ return dlg->selector;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-highlight-mode-dialog.h b/gedit/gedit-highlight-mode-dialog.h
new file mode 100644
index 000000000..57d406bb3
--- /dev/null
+++ b/gedit/gedit-highlight-mode-dialog.h
@@ -0,0 +1,41 @@
+/*
+ * gedit-highlight-mode-dialog.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2013 - Ignacio Casal Quinteiro
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef GEDIT_HIGHLIGHT_MODE_DIALOG_H
+#define GEDIT_HIGHLIGHT_MODE_DIALOG_H
+
+#include "gedit-highlight-mode-selector.h"
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_HIGHLIGHT_MODE_DIALOG (gedit_highlight_mode_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (GeditHighlightModeDialog, gedit_highlight_mode_dialog, GEDIT, HIGHLIGHT_MODE_DIALOG,
GtkDialog)
+
+GtkWidget *gedit_highlight_mode_dialog_new (GtkWindow *parent);
+
+GeditHighlightModeSelector *gedit_highlight_mode_dialog_get_selector (GeditHighlightModeDialog *dlg);
+
+G_END_DECLS
+
+#endif /* GEDIT_HIGHLIGHT_MODE_DIALOG_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-highlight-mode-selector.c b/gedit/gedit-highlight-mode-selector.c
new file mode 100644
index 000000000..cb6bd466f
--- /dev/null
+++ b/gedit/gedit-highlight-mode-selector.c
@@ -0,0 +1,375 @@
+/*
+ * gedit-highlight-mode-selector.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2013 - Ignacio Casal Quinteiro
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-highlight-mode-selector.h"
+#include <glib/gi18n.h>
+
+enum
+{
+ COLUMN_NAME,
+ COLUMN_LANG,
+ N_COLUMNS
+};
+
+struct _GeditHighlightModeSelector
+{
+ GtkGrid parent_instance;
+
+ GtkWidget *treeview;
+ GtkWidget *entry;
+ GtkListStore *liststore;
+ GtkTreeModelFilter *treemodelfilter;
+ GtkTreeSelection *treeview_selection;
+};
+
+/* Signals */
+enum
+{
+ LANGUAGE_SELECTED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GeditHighlightModeSelector, gedit_highlight_mode_selector, GTK_TYPE_GRID)
+
+static void
+gedit_highlight_mode_selector_language_selected (GeditHighlightModeSelector *widget,
+ GtkSourceLanguage *language)
+{
+}
+
+static void
+gedit_highlight_mode_selector_class_init (GeditHighlightModeSelectorClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ signals[LANGUAGE_SELECTED] =
+ g_signal_new_class_handler ("language-selected",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gedit_highlight_mode_selector_language_selected),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ GTK_SOURCE_TYPE_LANGUAGE);
+
+ /* Bind class to template */
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/gedit/ui/gedit-highlight-mode-selector.ui");
+ gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, treeview);
+ gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, entry);
+ gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, liststore);
+ gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, treemodelfilter);
+ gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, treeview_selection);
+}
+
+static gboolean
+visible_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GeditHighlightModeSelector *selector)
+{
+ const gchar *entry_text;
+ gchar *name;
+ gchar *name_normalized;
+ gchar *name_casefolded;
+ gchar *text_normalized;
+ gchar *text_casefolded;
+ gboolean visible = FALSE;
+
+ entry_text = gtk_entry_get_text (GTK_ENTRY (selector->entry));
+
+ if (*entry_text == '\0')
+ {
+ return TRUE;
+ }
+
+ gtk_tree_model_get (model, iter, COLUMN_NAME, &name, -1);
+
+ name_normalized = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
+ g_free (name);
+
+ name_casefolded = g_utf8_casefold (name_normalized, -1);
+ g_free (name_normalized);
+
+ text_normalized = g_utf8_normalize (entry_text, -1, G_NORMALIZE_ALL);
+ text_casefolded = g_utf8_casefold (text_normalized, -1);
+ g_free (text_normalized);
+
+ if (strstr (name_casefolded, text_casefolded) != NULL)
+ {
+ visible = TRUE;
+ }
+
+ g_free (name_casefolded);
+ g_free (text_casefolded);
+
+ return visible;
+}
+
+static void
+on_entry_activate (GtkEntry *entry,
+ GeditHighlightModeSelector *selector)
+{
+ gedit_highlight_mode_selector_activate_selected_language (selector);
+}
+
+static void
+on_entry_changed (GtkEntry *entry,
+ GeditHighlightModeSelector *selector)
+{
+ GtkTreeIter iter;
+
+ gtk_tree_model_filter_refilter (selector->treemodelfilter);
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (selector->treemodelfilter), &iter))
+ {
+ gtk_tree_selection_select_iter (selector->treeview_selection, &iter);
+ }
+}
+
+static gboolean
+move_selection (GeditHighlightModeSelector *selector,
+ gint howmany)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ gint *indices;
+ gint ret = FALSE;
+
+ if (!gtk_tree_selection_get_selected (selector->treeview_selection, NULL, &iter) &&
+ !gtk_tree_model_get_iter_first (GTK_TREE_MODEL (selector->treemodelfilter), &iter))
+ {
+ return FALSE;
+ }
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (selector->treemodelfilter), &iter);
+ indices = gtk_tree_path_get_indices (path);
+
+ if (indices)
+ {
+ gint num;
+ gint idx;
+ GtkTreePath *new_path;
+
+ idx = indices[0];
+ num = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (selector->treemodelfilter), NULL);
+
+ if ((idx + howmany) < 0)
+ {
+ idx = 0;
+ }
+ else if ((idx + howmany) >= num)
+ {
+ idx = num - 1;
+ }
+ else
+ {
+ idx = idx + howmany;
+ }
+
+ new_path = gtk_tree_path_new_from_indices (idx, -1);
+ gtk_tree_selection_select_path (selector->treeview_selection, new_path);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (selector->treeview),
+ new_path, NULL, TRUE, 0.5, 0);
+ gtk_tree_path_free (new_path);
+
+ ret = TRUE;
+ }
+
+ gtk_tree_path_free (path);
+
+ return ret;
+}
+
+static gboolean
+on_entry_key_press_event (GtkWidget *entry,
+ GdkEventKey *event,
+ GeditHighlightModeSelector *selector)
+{
+ if (event->keyval == GDK_KEY_Down)
+ {
+ return move_selection (selector, 1);
+ }
+ else if (event->keyval == GDK_KEY_Up)
+ {
+ return move_selection (selector, -1);
+ }
+ else if (event->keyval == GDK_KEY_Page_Down)
+ {
+ return move_selection (selector, 5);
+ }
+ else if (event->keyval == GDK_KEY_Page_Up)
+ {
+ return move_selection (selector, -5);
+ }
+
+ return FALSE;
+}
+
+static void
+on_row_activated (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ GeditHighlightModeSelector *selector)
+{
+ gedit_highlight_mode_selector_activate_selected_language (selector);
+}
+
+static void
+gedit_highlight_mode_selector_init (GeditHighlightModeSelector *selector)
+{
+ GtkSourceLanguageManager *lm;
+ const gchar * const *ids;
+ gint i;
+ GtkTreeIter iter;
+
+ selector = gedit_highlight_mode_selector_get_instance_private (selector);
+
+ gtk_widget_init_template (GTK_WIDGET (selector));
+
+ gtk_tree_model_filter_set_visible_func (selector->treemodelfilter,
+ (GtkTreeModelFilterVisibleFunc)visible_func,
+ selector,
+ NULL);
+
+ g_signal_connect (selector->entry, "activate",
+ G_CALLBACK (on_entry_activate), selector);
+ g_signal_connect (selector->entry, "changed",
+ G_CALLBACK (on_entry_changed), selector);
+ g_signal_connect (selector->entry, "key-press-event",
+ G_CALLBACK (on_entry_key_press_event), selector);
+
+ g_signal_connect (selector->treeview, "row-activated",
+ G_CALLBACK (on_row_activated), selector);
+
+ /* Populate tree model */
+ gtk_list_store_append (selector->liststore, &iter);
+ gtk_list_store_set (selector->liststore, &iter,
+ COLUMN_NAME, _("Plain Text"),
+ COLUMN_LANG, NULL,
+ -1);
+
+ lm = gtk_source_language_manager_get_default ();
+ ids = gtk_source_language_manager_get_language_ids (lm);
+
+ for (i = 0; ids[i] != NULL; i++)
+ {
+ GtkSourceLanguage *lang;
+
+ lang = gtk_source_language_manager_get_language (lm, ids[i]);
+
+ if (!gtk_source_language_get_hidden (lang))
+ {
+ gtk_list_store_append (selector->liststore, &iter);
+ gtk_list_store_set (selector->liststore, &iter,
+ COLUMN_NAME, gtk_source_language_get_name (lang),
+ COLUMN_LANG, lang,
+ -1);
+ }
+ }
+
+ /* select first item */
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (selector->treemodelfilter), &iter))
+ {
+ gtk_tree_selection_select_iter (selector->treeview_selection, &iter);
+ }
+}
+
+GeditHighlightModeSelector *
+gedit_highlight_mode_selector_new ()
+{
+ return g_object_new (GEDIT_TYPE_HIGHLIGHT_MODE_SELECTOR, NULL);
+}
+
+void
+gedit_highlight_mode_selector_select_language (GeditHighlightModeSelector *selector,
+ GtkSourceLanguage *language)
+{
+ GtkTreeIter iter;
+
+ g_return_if_fail (GEDIT_IS_HIGHLIGHT_MODE_SELECTOR (selector));
+
+ if (language == NULL)
+ {
+ return;
+ }
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (selector->treemodelfilter), &iter))
+ {
+ do
+ {
+ GtkSourceLanguage *lang;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (selector->treemodelfilter),
+ &iter,
+ COLUMN_LANG, &lang,
+ -1);
+
+ if (lang != NULL)
+ {
+ gboolean equal = (lang == language);
+
+ g_object_unref (lang);
+
+ if (equal)
+ {
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL
(selector->treemodelfilter), &iter);
+
+ gtk_tree_selection_select_iter (selector->treeview_selection, &iter);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (selector->treeview),
+ path, NULL, TRUE, 0.5, 0);
+ gtk_tree_path_free (path);
+ break;
+ }
+ }
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (selector->treemodelfilter), &iter));
+ }
+}
+
+void
+gedit_highlight_mode_selector_activate_selected_language (GeditHighlightModeSelector *selector)
+{
+ GtkSourceLanguage *lang;
+ GtkTreeIter iter;
+
+ g_return_if_fail (GEDIT_IS_HIGHLIGHT_MODE_SELECTOR (selector));
+
+ if (!gtk_tree_selection_get_selected (selector->treeview_selection, NULL, &iter))
+ {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (selector->treemodelfilter), &iter,
+ COLUMN_LANG, &lang,
+ -1);
+
+ g_signal_emit (G_OBJECT (selector), signals[LANGUAGE_SELECTED], 0, lang);
+
+ if (lang != NULL)
+ {
+ g_object_unref (lang);
+ }
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-highlight-mode-selector.h b/gedit/gedit-highlight-mode-selector.h
new file mode 100644
index 000000000..dc19e3cc4
--- /dev/null
+++ b/gedit/gedit-highlight-mode-selector.h
@@ -0,0 +1,44 @@
+/*
+ * gedit-highlight-mode-selector.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2013 - Ignacio Casal Quinteiro
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_HIGHLIGHT_MODE_SELECTOR_H
+#define GEDIT_HIGHLIGHT_MODE_SELECTOR_H
+
+#include <gtksourceview/gtksource.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_HIGHLIGHT_MODE_SELECTOR (gedit_highlight_mode_selector_get_type ())
+
+G_DECLARE_FINAL_TYPE (GeditHighlightModeSelector, gedit_highlight_mode_selector, GEDIT,
HIGHLIGHT_MODE_SELECTOR, GtkGrid)
+
+GeditHighlightModeSelector *gedit_highlight_mode_selector_new (void);
+
+void gedit_highlight_mode_selector_select_language (GeditHighlightModeSelector
*selector,
+ GtkSourceLanguage
*language);
+
+void gedit_highlight_mode_selector_activate_selected_language
+ (GeditHighlightModeSelector
*selector);
+
+G_END_DECLS
+
+#endif /* GEDIT_HIGHLIGHT_MODE_SELECTOR_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-io-error-info-bar.c b/gedit/gedit-io-error-info-bar.c
index 77ca04d7b..21e27e459 100644
--- a/gedit/gedit-io-error-info-bar.c
+++ b/gedit/gedit-io-error-info-bar.c
@@ -23,9 +23,16 @@
*/
#include "gedit-io-error-info-bar.h"
+
+#include <errno.h>
+#include <string.h>
#include <glib/gi18n.h>
-#include <tepl/tepl.h>
+#include <gio/gio.h>
+
#include "gedit-encodings-combo-box.h"
+#include "gedit-settings.h"
+#include "gedit-utils.h"
+#include "gedit-document.h"
#define MAX_URI_IN_DIALOG_LENGTH 50
@@ -220,7 +227,7 @@ parse_gio_error (gint code,
uri = g_file_get_uri (location);
}
- if (uri && tepl_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
+ if (uri && gedit_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
{
if (hn != NULL)
{
@@ -323,8 +330,8 @@ gedit_unrecoverable_reverting_error_info_bar_new (GFile *location,
* though the dialog uses wrapped text, if the URI doesn't contain
* white space then the text-wrapping code is too stupid to wrap it.
*/
- temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
- MAX_URI_IN_DIALOG_LENGTH);
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
g_free (full_formatted_uri);
uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -534,8 +541,8 @@ gedit_io_loading_error_info_bar_new (GFile *location,
* though the dialog uses wrapped text, if the URI doesn't contain
* white space then the text-wrapping code is too stupid to wrap it.
*/
- temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
- MAX_URI_IN_DIALOG_LENGTH);
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
g_free (full_formatted_uri);
uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -655,8 +662,8 @@ gedit_conversion_error_while_saving_info_bar_new (GFile *locat
* though the dialog uses wrapped text, if the URI doesn't contain
* white space then the text-wrapping code is too stupid to wrap it.
*/
- temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
- MAX_URI_IN_DIALOG_LENGTH);
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
g_free (full_formatted_uri);
uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -700,6 +707,88 @@ gedit_conversion_error_info_bar_get_encoding (GtkWidget *info_bar)
return NULL;
}
+GtkWidget *
+gedit_file_already_open_warning_info_bar_new (GFile *location)
+{
+ GtkWidget *info_bar;
+ GtkWidget *hbox_content;
+ GtkWidget *vbox;
+ gchar *primary_markup;
+ gchar *secondary_markup;
+ GtkWidget *primary_label;
+ GtkWidget *secondary_label;
+ gchar *primary_text;
+ const gchar *secondary_text;
+ gchar *full_formatted_uri;
+ gchar *uri_for_display;
+ gchar *temp_uri_for_display;
+
+ g_return_val_if_fail (G_IS_FILE (location), NULL);
+
+ full_formatted_uri = g_file_get_parse_name (location);
+
+ /* Truncate the URI so it doesn't get insanely wide. Note that even
+ * though the dialog uses wrapped text, if the URI doesn't contain
+ * white space then the text-wrapping code is too stupid to wrap it.
+ */
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
+ g_free (full_formatted_uri);
+
+ uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
+ g_free (temp_uri_for_display);
+
+ info_bar = gtk_info_bar_new ();
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ /* Translators: the access key chosen for this string should be
+ different from other main menu access keys (Open, Edit, View...) */
+ _("Edit Any_way"),
+ GTK_RESPONSE_YES);
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ /* Translators: the access key chosen for this string should be
+ different from other main menu access keys (Open, Edit, View...) */
+ _("D_on’t Edit"),
+ GTK_RESPONSE_CANCEL);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+ GTK_MESSAGE_WARNING);
+
+ hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
+
+ primary_text = g_strdup_printf (_("This file “%s†is already open in another window."),
uri_for_display);
+ g_free (uri_for_display);
+
+ primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
+ g_free (primary_text);
+ primary_label = gtk_label_new (primary_markup);
+ g_free (primary_markup);
+ gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
+ gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
+ gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
+ gtk_widget_set_can_focus (primary_label, TRUE);
+ gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
+
+ secondary_text = _("Do you want to edit it anyway?");
+ secondary_markup = g_strdup_printf ("<small>%s</small>",
+ secondary_text);
+ secondary_label = gtk_label_new (secondary_markup);
+ g_free (secondary_markup);
+ gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
+ gtk_widget_set_can_focus (secondary_label, TRUE);
+ gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
+ gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
+
+ gtk_widget_show_all (hbox_content);
+ set_contents (info_bar, hbox_content);
+
+ return info_bar;
+}
+
GtkWidget *
gedit_externally_modified_saving_error_info_bar_new (GFile *location,
const GError *error)
@@ -728,8 +817,8 @@ gedit_externally_modified_saving_error_info_bar_new (GFile *location,
* though the dialog uses wrapped text, if the URI doesn't contain
* white space then the text-wrapping code is too stupid to wrap it.
*/
- temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
- MAX_URI_IN_DIALOG_LENGTH);
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
g_free (full_formatted_uri);
uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -788,6 +877,110 @@ gedit_externally_modified_saving_error_info_bar_new (GFile *location,
return info_bar;
}
+GtkWidget *
+gedit_no_backup_saving_error_info_bar_new (GFile *location,
+ const GError *error)
+{
+ GtkWidget *info_bar;
+ GtkWidget *hbox_content;
+ GtkWidget *vbox;
+ gchar *primary_markup;
+ gchar *secondary_markup;
+ GtkWidget *primary_label;
+ GtkWidget *secondary_label;
+ gchar *primary_text;
+ const gchar *secondary_text;
+ gchar *full_formatted_uri;
+ gchar *uri_for_display;
+ gchar *temp_uri_for_display;
+ gboolean create_backup_copy;
+ GSettings *editor_settings;
+
+ g_return_val_if_fail (G_IS_FILE (location), NULL);
+ g_return_val_if_fail (error != NULL, NULL);
+ g_return_val_if_fail (error->domain == G_IO_ERROR &&
+ error->code == G_IO_ERROR_CANT_CREATE_BACKUP, NULL);
+
+ full_formatted_uri = g_file_get_parse_name (location);
+
+ /* Truncate the URI so it doesn't get insanely wide. Note that even
+ * though the dialog uses wrapped text, if the URI doesn't contain
+ * white space then the text-wrapping code is too stupid to wrap it.
+ */
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
+ g_free (full_formatted_uri);
+
+ uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
+ g_free (temp_uri_for_display);
+
+ info_bar = gtk_info_bar_new ();
+
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ _("S_ave Anyway"),
+ GTK_RESPONSE_YES);
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ _("D_on’t Save"),
+ GTK_RESPONSE_CANCEL);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+ GTK_MESSAGE_WARNING);
+
+ hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
+
+ editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
+
+ create_backup_copy = g_settings_get_boolean (editor_settings,
+ GEDIT_SETTINGS_CREATE_BACKUP_COPY);
+ g_object_unref (editor_settings);
+
+ /* FIXME: review this messages */
+ if (create_backup_copy)
+ {
+ primary_text = g_strdup_printf (_("Could not create a backup file while saving “%sâ€"),
+ uri_for_display);
+ }
+ else
+ {
+ primary_text = g_strdup_printf (_("Could not create a temporary backup file while saving
“%sâ€"),
+ uri_for_display);
+ }
+
+ g_free (uri_for_display);
+
+ primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
+ g_free (primary_text);
+ primary_label = gtk_label_new (primary_markup);
+ g_free (primary_markup);
+ gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
+ gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
+ gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
+ gtk_widget_set_can_focus (primary_label, TRUE);
+ gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
+
+ secondary_text = _("Could not back up the old copy of the file before saving the new one. "
+ "You can ignore this warning and save the file anyway, but if an error "
+ "occurs while saving, you could lose the old copy of the file. Save anyway?");
+ secondary_markup = g_strdup_printf ("<small>%s</small>",
+ secondary_text);
+ secondary_label = gtk_label_new (secondary_markup);
+ g_free (secondary_markup);
+ gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
+ gtk_widget_set_can_focus (secondary_label, TRUE);
+ gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
+ gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
+
+ gtk_widget_show_all (hbox_content);
+ set_contents (info_bar, hbox_content);
+
+ return info_bar;
+}
+
GtkWidget *
gedit_unrecoverable_saving_error_info_bar_new (GFile *location,
const GError *error)
@@ -812,8 +1005,8 @@ gedit_unrecoverable_saving_error_info_bar_new (GFile *location,
* though the dialog uses wrapped text, if the URI doesn't contain
* white space then the text-wrapping code is too stupid to wrap it.
*/
- temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
- MAX_URI_IN_DIALOG_LENGTH);
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
g_free (full_formatted_uri);
uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -917,4 +1110,149 @@ gedit_unrecoverable_saving_error_info_bar_new (GFile *location,
return info_bar;
}
+GtkWidget *
+gedit_externally_modified_info_bar_new (GFile *location,
+ gboolean document_modified)
+{
+ gchar *full_formatted_uri;
+ gchar *uri_for_display;
+ gchar *temp_uri_for_display;
+ gchar *primary_text;
+ GtkWidget *info_bar;
+
+ g_return_val_if_fail (G_IS_FILE (location), NULL);
+
+ full_formatted_uri = g_file_get_parse_name (location);
+
+ /* Truncate the URI so it doesn't get insanely wide. Note that even
+ * though the dialog uses wrapped text, if the URI doesn't contain
+ * white space then the text-wrapping code is too stupid to wrap it.
+ */
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
+ g_free (full_formatted_uri);
+
+ uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
+ g_free (temp_uri_for_display);
+
+ primary_text = g_strdup_printf (_("The file “%s†changed on disk."),
+ uri_for_display);
+ g_free (uri_for_display);
+
+ info_bar = gtk_info_bar_new ();
+
+ if (document_modified)
+ {
+ GtkWidget *box;
+ GtkWidget *button;
+ button = gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ _("Drop Changes and _Reload"),
+ GTK_RESPONSE_OK);
+ box = gtk_info_bar_get_action_area (GTK_INFO_BAR (info_bar));
+ gtk_button_box_set_child_non_homogeneous (GTK_BUTTON_BOX (box),
+ button,
+ TRUE);
+ }
+ else
+ {
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ _("_Reload"),
+ GTK_RESPONSE_OK);
+ }
+
+ gtk_info_bar_set_show_close_button (GTK_INFO_BAR (info_bar), TRUE);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+ GTK_MESSAGE_WARNING);
+
+ set_info_bar_text (info_bar,
+ primary_text,
+ NULL);
+
+ g_free (primary_text);
+
+ return info_bar;
+}
+
+GtkWidget *
+gedit_invalid_character_info_bar_new (GFile *location)
+{
+ GtkWidget *info_bar;
+ GtkWidget *hbox_content;
+ GtkWidget *vbox;
+ GtkWidget *primary_label;
+ GtkWidget *secondary_label;
+ gchar *primary_markup;
+ gchar *secondary_markup;
+ gchar *primary_text;
+ gchar *full_formatted_uri;
+ gchar *uri_for_display;
+ gchar *temp_uri_for_display;
+ const gchar *secondary_text;
+
+ g_return_val_if_fail (G_IS_FILE (location), NULL);
+
+ full_formatted_uri = g_file_get_parse_name (location);
+
+ /* Truncate the URI so it doesn't get insanely wide. Note that even
+ * though the dialog uses wrapped text, if the URI doesn't contain
+ * white space then the text-wrapping code is too stupid to wrap it.
+ */
+ temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
+ g_free (full_formatted_uri);
+
+ uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
+ g_free (temp_uri_for_display);
+
+ info_bar = gtk_info_bar_new ();
+
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ _("S_ave Anyway"),
+ GTK_RESPONSE_YES);
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ _("D_on’t Save"),
+ GTK_RESPONSE_CANCEL);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+ GTK_MESSAGE_WARNING);
+
+ hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
+
+ primary_text = g_strdup_printf (_("Some invalid chars have been detected while saving “%sâ€"),
+ uri_for_display);
+
+ g_free (uri_for_display);
+
+ primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
+ g_free (primary_text);
+ primary_label = gtk_label_new (primary_markup);
+ g_free (primary_markup);
+ gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
+ gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
+ gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
+ gtk_widget_set_can_focus (primary_label, TRUE);
+ gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
+
+ secondary_text = _("If you continue saving this file you can corrupt the document. "
+ " Save anyway?");
+ secondary_markup = g_strdup_printf ("<small>%s</small>",
+ secondary_text);
+ secondary_label = gtk_label_new (secondary_markup);
+ g_free (secondary_markup);
+ gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
+ gtk_widget_set_can_focus (secondary_label, TRUE);
+ gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
+ gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
+
+ gtk_widget_show_all (hbox_content);
+ set_contents (info_bar, hbox_content);
+
+ return info_bar;
+}
+
/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-io-error-info-bar.h b/gedit/gedit-io-error-info-bar.h
index 12780f7ae..9784652c7 100644
--- a/gedit/gedit-io-error-info-bar.h
+++ b/gedit/gedit-io-error-info-bar.h
@@ -39,12 +39,22 @@ GtkWidget *gedit_conversion_error_while_saving_info_bar_new (GFile
const GtkSourceEncoding
*gedit_conversion_error_info_bar_get_encoding (GtkWidget *info_bar);
+GtkWidget *gedit_file_already_open_warning_info_bar_new (GFile *location);
+
GtkWidget *gedit_externally_modified_saving_error_info_bar_new (GFile *location,
const GError *error);
+GtkWidget *gedit_no_backup_saving_error_info_bar_new (GFile *location,
+ const GError *error);
+
GtkWidget *gedit_unrecoverable_saving_error_info_bar_new (GFile *location,
const GError *error);
+GtkWidget *gedit_externally_modified_info_bar_new (GFile *location,
+ gboolean
document_modified);
+
+GtkWidget *gedit_invalid_character_info_bar_new (GFile *location);
+
G_END_DECLS
#endif /* GEDIT_IO_ERROR_INFO_BAR_H */
diff --git a/gedit/gedit-metadata-manager.c b/gedit/gedit-metadata-manager.c
new file mode 100644
index 000000000..8f858b286
--- /dev/null
+++ b/gedit/gedit-metadata-manager.c
@@ -0,0 +1,650 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gedit-metadata-manager.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2003-2007 Paolo Maggi
+ * Copyright (C) 2019 Canonical LTD
+ *
+ * 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 2 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/>.
+ */
+
+#include "gedit-metadata-manager.h"
+#include <libxml/xmlreader.h>
+#include "gedit-debug.h"
+
+/*
+#define GEDIT_METADATA_VERBOSE_DEBUG 1
+*/
+
+#define MAX_ITEMS 50
+
+typedef struct _Item Item;
+
+struct _Item
+{
+ /* Time of last access in seconds since January 1, 1970 UTC. */
+ gint64 atime;
+
+ GHashTable *values;
+};
+
+struct _GeditMetadataManager
+{
+ GObject parent_instance;
+
+ /* It is true if the file has been read. */
+ gboolean values_loaded;
+
+ guint timeout_id;
+
+ GHashTable *items;
+
+ gchar *metadata_filename;
+};
+
+enum
+{
+ PROP_0,
+ PROP_METADATA_FILENAME,
+ LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP];
+
+G_DEFINE_TYPE (GeditMetadataManager, gedit_metadata_manager, G_TYPE_OBJECT);
+
+static gboolean gedit_metadata_manager_save (GeditMetadataManager *self);
+
+static void
+item_free (gpointer data)
+{
+ Item *item;
+
+ g_return_if_fail (data != NULL);
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+ gedit_debug (DEBUG_METADATA);
+#endif
+
+ item = (Item *)data;
+
+ if (item->values != NULL)
+ g_hash_table_destroy (item->values);
+
+ g_free (item);
+}
+
+static void
+gedit_metadata_manager_arm_timeout (GeditMetadataManager *self)
+{
+ if (self->timeout_id == 0)
+ {
+ self->timeout_id =
+ g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE,
+ 2,
+ (GSourceFunc)gedit_metadata_manager_save,
+ self,
+ NULL);
+ }
+}
+
+static void
+gedit_metadata_manager_parse_item (GeditMetadataManager *self,
+ xmlDocPtr doc,
+ xmlNodePtr cur)
+{
+ Item *item;
+
+ xmlChar *uri;
+ xmlChar *atime;
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+ gedit_debug (DEBUG_METADATA);
+#endif
+
+ if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0)
+ return;
+
+ uri = xmlGetProp (cur, (const xmlChar *)"uri");
+ if (uri == NULL)
+ return;
+
+ atime = xmlGetProp (cur, (const xmlChar *)"atime");
+ if (atime == NULL)
+ {
+ xmlFree (uri);
+ return;
+ }
+
+ item = g_new0 (Item, 1);
+
+ item->atime = g_ascii_strtoll ((char *)atime, NULL, 0);
+
+ item->values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_free);
+
+ cur = cur->xmlChildrenNode;
+
+ while (cur != NULL)
+ {
+ if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0)
+ {
+ xmlChar *key;
+ xmlChar *value;
+
+ key = xmlGetProp (cur, (const xmlChar *)"key");
+ value = xmlGetProp (cur, (const xmlChar *)"value");
+
+ if ((key != NULL) && (value != NULL))
+ {
+ g_hash_table_insert (item->values,
+ g_strdup ((gchar *)key),
+ g_strdup ((gchar *)value));
+ }
+
+ if (key != NULL)
+ xmlFree (key);
+ if (value != NULL)
+ xmlFree (value);
+ }
+
+ cur = cur->next;
+ }
+
+ g_hash_table_insert (self->items,
+ g_strdup ((gchar *)uri),
+ item);
+
+ xmlFree (uri);
+ xmlFree (atime);
+}
+
+/* Returns FALSE in case of error. */
+static gboolean
+gedit_metadata_manager_load_values (GeditMetadataManager *self)
+{
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+
+ gedit_debug (DEBUG_METADATA);
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (self->values_loaded == FALSE, FALSE);
+
+ self->values_loaded = TRUE;
+
+ xmlKeepBlanksDefault (0);
+
+ if (self->metadata_filename == NULL)
+ {
+ return FALSE;
+ }
+
+ /* TODO: avoid races */
+ if (!g_file_test (self->metadata_filename, G_FILE_TEST_EXISTS))
+ {
+ return TRUE;
+ }
+
+ doc = xmlParseFile (self->metadata_filename);
+
+ if (doc == NULL)
+ {
+ return FALSE;
+ }
+
+ cur = xmlDocGetRootElement (doc);
+ if (cur == NULL)
+ {
+ g_message ("The metadata file '%s' is empty",
+ g_path_get_basename (self->metadata_filename));
+ xmlFreeDoc (doc);
+
+ return TRUE;
+ }
+
+ if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
+ {
+ g_message ("File '%s' is of the wrong type",
+ g_path_get_basename (self->metadata_filename));
+ xmlFreeDoc (doc);
+
+ return FALSE;
+ }
+
+ cur = xmlDocGetRootElement (doc);
+ cur = cur->xmlChildrenNode;
+
+ while (cur != NULL)
+ {
+ gedit_metadata_manager_parse_item (self, doc, cur);
+
+ cur = cur->next;
+ }
+
+ xmlFreeDoc (doc);
+
+ return TRUE;
+}
+
+/**
+ * gedit_metadata_manager_get:
+ * @self: a #GeditMetadataManager.
+ * @location: a #GFile.
+ * @key: a key.
+ *
+ * Gets the value associated with the specified @key for the file @location.
+ */
+gchar *
+gedit_metadata_manager_get (GeditMetadataManager *self,
+ GFile *location,
+ const gchar *key)
+{
+ Item *item;
+ gchar *value;
+ gchar *uri;
+
+ g_return_val_if_fail (GEDIT_IS_METADATA_MANAGER (self), NULL);
+ g_return_val_if_fail (G_IS_FILE (location), NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+
+ uri = g_file_get_uri (location);
+
+ gedit_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
+
+ if (!self->values_loaded)
+ {
+ gboolean res;
+
+ res = gedit_metadata_manager_load_values (self);
+
+ if (!res)
+ {
+ g_free (uri);
+ return NULL;
+ }
+ }
+
+ item = (Item *)g_hash_table_lookup (self->items, uri);
+
+ g_free (uri);
+
+ if (item == NULL)
+ return NULL;
+
+ item->atime = g_get_real_time () / 1000;
+
+ if (item->values == NULL)
+ return NULL;
+
+ value = g_hash_table_lookup (item->values, key);
+
+ if (value == NULL)
+ return NULL;
+ else
+ return g_strdup (value);
+}
+
+/**
+ * gedit_metadata_manager_set:
+ * @self: a #GeditMetadataManager.
+ * @location: a #GFile.
+ * @key: a key.
+ * @value: the value associated with the @key.
+ *
+ * Sets the @key to contain the given @value for the file @location.
+ */
+void
+gedit_metadata_manager_set (GeditMetadataManager *self,
+ GFile *location,
+ const gchar *key,
+ const gchar *value)
+{
+ Item *item;
+ gchar *uri;
+
+ g_return_if_fail (GEDIT_IS_METADATA_MANAGER (self));
+ g_return_if_fail (G_IS_FILE (location));
+ g_return_if_fail (key != NULL);
+
+ uri = g_file_get_uri (location);
+
+ gedit_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value);
+
+ if (!self->values_loaded)
+ {
+ gboolean ok;
+
+ ok = gedit_metadata_manager_load_values (self);
+
+ if (!ok)
+ {
+ g_free (uri);
+ return;
+ }
+ }
+
+ item = (Item *)g_hash_table_lookup (self->items, uri);
+
+ if (item == NULL)
+ {
+ item = g_new0 (Item, 1);
+
+ g_hash_table_insert (self->items,
+ g_strdup (uri),
+ item);
+ }
+
+ if (item->values == NULL)
+ {
+ item->values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_free);
+ }
+
+ if (value != NULL)
+ {
+ g_hash_table_insert (item->values,
+ g_strdup (key),
+ g_strdup (value));
+ }
+ else
+ {
+ g_hash_table_remove (item->values,
+ key);
+ }
+
+ item->atime = g_get_real_time () / 1000;
+
+ g_free (uri);
+
+ gedit_metadata_manager_arm_timeout (self);
+}
+
+static void
+save_values (const gchar *key, const gchar *value, xmlNodePtr parent)
+{
+ xmlNodePtr xml_node;
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+ gedit_debug (DEBUG_METADATA);
+#endif
+
+ g_return_if_fail (key != NULL);
+
+ if (value == NULL)
+ return;
+
+ xml_node = xmlNewChild (parent,
+ NULL,
+ (const xmlChar *)"entry",
+ NULL);
+
+ xmlSetProp (xml_node,
+ (const xmlChar *)"key",
+ (const xmlChar *)key);
+ xmlSetProp (xml_node,
+ (const xmlChar *)"value",
+ (const xmlChar *)value);
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+ gedit_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value);
+#endif
+}
+
+static void
+save_item (const gchar *key, const gpointer *data, xmlNodePtr parent)
+{
+ xmlNodePtr xml_node;
+ const Item *item = (const Item *)data;
+ gchar *atime;
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+ gedit_debug (DEBUG_METADATA);
+#endif
+
+ g_return_if_fail (key != NULL);
+
+ if (item == NULL)
+ return;
+
+ xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL);
+
+ xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key);
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+ gedit_debug_message (DEBUG_METADATA, "uri: %s", key);
+#endif
+
+ atime = g_strdup_printf ("%" G_GINT64_FORMAT, item->atime);
+ xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+ gedit_debug_message (DEBUG_METADATA, "atime: %s", atime);
+#endif
+
+ g_free (atime);
+
+ g_hash_table_foreach (item->values,
+ (GHFunc)save_values,
+ xml_node);
+}
+
+static const gchar *
+gedit_metadata_manager_get_oldest (GeditMetadataManager *self)
+{
+ GHashTableIter iter;
+ gpointer key, value, key_to_remove = NULL;
+ const Item *item_to_remove = NULL;
+
+ g_hash_table_iter_init (&iter, self->items);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ const Item *item = (const Item *) value;
+
+ if (key_to_remove == NULL)
+ {
+ key_to_remove = key;
+ item_to_remove = item;
+ }
+ else
+ {
+ g_return_val_if_fail (item_to_remove != NULL, NULL);
+
+ if (item->atime < item_to_remove->atime)
+ key_to_remove = key;
+ }
+ }
+
+ return key_to_remove;
+}
+
+static void
+gedit_metadata_manager_resize_items (GeditMetadataManager *self)
+{
+ while (g_hash_table_size (self->items) > MAX_ITEMS)
+ {
+ const gchar *key_to_remove;
+
+ key_to_remove = gedit_metadata_manager_get_oldest (self);
+ g_return_if_fail (key_to_remove != NULL);
+ g_hash_table_remove (self->items,
+ key_to_remove);
+ }
+}
+
+static gboolean
+gedit_metadata_manager_save (GeditMetadataManager *self)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root;
+
+ gedit_debug (DEBUG_METADATA);
+
+ self->timeout_id = 0;
+
+ gedit_metadata_manager_resize_items (self);
+
+ xmlIndentTreeOutput = TRUE;
+
+ doc = xmlNewDoc ((const xmlChar *)"1.0");
+ if (doc == NULL)
+ return TRUE;
+
+ /* Create metadata root */
+ root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL);
+ xmlDocSetRootElement (doc, root);
+
+ g_hash_table_foreach (self->items,
+ (GHFunc)save_item,
+ root);
+
+ /* FIXME: lock file - Paolo */
+ if (self->metadata_filename != NULL)
+ {
+ gchar *cache_dir;
+ int res;
+
+ /* make sure the cache dir exists */
+ cache_dir = g_path_get_dirname (self->metadata_filename);
+ res = g_mkdir_with_parents (cache_dir, 0755);
+ if (res != -1)
+ {
+ xmlSaveFormatFile (self->metadata_filename,
+ doc,
+ 1);
+ }
+
+ g_free (cache_dir);
+ }
+
+ xmlFreeDoc (doc);
+
+ gedit_debug_message (DEBUG_METADATA, "DONE");
+
+ return FALSE;
+}
+
+static void
+gedit_metadata_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeditMetadataManager *self = GEDIT_METADATA_MANAGER (object);
+
+ switch (prop_id)
+ {
+ case PROP_METADATA_FILENAME:
+ g_value_set_string (value, self->metadata_filename);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gedit_metadata_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditMetadataManager *self = GEDIT_METADATA_MANAGER (object);
+
+ switch (prop_id)
+ {
+ case PROP_METADATA_FILENAME:
+ self->metadata_filename = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_metadata_manager_init (GeditMetadataManager *self)
+{
+ gedit_debug (DEBUG_METADATA);
+
+ self->values_loaded = FALSE;
+
+ self->items =
+ g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ item_free);
+}
+
+static void
+gedit_metadata_manager_dispose (GObject *object)
+{
+ GeditMetadataManager *self = GEDIT_METADATA_MANAGER (object);
+
+ gedit_debug (DEBUG_METADATA);
+
+ if (self->timeout_id)
+ {
+ g_source_remove (self->timeout_id);
+ self->timeout_id = 0;
+ gedit_metadata_manager_save (self);
+ }
+
+ if (self->items != NULL)
+ g_hash_table_destroy (self->items);
+
+ g_free (self->metadata_filename);
+}
+
+static void
+gedit_metadata_manager_class_init (GeditMetadataManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gedit_metadata_manager_dispose;
+ object_class->get_property = gedit_metadata_manager_get_property;
+ object_class->set_property = gedit_metadata_manager_set_property;
+
+ /**
+ * GeditMetadataManager:metadata-filename:
+ *
+ * The filename where the metadata is stored.
+ */
+ properties[PROP_METADATA_FILENAME] =
+ g_param_spec_string ("metadata-filename",
+ "Metadata filename",
+ "The filename where the metadata is stored",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+GeditMetadataManager *
+gedit_metadata_manager_new (const gchar *metadata_filename)
+{
+ gedit_debug (DEBUG_METADATA);
+
+ return g_object_new (GEDIT_TYPE_METADATA_MANAGER,
+ "metadata-filename", metadata_filename,
+ NULL);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-metadata-manager.h b/gedit/gedit-metadata-manager.h
new file mode 100644
index 000000000..49c2f05bf
--- /dev/null
+++ b/gedit/gedit-metadata-manager.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gedit-metadata-manager.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2003 Paolo Maggi
+ * Copyright (C) 2019 Canonical LTD
+ *
+ * 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 2 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/>.
+ */
+
+#ifndef GEDIT_METADATA_MANAGER_H
+#define GEDIT_METADATA_MANAGER_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_METADATA_MANAGER (gedit_metadata_manager_get_type())
+
+G_DECLARE_FINAL_TYPE (GeditMetadataManager, gedit_metadata_manager, GEDIT, METADATA_MANAGER, GObject)
+
+GeditMetadataManager *gedit_metadata_manager_new (const gchar *metadata_filename);
+
+gchar *gedit_metadata_manager_get (GeditMetadataManager *self,
+ GFile *location,
+ const gchar *key);
+
+void gedit_metadata_manager_set (GeditMetadataManager *self,
+ GFile *location,
+ const gchar *key,
+ const gchar *value);
+
+G_END_DECLS
+
+#endif /* GEDIT_METADATA_MANAGER_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-helper.c b/gedit/gedit-open-document-selector-helper.c
new file mode 100644
index 000000000..369d12ea2
--- /dev/null
+++ b/gedit/gedit-open-document-selector-helper.c
@@ -0,0 +1,103 @@
+/*
+ * gedit-open-document-selector-helper.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-open-document-selector-helper.h"
+
+void
+gedit_open_document_selector_debug_print_list (const gchar *title,
+ GList *fileitem_list)
+{
+ FileItem *item;
+ GList *l;
+ glong time_sec;
+ glong time_usec;
+
+ g_print ("%s\n", title);
+
+ for (l = fileitem_list; l != NULL; l = l->next)
+ {
+ item = (FileItem *)l->data;
+ time_sec = item->access_time.tv_sec;
+ time_usec = item->access_time.tv_usec;
+
+ g_print ("%ld:%ld uri:%s (%s %s)\n",
+ time_sec,
+ time_usec,
+ item->uri,
+ item->name,
+ item->path);
+ }
+}
+
+FileItem *
+gedit_open_document_selector_create_fileitem_item (void)
+{
+ FileItem *item;
+
+ item = g_slice_new0 (FileItem);
+
+ return item;
+}
+
+void
+gedit_open_document_selector_free_fileitem_item (FileItem *item)
+{
+ g_free (item->uri);
+ g_free (item->name);
+ g_free (item->path);
+
+ g_slice_free (FileItem, item);
+}
+
+FileItem *
+gedit_open_document_selector_copy_fileitem_item (FileItem *item)
+{
+ FileItem *new_item;
+
+ new_item = gedit_open_document_selector_create_fileitem_item ();
+
+ new_item->uri = g_strdup (item->uri);
+ new_item->name = g_strdup (item->name);
+ new_item->path = g_strdup (item->path);
+ new_item->access_time = item->access_time;
+
+ return new_item;
+}
+
+inline GList *
+gedit_open_document_selector_copy_file_items_list (const GList *file_items_list)
+{
+ GList *new_file_items_list;
+
+ new_file_items_list = g_list_copy_deep ((GList *)file_items_list,
+ (GCopyFunc)gedit_open_document_selector_copy_fileitem_item,
+ NULL);
+
+ return new_file_items_list;
+}
+
+inline void
+gedit_open_document_selector_free_file_items_list (GList *file_items_list)
+{
+ g_list_free_full (file_items_list,
+ (GDestroyNotify)gedit_open_document_selector_free_fileitem_item);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-helper.h b/gedit/gedit-open-document-selector-helper.h
new file mode 100644
index 000000000..6feb65408
--- /dev/null
+++ b/gedit/gedit-open-document-selector-helper.h
@@ -0,0 +1,103 @@
+/*
+ * gedit-open-document-selector-helper.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H
+
+#include "gedit-open-document-selector.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ gchar *uri;
+ gchar *name;
+ gchar *path;
+ GTimeVal access_time;
+} FileItem;
+
+typedef enum
+{
+ GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST = 0,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_HOME_DIR_LIST,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_DESKTOP_DIR_LIST,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_LOCAL_BOOKMARKS_DIR_LIST,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_FILE_BROWSER_ROOT_DIR_LIST,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_ACTIVE_DOC_DIR_LIST,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_CURRENT_DOCS_LIST,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS
+} ListType;
+
+/* Use #if 1 and rebuild to activate selector debugging and timing */
+#if 0
+#define DEBUG_OPEN_DOCUMENT_SELECTOR
+#endif
+
+#ifdef DEBUG_OPEN_DOCUMENT_SELECTOR
+G_GNUC_UNUSED static const gchar *list_type_string[] =
+{
+ "RECENT_FILES_LIST",
+ "HOME_DIR_LIST",
+ "DESKTOP_DIR_LIST",
+ "LOCAL_BOOKMARKS_DIR_LIST",
+ "FILE_BROWSER_ROOT_DIR_LIST",
+ "ACTIVE_DOC_DIR_LIST",
+ "CURRENT_DOCS_LIST"
+};
+
+#define DEBUG_SELECTOR(x) do { x; } while (0)
+#define DEBUG_SELECTOR_TIMER_DECL G_GNUC_UNUSED GTimer *debug_timer;
+#define DEBUG_SELECTOR_TIMER_NEW debug_timer = g_timer_new ();
+#define DEBUG_SELECTOR_TIMER_DESTROY g_timer_destroy (debug_timer);
+#define DEBUG_SELECTOR_TIMER_GET g_timer_elapsed (debug_timer, NULL)
+#else
+#define DEBUG_SELECTOR(x)
+#define DEBUG_SELECTOR_TIMER_DECL
+#define DEBUG_SELECTOR_TIMER_NEW
+#define DEBUG_SELECTOR_TIMER_DESTROY
+#define DEBUG_SELECTOR_TIMER_GET
+#endif
+
+typedef struct
+{
+ GeditOpenDocumentSelector *selector;
+ ListType type;
+} PushMessage;
+
+void gedit_open_document_selector_debug_print_list (const gchar *title,
+ GList *fileitem_list);
+
+GList *gedit_open_document_selector_copy_file_items_list (const GList *file_items_list);
+
+void gedit_open_document_selector_free_file_items_list (GList *file_items_list);
+
+FileItem *gedit_open_document_selector_create_fileitem_item (void);
+
+void gedit_open_document_selector_free_fileitem_item (FileItem *item);
+
+FileItem *gedit_open_document_selector_copy_fileitem_item (FileItem *item);
+
+G_END_DECLS
+
+#endif /* GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-store.c b/gedit/gedit-open-document-selector-store.c
new file mode 100644
index 000000000..e3454f12c
--- /dev/null
+++ b/gedit/gedit-open-document-selector-store.c
@@ -0,0 +1,820 @@
+/*
+ * gedit-open-document-selector-store.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* You need to call gedit_open_document_selector_store_get_default()
+ * to get a singleton #GeditOpenDocumentSelectorStore object.
+ * #GeditOpenDocumentSelectorStore is responsible of managing
+ * the recent files list and computing others lists.
+ *
+ * The lists returned are lists of FileItem structs.
+ *
+ * #GeditOpenDocumentSelectorStore is destroyed automaticly at
+ * the end of your application.
+ *
+ * Call gedit_open_document_selector_store_update_list_async() with
+ * the corresponding ListType, then in your callback, call
+ * gedit_open_document_selector_store_update_list_finish() to get
+ * in return the list of FileItem structs.
+ *
+ * The recent files list can be filtered by calling
+ * gedit_open_document_selector_store_set_filter()
+ * and you can get the actual filter by calling
+ * gedit_open_document_selector_store_get_filter()
+ * ( this is in addition to the text mime type filter)
+ *
+ * The recent files list is not capped by Gedit settings like
+ * in gedit_recent_get_items() but you still can get the limit
+ * by calling gedit_open_document_selector_store_get_recent_limit().
+ *
+ * The original setting is stored in gsettings at :
+ * org.gnome.gedit.preferences.ui
+ * with the key : max-recents
+ */
+
+#include "gedit-open-document-selector-store.h"
+
+#include <time.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "gedit-recent.h"
+#include "gedit-utils.h"
+#include "gedit-window.h"
+#include "gedit-debug.h"
+
+struct _GeditOpenDocumentSelectorStore
+{
+ GObject parent_instance;
+
+ GSource *recent_source;
+
+ GeditRecentConfiguration recent_config;
+ gchar *filter;
+ GList *recent_items;
+ gint recent_config_limit;
+ gboolean recent_items_need_update;
+};
+
+G_LOCK_DEFINE_STATIC (recent_files_filter_lock);
+
+G_DEFINE_TYPE (GeditOpenDocumentSelectorStore, gedit_open_document_selector_store, G_TYPE_OBJECT)
+
+G_DEFINE_QUARK (gedit-open-document-selector-store-error-quark,
+ gedit_open_document_selector_store_error)
+
+static GList *
+get_current_docs_list (GeditOpenDocumentSelectorStore *selector_store G_GNUC_UNUSED,
+ GeditOpenDocumentSelector *selector)
+{
+ GeditWindow *window;
+ GList *docs;
+ GList *l;
+ GFile *file;
+ GFileInfo *info;
+ FileItem *item;
+ GList *file_items_list = NULL;
+
+ window = gedit_open_document_selector_get_window (selector);
+
+ docs = gedit_window_get_documents (window);
+ for (l = docs; l != NULL; l = l->next)
+ {
+ file = gtk_source_file_get_location (gedit_document_get_file (l->data));
+ if (file == NULL)
+ {
+ /* In case of not saved docs */
+ continue;
+ }
+
+ info = g_file_query_info (file,
+ "time::access,time::access-usec",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (info == NULL)
+ {
+ continue;
+ }
+
+ item = gedit_open_document_selector_create_fileitem_item ();
+
+ item->access_time.tv_sec = g_file_info_get_attribute_uint64 (info, "time::access");
+ item->access_time.tv_usec = g_file_info_get_attribute_uint32 (info, "time::access-usec");
+ item->uri = g_file_get_uri (file);
+
+ file_items_list = g_list_prepend (file_items_list, item);
+
+ g_object_unref (info);
+ }
+
+ g_list_free (docs);
+ return file_items_list;
+}
+
+/* Notice that a content-type attribute must have been query to work */
+static gboolean
+check_mime_type (GFileInfo *info)
+{
+ const gchar *content_type;
+ G_GNUC_UNUSED gchar *mime_type;
+
+ content_type = g_file_info_get_attribute_string (info, "standard::fast-content-type");
+ if (content_type == NULL)
+ {
+ return FALSE;
+ }
+
+#ifdef G_OS_WIN32
+ if (g_content_type_is_a (content_type, "text"))
+ {
+ return TRUE;
+ }
+
+ mime_type = g_content_type_get_mime_type (content_type);
+ if (mime_type == NULL)
+ {
+ return FALSE;
+ }
+
+ if (g_strcmp0 (mime_type, "text/plain") == 0)
+ {
+ g_free (mime_type);
+ return TRUE;
+ }
+
+ g_free (mime_type);
+#else
+ if (g_content_type_is_a (content_type, "text/plain"))
+ {
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+static GList *
+get_children_from_dir (GeditOpenDocumentSelectorStore *selector_store G_GNUC_UNUSED,
+ GFile *dir)
+{
+ GList *file_items_list = NULL;
+ GFileEnumerator *file_enum;
+ GFileInfo *info;
+ GFileType filetype;
+ GFile *file;
+ FileItem *item;
+ gboolean is_text;
+ gboolean is_correct_type;
+
+ g_return_val_if_fail (G_IS_FILE (dir), NULL);
+
+ file_enum = g_file_enumerate_children (dir,
+ "standard::name,"
+ "standard::type,"
+ "standard::fast-content-type,"
+ "time::access,time::access-usec",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (file_enum == NULL)
+ {
+ return NULL;
+ }
+
+ while ((info = g_file_enumerator_next_file (file_enum, NULL, NULL)))
+ {
+ filetype = g_file_info_get_file_type (info);
+ is_text = check_mime_type (info);
+ is_correct_type = (filetype == G_FILE_TYPE_REGULAR ||
+ filetype == G_FILE_TYPE_SYMBOLIC_LINK ||
+ filetype == G_FILE_TYPE_SHORTCUT);
+
+ if (is_text &&
+ is_correct_type &&
+ (file = g_file_enumerator_get_child (file_enum, info)) != NULL)
+ {
+ item = gedit_open_document_selector_create_fileitem_item ();
+ item->uri = g_file_get_uri (file);
+
+ item->access_time.tv_sec = g_file_info_get_attribute_uint64 (info, "time::access");
+ item->access_time.tv_usec = g_file_info_get_attribute_uint32 (info,
"time::access-usec");
+
+ file_items_list = g_list_prepend (file_items_list, item);
+ g_object_unref (file);
+ }
+
+ g_object_unref (info);
+ }
+
+ g_file_enumerator_close (file_enum, NULL, NULL);
+ g_object_unref (file_enum);
+
+ return file_items_list;
+}
+
+static GList *
+get_active_doc_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+ GeditOpenDocumentSelector *selector)
+{
+ GeditWindow *window;
+ GeditDocument *active_doc;
+ GtkSourceFile *source_file;
+ GList *file_items_list = NULL;
+
+ window = gedit_open_document_selector_get_window (selector);
+
+ active_doc = gedit_window_get_active_document (window);
+
+ if (active_doc == NULL)
+ {
+ return NULL;
+ }
+
+ source_file = gedit_document_get_file (active_doc);
+ if (gtk_source_file_is_local (source_file))
+ {
+ GFile *location;
+ GFile *parent_dir;
+
+ location = gtk_source_file_get_location (source_file);
+ parent_dir = g_file_get_parent (location);
+
+ if (parent_dir != NULL)
+ {
+ file_items_list = get_children_from_dir (selector_store, parent_dir);
+ g_object_unref (parent_dir);
+ }
+ }
+
+ return file_items_list;
+}
+
+static GFile *
+get_file_browser_root (GeditOpenDocumentSelectorStore *selector_store G_GNUC_UNUSED,
+ GeditOpenDocumentSelector *selector)
+{
+ GeditWindow *window;
+ GeditMessageBus *bus;
+ GeditMessage *msg;
+ GFile *root = NULL;
+
+ window = gedit_open_document_selector_get_window (selector);
+
+ bus = gedit_window_get_message_bus (window);
+ if (gedit_message_bus_is_registered (bus, "/plugins/filebrowser", "get_root"))
+ {
+ msg = gedit_message_bus_send_sync (bus, "/plugins/filebrowser", "get_root", NULL, NULL);
+ g_object_get (msg, "location", &root, NULL);
+ g_object_unref (msg);
+ }
+
+ return root;
+}
+
+static GList *
+get_file_browser_root_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+ GeditOpenDocumentSelector *selector)
+{
+ GFile *root;
+ GList *file_items_list = NULL;
+
+ root = get_file_browser_root (selector_store, selector);
+ if (root != NULL && g_file_is_native (root))
+ {
+ file_items_list = get_children_from_dir (selector_store, root);
+ }
+
+ g_clear_object (&root);
+ return file_items_list;
+}
+
+/* Taken and adapted from gtk+ gtkbookmarksmanager.c */
+static GList *
+read_bookmarks_file (GFile *file)
+{
+ gchar *contents;
+ gchar **lines, *space;
+ GList *uri_list = NULL;
+ gint i;
+
+ if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, NULL))
+ {
+ return NULL;
+ }
+
+ lines = g_strsplit (contents, "\n", -1);
+
+ for (i = 0; lines[i]; i++)
+ {
+ if (*lines[i] == '\0')
+ {
+ continue;
+ }
+
+ if (!g_utf8_validate (lines[i], -1, NULL))
+ {
+ continue;
+ }
+
+ if ((space = strchr (lines[i], ' ')) != NULL)
+ {
+ space[0] = '\0';
+ }
+
+ uri_list = g_list_prepend (uri_list, g_strdup (lines[i]));
+ }
+
+ g_strfreev (lines);
+ g_free (contents);
+
+ return uri_list;
+}
+
+static GList *
+get_local_bookmarks_list (GeditOpenDocumentSelectorStore *selector_store,
+ GeditOpenDocumentSelector *selector G_GNUC_UNUSED)
+{
+ GList *bookmarks_uri_list = NULL;
+ GList *file_items_list = NULL;
+ GList *new_file_items_list = NULL;
+ GFile *bookmarks_file;
+ GFile *file;
+ gchar *filename;
+ GList *l;
+
+ filename = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "bookmarks", NULL);
+ bookmarks_file = g_file_new_for_path (filename);
+ g_free (filename);
+
+ bookmarks_uri_list = read_bookmarks_file (bookmarks_file);
+ g_object_unref (bookmarks_file);
+
+ for (l = bookmarks_uri_list; l != NULL; l = l->next)
+ {
+ file = g_file_new_for_uri (l->data);
+ if (g_file_is_native (file))
+ {
+ new_file_items_list = get_children_from_dir (selector_store, file);
+ file_items_list = g_list_concat (file_items_list, new_file_items_list);
+ }
+
+ g_object_unref (file);
+ }
+
+ g_list_free_full (bookmarks_uri_list, g_free);
+ return file_items_list;
+}
+
+/* Taken and adapted from gtk+ gtkplacessidebar.c */
+static gboolean
+path_is_home_dir (const gchar *path)
+{
+ GFile *home_dir;
+ GFile *location;
+ const gchar *home_path;
+ gboolean res;
+
+ home_path = g_get_home_dir ();
+ if (home_path == NULL)
+ {
+ return FALSE;
+ }
+
+ home_dir = g_file_new_for_path (home_path);
+ location = g_file_new_for_path (path);
+ res = g_file_equal (home_dir, location);
+
+ g_object_unref (home_dir);
+ g_object_unref (location);
+
+ return res;
+}
+
+static GList *
+get_desktop_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+ GeditOpenDocumentSelector *selector G_GNUC_UNUSED)
+{
+ GList *file_items_list = NULL;
+ const gchar *desktop_dir_name;
+ gchar *desktop_uri;
+ GFile *desktop_file;
+
+ desktop_dir_name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
+
+ /* "To disable a directory, point it to the homedir."
+ * See http://freedesktop.org/wiki/Software/xdg-user-dirs
+ */
+ if (path_is_home_dir (desktop_dir_name))
+ {
+ return NULL;
+ }
+
+ desktop_uri = g_strconcat ("file://", desktop_dir_name, NULL);
+ desktop_file = g_file_new_for_uri (desktop_uri);
+ file_items_list = get_children_from_dir (selector_store, desktop_file);
+
+ g_free (desktop_uri);
+ g_object_unref (desktop_file);
+
+ return file_items_list;
+}
+
+static GList *
+get_home_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+ GeditOpenDocumentSelector *selector G_GNUC_UNUSED)
+{
+ GList *file_items_list = NULL;
+ const gchar *home_name;
+ gchar *home_uri;
+ GFile *home_file;
+
+ home_name = g_get_home_dir ();
+ if (home_name == NULL)
+ {
+ return NULL;
+ }
+
+ home_uri = g_strconcat ("file://", home_name, NULL);
+ home_file = g_file_new_for_uri (home_uri);
+ file_items_list = get_children_from_dir (selector_store, home_file);
+
+ g_free (home_uri);
+ g_object_unref (home_file);
+
+ return file_items_list;
+}
+
+static GList *
+convert_recent_item_list_to_fileitem_list (GList *uri_list)
+{
+ GList *l;
+ GList *fileitem_list = NULL;
+
+ for (l = uri_list; l != NULL; l = l->next)
+ {
+ gchar *uri;
+ FileItem *item;
+
+ uri = g_strdup (gtk_recent_info_get_uri (l->data));
+
+ item = gedit_open_document_selector_create_fileitem_item ();
+ item->uri = uri;
+
+ item->access_time.tv_sec = gtk_recent_info_get_visited (l->data);
+ item->access_time.tv_usec = 0;
+
+ fileitem_list = g_list_prepend (fileitem_list, item);
+ }
+
+ fileitem_list = g_list_reverse (fileitem_list);
+ return fileitem_list;
+}
+
+static GList *
+get_recent_files_list (GeditOpenDocumentSelectorStore *selector_store,
+ GeditOpenDocumentSelector *selector G_GNUC_UNUSED)
+{
+ GList *recent_items_list;
+ GList *file_items_list;
+
+ G_LOCK (recent_files_filter_lock);
+ recent_items_list = gedit_recent_get_items (&selector_store->recent_config);
+ G_UNLOCK (recent_files_filter_lock);
+
+ file_items_list = convert_recent_item_list_to_fileitem_list (recent_items_list);
+ g_list_free_full (recent_items_list, (GDestroyNotify)gtk_recent_info_unref);
+
+ return file_items_list;
+}
+
+static void
+update_list_cb (GeditOpenDocumentSelectorStore *selector_store,
+ GAsyncResult *res,
+ gpointer user_data G_GNUC_UNUSED)
+{
+ GList *list;
+ GError *error;
+ PushMessage *message;
+ ListType type;
+
+ list = gedit_open_document_selector_store_update_list_finish (selector_store, res, &error);
+
+ message = g_task_get_task_data (G_TASK (res));
+ type = message->type;
+
+ switch (type)
+ {
+ case GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST:
+ gedit_open_document_selector_free_file_items_list (selector_store->recent_items);
+ selector_store->recent_items = list;
+
+ DEBUG_SELECTOR (g_print ("\tStore(%p): update_list_cb: type:%s, length:%i\n",
+ selector_store, list_type_string[type], g_list_length
(list)););
+
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+on_recent_manager_changed (GtkRecentManager *manager G_GNUC_UNUSED,
+ gpointer user_data)
+{
+ GeditOpenDocumentSelectorStore *selector_store = GEDIT_OPEN_DOCUMENT_SELECTOR_STORE (user_data);
+
+ selector_store->recent_items_need_update = TRUE;
+ gedit_open_document_selector_store_update_list_async (selector_store,
+ NULL,
+ NULL,
+ (GAsyncReadyCallback)update_list_cb,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST,
+ NULL);
+}
+
+static void
+gedit_open_document_selector_store_dispose (GObject *object)
+{
+ GeditOpenDocumentSelectorStore *selector_store = GEDIT_OPEN_DOCUMENT_SELECTOR_STORE (object);
+
+ gedit_recent_configuration_destroy (&selector_store->recent_config);
+
+ g_clear_pointer (&selector_store->recent_source, g_source_destroy);
+ g_clear_pointer (&selector_store->filter, g_free);
+
+ if (selector_store->recent_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector_store->recent_items);
+ selector_store->recent_items = NULL;
+ }
+
+ G_OBJECT_CLASS (gedit_open_document_selector_store_parent_class)->dispose (object);
+}
+
+static void
+gedit_open_document_selector_store_class_init (GeditOpenDocumentSelectorStoreClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = gedit_open_document_selector_store_dispose;
+}
+
+/* The order of functions pointers must be the same as in
+ * ListType enum define in ./gedit-open-document-selector-helper.h
+ */
+static GList * (*list_func [])(GeditOpenDocumentSelectorStore *selector_store,
+ GeditOpenDocumentSelector *selector) =
+{
+ get_recent_files_list,
+ get_home_dir_list,
+ get_desktop_dir_list,
+ get_local_bookmarks_list,
+ get_file_browser_root_dir_list,
+ get_active_doc_dir_list,
+ get_current_docs_list
+};
+
+static gboolean
+update_recent_list (gpointer user_data)
+{
+ GeditOpenDocumentSelectorStore *selector_store;
+ GeditOpenDocumentSelector *selector;
+ PushMessage *message;
+ /* The type variable is only used when debug code activated */
+ G_GNUC_UNUSED ListType type;
+ GList *file_items_list;
+ GTask *task = G_TASK(user_data);
+
+ selector_store = g_task_get_source_object (task);
+ message = g_task_get_task_data (task);
+ selector = message->selector;
+ type = message->type;
+
+ DEBUG_SELECTOR_TIMER_DECL
+ DEBUG_SELECTOR_TIMER_NEW
+ DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: type:%s\n",
+ selector, list_type_string[type]););
+
+ /* Update the recent list only when it changes, copy otherwise but keep it the first time */
+ if (selector_store->recent_items != NULL && selector_store->recent_items_need_update == FALSE)
+ {
+ file_items_list = gedit_open_document_selector_copy_file_items_list
(selector_store->recent_items);
+
+ DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: recent list copy\n", selector););
+ }
+ else
+ {
+ selector_store->recent_items_need_update = FALSE;
+ file_items_list = get_recent_files_list (selector_store, selector);
+
+ DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: recent list compute\n", selector););
+
+ if (selector_store->recent_items == NULL)
+ {
+ selector_store->recent_items = gedit_open_document_selector_copy_file_items_list
(file_items_list);
+ }
+ }
+
+ g_task_return_pointer (task,
+ file_items_list,
+ (GDestroyNotify)gedit_open_document_selector_free_file_items_list);
+
+ DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: type:%s, time:%lf\n",
+ selector, list_type_string[type], DEBUG_SELECTOR_TIMER_GET););
+ DEBUG_SELECTOR_TIMER_DESTROY
+
+ selector_store->recent_source = NULL;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+update_list_dispatcher (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable G_GNUC_UNUSED)
+{
+ GeditOpenDocumentSelectorStore *selector_store = source_object;
+ GeditOpenDocumentSelector *selector;
+ PushMessage *message;
+ ListType type;
+ GList *file_items_list;
+
+ message = task_data;
+ selector = message->selector;
+ type = message->type;
+
+ DEBUG_SELECTOR_TIMER_DECL
+ DEBUG_SELECTOR_TIMER_NEW
+ DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: Thread:%p, type:%s\n",
+ selector, g_thread_self (), list_type_string[type]););
+
+ if (type >= GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS)
+ {
+ g_task_return_new_error (task,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_ERROR, TYPE_OUT_OF_RANGE,
+ "List Type out of range");
+ g_object_unref (task);
+ return;
+ }
+
+ /* Here we call the corresponding list creator function */
+ file_items_list = (*list_func[type]) (selector_store, selector);
+
+ DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: Thread:%p, type:%s, time:%lf\n",
+ selector, g_thread_self (), list_type_string[type],
DEBUG_SELECTOR_TIMER_GET););
+ DEBUG_SELECTOR_TIMER_DESTROY
+
+ g_task_return_pointer (task,
+ file_items_list,
+ (GDestroyNotify)gedit_open_document_selector_free_file_items_list);
+}
+
+GList *
+gedit_open_document_selector_store_update_list_finish (GeditOpenDocumentSelectorStore
*open_document_selector_store,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (open_document_selector_store), NULL);
+ g_return_val_if_fail (g_task_is_valid (result, open_document_selector_store), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+void
+gedit_open_document_selector_store_update_list_async (GeditOpenDocumentSelectorStore *selector_store,
+ GeditOpenDocumentSelector *selector,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ ListType type,
+ gpointer user_data)
+{
+ GTask *task;
+ PushMessage *message;
+
+ g_return_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store));
+ g_return_if_fail (selector == NULL || GEDIT_IS_OPEN_DOCUMENT_SELECTOR (selector));
+
+ message = g_new (PushMessage, 1);
+ message->selector = selector;
+ message->type = type;
+
+ task = g_task_new (selector_store, cancellable, callback, user_data);
+ g_task_set_source_tag (task, gedit_open_document_selector_store_update_list_async);
+ g_task_set_priority (task, G_PRIORITY_DEFAULT);
+ g_task_set_task_data (task, message, (GDestroyNotify)g_free);
+
+ if (type == GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST &&
+ selector_store->recent_source == NULL)
+ {
+ selector_store->recent_source = g_idle_source_new ();
+ g_task_attach_source (task, selector_store->recent_source, update_recent_list);
+ }
+ else
+ {
+ g_task_run_in_thread (task, update_list_dispatcher);
+ }
+
+ g_object_unref (task);
+}
+
+static void
+gedit_open_document_selector_store_init (GeditOpenDocumentSelectorStore *selector_store)
+{
+ gedit_recent_configuration_init_default (&selector_store->recent_config);
+
+ /* We remove the recent files limit since we need the whole list but
+ * we back it up as gedit_open_document_selector_store_get_recent_limit
+ * use it
+ */
+ selector_store->recent_config_limit = selector_store->recent_config.limit;
+ selector_store->recent_config.limit = -1;
+
+ g_signal_connect_object (selector_store->recent_config.manager,
+ "changed",
+ G_CALLBACK (on_recent_manager_changed),
+ selector_store,
+ 0);
+
+ selector_store->recent_items_need_update = TRUE;
+}
+
+gint
+gedit_open_document_selector_store_get_recent_limit (GeditOpenDocumentSelectorStore *selector_store)
+{
+ g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store), -1);
+
+ return selector_store->recent_config_limit;
+}
+
+void
+gedit_open_document_selector_store_set_filter (GeditOpenDocumentSelectorStore *selector_store,
+ const gchar *filter)
+{
+ gchar *old_filter;
+
+ g_return_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store));
+ g_return_if_fail (filter != NULL);
+
+ G_LOCK (recent_files_filter_lock);
+
+ old_filter = selector_store->filter;
+ selector_store->filter = g_strdup (filter);
+
+ G_UNLOCK (recent_files_filter_lock);
+ g_free (old_filter);
+}
+
+gchar *
+gedit_open_document_selector_store_get_filter (GeditOpenDocumentSelectorStore *selector_store)
+{
+ gchar *recent_filter;
+
+ g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store), NULL);
+
+ G_LOCK (recent_files_filter_lock);
+ recent_filter = g_strdup (selector_store->filter);
+ G_UNLOCK (recent_files_filter_lock);
+
+ return recent_filter;
+}
+
+/* Gets a unique instance of #GeditOpenDocumentSelectorStore
+ *
+ * Returns: (transfer none): A unique #GeditOpenDocumentSelectorStore.
+ * Do not ref or unref it, it will be destroyed at the end of the application.
+ */
+GeditOpenDocumentSelectorStore *
+gedit_open_document_selector_store_get_default (void)
+{
+ static GeditOpenDocumentSelectorStore *instance;
+
+ if (instance == NULL)
+ {
+ instance = g_object_new (GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE, NULL);
+ g_object_add_weak_pointer (G_OBJECT (instance), (gpointer) &instance);
+ }
+
+ return instance;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-store.h b/gedit/gedit-open-document-selector-store.h
new file mode 100644
index 000000000..d1e17a908
--- /dev/null
+++ b/gedit/gedit-open-document-selector-store.h
@@ -0,0 +1,68 @@
+/*
+ * gedit-open-document-selector-store.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H
+
+#include "gedit-open-document-selector-helper.h"
+#include "gedit-open-document-selector.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE (gedit_open_document_selector_store_get_type ())
+
+G_DECLARE_FINAL_TYPE (GeditOpenDocumentSelectorStore, gedit_open_document_selector_store, GEDIT,
OPEN_DOCUMENT_SELECTOR_STORE, GObject)
+
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_ERROR gedit_open_document_selector_store_error_quark ()
+
+typedef enum
+{
+ TYPE_OUT_OF_RANGE
+} GeditOpenDocumentSelectorStoreError;
+
+GQuark gedit_open_document_selector_store_error_quark
(void);
+
+gint gedit_open_document_selector_store_get_recent_limit
(GeditOpenDocumentSelectorStore *store);
+
+void gedit_open_document_selector_store_set_filter
(GeditOpenDocumentSelectorStore *store,
+
const gchar *filter);
+
+gchar *gedit_open_document_selector_store_get_filter
(GeditOpenDocumentSelectorStore *store);
+
+GList *gedit_open_document_selector_store_update_list_finish
(GeditOpenDocumentSelectorStore *open_document_selector_store,
+
GAsyncResult *res,
+
GError **error);
+
+void gedit_open_document_selector_store_update_list_async
(GeditOpenDocumentSelectorStore *open_document_selector_store,
+
GeditOpenDocumentSelector *open_document_selector,
+
GCancellable *cancellable,
+
GAsyncReadyCallback callback,
+
ListType type,
+
gpointer user_data);
+
+GeditOpenDocumentSelectorStore *gedit_open_document_selector_store_get_default
(void);
+
+G_END_DECLS
+
+#endif /* GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H */
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector.c b/gedit/gedit-open-document-selector.c
new file mode 100644
index 000000000..f67a6ba6d
--- /dev/null
+++ b/gedit/gedit-open-document-selector.c
@@ -0,0 +1,1304 @@
+/*
+ * gedit-open-document-selector.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Sébastien Lafargue
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-open-document-selector.h"
+#include "gedit-open-document-selector-store.h"
+#include "gedit-open-document-selector-helper.h"
+
+#include <time.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#include "gedit-recent.h"
+#include "gedit-utils.h"
+#include "gedit-window.h"
+#include "gedit-debug.h"
+
+struct _GeditOpenDocumentSelector
+{
+ GtkBox parent_instance;
+
+ GeditWindow *window;
+ GtkWidget *search_entry;
+
+ GtkWidget *open_button;
+ GtkWidget *treeview;
+ GtkListStore *liststore;
+ GtkCellRenderer *name_renderer;
+ GtkCellRenderer *path_renderer;
+ GtkWidget *placeholder_box;
+ GtkWidget *scrolled_window;
+
+ guint populate_listbox_id;
+
+ GdkRGBA name_label_color;
+ PangoFontDescription *name_font;
+ GdkRGBA path_label_color;
+ PangoFontDescription *path_font;
+ gchar *match_markup_color;
+
+ GeditOpenDocumentSelectorStore *selector_store;
+ GList *recent_items;
+ GList *home_dir_items;
+ GList *desktop_dir_items;
+ GList *local_bookmarks_dir_items;
+ GList *file_browser_root_items;
+ GList *active_doc_dir_items;
+ GList *current_docs_items;
+ GList *all_items;
+};
+
+typedef enum
+{
+ SELECTOR_TAG_NONE,
+ SELECTOR_TAG_MATCH
+} SelectorTag;
+
+enum
+{
+ NAME_COLUMN,
+ PATH_COLUMN,
+ URI_COLUMN,
+ N_COLUMNS
+};
+
+enum
+{
+ PROP_0,
+ PROP_WINDOW,
+ LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP];
+
+enum
+{
+ SELECTOR_FILE_ACTIVATED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+/* Value 0xFF is reserved to mark the end of the array */
+#define BYTE_ARRAY_END 0xFF
+
+#define OPEN_DOCUMENT_SELECTOR_WIDTH 400
+#define OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS 10
+
+G_DEFINE_TYPE (GeditOpenDocumentSelector, gedit_open_document_selector, GTK_TYPE_BOX)
+
+static inline const guint8 *
+get_byte_run (const guint8 *byte_array,
+ gsize *count,
+ SelectorTag *tag)
+{
+ guint8 tag_found;
+ gsize c = 1;
+
+ tag_found = *byte_array++;
+
+ while ( *byte_array != BYTE_ARRAY_END && *byte_array == tag_found)
+ {
+ c++;
+ byte_array++;
+ }
+
+ *count = c;
+ *tag = tag_found;
+
+ return ( *byte_array != BYTE_ARRAY_END) ? byte_array : NULL;
+}
+
+static gchar*
+get_markup_from_tagged_byte_array (GeditOpenDocumentSelector *selector,
+ const gchar *str,
+ const guint8 *byte_array)
+{
+ gchar *txt;
+ GString *string;
+ gchar *result_str;
+ SelectorTag tag;
+ gsize count;
+
+ string = g_string_sized_new (255);
+
+ while (TRUE)
+ {
+ byte_array = get_byte_run (byte_array, &count, &tag);
+ txt = g_markup_escape_text (str, count);
+ if (tag == SELECTOR_TAG_MATCH)
+ {
+ g_string_append (string, selector->match_markup_color);
+ g_string_append (string, txt);
+ g_string_append (string, "</span>");
+ }
+ else
+ {
+ g_string_append (string, txt);
+ }
+
+ g_free (txt);
+
+ if (!byte_array)
+ {
+ break;
+ }
+
+ str = (const gchar *)((gsize)str + count);
+ }
+
+ result_str = g_string_free (string, FALSE);
+ return result_str;
+}
+
+static guint8 *
+get_tagged_byte_array (const gchar *uri,
+ GRegex *filter_regex)
+{
+ guint8 *byte_array;
+ gsize uri_len;
+ GMatchInfo *match_info;
+ gboolean no_match = TRUE;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ uri_len = strlen (uri);
+ byte_array = g_malloc0 (uri_len + 1);
+ byte_array[uri_len] = BYTE_ARRAY_END;
+
+ if (g_regex_match (filter_regex, uri, 0, &match_info) == TRUE)
+ {
+ while (g_match_info_matches (match_info) == TRUE)
+ {
+ guint8 *p;
+ gint match_len;
+ gint start_pos;
+ gint end_pos;
+
+ if (g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos) == TRUE)
+ {
+ match_len = end_pos - start_pos;
+ no_match = FALSE;
+
+ p = (guint8 *)((gsize)byte_array + start_pos);
+ memset (p, SELECTOR_TAG_MATCH, match_len);
+ }
+
+ g_match_info_next (match_info, NULL);
+ }
+ }
+
+ g_match_info_free (match_info);
+
+ if (no_match)
+ {
+ g_free (byte_array);
+ return NULL;
+ }
+
+ return byte_array;
+}
+
+static void
+get_markup_for_path_and_name (GeditOpenDocumentSelector *selector,
+ GRegex *filter_regex,
+ const gchar *src_path,
+ const gchar *src_name,
+ gchar **dst_path,
+ gchar **dst_name)
+{
+ gchar *filename;
+ gsize path_len;
+ gsize name_len;
+ gsize path_separator_len;
+ guint8 *byte_array;
+ guint8 *path_byte_array;
+ guint8 *name_byte_array;
+
+ filename = g_build_filename (src_path, src_name, NULL);
+
+ path_len = g_utf8_strlen (src_path, -1);
+ name_len = g_utf8_strlen (src_name, -1);
+ path_separator_len = g_utf8_strlen (filename, -1) - ( path_len + name_len);
+
+ byte_array = get_tagged_byte_array (filename, filter_regex);
+ if (byte_array)
+ {
+ path_byte_array = g_memdup (byte_array, path_len + 1);
+ path_byte_array[path_len] = BYTE_ARRAY_END;
+
+ /* name_byte_array is part of byte_array, so released with it */
+ name_byte_array = (guint8 *)((gsize)byte_array + path_len + path_separator_len);
+
+ *dst_path = get_markup_from_tagged_byte_array (selector, src_path, path_byte_array);
+ *dst_name = get_markup_from_tagged_byte_array (selector, src_name, name_byte_array);
+
+ g_free (byte_array);
+ g_free (path_byte_array);
+ }
+ else
+ {
+ *dst_path = g_strdup (src_path);
+ *dst_name = g_strdup (src_name);
+ }
+
+ g_free (filename);
+}
+
+static void
+create_row (GeditOpenDocumentSelector *selector,
+ const FileItem *item,
+ GRegex *filter_regex)
+{
+ GtkTreeIter iter;
+ gchar *uri;
+ gchar *dst_path;
+ gchar *dst_name;
+
+ uri =item->uri;
+
+ if (filter_regex)
+ {
+ get_markup_for_path_and_name (selector,
+ filter_regex,
+ (const gchar *)item->path,
+ (const gchar *)item->name,
+ &dst_path,
+ &dst_name);
+ }
+ else
+ {
+ dst_path = g_markup_escape_text (item->path, -1);
+ dst_name = g_markup_escape_text (item->name, -1);
+ }
+
+ gtk_list_store_append (selector->liststore, &iter);
+ gtk_list_store_set (selector->liststore, &iter,
+ URI_COLUMN, uri,
+ NAME_COLUMN, dst_name,
+ PATH_COLUMN, dst_path,
+ -1);
+
+ g_free (dst_path);
+ g_free (dst_name);
+}
+
+static gint
+sort_items_by_mru (FileItem *a,
+ FileItem *b,
+ gpointer unused G_GNUC_UNUSED)
+{
+ glong diff;
+
+ g_assert (a != NULL && b != NULL);
+ diff = b->access_time.tv_sec - a->access_time.tv_sec;
+
+ if (diff == 0)
+ {
+ return (b->access_time.tv_usec - a->access_time.tv_usec);
+ }
+ else
+ {
+ return diff;
+ }
+}
+
+static GList *
+compute_all_items_list (GeditOpenDocumentSelector *selector)
+{
+ GList *recent_items;
+ GList *home_dir_items;
+ GList *desktop_dir_items;
+ GList *local_bookmarks_dir_items;
+ GList *file_browser_root_items;
+ GList *active_doc_dir_items;
+ GList *current_docs_items;
+ GList *all_items = NULL;
+
+ /* Copy/concat the whole list */
+ recent_items = gedit_open_document_selector_copy_file_items_list ((const GList
*)selector->recent_items);
+ home_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList
*)selector->home_dir_items);
+ desktop_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList
*)selector->desktop_dir_items);
+ local_bookmarks_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList
*)selector->local_bookmarks_dir_items);
+ file_browser_root_items = gedit_open_document_selector_copy_file_items_list ((const GList
*)selector->file_browser_root_items);
+ active_doc_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList
*)selector->active_doc_dir_items);
+ current_docs_items = gedit_open_document_selector_copy_file_items_list ((const GList
*)selector->current_docs_items);
+
+ if (selector->all_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->all_items);
+ selector->all_items = NULL;
+ }
+
+ all_items = g_list_concat (all_items, recent_items);
+ all_items = g_list_concat (all_items, home_dir_items);
+ all_items = g_list_concat (all_items, desktop_dir_items);
+ all_items = g_list_concat (all_items, local_bookmarks_dir_items);
+ all_items = g_list_concat (all_items, file_browser_root_items);
+ all_items = g_list_concat (all_items, active_doc_dir_items);
+ all_items = g_list_concat (all_items, current_docs_items);
+
+ return all_items;
+}
+
+static GList *
+clamp_recent_items_list (GList *recent_items,
+ gint limit)
+{
+ GList *recent_items_capped = NULL;
+ GList *l;
+ FileItem *item;
+
+ l = recent_items;
+ while (limit > 0 && l != NULL)
+ {
+ item = gedit_open_document_selector_copy_fileitem_item (l->data);
+ recent_items_capped = g_list_prepend (recent_items_capped, item);
+ l = l->next;
+ limit -= 1;
+ }
+
+ recent_items_capped = g_list_reverse (recent_items_capped);
+ return recent_items_capped;
+}
+
+/* Setup the fileitem, depending uri's scheme
+ * Return a string to search in.
+ */
+static gchar *
+fileitem_setup (FileItem *item)
+{
+ gchar *scheme;
+ gchar *filename;
+ gchar *normalized_filename = NULL;
+ gchar *candidate = NULL;
+ gchar *path;
+ gchar *name;
+
+ scheme = g_uri_parse_scheme (item->uri);
+ if (g_strcmp0 (scheme, "file") == 0)
+ {
+ filename = g_filename_from_uri ((const gchar *)item->uri, NULL, NULL);
+ if (filename)
+ {
+ path = g_path_get_dirname (filename);
+ item->path = g_filename_to_utf8 (path, -1, NULL, NULL, NULL);
+ g_free (path);
+
+ name = g_path_get_basename (filename);
+ item->name = g_filename_to_utf8 (name, -1, NULL, NULL, NULL);
+ g_free (name);
+
+ normalized_filename = g_utf8_normalize (filename, -1, G_NORMALIZE_ALL);
+ g_free (filename);
+ }
+ }
+ else
+ {
+ GFile *file;
+ gchar *parse_name;
+
+ file = g_file_new_for_uri (item->uri);
+ item->path = gedit_utils_location_get_dirname_for_display (file);
+ item->name = gedit_utils_basename_for_display (file);
+ parse_name = g_file_get_parse_name (file);
+ g_object_unref (file);
+
+ normalized_filename = g_utf8_normalize (parse_name, -1, G_NORMALIZE_ALL);
+ g_free (parse_name);
+ }
+
+ if (normalized_filename)
+ {
+ candidate = g_utf8_casefold (normalized_filename, -1);
+ g_free (normalized_filename);
+ }
+
+ g_free (scheme);
+
+ return candidate;
+}
+
+static inline gboolean
+is_filter_in_candidate (const gchar *candidate,
+ const gchar *filter)
+{
+ gchar *candidate_fold;
+ gboolean ret;
+
+ g_assert (candidate != NULL);
+ g_assert (filter != NULL);
+
+ candidate_fold = g_utf8_casefold (candidate, -1);
+ ret = (strstr (candidate_fold, filter) != NULL);
+
+ g_free (candidate_fold);
+ return ret;
+}
+
+/* If filter == NULL then items are
+ * not checked against the filter.
+ */
+static GList *
+fileitem_list_filter (GList *items,
+ const gchar *filter)
+{
+ GList *new_items = NULL;
+ GList *l;
+ gchar *filter_fold = NULL;
+
+ if (filter != NULL)
+ filter_fold = g_utf8_casefold (filter, -1);
+
+ for (l = items; l != NULL; l = l->next)
+ {
+ FileItem *item;
+ gchar *candidate;
+
+ item = l->data;
+ candidate = fileitem_setup (item);
+ if (candidate != NULL)
+ {
+ if (filter == NULL || is_filter_in_candidate (candidate, filter_fold))
+ {
+ new_items = g_list_prepend (new_items,
+ gedit_open_document_selector_copy_fileitem_item
(item));
+ }
+
+ g_free (candidate);
+ }
+ }
+
+ g_free (filter_fold);
+ new_items = g_list_reverse (new_items);
+ return new_items;
+}
+
+/* Remove duplicated, the HEAD of the list never change,
+ * the list passed in is modified.
+ */
+static void
+fileitem_list_remove_duplicates (GList *items)
+{
+ GList *l;
+ G_GNUC_UNUSED GList *dummy_ptr;
+
+ l = items;
+ while (l != NULL)
+ {
+ gchar *l_uri, *l1_uri;
+ GList *l1;
+
+ if ((l1 = l->next) == NULL)
+ {
+ break;
+ }
+
+ l_uri = ((FileItem *)l->data)->uri;
+ l1_uri = ((FileItem *)l1->data)->uri;
+ if (g_strcmp0 (l_uri, l1_uri) == 0)
+ {
+ gedit_open_document_selector_free_fileitem_item ((FileItem *)l1->data);
+ dummy_ptr = g_list_delete_link (items, l1);
+ }
+ else
+ {
+ l = l->next;
+ }
+ }
+}
+
+static gboolean
+real_populate_liststore (gpointer data)
+{
+ GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (data);
+ GeditOpenDocumentSelectorStore *selector_store;
+ GList *l;
+ GList *filter_items = NULL;
+ gchar *filter;
+ GRegex *filter_regex = NULL;
+
+ DEBUG_SELECTOR_TIMER_DECL
+ DEBUG_SELECTOR_TIMER_NEW
+
+ gtk_list_store_clear (selector->liststore);
+
+ selector_store = selector->selector_store;
+ filter = gedit_open_document_selector_store_get_filter (selector_store);
+ if (filter && *filter != '\0')
+ {
+ DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: all lists\n", selector););
+
+ filter_items = fileitem_list_filter (selector->all_items, (const gchar *)filter);
+ filter_items = g_list_sort_with_data (filter_items, (GCompareDataFunc)sort_items_by_mru,
NULL);
+ fileitem_list_remove_duplicates (filter_items);
+
+ filter_regex = g_regex_new (filter, G_REGEX_CASELESS, 0, NULL);
+ }
+ else
+ {
+ gint recent_limit;
+ GList *recent_items;
+
+ DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: recent files list\n", selector););
+
+ recent_limit = gedit_open_document_selector_store_get_recent_limit (selector_store);
+
+ if (recent_limit > 0 )
+ {
+ recent_items = fileitem_list_filter (selector->recent_items, NULL);
+ filter_items = clamp_recent_items_list (recent_items, recent_limit);
+ gedit_open_document_selector_free_file_items_list (recent_items);
+ }
+ else
+ {
+ filter_items = fileitem_list_filter (selector->recent_items, NULL);
+ }
+ }
+
+ g_free (filter);
+
+ DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: length:%i\n",
+ selector, g_list_length (filter_items)););
+
+ /* Show the placeholder if no results, show the treeview otherwise */
+ gtk_widget_set_visible (selector->scrolled_window, (filter_items != NULL));
+ gtk_widget_set_visible (selector->placeholder_box, (filter_items == NULL));
+
+ for (l = filter_items; l != NULL; l = l->next)
+ {
+ FileItem *item;
+
+ item = l->data;
+ create_row (selector, (const FileItem *)item, filter_regex);
+ }
+
+ if (filter_regex)
+ {
+ g_regex_unref (filter_regex);
+ }
+
+ gedit_open_document_selector_free_file_items_list (filter_items);
+
+ DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: time:%lf\n\n",
+ selector, DEBUG_SELECTOR_TIMER_GET););
+ DEBUG_SELECTOR_TIMER_DESTROY
+
+ selector->populate_listbox_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+populate_liststore (GeditOpenDocumentSelector *selector)
+{
+ /* Populate requests are compressed */
+ if (selector->populate_listbox_id != 0)
+ {
+ DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: idle\n", selector););
+ return;
+ }
+
+ DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: scheduled\n", selector););
+ selector->populate_listbox_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
+ real_populate_liststore,
+ selector,
+ NULL);
+}
+
+static gboolean
+on_treeview_key_press (GtkTreeView *treeview,
+ GdkEventKey *event,
+ GeditOpenDocumentSelector *selector)
+{
+ guint keyval;
+ gboolean is_control_pressed;
+ GtkTreeSelection *tree_selection;
+ GtkTreePath *root_path;
+ GdkModifierType modifiers;
+
+ if (gdk_event_get_keyval ((GdkEvent *)event, &keyval) == TRUE)
+ {
+ tree_selection = gtk_tree_view_get_selection (treeview);
+ root_path = gtk_tree_path_new_from_string ("0");
+
+ modifiers = gtk_accelerator_get_default_mod_mask ();
+ is_control_pressed = (event->state & modifiers) == GDK_CONTROL_MASK;
+
+ if ((keyval == GDK_KEY_Up || keyval == GDK_KEY_KP_Up) &&
+ !is_control_pressed)
+ {
+ if (gtk_tree_selection_path_is_selected (tree_selection, root_path))
+ {
+ gtk_tree_selection_unselect_all (tree_selection);
+ gtk_widget_grab_focus (selector->search_entry);
+
+ return GDK_EVENT_STOP;
+ }
+ }
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static void
+on_entry_changed (GtkEntry *entry,
+ GeditOpenDocumentSelector *selector)
+{
+ const gchar *entry_text;
+
+ entry_text = gtk_entry_get_text (entry);
+ gedit_open_document_selector_store_set_filter (selector->selector_store,
+ entry_text);
+
+ if (gtk_widget_get_mapped ( GTK_WIDGET (selector)))
+ {
+ populate_liststore (selector);
+ }
+}
+
+static void
+on_entry_activated (GtkEntry *entry,
+ GeditOpenDocumentSelector *selector)
+{
+ const gchar *entry_text;
+ GtkTreeSelection *selection;
+ gchar *uri;
+ GFile *file;
+ gchar *scheme;
+
+ entry_text = gtk_entry_get_text (entry);
+ scheme = g_uri_parse_scheme (entry_text);
+ if (!scheme)
+ {
+ const gchar *home_dir = g_get_home_dir ();
+
+ if ( home_dir != NULL && g_str_has_prefix (entry_text, "~/"))
+ {
+ uri = g_strconcat ("file://", home_dir, "/", entry_text + 2, NULL);
+ }
+ else
+ {
+ uri = g_strconcat ("file://", entry_text, NULL);
+ }
+ }
+ else
+ {
+ g_free (scheme);
+ uri = g_strdup (entry_text);
+ }
+
+ file = g_file_new_for_uri (uri);
+ if (g_file_query_exists (file, NULL))
+ {
+ DEBUG_SELECTOR (g_print ("Selector(%p): search entry activated : loading '%s'\n",
+ selector, uri););
+
+ gtk_entry_set_text (entry, "");
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector->treeview));
+ gtk_tree_selection_unselect_all (selection);
+
+ g_signal_emit (G_OBJECT (selector), signals[SELECTOR_FILE_ACTIVATED], 0, uri);
+ }
+
+ g_object_unref (file);
+}
+
+static void
+gedit_open_document_selector_dispose (GObject *object)
+{
+ GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+ if (selector->populate_listbox_id != 0)
+ {
+ g_source_remove (selector->populate_listbox_id);
+ selector->populate_listbox_id = 0;
+ }
+
+ g_clear_pointer (&selector->name_font, pango_font_description_free);
+ g_clear_pointer (&selector->path_font, pango_font_description_free);
+ g_clear_pointer (&selector->match_markup_color, g_free);
+
+ if (selector->recent_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->recent_items);
+ selector->recent_items = NULL;
+ }
+
+ if (selector->home_dir_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->home_dir_items);
+ selector->home_dir_items = NULL;
+ }
+
+ if (selector->desktop_dir_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->desktop_dir_items);
+ selector->desktop_dir_items = NULL;
+ }
+
+ if (selector->local_bookmarks_dir_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->local_bookmarks_dir_items);
+ selector->local_bookmarks_dir_items = NULL;
+ }
+
+ if (selector->file_browser_root_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->file_browser_root_items);
+ selector->file_browser_root_items = NULL;
+ }
+
+ if (selector->active_doc_dir_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->active_doc_dir_items);
+ selector->active_doc_dir_items = NULL;
+ }
+
+ if (selector->current_docs_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->current_docs_items);
+ selector->current_docs_items = NULL;
+ }
+
+ if (selector->all_items)
+ {
+ gedit_open_document_selector_free_file_items_list (selector->all_items);
+ selector->all_items = NULL;
+ }
+
+ G_OBJECT_CLASS (gedit_open_document_selector_parent_class)->dispose (object);
+}
+
+static void
+on_row_activated (GtkTreeView *treeview,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column G_GNUC_UNUSED,
+ GeditOpenDocumentSelector *selector)
+{
+ GtkTreeModel *liststore = GTK_TREE_MODEL (selector->liststore);
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ gchar *uri;
+
+ g_return_if_fail (gtk_tree_model_get_iter (liststore, &iter, path));
+ gtk_tree_model_get (liststore, &iter,
+ URI_COLUMN, &uri,
+ -1);
+
+ selection = gtk_tree_view_get_selection (treeview);
+ gtk_tree_selection_unselect_all (selection);
+
+ /* Leak of uri */
+ g_signal_emit (G_OBJECT (selector), signals[SELECTOR_FILE_ACTIVATED], 0, uri);
+}
+
+static void
+update_list_cb (GeditOpenDocumentSelectorStore *selector_store,
+ GAsyncResult *res,
+ gpointer user_data G_GNUC_UNUSED)
+{
+ GList *list;
+ GError *error;
+ PushMessage *message;
+ ListType type;
+ GeditOpenDocumentSelector *selector;
+
+ list = gedit_open_document_selector_store_update_list_finish (selector_store, res, &error);
+ message = g_task_get_task_data (G_TASK (res));
+ selector = message->selector;
+ type = message->type;
+
+ DEBUG_SELECTOR (g_print ("Selector(%p): update_list_cb - type:%s, length:%i\n",
+ selector, list_type_string[type], g_list_length (list)););
+
+ switch (type)
+ {
+ case GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST:
+ gedit_open_document_selector_free_file_items_list (selector->recent_items);
+ selector->recent_items = list;
+ break;
+
+ case GEDIT_OPEN_DOCUMENT_SELECTOR_HOME_DIR_LIST:
+ gedit_open_document_selector_free_file_items_list (selector->home_dir_items);
+ selector->home_dir_items = list;
+ break;
+
+ case GEDIT_OPEN_DOCUMENT_SELECTOR_DESKTOP_DIR_LIST:
+ gedit_open_document_selector_free_file_items_list (selector->desktop_dir_items);
+ selector->desktop_dir_items = list;
+ break;
+
+ case GEDIT_OPEN_DOCUMENT_SELECTOR_LOCAL_BOOKMARKS_DIR_LIST:
+ gedit_open_document_selector_free_file_items_list
(selector->local_bookmarks_dir_items);
+ selector->local_bookmarks_dir_items = list;
+ break;
+
+ case GEDIT_OPEN_DOCUMENT_SELECTOR_FILE_BROWSER_ROOT_DIR_LIST:
+ gedit_open_document_selector_free_file_items_list (selector->file_browser_root_items);
+ selector->file_browser_root_items = list;
+ break;
+
+ case GEDIT_OPEN_DOCUMENT_SELECTOR_ACTIVE_DOC_DIR_LIST:
+ gedit_open_document_selector_free_file_items_list (selector->active_doc_dir_items);
+ selector->active_doc_dir_items = list;
+ break;
+
+ case GEDIT_OPEN_DOCUMENT_SELECTOR_CURRENT_DOCS_LIST:
+ gedit_open_document_selector_free_file_items_list (selector->current_docs_items);
+ selector->current_docs_items = list;
+ break;
+
+ default:
+ g_return_if_reached ();
+ }
+
+ selector->all_items = compute_all_items_list (selector);
+ populate_liststore (selector);
+}
+
+static void
+gedit_open_document_selector_constructed (GObject *object)
+{
+ GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+ G_OBJECT_CLASS (gedit_open_document_selector_parent_class)->constructed (object);
+
+ DEBUG_SELECTOR (g_print ("Selector(%p): constructed - ask recent file list\n", selector););
+
+ gedit_open_document_selector_store_update_list_async (selector->selector_store,
+ selector,
+ NULL,
+ (GAsyncReadyCallback)update_list_cb,
+ GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST,
+ selector);
+}
+
+static void
+gedit_open_document_selector_mapped (GtkWidget *widget)
+{
+ GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (widget);
+ ListType list_number;
+
+ /* We update all the lists */
+ DEBUG_SELECTOR (g_print ("Selector(%p): mapped - ask all lists\n", selector););
+
+ for (list_number = 0; list_number < GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS;
list_number++)
+ {
+ gedit_open_document_selector_store_update_list_async (selector->selector_store,
+ selector,
+ NULL,
+ (GAsyncReadyCallback)update_list_cb,
+ list_number,
+ selector);
+ }
+
+ GTK_WIDGET_CLASS (gedit_open_document_selector_parent_class)->map (widget);
+}
+
+static GtkSizeRequestMode
+gedit_open_document_selector_get_request_mode (GtkWidget *widget G_GNUC_UNUSED)
+{
+ return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+}
+
+static void
+gedit_open_document_selector_get_preferred_width (GtkWidget *widget G_GNUC_UNUSED,
+ gint *minimum_width,
+ gint *natural_width)
+{
+ *minimum_width = *natural_width = OPEN_DOCUMENT_SELECTOR_WIDTH;
+}
+
+static void
+gedit_open_document_selector_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ selector->window = g_value_get_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_open_document_selector_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ g_value_set_object (value, selector->window);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_open_document_selector_file_activated (GeditOpenDocumentSelector *selector G_GNUC_UNUSED,
+ const gchar *uri G_GNUC_UNUSED)
+{
+ /* Do nothing in the default handler */
+}
+
+static void
+gedit_open_document_selector_class_init (GeditOpenDocumentSelectorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = gedit_open_document_selector_constructed;
+ object_class->dispose = gedit_open_document_selector_dispose;
+
+ object_class->get_property = gedit_open_document_selector_get_property;
+ object_class->set_property = gedit_open_document_selector_set_property;
+
+ widget_class->get_request_mode = gedit_open_document_selector_get_request_mode;
+ widget_class->get_preferred_width = gedit_open_document_selector_get_preferred_width;
+ widget_class->map = gedit_open_document_selector_mapped;
+
+ properties[PROP_WINDOW] =
+ g_param_spec_object ("window",
+ "Window",
+ "The GeditWindow this GeditOpenDocumentSelector is associated with",
+ GEDIT_TYPE_WINDOW,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+ signals[SELECTOR_FILE_ACTIVATED] =
+ g_signal_new_class_handler ("file-activated",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gedit_open_document_selector_file_activated),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/gedit/ui/gedit-open-document-selector.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, open_button);
+ gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, treeview);
+ gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, placeholder_box);
+ gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, scrolled_window);
+ gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, search_entry);
+}
+
+static void
+on_treeview_allocate (GtkWidget *widget G_GNUC_UNUSED,
+ GdkRectangle *allocation G_GNUC_UNUSED,
+ GeditOpenDocumentSelector *selector)
+{
+ GeditOpenDocumentSelectorStore *selector_store;
+ GtkStyleContext *context;
+ gint name_renderer_natural_size;
+ gint path_renderer_natural_size;
+ GtkBorder padding;
+ gint ypad;
+ gint limit_capped;
+ gint treeview_height;
+ gint grid_line_width;
+ gint row_height;
+ gint recent_limit;
+
+ selector_store = selector->selector_store;
+
+ context = gtk_widget_get_style_context (selector->treeview);
+ gtk_style_context_get_padding (context,
+ gtk_style_context_get_state (context),
+ &padding);
+
+ /* Treeview height computation */
+ gtk_cell_renderer_get_preferred_height (selector->name_renderer,
+ selector->treeview,
+ NULL,
+ &name_renderer_natural_size);
+
+ gtk_cell_renderer_get_preferred_height (selector->path_renderer,
+ selector->treeview,
+ NULL,
+ &path_renderer_natural_size);
+
+ gtk_cell_renderer_get_padding (selector->name_renderer, NULL, &ypad);
+ gtk_widget_style_get (selector->treeview, "grid-line-width", &grid_line_width, NULL);
+
+ recent_limit = gedit_open_document_selector_store_get_recent_limit (selector_store);
+
+ limit_capped = (recent_limit > 0 ) ? MIN (recent_limit, OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS) :
+ OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS;
+
+ row_height = name_renderer_natural_size +
+ path_renderer_natural_size +
+ 2 * (padding.top + padding.bottom) +
+ ypad +
+ grid_line_width;
+
+ treeview_height = row_height * limit_capped;
+ gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (selector->scrolled_window),
+ treeview_height);
+ gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (selector->scrolled_window),
+ treeview_height);
+
+ gtk_widget_set_size_request (selector->placeholder_box, -1, treeview_height);
+}
+
+static inline gchar *
+rgba_to_hex8 (GdkRGBA *rgba)
+{
+ guint red = (guint)(0.5 + CLAMP (rgba->red, 0.0, 1.0) * 255.0);
+ guint green = (guint)(0.5 + CLAMP (rgba->green, 0.0, 1.0) * 255.0);
+ guint blue = (guint)(0.5 + CLAMP (rgba->blue, 0.0, 1.0) * 255.0);
+ guint alpha = (guint)(0.5 + CLAMP (rgba->alpha, 0.0, 1.0) * 255.0);
+ gchar *str = g_strdup_printf ("#%02X%02X%02X%02X", red, green, blue, alpha);
+
+ return str;
+}
+
+static void
+on_treeview_style_updated (GtkWidget *widget,
+ GeditOpenDocumentSelector *selector)
+{
+ GtkStyleContext *context;
+ GdkRGBA match_foreground_rgba = {0.0, 0.0, 0.0, 0.0};
+ GdkRGBA match_background_rgba = {0.0, 0.0, 0.0, 0.0};
+ gchar *match_foreground_hex8;
+ gchar *match_background_hex8;
+
+ context = gtk_widget_get_style_context (widget);
+
+ /* Name label foreground and font size styling */
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, "open-document-selector-name-label");
+
+ gtk_style_context_get_color (context,
+ gtk_style_context_get_state (context),
+ &selector->name_label_color);
+
+ g_clear_pointer (&selector->name_font, pango_font_description_free);
+ gtk_style_context_get (context,
+ gtk_style_context_get_state (context),
+ "font", &selector->name_font,
+ NULL);
+
+ gtk_style_context_restore (context);
+
+ /* Path label foreground and font size styling */
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, "open-document-selector-path-label");
+
+ gtk_style_context_get_color (context,
+ gtk_style_context_get_state (context),
+ &selector->path_label_color);
+
+ g_clear_pointer (&selector->path_font, pango_font_description_free);
+ gtk_style_context_get (context,
+ gtk_style_context_get_state (context),
+ "font", &selector->path_font,
+ NULL);
+
+ gtk_style_context_restore (context);
+
+ /* Match styling */
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, "open-document-selector-match");
+
+ gtk_style_context_get_color (context,
+ gtk_style_context_get_state (context),
+ &match_foreground_rgba);
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+ gtk_style_context_get_background_color (context,
+ gtk_style_context_get_state (context),
+ &match_background_rgba);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+
+ gtk_style_context_restore (context);
+ g_free (selector->match_markup_color);
+
+ match_foreground_hex8 = rgba_to_hex8 (&match_foreground_rgba);
+ match_background_hex8 = rgba_to_hex8 (&match_background_rgba);
+
+ selector->match_markup_color = g_strdup_printf ("<span weight =\"heavy\" foreground =\"%s\"
background =\"%s\">",
+ match_foreground_hex8,
+ match_background_hex8);
+
+ g_free (match_foreground_hex8);
+ g_free (match_background_hex8);
+}
+
+static void
+name_renderer_datafunc (GtkTreeViewColumn *column G_GNUC_UNUSED,
+ GtkCellRenderer *name_renderer G_GNUC_UNUSED,
+ GtkTreeModel *liststore G_GNUC_UNUSED,
+ GtkTreeIter *iter G_GNUC_UNUSED,
+ GeditOpenDocumentSelector *selector)
+{
+ g_object_set (selector->name_renderer, "foreground-rgba", &selector->name_label_color, NULL);
+ g_object_set (selector->name_renderer, "font-desc", selector->name_font, NULL);
+}
+
+static void
+path_renderer_datafunc (GtkTreeViewColumn *column G_GNUC_UNUSED,
+ GtkCellRenderer *path_renderer G_GNUC_UNUSED,
+ GtkTreeModel *liststore G_GNUC_UNUSED,
+ GtkTreeIter *iter G_GNUC_UNUSED,
+ GeditOpenDocumentSelector *selector)
+{
+ g_object_set (selector->path_renderer, "foreground-rgba", &selector->path_label_color, NULL);
+ g_object_set (selector->path_renderer, "font-desc", selector->path_font, NULL);
+}
+
+static void
+setup_treeview (GeditOpenDocumentSelector *selector)
+{
+ GtkTreeViewColumn *column;
+ GtkCellArea *cell_area;
+ GtkStyleContext *context;
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (selector->treeview), GTK_TREE_MODEL (selector->liststore));
+ g_object_unref(GTK_TREE_MODEL (selector->liststore));
+
+ selector->name_renderer = gtk_cell_renderer_text_new ();
+ selector->path_renderer = gtk_cell_renderer_text_new ();
+
+ g_object_set (selector->name_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ g_object_set (selector->path_renderer, "ellipsize", PANGO_ELLIPSIZE_START, NULL);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+
+ gtk_tree_view_column_pack_start (column, selector->name_renderer, TRUE);
+ gtk_tree_view_column_pack_start (column, selector->path_renderer, TRUE);
+
+ gtk_tree_view_column_set_attributes (column, selector->name_renderer, "markup", NAME_COLUMN, NULL);
+ gtk_tree_view_column_set_attributes (column, selector->path_renderer, "markup", PATH_COLUMN, NULL);
+
+ gtk_tree_view_append_column (GTK_TREE_VIEW (selector->treeview), column);
+ cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column));
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (cell_area), GTK_ORIENTATION_VERTICAL);
+
+ context = gtk_widget_get_style_context (selector->treeview);
+ gtk_style_context_add_class (context, "open-document-selector-treeview");
+
+ gtk_tree_view_column_set_cell_data_func (column,
+ selector->name_renderer,
+ (GtkTreeCellDataFunc)name_renderer_datafunc,
+ selector,
+ NULL);
+
+ gtk_tree_view_column_set_cell_data_func (column,
+ selector->path_renderer,
+ (GtkTreeCellDataFunc)path_renderer_datafunc,
+ selector,
+ NULL);
+}
+
+static void
+gedit_open_document_selector_init (GeditOpenDocumentSelector *selector)
+{
+ gedit_debug (DEBUG_WINDOW);
+
+ gtk_widget_init_template (GTK_WIDGET (selector));
+
+ selector->selector_store = gedit_open_document_selector_store_get_default ();
+
+ selector->liststore = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+ setup_treeview (selector);
+
+ g_signal_connect (selector->search_entry,
+ "changed",
+ G_CALLBACK (on_entry_changed),
+ selector);
+
+ g_signal_connect (selector->search_entry,
+ "activate",
+ G_CALLBACK (on_entry_activated),
+ selector);
+
+ g_signal_connect (selector->treeview,
+ "row-activated",
+ G_CALLBACK (on_row_activated),
+ selector);
+
+ g_signal_connect (selector->treeview,
+ "size-allocate",
+ G_CALLBACK (on_treeview_allocate),
+ selector);
+
+ g_signal_connect (selector->treeview,
+ "key-press-event",
+ G_CALLBACK (on_treeview_key_press),
+ selector);
+
+ g_signal_connect (selector->treeview,
+ "style-updated",
+ G_CALLBACK (on_treeview_style_updated),
+ selector);
+}
+
+GeditOpenDocumentSelector *
+gedit_open_document_selector_new (GeditWindow *window)
+{
+ g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
+
+ return g_object_new (GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR,
+ "window", window,
+ NULL);
+}
+
+GeditWindow *
+gedit_open_document_selector_get_window (GeditOpenDocumentSelector *selector)
+{
+ g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR (selector), NULL);
+
+ return selector->window;
+}
+
+GtkWidget *
+gedit_open_document_selector_get_search_entry (GeditOpenDocumentSelector *selector)
+{
+ g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR (selector), NULL);
+
+ return selector->search_entry;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector.h b/gedit/gedit-open-document-selector.h
new file mode 100644
index 000000000..b4d50cefd
--- /dev/null
+++ b/gedit/gedit-open-document-selector.h
@@ -0,0 +1,44 @@
+/*
+ * gedit-open-document-selector.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Sébastien Lafargue
+ *
+ * gedit 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_OPEN_DOCUMENT_SELECTOR_H
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_H
+
+#include <glib-object.h>
+#include "gedit-window.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR (gedit_open_document_selector_get_type ())
+
+G_DECLARE_FINAL_TYPE (GeditOpenDocumentSelector, gedit_open_document_selector, GEDIT,
OPEN_DOCUMENT_SELECTOR, GtkBox)
+
+GeditOpenDocumentSelector *gedit_open_document_selector_new (GeditWindow
*window);
+
+GeditWindow *gedit_open_document_selector_get_window (GeditOpenDocumentSelector
*selector);
+
+GtkWidget *gedit_open_document_selector_get_search_entry (GeditOpenDocumentSelector
*selector);
+
+G_END_DECLS
+
+#endif /* GEDIT_OPEN_DOCUMENT_SELECTOR_H */
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-pango.c b/gedit/gedit-pango.c
new file mode 100644
index 000000000..0488bbcd2
--- /dev/null
+++ b/gedit/gedit-pango.c
@@ -0,0 +1,230 @@
+/* gedit-pango.c
+ *
+ * This file is a copy of pango_font_description_to_css from gtk gtkfontbutton.c
+ *
+ * Copyright (C) 2016 Matthias Clasen <mclasen redhat com>
+ *
+ * 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 2 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/>.
+ */
+
+#define G_LOG_DOMAIN "gedit-pango"
+
+#include "config.h"
+
+#include "gedit-pango.h"
+
+#if PANGO_VERSION_CHECK (1, 44, 0)
+static void
+add_css_variations (GString *s,
+ const char *variations)
+{
+ const char *p;
+ const char *sep = "";
+
+ if (variations == NULL || variations[0] == '\0')
+ {
+ g_string_append (s, "normal");
+ return;
+ }
+
+ p = variations;
+ while (p && *p)
+ {
+ const char *start;
+ const char *end, *end2;
+ double value;
+ char name[5];
+
+ while (g_ascii_isspace (*p)) p++;
+
+ start = p;
+ end = strchr (p, ',');
+ if (end && (end - p < 6))
+ goto skip;
+
+ name[0] = p[0];
+ name[1] = p[1];
+ name[2] = p[2];
+ name[3] = p[3];
+ name[4] = '\0';
+
+ p += 4;
+ while (g_ascii_isspace (*p)) p++;
+ if (*p == '=') p++;
+
+ if (p - start < 5)
+ goto skip;
+
+ value = g_ascii_strtod (p, (char **) &end2);
+
+ while (end2 && g_ascii_isspace (*end2)) end2++;
+
+ if (end2 && (*end2 != ',' && *end2 != '\0'))
+ goto skip;
+
+ g_string_append_printf (s, "%s\"%s\" %g", sep, name, value);
+ sep = ", ";
+
+skip:
+ p = end ? end + 1 : NULL;
+ }
+}
+#endif
+
+/**
+ * gedit_pango_font_description_to_css:
+ *
+ * This function will generate CSS suitable for Gtk's CSS engine
+ * based on the properties of the #PangoFontDescription.
+ *
+ * Returns: (transfer full): A newly allocated string containing the
+ * CSS describing the font description.
+ */
+gchar *
+gedit_pango_font_description_to_css (const PangoFontDescription *desc)
+{
+ GString *s;
+ PangoFontMask set;
+
+ s = g_string_new ("");
+
+ set = pango_font_description_get_set_fields (desc);
+ if (set & PANGO_FONT_MASK_FAMILY)
+ {
+ g_string_append (s, "font-family: ");
+ g_string_append (s, pango_font_description_get_family (desc));
+ g_string_append (s, "; ");
+ }
+ if (set & PANGO_FONT_MASK_STYLE)
+ {
+ switch (pango_font_description_get_style (desc))
+ {
+ case PANGO_STYLE_NORMAL:
+ g_string_append (s, "font-style: normal; ");
+ break;
+ case PANGO_STYLE_OBLIQUE:
+ g_string_append (s, "font-style: oblique; ");
+ break;
+ case PANGO_STYLE_ITALIC:
+ g_string_append (s, "font-style: italic; ");
+ break;
+ default:
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_VARIANT)
+ {
+ switch (pango_font_description_get_variant (desc))
+ {
+ case PANGO_VARIANT_NORMAL:
+ g_string_append (s, "font-variant: normal; ");
+ break;
+ case PANGO_VARIANT_SMALL_CAPS:
+ g_string_append (s, "font-variant: small-caps; ");
+ break;
+ default:
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_WEIGHT)
+ {
+ switch (pango_font_description_get_weight (desc))
+ {
+ case PANGO_WEIGHT_THIN:
+ g_string_append (s, "font-weight: 100; ");
+ break;
+ case PANGO_WEIGHT_ULTRALIGHT:
+ g_string_append (s, "font-weight: 200; ");
+ break;
+ case PANGO_WEIGHT_LIGHT:
+ case PANGO_WEIGHT_SEMILIGHT:
+ g_string_append (s, "font-weight: 300; ");
+ break;
+ case PANGO_WEIGHT_BOOK:
+ case PANGO_WEIGHT_NORMAL:
+ g_string_append (s, "font-weight: 400; ");
+ break;
+ case PANGO_WEIGHT_MEDIUM:
+ g_string_append (s, "font-weight: 500; ");
+ break;
+ case PANGO_WEIGHT_SEMIBOLD:
+ g_string_append (s, "font-weight: 600; ");
+ break;
+ case PANGO_WEIGHT_BOLD:
+ g_string_append (s, "font-weight: 700; ");
+ break;
+ case PANGO_WEIGHT_ULTRABOLD:
+ g_string_append (s, "font-weight: 800; ");
+ break;
+ case PANGO_WEIGHT_HEAVY:
+ case PANGO_WEIGHT_ULTRAHEAVY:
+ g_string_append (s, "font-weight: 900; ");
+ break;
+ default:
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_STRETCH)
+ {
+ switch (pango_font_description_get_stretch (desc))
+ {
+ case PANGO_STRETCH_ULTRA_CONDENSED:
+ g_string_append (s, "font-stretch: ultra-condensed; ");
+ break;
+ case PANGO_STRETCH_EXTRA_CONDENSED:
+ g_string_append (s, "font-stretch: extra-condensed; ");
+ break;
+ case PANGO_STRETCH_CONDENSED:
+ g_string_append (s, "font-stretch: condensed; ");
+ break;
+ case PANGO_STRETCH_SEMI_CONDENSED:
+ g_string_append (s, "font-stretch: semi-condensed; ");
+ break;
+ case PANGO_STRETCH_NORMAL:
+ g_string_append (s, "font-stretch: normal; ");
+ break;
+ case PANGO_STRETCH_SEMI_EXPANDED:
+ g_string_append (s, "font-stretch: semi-expanded; ");
+ break;
+ case PANGO_STRETCH_EXPANDED:
+ g_string_append (s, "font-stretch: expanded; ");
+ break;
+ case PANGO_STRETCH_EXTRA_EXPANDED:
+ break;
+ case PANGO_STRETCH_ULTRA_EXPANDED:
+ g_string_append (s, "font-stretch: ultra-expanded; ");
+ break;
+ default:
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_SIZE)
+ {
+ g_string_append_printf (s, "font-size: %dpt; ", pango_font_description_get_size (desc) / PANGO_SCALE);
+ }
+
+#if PANGO_VERSION_CHECK (1, 44, 0)
+ if (set & PANGO_FONT_MASK_VARIATIONS)
+ {
+ const char *variations;
+
+ g_string_append (s, "font-variation-settings: ");
+ variations = pango_font_description_get_variations (desc);
+ add_css_variations (s, variations);
+ g_string_append (s, "; ");
+ }
+#endif
+
+ return g_string_free (s, FALSE);
+}
diff --git a/gedit/gedit-pango.h b/gedit/gedit-pango.h
new file mode 100644
index 000000000..8c800d502
--- /dev/null
+++ b/gedit/gedit-pango.h
@@ -0,0 +1,28 @@
+/* gedit-pango.h
+ *
+ * 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 2 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/>.
+ */
+
+#ifndef GEDIT_PANGO_H
+#define GEDIT_PANGO_H
+
+#include <pango/pango.h>
+
+G_BEGIN_DECLS
+
+gchar *gedit_pango_font_description_to_css (const PangoFontDescription *font_desc);
+
+G_END_DECLS
+
+#endif /* GEDIT_PANGO_H */
diff --git a/gedit/gedit-preferences-dialog.c b/gedit/gedit-preferences-dialog.c
index 016baf189..ec3f53a3d 100644
--- a/gedit/gedit-preferences-dialog.c
+++ b/gedit/gedit-preferences-dialog.c
@@ -23,14 +23,22 @@
#include "gedit-preferences-dialog.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
#include <glib/gi18n.h>
#include <glib/gstdio.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
#include <libpeas-gtk/peas-gtk.h>
+#include "gedit-utils.h"
#include "gedit-debug.h"
+#include "gedit-document.h"
#include "gedit-dirs.h"
#include "gedit-settings.h"
+#include "gedit-utils.h"
+#include "gedit-file-chooser-dialog.h"
/*
* gedit-preferences dialog is a singleton since we don't
@@ -83,9 +91,11 @@ struct _GeditPreferencesDialog
GtkWidget *schemes_list;
GtkWidget *install_scheme_button;
GtkWidget *uninstall_scheme_button;
+ GtkWidget *schemes_scrolled_window;
GtkWidget *schemes_toolbar;
- GtkFileChooserNative *
- install_scheme_file_chooser;
+
+ GeditFileChooserDialog *
+ install_scheme_file_schooser;
/* Tabs */
GtkWidget *tabs_width_spinbutton;
@@ -105,6 +115,7 @@ struct _GeditPreferencesDialog
GtkWidget *display_line_numbers_checkbutton;
GtkWidget *display_statusbar_checkbutton;
+ GtkWidget *display_overview_map_checkbutton;
GtkWidget *display_grid_checkbutton;
/* Right margin */
@@ -170,6 +181,7 @@ gedit_preferences_dialog_class_init (GeditPreferencesDialogClass *klass)
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog,
display_line_numbers_checkbutton);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog,
display_statusbar_checkbutton);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, display_grid_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog,
display_overview_map_checkbutton);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, right_margin_checkbutton);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog,
right_margin_position_grid);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog,
right_margin_position_spinbutton);
@@ -187,6 +199,7 @@ gedit_preferences_dialog_class_init (GeditPreferencesDialogClass *klass)
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, font_button);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, font_grid);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_list);
+ gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_scrolled_window);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, install_scheme_button);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, uninstall_scheme_button);
gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_toolbar);
@@ -386,6 +399,11 @@ setup_view_page (GeditPreferencesDialog *dlg)
dlg->display_statusbar_checkbutton,
"active",
G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ g_settings_bind (dlg->editor,
+ GEDIT_SETTINGS_DISPLAY_OVERVIEW_MAP,
+ dlg->display_overview_map_checkbutton,
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
g_settings_bind (dlg->editor,
GEDIT_SETTINGS_DISPLAY_RIGHT_MARGIN,
dlg->right_margin_checkbutton,
@@ -434,7 +452,7 @@ setup_font_colors_page_font_section (GeditPreferencesDialog *dlg)
/* Get values */
settings = _gedit_settings_get_singleton ();
- system_font = _gedit_settings_get_system_font (settings);
+ system_font = gedit_settings_get_system_font (settings);
label = g_strdup_printf(_("_Use the system fixed width font (%s)"),
system_font);
@@ -462,172 +480,255 @@ setup_font_colors_page_font_section (GeditPreferencesDialog *dlg)
}
static void
-update_style_scheme_buttons_sensisitivity (GeditPreferencesDialog *dlg)
+set_buttons_sensisitivity_according_to_scheme (GeditPreferencesDialog *dlg,
+ GtkSourceStyleScheme *scheme)
{
- GtkSourceStyleScheme *selected_style_scheme;
gboolean editable = FALSE;
- selected_style_scheme = gtk_source_style_scheme_chooser_get_style_scheme
(GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list));
-
- if (selected_style_scheme != NULL)
+ if (scheme != NULL)
{
const gchar *filename;
- filename = gtk_source_style_scheme_get_filename (selected_style_scheme);
+ filename = gtk_source_style_scheme_get_filename (scheme);
if (filename != NULL)
{
editable = g_str_has_prefix (filename, gedit_dirs_get_user_styles_dir ());
}
}
- gtk_widget_set_sensitive (dlg->uninstall_scheme_button, editable);
+ gtk_widget_set_sensitive (dlg->uninstall_scheme_button,
+ editable);
}
static void
-style_scheme_notify_cb (GtkSourceStyleSchemeChooser *chooser,
- GParamSpec *pspec,
- GeditPreferencesDialog *dlg)
+style_scheme_changed (GtkSourceStyleSchemeChooser *chooser,
+ GParamSpec *pspec,
+ GeditPreferencesDialog *dlg)
{
- update_style_scheme_buttons_sensisitivity (dlg);
+ GtkSourceStyleScheme *scheme;
+ const gchar *id;
+
+ scheme = gtk_source_style_scheme_chooser_get_style_scheme (chooser);
+ id = gtk_source_style_scheme_get_id (scheme);
+
+ g_settings_set_string (dlg->editor, GEDIT_SETTINGS_SCHEME, id);
+ set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
}
-static GFile *
-get_user_style_scheme_destination_file (GFile *src_file)
+static GtkSourceStyleScheme *
+get_default_color_scheme (GeditPreferencesDialog *dlg)
{
- gchar *basename;
- const gchar *styles_dir;
- GFile *dest_file;
+ GtkSourceStyleSchemeManager *manager;
+ GtkSourceStyleScheme *scheme = NULL;
+ gchar *pref_id;
- basename = g_file_get_basename (src_file);
- g_return_val_if_fail (basename != NULL, NULL);
+ manager = gtk_source_style_scheme_manager_get_default ();
- styles_dir = gedit_dirs_get_user_styles_dir ();
- dest_file = g_file_new_build_filename (styles_dir, basename, NULL);
+ pref_id = g_settings_get_string (dlg->editor,
+ GEDIT_SETTINGS_SCHEME);
- g_free (basename);
- return dest_file;
+ scheme = gtk_source_style_scheme_manager_get_scheme (manager,
+ pref_id);
+ g_free (pref_id);
+
+ if (scheme == NULL)
+ {
+ /* Fall-back to classic style scheme */
+ scheme = gtk_source_style_scheme_manager_get_scheme (manager,
+ "classic");
+ }
+
+ return scheme;
}
-/* Returns: whether @src_file has been correctly copied to @dest_file. */
+/*
+ * file_copy:
+ * @name: a pointer to a %NULL-terminated string, that names
+ * the file to be copied, in the GLib file name encoding
+ * @dest_name: a pointer to a %NULL-terminated string, that is the
+ * name for the destination file, in the GLib file name encoding
+ * @error: return location for a #GError, or %NULL
+ *
+ * Copies file @name to @dest_name.
+ *
+ * If the call was successful, it returns %TRUE. If the call was not
+ * successful, it returns %FALSE and sets @error. The error domain
+ * is #G_FILE_ERROR. Possible error
+ * codes are those in the #GFileError enumeration.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ */
static gboolean
-copy_file (GFile *src_file,
- GFile *dest_file,
- GError **error)
+file_copy (const gchar *name,
+ const gchar *dest_name,
+ GError **error)
{
- if (g_file_equal (src_file, dest_file))
+ gchar *contents;
+ gsize length;
+ gchar *dest_dir;
+
+ /* FIXME - Paolo (Aug. 13, 2007):
+ * Since the style scheme files are relatively small, we can implement
+ * file copy getting all the content of the source file in a buffer and
+ * then write the content to the destination file. In this way we
+ * can use the g_file_get_contents and g_file_set_contents and avoid to
+ * write custom code to copy the file (with sane error management).
+ * If needed we can improve this code later. */
+
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (dest_name != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* Note: we allow to copy a file to itself since this is not a problem
+ * in our use case */
+
+ /* Ensure the destination directory exists */
+ dest_dir = g_path_get_dirname (dest_name);
+
+ errno = 0;
+ if (g_mkdir_with_parents (dest_dir, 0755) != 0)
{
+ gint save_errno = errno;
+ gchar *display_filename = g_filename_display_name (dest_dir);
+
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (save_errno),
+ _("Directory “%s†could not be created: g_mkdir_with_parents() failed: %s"),
+ display_filename,
+ g_strerror (save_errno));
+
+ g_free (dest_dir);
+ g_free (display_filename);
+
return FALSE;
}
- if (!tepl_utils_create_parent_directories (dest_file, NULL, error))
+ g_free (dest_dir);
+
+ if (!g_file_get_contents (name, &contents, &length, error))
+ return FALSE;
+
+ if (!g_file_set_contents (dest_name, contents, length, error))
{
+ g_free (contents);
return FALSE;
}
- return g_file_copy (src_file,
- dest_file,
- G_FILE_COPY_OVERWRITE | G_FILE_COPY_TARGET_DEFAULT_PERMS,
- NULL, /* cancellable */
- NULL, NULL, /* progress callback */
- error);
+ g_free (contents);
+
+ return TRUE;
}
-/* Get the style scheme ID of @user_style_scheme_file if it has been correctly
- * installed and @user_style_scheme_file is a valid style scheme file.
+/*
+ * install_style_scheme:
+ * @manager: a #GtkSourceStyleSchemeManager
+ * @fname: the file name of the style scheme to be installed
+ *
+ * Install a new user scheme.
+ * This function copies @fname in #GEDIT_STYLES_DIR and ask the style manager to
+ * recompute the list of available style schemes. It then checks if a style
+ * scheme with the right file name exists.
+ *
+ * If the call was succesful, it returns the id of the installed scheme
+ * otherwise %NULL.
+ *
+ * Return value: the id of the installed scheme, %NULL otherwise.
*/
-static const gchar *
-get_style_scheme_id_after_installing_user_style_scheme (GFile *user_style_scheme_file)
+static GtkSourceStyleScheme *
+install_style_scheme (const gchar *fname)
{
GtkSourceStyleSchemeManager *manager;
- const gchar * const *scheme_ids;
- gint i;
+ gchar *new_file_name = NULL;
+ gchar *dirname;
+ const gchar *styles_dir;
+ GError *error = NULL;
+ gboolean copied = FALSE;
+ const gchar * const *ids;
+
+ g_return_val_if_fail (fname != NULL, NULL);
manager = gtk_source_style_scheme_manager_get_default ();
- gtk_source_style_scheme_manager_force_rescan (manager);
- scheme_ids = gtk_source_style_scheme_manager_get_scheme_ids (manager);
+ dirname = g_path_get_dirname (fname);
+ styles_dir = gedit_dirs_get_user_styles_dir ();
- for (i = 0; scheme_ids != NULL && scheme_ids[i] != NULL; i++)
+ if (strcmp (dirname, styles_dir) != 0)
{
- const gchar *cur_scheme_id = scheme_ids[i];
- GtkSourceStyleScheme *scheme;
- const gchar *filename;
- GFile *scheme_file;
+ gchar *basename;
- scheme = gtk_source_style_scheme_manager_get_scheme (manager, cur_scheme_id);
- filename = gtk_source_style_scheme_get_filename (scheme);
- if (filename == NULL)
- {
- continue;
- }
+ basename = g_path_get_basename (fname);
+ new_file_name = g_build_filename (styles_dir, basename, NULL);
+ g_free (basename);
- scheme_file = g_file_new_for_path (filename);
- if (g_file_equal (scheme_file, user_style_scheme_file))
+ /* Copy the style scheme file into GEDIT_STYLES_DIR */
+ if (!file_copy (fname, new_file_name, &error))
{
- g_object_unref (scheme_file);
- return cur_scheme_id;
+ g_free (new_file_name);
+ g_free (dirname);
+
+ g_message ("Cannot install style scheme:\n%s",
+ error->message);
+
+ g_error_free (error);
+
+ return NULL;
}
- g_object_unref (scheme_file);
+ copied = TRUE;
+ }
+ else
+ {
+ new_file_name = g_strdup (fname);
}
- return NULL;
-}
-
-/* Returns: (nullable): the installed style scheme ID, or %NULL on failure. */
-static const gchar *
-install_style_scheme (GFile *src_file,
- GError **error)
-{
- GFile *dest_file;
- gboolean copied;
- const gchar *installed_style_scheme_id = NULL;
- GError *my_error = NULL;
+ g_free (dirname);
- g_return_val_if_fail (G_IS_FILE (src_file), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ /* Reload the available style schemes */
+ gtk_source_style_scheme_manager_force_rescan (manager);
- dest_file = get_user_style_scheme_destination_file (src_file);
- g_return_val_if_fail (dest_file != NULL, NULL);
+ /* Check the new style scheme has been actually installed */
+ ids = gtk_source_style_scheme_manager_get_scheme_ids (manager);
- copied = copy_file (src_file, dest_file, &my_error);
- if (my_error != NULL)
+ while (*ids != NULL)
{
- g_propagate_error (error, my_error);
- g_object_unref (dest_file);
- return NULL;
- }
+ GtkSourceStyleScheme *scheme;
+ const gchar *filename;
- installed_style_scheme_id = get_style_scheme_id_after_installing_user_style_scheme (dest_file);
+ scheme = gtk_source_style_scheme_manager_get_scheme (manager, *ids);
- if (installed_style_scheme_id == NULL && copied)
- {
- /* The style scheme has not been correctly installed. */
- g_file_delete (dest_file, NULL, &my_error);
- if (my_error != NULL)
- {
- gchar *dest_file_parse_name = g_file_get_parse_name (dest_file);
+ filename = gtk_source_style_scheme_get_filename (scheme);
- g_warning ("Failed to delete the file “%sâ€: %s",
- dest_file_parse_name,
- my_error->message);
+ if (filename && (strcmp (filename, new_file_name) == 0))
+ {
+ /* The style scheme has been correctly installed */
+ g_free (new_file_name);
- g_free (dest_file_parse_name);
- g_clear_error (&my_error);
+ return scheme;
}
+ ++ids;
}
- g_object_unref (dest_file);
- return installed_style_scheme_id;
+ /* The style scheme has not been correctly installed */
+ if (copied)
+ g_unlink (new_file_name);
+
+ g_free (new_file_name);
+
+ return NULL;
}
-/*
+/**
* uninstall_style_scheme:
+ * @manager: a #GtkSourceStyleSchemeManager
* @scheme: a #GtkSourceStyleScheme
*
* Uninstall a user scheme.
*
- * Returns: %TRUE on success, %FALSE otherwise.
+ * If the call was succesful, it returns %TRUE
+ * otherwise %FALSE.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
*/
static gboolean
uninstall_style_scheme (GtkSourceStyleScheme *scheme)
@@ -653,94 +754,92 @@ uninstall_style_scheme (GtkSourceStyleScheme *scheme)
}
static void
-add_scheme_chooser_response_cb (GtkFileChooserNative *chooser,
- gint response_id,
- GeditPreferencesDialog *dialog)
+add_scheme_chooser_response_cb (GeditFileChooserDialog *chooser,
+ gint res_id,
+ GeditPreferencesDialog *dlg)
{
GFile *file;
- const gchar *scheme_id;
- GeditSettings *settings;
- GSettings *editor_settings;
- GError *error = NULL;
+ gchar *filename;
+ GtkSourceStyleScheme *scheme;
- if (response_id != GTK_RESPONSE_ACCEPT)
+ if (res_id != GTK_RESPONSE_ACCEPT)
{
+ gedit_file_chooser_dialog_hide (chooser);
return;
}
- file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser));
+ file = gedit_file_chooser_dialog_get_file (chooser);
+
if (file == NULL)
{
return;
}
- scheme_id = install_style_scheme (file, &error);
+ filename = g_file_get_path (file);
g_object_unref (file);
- if (scheme_id == NULL)
+ if (filename == NULL)
{
- if (error != NULL)
- {
- tepl_utils_show_warning_dialog (GTK_WINDOW (dialog),
- _("The selected color scheme cannot be installed:
%s"),
- error->message);
- }
- else
- {
- tepl_utils_show_warning_dialog (GTK_WINDOW (dialog),
- _("The selected color scheme cannot be installed."));
- }
+ return;
+ }
+
+ gedit_file_chooser_dialog_hide (chooser);
+
+ scheme = install_style_scheme (filename);
+ g_free (filename);
+
+ if (scheme == NULL)
+ {
+ gedit_warning (GTK_WINDOW (dlg),
+ _("The selected color scheme cannot be installed."));
- g_clear_error (&error);
return;
}
- settings = _gedit_settings_get_singleton ();
- editor_settings = _gedit_settings_peek_editor_settings (settings);
- g_settings_set_string (editor_settings, GEDIT_SETTINGS_SCHEME, scheme_id);
+ g_settings_set_string (dlg->editor, GEDIT_SETTINGS_SCHEME,
+ gtk_source_style_scheme_get_id (scheme));
+
+ set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
}
static void
install_scheme_clicked (GtkButton *button,
- GeditPreferencesDialog *dialog)
+ GeditPreferencesDialog *dlg)
{
- GtkFileChooserNative *chooser;
- GtkFileFilter *scheme_filter;
- GtkFileFilter *all_filter;
+ GeditFileChooserDialog *chooser;
- if (dialog->install_scheme_file_chooser != NULL)
+ if (dlg->install_scheme_file_schooser != NULL)
{
- gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog->install_scheme_file_chooser));
+ gedit_file_chooser_dialog_show (dlg->install_scheme_file_schooser);
return;
}
- chooser = gtk_file_chooser_native_new (_("Add Color Scheme"),
- GTK_WINDOW (dialog),
- GTK_FILE_CHOOSER_ACTION_OPEN,
- _("_Add Scheme"),
- _("_Cancel"));
+ chooser = gedit_file_chooser_dialog_create (_("Add Scheme"),
+ GTK_WINDOW (dlg),
+ GEDIT_FILE_CHOOSER_FLAG_OPEN,
+ _("_Cancel"),
+ _("A_dd Scheme"));
/* Filters */
- scheme_filter = gtk_file_filter_new ();
- gtk_file_filter_set_name (scheme_filter, _("Color Scheme Files"));
- gtk_file_filter_add_pattern (scheme_filter, "*.xml");
- gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), scheme_filter);
-
- all_filter = gtk_file_filter_new ();
- gtk_file_filter_set_name (all_filter, _("All Files"));
- gtk_file_filter_add_pattern (all_filter, "*");
- gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), all_filter);
+ gedit_file_chooser_dialog_add_pattern_filter (chooser,
+ _("Color Scheme Files"),
+ "*.xml");
- gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser), scheme_filter);
+ gedit_file_chooser_dialog_add_pattern_filter (chooser,
+ _("All Files"),
+ "*");
g_signal_connect (chooser,
"response",
G_CALLBACK (add_scheme_chooser_response_cb),
- dialog);
+ dlg);
- g_set_weak_pointer (&dialog->install_scheme_file_chooser, chooser);
+ dlg->install_scheme_file_schooser = chooser;
- gtk_native_dialog_show (GTK_NATIVE_DIALOG (chooser));
+ g_object_add_weak_pointer (G_OBJECT (chooser),
+ (gpointer) &dlg->install_scheme_file_schooser);
+
+ gedit_file_chooser_dialog_show (chooser);
}
static void
@@ -748,33 +847,14 @@ uninstall_scheme_clicked (GtkButton *button,
GeditPreferencesDialog *dlg)
{
GtkSourceStyleScheme *scheme;
- GtkSourceStyleScheme *new_selected_scheme;
scheme = gtk_source_style_scheme_chooser_get_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER
(dlg->schemes_list));
- if (scheme == NULL)
- {
- return;
- }
-
if (!uninstall_style_scheme (scheme))
{
- tepl_utils_show_warning_dialog (GTK_WINDOW (dlg),
- _("Could not remove color scheme “%sâ€."),
- gtk_source_style_scheme_get_name (scheme));
- return;
- }
-
- new_selected_scheme = gtk_source_style_scheme_chooser_get_style_scheme
(GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list));
- if (new_selected_scheme == NULL)
- {
- GeditSettings *settings;
- GSettings *editor_settings;
-
- settings = _gedit_settings_get_singleton ();
- editor_settings = _gedit_settings_peek_editor_settings (settings);
-
- g_settings_reset (editor_settings, GEDIT_SETTINGS_SCHEME);
+ gedit_warning (GTK_WINDOW (dlg),
+ _("Could not remove color scheme “%sâ€."),
+ gtk_source_style_scheme_get_name (scheme));
}
}
@@ -782,13 +862,14 @@ static void
setup_font_colors_page_style_scheme_section (GeditPreferencesDialog *dlg)
{
GtkStyleContext *context;
- GeditSettings *settings;
- GSettings *editor_settings;
+ GtkSourceStyleScheme *scheme;
gedit_debug (DEBUG_PREFS);
- /* junction between the schemes list and the toolbar */
- context = gtk_widget_get_style_context (dlg->schemes_list);
+ scheme = get_default_color_scheme (dlg);
+
+ /* junction between the scrolled window and the toolbar */
+ context = gtk_widget_get_style_context (dlg->schemes_scrolled_window);
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
context = gtk_widget_get_style_context (dlg->schemes_toolbar);
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
@@ -796,7 +877,7 @@ setup_font_colors_page_style_scheme_section (GeditPreferencesDialog *dlg)
/* Connect signals */
g_signal_connect (dlg->schemes_list,
"notify::style-scheme",
- G_CALLBACK (style_scheme_notify_cb),
+ G_CALLBACK (style_scheme_changed),
dlg);
g_signal_connect (dlg->install_scheme_button,
"clicked",
@@ -807,13 +888,11 @@ setup_font_colors_page_style_scheme_section (GeditPreferencesDialog *dlg)
G_CALLBACK (uninstall_scheme_clicked),
dlg);
- settings = _gedit_settings_get_singleton ();
- editor_settings = _gedit_settings_peek_editor_settings (settings);
- g_settings_bind (editor_settings, GEDIT_SETTINGS_SCHEME,
- dlg->schemes_list, "tepl-style-scheme-id",
- G_SETTINGS_BIND_DEFAULT);
+ gtk_source_style_scheme_chooser_set_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list),
+ scheme);
- update_style_scheme_buttons_sensisitivity (dlg);
+ /* Set initial widget sensitivity */
+ set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
}
static void
diff --git a/gedit/gedit-print-job.c b/gedit/gedit-print-job.c
index 6083669f9..e6c1dcdcb 100644
--- a/gedit/gedit-print-job.c
+++ b/gedit/gedit-print-job.c
@@ -23,7 +23,7 @@
#include "gedit-print-job.h"
#include <glib/gi18n.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
#include "gedit-debug.h"
#include "gedit-document-private.h"
@@ -535,7 +535,7 @@ create_compositor (GeditPrintJob *job)
gchar *left;
doc_name = _gedit_document_get_uri_for_display (GEDIT_DOCUMENT (buf));
- name_to_display = tepl_utils_str_middle_truncate (doc_name, 60);
+ name_to_display = gedit_utils_str_middle_truncate (doc_name, 60);
left = g_strdup_printf (_("File: %s"), name_to_display);
diff --git a/gedit/gedit-progress-info-bar.c b/gedit/gedit-progress-info-bar.c
new file mode 100644
index 000000000..d547189fb
--- /dev/null
+++ b/gedit/gedit-progress-info-bar.c
@@ -0,0 +1,177 @@
+/*
+ * gedit-progress-info-bar.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ *
+ * 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 2 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/>.
+ */
+
+#include "gedit-progress-info-bar.h"
+#include <glib/gi18n.h>
+
+enum {
+ PROP_0,
+ PROP_HAS_CANCEL_BUTTON,
+ LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP];
+
+struct _GeditProgressInfoBar
+{
+ GtkInfoBar parent_instance;
+
+ GtkWidget *image;
+ GtkWidget *label;
+ GtkWidget *progress;
+};
+
+G_DEFINE_TYPE (GeditProgressInfoBar, gedit_progress_info_bar, GTK_TYPE_INFO_BAR)
+
+static void
+gedit_progress_info_bar_set_has_cancel_button (GeditProgressInfoBar *bar,
+ gboolean has_button)
+{
+ if (has_button)
+ {
+ gtk_info_bar_add_button (GTK_INFO_BAR (bar), _("_Cancel"), GTK_RESPONSE_CANCEL);
+ }
+}
+
+static void
+gedit_progress_info_bar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditProgressInfoBar *bar;
+
+ bar = GEDIT_PROGRESS_INFO_BAR (object);
+
+ switch (prop_id)
+ {
+ case PROP_HAS_CANCEL_BUTTON:
+ gedit_progress_info_bar_set_has_cancel_button (bar,
+ g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_progress_info_bar_class_init (GeditProgressInfoBarClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->set_property = gedit_progress_info_bar_set_property;
+
+ properties[PROP_HAS_CANCEL_BUTTON] =
+ g_param_spec_boolean ("has-cancel-button",
+ "Has Cancel Button",
+ "If the message bar has a cancel button",
+ TRUE,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class, LAST_PROP, properties);
+
+ /* Bind class to template */
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/gedit/ui/gedit-progress-info-bar.ui");
+ gtk_widget_class_bind_template_child (widget_class, GeditProgressInfoBar, image);
+ gtk_widget_class_bind_template_child (widget_class, GeditProgressInfoBar, label);
+ gtk_widget_class_bind_template_child (widget_class, GeditProgressInfoBar, progress);
+}
+
+static void
+gedit_progress_info_bar_init (GeditProgressInfoBar *bar)
+{
+ gtk_widget_init_template (GTK_WIDGET (bar));
+}
+
+GtkWidget *
+gedit_progress_info_bar_new (const gchar *icon_name,
+ const gchar *markup,
+ gboolean has_cancel)
+{
+ GeditProgressInfoBar *bar;
+
+ g_return_val_if_fail (icon_name != NULL, NULL);
+ g_return_val_if_fail (markup != NULL, NULL);
+
+ bar = GEDIT_PROGRESS_INFO_BAR (g_object_new (GEDIT_TYPE_PROGRESS_INFO_BAR,
+ "has-cancel-button", has_cancel,
+ NULL));
+
+ gedit_progress_info_bar_set_icon_name (bar, icon_name);
+ gedit_progress_info_bar_set_markup (bar, markup);
+
+ return GTK_WIDGET (bar);
+}
+
+void
+gedit_progress_info_bar_set_icon_name (GeditProgressInfoBar *bar,
+ const gchar *icon_name)
+{
+ g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+ g_return_if_fail (icon_name != NULL);
+
+ gtk_image_set_from_icon_name (GTK_IMAGE (bar->image),
+ icon_name,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+}
+
+void
+gedit_progress_info_bar_set_markup (GeditProgressInfoBar *bar,
+ const gchar *markup)
+{
+ g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+ g_return_if_fail (markup != NULL);
+
+ gtk_label_set_markup (GTK_LABEL (bar->label), markup);
+}
+
+void
+gedit_progress_info_bar_set_text (GeditProgressInfoBar *bar,
+ const gchar *text)
+{
+ g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+ g_return_if_fail (text != NULL);
+
+ gtk_label_set_text (GTK_LABEL (bar->label), text);
+}
+
+void
+gedit_progress_info_bar_set_fraction (GeditProgressInfoBar *bar,
+ gdouble fraction)
+{
+ g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (bar->progress), fraction);
+}
+
+void
+gedit_progress_info_bar_pulse (GeditProgressInfoBar *bar)
+{
+ g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+
+ gtk_progress_bar_pulse (GTK_PROGRESS_BAR (bar->progress));
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-progress-info-bar.h b/gedit/gedit-progress-info-bar.h
new file mode 100644
index 000000000..0d820d8e4
--- /dev/null
+++ b/gedit/gedit-progress-info-bar.h
@@ -0,0 +1,53 @@
+/*
+ * gedit-progress-info-bar.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ *
+ * 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 2 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/>.
+ */
+
+#ifndef GEDIT_PROGRESS_INFO_BAR_H
+#define GEDIT_PROGRESS_INFO_BAR_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_PROGRESS_INFO_BAR (gedit_progress_info_bar_get_type ())
+G_DECLARE_FINAL_TYPE (GeditProgressInfoBar, gedit_progress_info_bar, GEDIT, PROGRESS_INFO_BAR, GtkInfoBar)
+
+GtkWidget *gedit_progress_info_bar_new (const gchar *icon_name,
+ const gchar *markup,
+ gboolean has_cancel);
+
+void gedit_progress_info_bar_set_icon_name (GeditProgressInfoBar *bar,
+ const gchar *icon_name);
+
+void gedit_progress_info_bar_set_markup (GeditProgressInfoBar *bar,
+ const gchar *markup);
+
+void gedit_progress_info_bar_set_text (GeditProgressInfoBar *bar,
+ const gchar *text);
+
+void gedit_progress_info_bar_set_fraction (GeditProgressInfoBar *bar,
+ gdouble fraction);
+
+void gedit_progress_info_bar_pulse (GeditProgressInfoBar *bar);
+
+G_END_DECLS
+
+#endif /* GEDIT_PROGRESS_INFO_BAR_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-recent.c b/gedit/gedit-recent.c
index b1535d057..2a0063306 100644
--- a/gedit/gedit-recent.c
+++ b/gedit/gedit-recent.c
@@ -24,7 +24,7 @@
void
gedit_recent_add_document (GeditDocument *document)
{
- TeplFile *file;
+ GtkSourceFile *file;
GFile *location;
GtkRecentManager *recent_manager;
GtkRecentData recent_data;
@@ -33,8 +33,8 @@ gedit_recent_add_document (GeditDocument *document)
g_return_if_fail (GEDIT_IS_DOCUMENT (document));
- file = tepl_buffer_get_file (TEPL_BUFFER (document));
- location = tepl_file_get_location (file);
+ file = gedit_document_get_file (document);
+ location = gtk_source_file_get_location (file);
if (location == NULL)
{
@@ -89,4 +89,229 @@ gedit_recent_remove_if_local (GFile *location)
}
}
+static gint
+sort_recent_items_mru (GtkRecentInfo *a,
+ GtkRecentInfo *b,
+ gpointer unused)
+{
+ g_assert (a != NULL && b != NULL);
+ return gtk_recent_info_get_modified (b) - gtk_recent_info_get_modified (a);
+}
+
+static void
+populate_filter_info (GtkRecentInfo *info,
+ GtkRecentFilterInfo *filter_info,
+ GtkRecentFilterFlags needed)
+{
+ filter_info->uri = gtk_recent_info_get_uri (info);
+ filter_info->mime_type = gtk_recent_info_get_mime_type (info);
+
+ filter_info->contains = GTK_RECENT_FILTER_URI | GTK_RECENT_FILTER_MIME_TYPE;
+
+ if (needed & GTK_RECENT_FILTER_DISPLAY_NAME)
+ {
+ filter_info->display_name = gtk_recent_info_get_display_name (info);
+ filter_info->contains |= GTK_RECENT_FILTER_DISPLAY_NAME;
+ }
+ else
+ {
+ filter_info->uri = NULL;
+ }
+
+ if (needed & GTK_RECENT_FILTER_APPLICATION)
+ {
+ filter_info->applications = (const gchar **) gtk_recent_info_get_applications (info, NULL);
+ filter_info->contains |= GTK_RECENT_FILTER_APPLICATION;
+ }
+ else
+ {
+ filter_info->applications = NULL;
+ }
+
+ if (needed & GTK_RECENT_FILTER_GROUP)
+ {
+ filter_info->groups = (const gchar **) gtk_recent_info_get_groups (info, NULL);
+ filter_info->contains |= GTK_RECENT_FILTER_GROUP;
+ }
+ else
+ {
+ filter_info->groups = NULL;
+ }
+
+ if (needed & GTK_RECENT_FILTER_AGE)
+ {
+ filter_info->age = gtk_recent_info_get_age (info);
+ filter_info->contains |= GTK_RECENT_FILTER_AGE;
+ }
+ else
+ {
+ filter_info->age = -1;
+ }
+}
+
+/* The GeditRecentConfiguration struct is allocated and owned by the caller */
+void
+gedit_recent_configuration_init_default (GeditRecentConfiguration *config)
+{
+ config->manager = gtk_recent_manager_get_default ();
+
+ if (config->filter != NULL)
+ {
+ g_object_unref (config->filter);
+ }
+
+ config->filter = gtk_recent_filter_new ();
+ gtk_recent_filter_add_application (config->filter, g_get_application_name ());
+ gtk_recent_filter_add_mime_type (config->filter, "text/plain");
+ g_object_ref_sink (config->filter);
+
+ config->limit = 5;
+ config->show_not_found = TRUE;
+ config->show_private = FALSE;
+ config->local_only = FALSE;
+
+ config->substring_filter = NULL;
+}
+
+/* The GeditRecentConfiguration struct is owned and destroyed by the caller */
+void
+gedit_recent_configuration_destroy (GeditRecentConfiguration *config)
+{
+ g_clear_object (&config->filter);
+ config->manager = NULL;
+
+ g_clear_pointer (&config->substring_filter, (GDestroyNotify)g_free);
+}
+
+GList *
+gedit_recent_get_items (GeditRecentConfiguration *config)
+{
+ GtkRecentFilterFlags needed;
+ GList *items;
+ GList *retitems = NULL;
+ gint length;
+ char *substring_filter = NULL;
+
+ if (config->limit == 0)
+ {
+ return NULL;
+ }
+
+ items = gtk_recent_manager_get_items (config->manager);
+
+ if (!items)
+ {
+ return NULL;
+ }
+
+ needed = gtk_recent_filter_get_needed (config->filter);
+ if (config->substring_filter && *config->substring_filter != '\0')
+ {
+ gchar *filter_normalized;
+
+ filter_normalized = g_utf8_normalize (config->substring_filter, -1, G_NORMALIZE_ALL);
+ substring_filter = g_utf8_casefold (filter_normalized, -1);
+ g_free (filter_normalized);
+ }
+
+ while (items)
+ {
+ GtkRecentInfo *info;
+ GtkRecentFilterInfo filter_info;
+ gboolean is_filtered;
+
+ info = items->data;
+ is_filtered = FALSE;
+
+ if (config->local_only && !gtk_recent_info_is_local (info))
+ {
+ is_filtered = TRUE;
+ }
+ else if (!config->show_private && gtk_recent_info_get_private_hint (info))
+ {
+ is_filtered = TRUE;
+ }
+ else if (!config->show_not_found && !gtk_recent_info_exists (info))
+ {
+ is_filtered = TRUE;
+ }
+ else
+ {
+ if (substring_filter)
+ {
+ gchar *uri_normalized;
+ gchar *uri_casefolded;
+
+ uri_normalized = g_utf8_normalize (gtk_recent_info_get_uri_display (info),
-1, G_NORMALIZE_ALL);
+ uri_casefolded = g_utf8_casefold (uri_normalized, -1);
+ g_free (uri_normalized);
+
+ if (strstr (uri_casefolded, substring_filter) == NULL)
+ {
+ is_filtered = TRUE;
+ }
+
+ g_free (uri_casefolded);
+ }
+
+ if (!is_filtered)
+ {
+ populate_filter_info (info, &filter_info, needed);
+ is_filtered = !gtk_recent_filter_filter (config->filter, &filter_info);
+
+ /* these we own */
+ if (filter_info.applications)
+ {
+ g_strfreev ((gchar **) filter_info.applications);
+ }
+
+ if (filter_info.groups)
+ {
+ g_strfreev ((gchar **) filter_info.groups);
+ }
+ }
+ }
+
+ if (!is_filtered)
+ {
+ retitems = g_list_prepend (retitems, info);
+ }
+ else
+ {
+ gtk_recent_info_unref (info);
+ }
+
+ items = g_list_delete_link (items, items);
+ }
+
+ g_free (substring_filter);
+
+ if (!retitems)
+ {
+ return NULL;
+ }
+
+ retitems = g_list_sort_with_data (retitems, (GCompareDataFunc) sort_recent_items_mru, NULL);
+ length = g_list_length (retitems);
+
+ if ((config->limit != -1) && (length > config->limit))
+ {
+ GList *clamp, *l;
+
+ clamp = g_list_nth (retitems, config->limit - 1);
+
+ if (!clamp)
+ {
+ return retitems;
+ }
+
+ l = clamp->next;
+ clamp->next = NULL;
+
+ g_list_free_full (l, (GDestroyNotify) gtk_recent_info_unref);
+ }
+
+ return retitems;
+}
+
/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-recent.h b/gedit/gedit-recent.h
index 068d89c72..5c72837ed 100644
--- a/gedit/gedit-recent.h
+++ b/gedit/gedit-recent.h
@@ -27,12 +27,29 @@
G_BEGIN_DECLS
-void gedit_recent_add_document (GeditDocument *document);
+typedef struct
+{
+ GtkRecentManager *manager;
+ GtkRecentFilter *filter;
-void gedit_recent_remove_if_local (GFile *location);
+ gint limit;
+ gchar *substring_filter;
+
+ guint show_private : 1;
+ guint show_not_found : 1;
+ guint local_only : 1;
+} GeditRecentConfiguration;
+
+void gedit_recent_add_document (GeditDocument *document);
+
+void gedit_recent_remove_if_local (GFile *location);
+
+void gedit_recent_configuration_init_default (GeditRecentConfiguration *config);
+void gedit_recent_configuration_destroy (GeditRecentConfiguration *config);
+GList *gedit_recent_get_items (GeditRecentConfiguration *config);
G_END_DECLS
-#endif /* GEDIT_RECENT_H */
+#endif /* GEDIT_RECENT_H */
/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-settings.c b/gedit/gedit-settings.c
index a762a1dc2..6fa300f29 100644
--- a/gedit/gedit-settings.c
+++ b/gedit/gedit-settings.c
@@ -37,13 +37,7 @@ struct _GeditSettings
GSettings *settings_file_chooser_state;
};
-enum
-{
- SIGNAL_FONTS_CHANGED,
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS];
+/* GeditSettings is a singleton. */
static GeditSettings *singleton = NULL;
G_DEFINE_TYPE (GeditSettings, gedit_settings, G_TYPE_OBJECT)
@@ -81,46 +75,92 @@ gedit_settings_class_init (GeditSettingsClass *klass)
object_class->dispose = gedit_settings_dispose;
object_class->finalize = gedit_settings_finalize;
+}
- /* This signal is emitted when the return value of
- * _gedit_settings_get_selected_font() has potentially changed.
- */
- signals[SIGNAL_FONTS_CHANGED] =
- g_signal_new ("fonts-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
+static void
+set_font (GeditSettings *self,
+ const gchar *font)
+{
+ guint tabs_size;
+ GList *views;
+ GList *l;
+
+ tabs_size = g_settings_get_uint (self->settings_editor, GEDIT_SETTINGS_TABS_SIZE);
+
+ views = gedit_app_get_views (GEDIT_APP (g_application_get_default ()));
+
+ for (l = views; l != NULL; l = l->next)
+ {
+ /* Note: we use def=FALSE to avoid GeditView to query dconf. */
+ gedit_view_set_font (GEDIT_VIEW (l->data), FALSE, font);
+
+ /* FIXME: setting the tab width seems unrelated to set_font(). */
+ gtk_source_view_set_tab_width (GTK_SOURCE_VIEW (l->data), tabs_size);
+ }
+
+ g_list_free (views);
}
static void
-system_font_changed_cb (GSettings *settings,
+on_system_font_changed (GSettings *settings,
const gchar *key,
GeditSettings *self)
{
- if (g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT))
+
+ gboolean use_default_font;
+
+ use_default_font = g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT);
+
+ if (use_default_font)
{
- g_signal_emit (self, signals[SIGNAL_FONTS_CHANGED], 0);
+ gchar *font;
+
+ font = g_settings_get_string (settings, key);
+ set_font (self, font);
+ g_free (font);
}
}
static void
-use_default_font_changed_cb (GSettings *settings,
+on_use_default_font_changed (GSettings *settings,
const gchar *key,
GeditSettings *self)
{
- g_signal_emit (self, signals[SIGNAL_FONTS_CHANGED], 0);
+ gboolean use_default_font;
+ gchar *font;
+
+ use_default_font = g_settings_get_boolean (settings, key);
+
+ if (use_default_font)
+ {
+ font = g_settings_get_string (self->settings_interface, GEDIT_SETTINGS_SYSTEM_FONT);
+ }
+ else
+ {
+ font = g_settings_get_string (self->settings_editor, GEDIT_SETTINGS_EDITOR_FONT);
+ }
+
+ set_font (self, font);
+
+ g_free (font);
}
static void
-editor_font_changed_cb (GSettings *settings,
+on_editor_font_changed (GSettings *settings,
const gchar *key,
GeditSettings *self)
{
- if (!g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT))
+ gboolean use_default_font;
+
+ use_default_font = g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT);
+
+ if (!use_default_font)
{
- g_signal_emit (self, signals[SIGNAL_FONTS_CHANGED], 0);
+ gchar *font;
+
+ font = g_settings_get_string (settings, key);
+ set_font (self, font);
+ g_free (font);
}
}
@@ -207,47 +247,43 @@ on_syntax_highlighting_changed (GSettings *settings,
static void
gedit_settings_init (GeditSettings *self)
{
- self->settings_interface = g_settings_new ("org.gnome.desktop.interface");
-
self->settings_editor = g_settings_new ("org.gnome.gedit.preferences.editor");
self->settings_ui = g_settings_new ("org.gnome.gedit.preferences.ui");
self->settings_file_chooser_state = g_settings_new ("org.gnome.gedit.state.file-chooser");
- g_signal_connect_object (self->settings_interface,
- "changed::" GEDIT_SETTINGS_SYSTEM_FONT,
- G_CALLBACK (system_font_changed_cb),
- self,
- 0);
-
- g_signal_connect_object (self->settings_editor,
- "changed::" GEDIT_SETTINGS_USE_DEFAULT_FONT,
- G_CALLBACK (use_default_font_changed_cb),
- self,
- 0);
-
- g_signal_connect_object (self->settings_editor,
- "changed::" GEDIT_SETTINGS_EDITOR_FONT,
- G_CALLBACK (editor_font_changed_cb),
- self,
- 0);
-
- g_signal_connect_object (self->settings_editor,
- "changed::auto-save",
- G_CALLBACK (on_auto_save_changed),
- self,
- 0);
-
- g_signal_connect_object (self->settings_editor,
- "changed::auto-save-interval",
- G_CALLBACK (on_auto_save_interval_changed),
- self,
- 0);
-
- g_signal_connect_object (self->settings_editor,
- "changed::syntax-highlighting",
- G_CALLBACK (on_syntax_highlighting_changed),
- self,
- 0);
+ self->settings_interface = g_settings_new ("org.gnome.desktop.interface");
+
+ g_signal_connect (self->settings_interface,
+ "changed::monospace-font-name",
+ G_CALLBACK (on_system_font_changed),
+ self);
+
+ /* editor changes */
+
+ g_signal_connect (self->settings_editor,
+ "changed::use-default-font",
+ G_CALLBACK (on_use_default_font_changed),
+ self);
+
+ g_signal_connect (self->settings_editor,
+ "changed::editor-font",
+ G_CALLBACK (on_editor_font_changed),
+ self);
+
+ g_signal_connect (self->settings_editor,
+ "changed::auto-save",
+ G_CALLBACK (on_auto_save_changed),
+ self);
+
+ g_signal_connect (self->settings_editor,
+ "changed::auto-save-interval",
+ G_CALLBACK (on_auto_save_interval_changed),
+ self);
+
+ g_signal_connect (self->settings_editor,
+ "changed::syntax-highlighting",
+ G_CALLBACK (on_syntax_highlighting_changed),
+ self);
}
GeditSettings *
@@ -292,24 +328,11 @@ _gedit_settings_peek_file_chooser_state_settings (GeditSettings *self)
}
gchar *
-_gedit_settings_get_system_font (GeditSettings *self)
+gedit_settings_get_system_font (GeditSettings *self)
{
g_return_val_if_fail (GEDIT_IS_SETTINGS (self), NULL);
- return g_settings_get_string (self->settings_interface, GEDIT_SETTINGS_SYSTEM_FONT);
-}
-
-gchar *
-_gedit_settings_get_selected_font (GeditSettings *self)
-{
- g_return_val_if_fail (GEDIT_IS_SETTINGS (self), NULL);
-
- if (g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT))
- {
- return _gedit_settings_get_system_font (self);
- }
-
- return g_settings_get_string (self->settings_editor, GEDIT_SETTINGS_EDITOR_FONT);
+ return g_settings_get_string (self->settings_interface, "monospace-font-name");
}
static gboolean
diff --git a/gedit/gedit-settings.h b/gedit/gedit-settings.h
index a7993d5d1..a2fe9e47b 100644
--- a/gedit/gedit-settings.h
+++ b/gedit/gedit-settings.h
@@ -43,11 +43,7 @@ GSettings * _gedit_settings_peek_editor_settings (GeditSettings *self);
G_GNUC_INTERNAL
GSettings * _gedit_settings_peek_file_chooser_state_settings (GeditSettings *self);
-G_GNUC_INTERNAL
-gchar * _gedit_settings_get_system_font (GeditSettings *self);
-
-G_GNUC_INTERNAL
-gchar * _gedit_settings_get_selected_font (GeditSettings *self);
+gchar * gedit_settings_get_system_font (GeditSettings *self);
GSList * gedit_settings_get_candidate_encodings (gboolean *default_candidates);
@@ -73,6 +69,7 @@ GSList * gedit_settings_get_candidate_encodings (gboolean
*default_candidates)
#define GEDIT_SETTINGS_RESTORE_CURSOR_POSITION "restore-cursor-position"
#define GEDIT_SETTINGS_SYNTAX_HIGHLIGHTING "syntax-highlighting"
#define GEDIT_SETTINGS_SEARCH_HIGHLIGHTING "search-highlighting"
+#define GEDIT_SETTINGS_DISPLAY_OVERVIEW_MAP "display-overview-map"
#define GEDIT_SETTINGS_BACKGROUND_PATTERN "background-pattern"
#define GEDIT_SETTINGS_STATUSBAR_VISIBLE "statusbar-visible"
#define GEDIT_SETTINGS_SIDE_PANEL_VISIBLE "side-panel-visible"
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index 8bff54690..45e80c828 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -24,7 +24,6 @@
#include <stdlib.h>
#include <glib/gi18n.h>
-#include <tepl/tepl.h>
#include "gedit-app.h"
#include "gedit-app-private.h"
@@ -33,6 +32,7 @@
#include "gedit-io-error-info-bar.h"
#include "gedit-print-job.h"
#include "gedit-print-preview.h"
+#include "gedit-progress-info-bar.h"
#include "gedit-debug.h"
#include "gedit-document.h"
#include "gedit-document-private.h"
@@ -577,9 +577,9 @@ document_location_notify_handler (GtkSourceFile *file,
}
static void
-document_shortname_notify_handler (TeplFile *file,
- GParamSpec *pspec,
- GeditTab *tab)
+document_shortname_notify_handler (GeditDocument *document,
+ GParamSpec *pspec,
+ GeditTab *tab)
{
gedit_debug (DEBUG_TAB);
@@ -737,7 +737,7 @@ load_cancelled (GtkWidget *bar,
{
LoaderData *data = g_task_get_task_data (loading_task);
- g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (data->tab->info_bar));
+ g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (data->tab->info_bar));
g_cancellable_cancel (g_task_get_cancellable (loading_task));
remove_tab (data->tab);
@@ -768,7 +768,7 @@ static void
show_loading_info_bar (GTask *loading_task)
{
LoaderData *data = g_task_get_task_data (loading_task);
- TeplProgressInfoBar *bar;
+ GtkWidget *bar;
GeditDocument *doc;
gchar *name;
gchar *dirname = NULL;
@@ -796,7 +796,7 @@ show_loading_info_bar (GTask *loading_task)
{
gchar *str;
- str = tepl_utils_str_middle_truncate (name, MAX_MSG_LENGTH);
+ str = gedit_utils_str_middle_truncate (name, MAX_MSG_LENGTH);
g_free (name);
name = str;
}
@@ -815,8 +815,8 @@ show_loading_info_bar (GTask *loading_task)
* we have a title long 99 + 20, but I think it's a rare enough
* case to be acceptable. It's justa darn title afterall :)
*/
- dirname = tepl_utils_str_middle_truncate (str,
- MAX (20, MAX_MSG_LENGTH - len));
+ dirname = gedit_utils_str_middle_truncate (str,
+ MAX (20, MAX_MSG_LENGTH - len));
g_free (str);
}
}
@@ -841,7 +841,7 @@ show_loading_info_bar (GTask *loading_task)
msg = g_strdup_printf (_("Reverting %s"), name_markup);
}
- bar = tepl_progress_info_bar_new ("document-revert", msg, TRUE);
+ bar = gedit_progress_info_bar_new ("document-revert", msg, TRUE);
}
else
{
@@ -861,7 +861,7 @@ show_loading_info_bar (GTask *loading_task)
msg = g_strdup_printf (_("Loading %s"), name_markup);
}
- bar = tepl_progress_info_bar_new ("document-open", msg, TRUE);
+ bar = gedit_progress_info_bar_new ("document-open", msg, TRUE);
}
g_signal_connect_object (bar,
@@ -870,7 +870,7 @@ show_loading_info_bar (GTask *loading_task)
loading_task,
0);
- set_info_bar (data->tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
+ set_info_bar (data->tab, bar, GTK_RESPONSE_NONE);
g_free (msg);
g_free (name);
@@ -882,7 +882,7 @@ static void
show_saving_info_bar (GTask *saving_task)
{
GeditTab *tab = g_task_get_source_object (saving_task);
- TeplProgressInfoBar *bar;
+ GtkWidget *bar;
GeditDocument *doc;
gchar *short_name;
gchar *from;
@@ -910,7 +910,7 @@ show_saving_info_bar (GTask *saving_task)
*/
if (len > MAX_MSG_LENGTH)
{
- from = tepl_utils_str_middle_truncate (short_name, MAX_MSG_LENGTH);
+ from = gedit_utils_str_middle_truncate (short_name, MAX_MSG_LENGTH);
g_free (short_name);
}
else
@@ -924,7 +924,7 @@ show_saving_info_bar (GTask *saving_task)
from = short_name;
to = g_file_get_parse_name (location);
- str = tepl_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len));
+ str = gedit_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len));
g_free (to);
to = str;
@@ -946,9 +946,9 @@ show_saving_info_bar (GTask *saving_task)
msg = g_strdup_printf (_("Saving %s"), from_markup);
}
- bar = tepl_progress_info_bar_new ("document-save", msg, FALSE);
+ bar = gedit_progress_info_bar_new ("document-save", msg, FALSE);
- set_info_bar (tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
+ set_info_bar (tab, bar, GTK_RESPONSE_NONE);
g_free (msg);
g_free (to);
@@ -961,7 +961,7 @@ info_bar_set_progress (GeditTab *tab,
goffset size,
goffset total_size)
{
- TeplProgressInfoBar *progress_info_bar;
+ GeditProgressInfoBar *progress_info_bar;
if (tab->info_bar == NULL)
{
@@ -970,23 +970,23 @@ info_bar_set_progress (GeditTab *tab,
gedit_debug_message (DEBUG_TAB, "%" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT, size, total_size);
- g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (tab->info_bar));
+ g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (tab->info_bar));
- progress_info_bar = TEPL_PROGRESS_INFO_BAR (tab->info_bar);
+ progress_info_bar = GEDIT_PROGRESS_INFO_BAR (tab->info_bar);
if (total_size != 0)
{
gdouble frac = (gdouble)size / (gdouble)total_size;
- tepl_progress_info_bar_set_fraction (progress_info_bar, frac);
+ gedit_progress_info_bar_set_fraction (progress_info_bar, frac);
}
else if (size != 0)
{
- tepl_progress_info_bar_pulse (progress_info_bar);
+ gedit_progress_info_bar_pulse (progress_info_bar);
}
else
{
- tepl_progress_info_bar_set_fraction (progress_info_bar, 0);
+ gedit_progress_info_bar_set_fraction (progress_info_bar, 0);
}
}
@@ -1045,7 +1045,7 @@ scroll_to_cursor (GeditTab *tab)
GeditView *view;
view = gedit_tab_get_view (tab);
- tepl_view_scroll_to_cursor (TEPL_VIEW (view));
+ gedit_view_scroll_to_cursor (view);
tab->idle_scroll = 0;
return G_SOURCE_REMOVE;
@@ -1129,9 +1129,9 @@ invalid_character_info_bar_response (GtkWidget *info_bar,
}
static void
-cant_create_backup_error_info_bar_response (GtkWidget *info_bar,
- gint response_id,
- GTask *saving_task)
+no_backup_error_info_bar_response (GtkWidget *info_bar,
+ gint response_id,
+ GTask *saving_task)
{
if (response_id == GTK_RESPONSE_YES)
{
@@ -1237,7 +1237,7 @@ externally_modified_notification_info_bar_response (GtkWidget *info_bar,
static void
display_externally_modified_notification (GeditTab *tab)
{
- TeplInfoBar *info_bar;
+ GtkWidget *info_bar;
GeditDocument *doc;
GtkSourceFile *file;
GFile *location;
@@ -1251,9 +1251,9 @@ display_externally_modified_notification (GeditTab *tab)
g_return_if_fail (location != NULL);
document_modified = gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc));
- info_bar = tepl_io_error_info_bar_externally_modified (location, document_modified);
+ info_bar = gedit_externally_modified_info_bar_new (location, document_modified);
- set_info_bar (tab, GTK_WIDGET (info_bar), GTK_RESPONSE_OK);
+ set_info_bar (tab, info_bar, GTK_RESPONSE_OK);
g_signal_connect (info_bar,
"response",
@@ -1318,7 +1318,6 @@ gedit_tab_init (GeditTab *tab)
GeditDocument *doc;
GeditView *view;
GtkSourceFile *file;
- TeplFile *tepl_file;
tab->state = GEDIT_TAB_STATE_NORMAL;
@@ -1349,7 +1348,6 @@ gedit_tab_init (GeditTab *tab)
g_object_set_data (G_OBJECT (doc), GEDIT_TAB_KEY, tab);
file = gedit_document_get_file (doc);
- tepl_file = tepl_buffer_get_file (TEPL_BUFFER (doc));
g_signal_connect_object (file,
"notify::location",
@@ -1357,11 +1355,10 @@ gedit_tab_init (GeditTab *tab)
tab,
0);
- g_signal_connect_object (tepl_file,
- "notify::short-name",
- G_CALLBACK (document_shortname_notify_handler),
- tab,
- 0);
+ g_signal_connect (doc,
+ "notify::shortname",
+ G_CALLBACK (document_shortname_notify_handler),
+ tab);
g_signal_connect (doc,
"modified_changed",
@@ -1445,7 +1442,7 @@ _gedit_tab_get_name (GeditTab *tab)
name = gedit_document_get_short_name_for_display (doc);
/* Truncate the name so it doesn't get insanely wide. */
- docname = tepl_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
+ docname = gedit_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
{
@@ -1478,7 +1475,7 @@ _gedit_tab_get_tooltip (GeditTab *tab)
uri = _gedit_document_get_uri_for_display (doc);
g_return_val_if_fail (uri != NULL, NULL);
- ruri = tepl_utils_replace_home_dir_with_tilde (uri);
+ ruri = gedit_utils_replace_home_dir_with_tilde (uri);
g_free (uri);
ruri_markup = g_markup_printf_escaped ("<i>%s</i>", ruri);
@@ -1644,11 +1641,9 @@ goto_line (GTask *loading_task)
/* Move the cursor at the requested line if any. */
if (data->line_pos > 0)
{
- TeplView *view = TEPL_VIEW (gedit_tab_get_view (data->tab));
-
- tepl_view_goto_line_offset (view,
- data->line_pos - 1,
- MAX (0, data->column_pos - 1));
+ gedit_document_goto_line_offset (doc,
+ data->line_pos - 1,
+ MAX (0, data->column_pos - 1));
return;
}
@@ -1764,18 +1759,18 @@ successful_load (GTask *loading_task)
if (!gtk_source_file_is_readonly (file) &&
file_already_opened (doc, location))
{
- TeplInfoBar *info_bar;
+ GtkWidget *info_bar;
set_editable (data->tab, FALSE);
- info_bar = tepl_io_error_info_bar_file_already_open (location);
+ info_bar = gedit_file_already_open_warning_info_bar_new (location);
g_signal_connect (info_bar,
"response",
G_CALLBACK (file_already_open_warning_info_bar_response),
data->tab);
- set_info_bar (data->tab, GTK_WIDGET (info_bar), GTK_RESPONSE_CANCEL);
+ set_info_bar (data->tab, info_bar, GTK_RESPONSE_CANCEL);
}
/* When loading from stdin, the contents may not be saved, so set the
@@ -2406,12 +2401,12 @@ save_cb (GtkSourceFileSaver *saver,
error->code == G_IO_ERROR_CANT_CREATE_BACKUP)
{
/* This error is recoverable */
- info_bar = GTK_WIDGET (tepl_io_error_info_bar_cant_create_backup (location, error));
+ info_bar = gedit_no_backup_saving_error_info_bar_new (location, error);
g_return_if_fail (info_bar != NULL);
g_signal_connect (info_bar,
"response",
- G_CALLBACK (cant_create_backup_error_info_bar_response),
+ G_CALLBACK (no_backup_error_info_bar_response),
saving_task);
}
else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
@@ -2420,7 +2415,7 @@ save_cb (GtkSourceFileSaver *saver,
/* If we have any invalid char in the document we must warn the user
* as it can make the document useless if it is saved.
*/
- info_bar = GTK_WIDGET (tepl_io_error_info_bar_invalid_characters (location));
+ info_bar = gedit_invalid_character_info_bar_new (location);
g_return_if_fail (info_bar != NULL);
g_signal_connect (info_bar,
@@ -2802,15 +2797,15 @@ printing_cb (GeditPrintJob *job,
GeditPrintJobStatus status,
GeditTab *tab)
{
- g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (tab->info_bar));
+ g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (tab->info_bar));
gtk_widget_show (tab->info_bar);
- tepl_progress_info_bar_set_text (TEPL_PROGRESS_INFO_BAR (tab->info_bar),
- gedit_print_job_get_status_string (job));
+ gedit_progress_info_bar_set_text (GEDIT_PROGRESS_INFO_BAR (tab->info_bar),
+ gedit_print_job_get_status_string (job));
- tepl_progress_info_bar_set_fraction (TEPL_PROGRESS_INFO_BAR (tab->info_bar),
- gedit_print_job_get_progress (job));
+ gedit_progress_info_bar_set_fraction (GEDIT_PROGRESS_INFO_BAR (tab->info_bar),
+ gedit_print_job_get_progress (job));
}
static void
@@ -2920,19 +2915,21 @@ print_cancelled (GtkWidget *bar,
static void
add_printing_info_bar (GeditTab *tab)
{
- TeplProgressInfoBar *bar;
+ GtkWidget *bar;
- bar = tepl_progress_info_bar_new ("document-print", NULL, TRUE);
+ bar = gedit_progress_info_bar_new ("document-print",
+ "",
+ TRUE);
g_signal_connect (bar,
"response",
G_CALLBACK (print_cancelled),
tab);
- set_info_bar (tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
+ set_info_bar (tab, bar, GTK_RESPONSE_NONE);
/* hide until we start printing */
- gtk_widget_hide (GTK_WIDGET (bar));
+ gtk_widget_hide (bar);
}
void
diff --git a/gedit/gedit-utils.c b/gedit/gedit-utils.c
index 9fc9e4fb0..ae7e92156 100644
--- a/gedit/gedit-utils.c
+++ b/gedit/gedit-utils.c
@@ -23,7 +23,6 @@
#include "gedit-utils.h"
#include <string.h>
#include <glib/gi18n.h>
-#include <tepl/tepl.h>
#include "gedit-debug.h"
gboolean
@@ -87,6 +86,122 @@ gedit_utils_set_atk_name_description (GtkWidget *widget,
atk_object_set_description (aobj, description);
}
+void
+gedit_warning (GtkWindow *parent, const gchar *format, ...)
+{
+ va_list args;
+ gchar *str;
+ GtkWidget *dialog;
+ GtkWindowGroup *wg = NULL;
+
+ g_return_if_fail (format != NULL);
+
+ if (parent != NULL)
+ wg = gtk_window_get_group (parent);
+
+ va_start (args, format);
+ str = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ dialog = gtk_message_dialog_new_with_markup (
+ parent,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", str);
+
+ g_free (str);
+
+ if (wg != NULL)
+ gtk_window_group_add_window (wg, GTK_WINDOW (dialog));
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+ g_signal_connect (G_OBJECT (dialog),
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+
+ gtk_widget_show (dialog);
+}
+
+/* the following functions are taken from eel */
+
+static gchar *
+gedit_utils_str_truncate (const gchar *string,
+ guint truncate_length,
+ gboolean middle)
+{
+ GString *truncated;
+ guint length;
+ guint n_chars;
+ guint num_left_chars;
+ guint right_offset;
+ guint delimiter_length;
+ const gchar *delimiter = "\342\200\246";
+
+ g_return_val_if_fail (string != NULL, NULL);
+
+ length = strlen (string);
+
+ g_return_val_if_fail (g_utf8_validate (string, length, NULL), NULL);
+
+ /* It doesnt make sense to truncate strings to less than
+ * the size of the delimiter plus 2 characters (one on each
+ * side)
+ */
+ delimiter_length = g_utf8_strlen (delimiter, -1);
+ if (truncate_length < (delimiter_length + 2))
+ {
+ return g_strdup (string);
+ }
+
+ n_chars = g_utf8_strlen (string, length);
+
+ /* Make sure the string is not already small enough. */
+ if (n_chars <= truncate_length)
+ {
+ return g_strdup (string);
+ }
+
+ /* Find the 'middle' where the truncation will occur. */
+ if (middle)
+ {
+ num_left_chars = (truncate_length - delimiter_length) / 2;
+ right_offset = n_chars - truncate_length + num_left_chars + delimiter_length;
+
+ truncated = g_string_new_len (string,
+ g_utf8_offset_to_pointer (string, num_left_chars) - string);
+ g_string_append (truncated, delimiter);
+ g_string_append (truncated, g_utf8_offset_to_pointer (string, right_offset));
+ }
+ else
+ {
+ num_left_chars = truncate_length - delimiter_length;
+ truncated = g_string_new_len (string,
+ g_utf8_offset_to_pointer (string, num_left_chars) - string);
+ g_string_append (truncated, delimiter);
+ }
+
+ return g_string_free (truncated, FALSE);
+}
+
+gchar *
+gedit_utils_str_middle_truncate (const gchar *string,
+ guint truncate_length)
+{
+ return gedit_utils_str_truncate (string, truncate_length, TRUE);
+}
+
+gchar *
+gedit_utils_str_end_truncate (const gchar *string,
+ guint truncate_length)
+{
+ return gedit_utils_str_truncate (string, truncate_length, FALSE);
+}
+
static gchar *
uri_get_dirname (const gchar *uri)
{
@@ -106,7 +221,7 @@ uri_get_dirname (const gchar *uri)
return NULL;
}
- res = tepl_utils_replace_home_dir_with_tilde (str);
+ res = gedit_utils_replace_home_dir_with_tilde (str);
g_free (str);
@@ -149,10 +264,10 @@ gedit_utils_location_get_dirname_for_display (GFile *location)
g_object_unref (mount);
/* obtain the "path" part of the uri */
- tepl_utils_decode_uri (uri,
- NULL, NULL,
- NULL, NULL,
- &path);
+ gedit_utils_decode_uri (uri,
+ NULL, NULL,
+ NULL, NULL,
+ &path);
if (path == NULL)
{
@@ -187,6 +302,51 @@ gedit_utils_location_get_dirname_for_display (GFile *location)
return res;
}
+gchar *
+gedit_utils_replace_home_dir_with_tilde (const gchar *uri)
+{
+ gchar *tmp;
+ gchar *home;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ /* Note that g_get_home_dir returns a const string */
+ tmp = (gchar *)g_get_home_dir ();
+
+ if (tmp == NULL)
+ return g_strdup (uri);
+
+ home = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
+ if (home == NULL)
+ return g_strdup (uri);
+
+ if (strcmp (uri, home) == 0)
+ {
+ g_free (home);
+
+ return g_strdup ("~/");
+ }
+
+ tmp = home;
+ home = g_strdup_printf ("%s/", tmp);
+ g_free (tmp);
+
+ if (g_str_has_prefix (uri, home))
+ {
+ gchar *res;
+
+ res = g_strdup_printf ("~/%s", uri + strlen (home));
+
+ g_free (home);
+
+ return res;
+ }
+
+ g_free (home);
+
+ return g_strdup (uri);
+}
+
static gboolean
is_valid_scheme_character (gchar c)
{
@@ -353,7 +513,7 @@ gedit_utils_basename_for_display (GFile *location)
}
}
else if (g_file_has_parent (location, NULL) ||
- !tepl_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
+ !gedit_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
{
/* For remote files with a parent (so not just http://foo.com)
or remote file for which the decoding of the host name fails,
@@ -438,6 +598,165 @@ gedit_utils_drop_get_uris (GtkSelectionData *selection_data)
return uri_list;
}
+static void
+null_ptr (gchar **ptr)
+{
+ if (ptr)
+ *ptr = NULL;
+}
+
+/**
+ * gedit_utils_decode_uri:
+ * @uri: the uri to decode
+ * @scheme: (out) (allow-none): return value pointer for the uri's
+ * scheme (e.g. http, sftp, ...), or %NULL
+ * @user: (out) (allow-none): return value pointer for the uri user info, or %NULL
+ * @port: (out) (allow-none): return value pointer for the uri port, or %NULL
+ * @host: (out) (allow-none): return value pointer for the uri host, or %NULL
+ * @path: (out) (allow-none): return value pointer for the uri path, or %NULL
+ *
+ * Parse and break an uri apart in its individual components like the uri
+ * scheme, user info, port, host and path. The return value pointer can be
+ * %NULL to ignore certain parts of the uri. If the function returns %TRUE, then
+ * all return value pointers should be freed using g_free
+ *
+ * Return value: %TRUE if the uri could be properly decoded, %FALSE otherwise.
+ */
+gboolean
+gedit_utils_decode_uri (const gchar *uri,
+ gchar **scheme,
+ gchar **user,
+ gchar **host,
+ gchar **port,
+ gchar **path)
+{
+ /* Largely copied from glib/gio/gdummyfile.c:_g_decode_uri. This
+ * functionality should be in glib/gio, but for now we implement it
+ * ourselves (see bug #546182) */
+
+ const char *p, *in, *hier_part_start, *hier_part_end;
+ char *out;
+ char c;
+
+ /* From RFC 3986 Decodes:
+ * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+ */
+
+ p = uri;
+
+ null_ptr (scheme);
+ null_ptr (user);
+ null_ptr (port);
+ null_ptr (host);
+ null_ptr (path);
+
+ /* Decode scheme:
+ * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ */
+
+ if (!g_ascii_isalpha (*p))
+ return FALSE;
+
+ while (1)
+ {
+ c = *p++;
+
+ if (c == ':')
+ break;
+
+ if (!(g_ascii_isalnum(c) ||
+ c == '+' ||
+ c == '-' ||
+ c == '.'))
+ {
+ return FALSE;
+ }
+ }
+
+ if (scheme)
+ {
+ *scheme = g_malloc (p - uri);
+ out = *scheme;
+
+ for (in = uri; in < p - 1; in++)
+ {
+ *out++ = g_ascii_tolower (*in);
+ }
+
+ *out = '\0';
+ }
+
+ hier_part_start = p;
+ hier_part_end = p + strlen (p);
+
+ if (hier_part_start[0] == '/' && hier_part_start[1] == '/')
+ {
+ const char *authority_start, *authority_end;
+ const char *userinfo_start, *userinfo_end;
+ const char *host_start, *host_end;
+ const char *port_start;
+
+ authority_start = hier_part_start + 2;
+ /* authority is always followed by / or nothing */
+ authority_end = memchr (authority_start, '/', hier_part_end - authority_start);
+
+ if (authority_end == NULL)
+ authority_end = hier_part_end;
+
+ /* 3.2:
+ * authority = [ userinfo "@" ] host [ ":" port ]
+ */
+
+ userinfo_end = memchr (authority_start, '@', authority_end - authority_start);
+
+ if (userinfo_end)
+ {
+ userinfo_start = authority_start;
+
+ if (user)
+ *user = g_uri_unescape_segment (userinfo_start, userinfo_end, NULL);
+
+ if (user && *user == NULL)
+ {
+ if (scheme)
+ g_free (*scheme);
+
+ return FALSE;
+ }
+
+ host_start = userinfo_end + 1;
+ }
+ else
+ {
+ host_start = authority_start;
+ }
+
+ port_start = memchr (host_start, ':', authority_end - host_start);
+
+ if (port_start)
+ {
+ host_end = port_start++;
+
+ if (port)
+ *port = g_strndup (port_start, authority_end - port_start);
+ }
+ else
+ {
+ host_end = authority_end;
+ }
+
+ if (host)
+ *host = g_strndup (host_start, host_end - host_start);
+
+ hier_part_start = authority_end;
+ }
+
+ if (path)
+ *path = g_uri_unescape_segment (hier_part_start, hier_part_end, "/");
+
+ return TRUE;
+}
+
GtkSourceCompressionType
gedit_utils_get_compression_type_from_content_type (const gchar *content_type)
{
diff --git a/gedit/gedit-utils.h b/gedit/gedit-utils.h
index a6b423db0..64af070d2 100644
--- a/gedit/gedit-utils.h
+++ b/gedit/gedit-utils.h
@@ -27,19 +27,38 @@
G_BEGIN_DECLS
+/* useful macro */
+#define GBOOLEAN_TO_POINTER(i) (GINT_TO_POINTER ((i) ? 2 : 1))
+#define GPOINTER_TO_BOOLEAN(i) ((gboolean) ((GPOINTER_TO_INT(i) == 2) ? TRUE : FALSE))
+
gboolean gedit_utils_menu_position_under_tree_view (GtkTreeView *tree_view,
GdkRectangle *rect);
+gchar *gedit_utils_str_middle_truncate (const gchar *string,
+ guint
truncate_length);
+gchar *gedit_utils_str_end_truncate (const gchar *string,
+ guint
truncate_length);
void gedit_utils_set_atk_name_description (GtkWidget *widget,
const gchar *name,
const gchar *description);
+void gedit_warning (GtkWindow *parent,
+ const gchar *format,
+ ...) G_GNUC_PRINTF(2, 3);
-gchar *gedit_utils_location_get_dirname_for_display (GFile *location);
+gchar *gedit_utils_location_get_dirname_for_display (GFile *location);
+gchar *gedit_utils_replace_home_dir_with_tilde (const gchar *uri);
gboolean gedit_utils_is_valid_location (GFile *location);
gchar *gedit_utils_basename_for_display (GFile *location);
+gboolean gedit_utils_decode_uri (const gchar *uri,
+ gchar **scheme,
+ gchar **user,
+ gchar **host,
+ gchar **port,
+ gchar **path);
+
/* Turns data from a drop into a list of well formatted uris */
gchar **gedit_utils_drop_get_uris (GtkSelectionData
*selection_data);
diff --git a/gedit/gedit-view-centering.c b/gedit/gedit-view-centering.c
new file mode 100644
index 000000000..f9c742076
--- /dev/null
+++ b/gedit/gedit-view-centering.c
@@ -0,0 +1,495 @@
+/*
+ * gedit-view-centering.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Sébastien Lafargue
+ *
+ * Gedit is free software; you can redistribute this file and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Gedit 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Based on Christian Hergert's prototype.
+ */
+
+#include "gedit-view-centering.h"
+
+#include <gtksourceview/gtksource.h>
+
+#include "gedit-view.h"
+#include "gedit-debug.h"
+
+struct _GeditViewCenteringPrivate
+{
+ GtkWidget *box;
+ GtkWidget *scrolled_window;
+ GtkWidget *sourceview;
+ GtkWidget *spacer;
+
+ GtkStyleContext *view_context;
+ GdkRGBA view_background;
+ GdkRGBA view_line_margin_fg;
+ GdkRGBA view_margin_background;
+ guint view_text_width;
+
+ guint centered : 1;
+ guint view_background_set : 1;
+ guint view_line_margin_fg_set : 1;
+ guint view_margin_background_set : 1;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GeditViewCentering, gedit_view_centering, GTK_TYPE_BIN)
+
+#define STYLE_TEXT "text"
+#define STYLE_RIGHT_MARGIN "right-margin"
+
+#define RIGHT_MARGIN_LINE_ALPHA 40
+#define RIGHT_MARGIN_OVERLAY_ALPHA 15
+
+static gboolean
+get_style (GtkSourceStyleScheme *scheme,
+ const gchar *style_id,
+ const gchar *attribute,
+ GdkRGBA *color)
+{
+ GtkSourceStyle *style;
+ gchar *style_string;
+
+ style = gtk_source_style_scheme_get_style (scheme, style_id);
+ if (!style)
+ {
+ return FALSE;
+ }
+
+ g_object_get (style, attribute, &style_string, NULL);
+ if (style_string)
+ {
+ gdk_rgba_parse (color, style_string);
+ g_free (style_string);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+get_spacer_colors (GeditViewCentering *container,
+ GtkSourceStyleScheme *scheme)
+{
+ GeditViewCenteringPrivate *priv = container->priv;
+
+ if (scheme)
+ {
+ priv->view_background_set = get_style (scheme,
+ STYLE_TEXT, "background",
+ &priv->view_background);
+
+ priv->view_line_margin_fg_set = get_style (scheme,
+ STYLE_RIGHT_MARGIN, "foreground",
+ &priv->view_line_margin_fg);
+ priv->view_line_margin_fg.alpha = RIGHT_MARGIN_LINE_ALPHA / 255.0;
+
+ priv->view_margin_background_set = get_style (scheme,
+ STYLE_RIGHT_MARGIN, "background",
+ &priv->view_margin_background);
+ priv->view_margin_background.alpha = RIGHT_MARGIN_OVERLAY_ALPHA / 255.0;
+ }
+}
+
+/* FIXME: when GeditViewCentering will be transfered to GtkSourceView,
+ * this method will be replaced by a call to a new method called
+ * gtk_source_view_get_right_margin_pixel_position ()
+ */
+static guint
+_gedit_view_centering_get_right_margin_pixel_position (GeditViewCentering *container)
+{
+ GeditViewCenteringPrivate *priv;
+ gchar *str;
+ PangoFontDescription *font_desc;
+ PangoLayout *layout;
+ guint right_margin_position;
+ gint width = 0;
+
+ g_return_val_if_fail (GEDIT_IS_VIEW_CENTERING (container), 0);
+
+ priv = container->priv;
+
+ right_margin_position = gtk_source_view_get_right_margin_position (GTK_SOURCE_VIEW
(priv->sourceview));
+
+ gtk_style_context_save (priv->view_context);
+ gtk_style_context_set_state (priv->view_context, GTK_STATE_FLAG_NORMAL);
+ gtk_style_context_get (priv->view_context,
+ gtk_style_context_get_state (priv->view_context),
+ GTK_STYLE_PROPERTY_FONT, &font_desc,
+ NULL);
+ gtk_style_context_restore (priv->view_context);
+
+ str = g_strnfill (right_margin_position, '_');
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (priv->sourceview), str);
+ g_free (str);
+
+ pango_layout_set_font_description (layout, font_desc);
+ pango_font_description_free (font_desc);
+ pango_layout_get_pixel_size (layout, &width, NULL);
+
+ g_object_unref (G_OBJECT (layout));
+
+ return width;
+}
+
+static void
+on_view_right_margin_visibility_changed (GeditView *view,
+ GParamSpec *pspec,
+ GeditViewCentering *container)
+{
+ GeditViewCenteringPrivate *priv = container->priv;
+ gboolean visibility;
+
+ visibility = gtk_source_view_get_show_right_margin (GTK_SOURCE_VIEW (priv->sourceview));
+
+ gtk_widget_set_visible (GTK_WIDGET (container->priv->spacer), visibility && priv->centered);
+}
+
+static void
+on_view_right_margin_position_changed (GeditView *view,
+ GParamSpec *pspec,
+ GeditViewCentering *container)
+{
+ GeditViewCenteringPrivate *priv = container->priv;
+ gboolean visibility;
+
+ priv->view_text_width = _gedit_view_centering_get_right_margin_pixel_position (container);
+
+ visibility = gtk_source_view_get_show_right_margin (GTK_SOURCE_VIEW (priv->sourceview));
+
+ if (visibility)
+ {
+ gtk_widget_queue_resize (priv->spacer);
+ }
+}
+
+static void
+on_view_context_changed (GtkStyleContext *stylecontext,
+ GeditViewCentering *container)
+{
+ GeditViewCenteringPrivate *priv = container->priv;
+ GtkTextBuffer *buffer;
+ GtkSourceStyleScheme *scheme;
+ gboolean visibility;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->sourceview));
+ scheme = gtk_source_buffer_get_style_scheme (GTK_SOURCE_BUFFER (buffer));
+ get_spacer_colors (container, scheme);
+
+ priv->view_text_width = _gedit_view_centering_get_right_margin_pixel_position (container);
+
+ visibility = gtk_source_view_get_show_right_margin (GTK_SOURCE_VIEW (priv->sourceview));
+
+ if (visibility)
+ {
+ gtk_widget_queue_resize (priv->spacer);
+ }
+}
+
+static gboolean
+on_spacer_draw (GeditViewCentering *container,
+ cairo_t *cr,
+ GtkDrawingArea *spacer)
+{
+ GeditViewCenteringPrivate *priv = container->priv;
+ GtkStyleContext *context;
+ guint width, height;
+
+ if (!container->priv->sourceview)
+ {
+ return FALSE;
+ }
+
+ width = gtk_widget_get_allocated_width (GTK_WIDGET (spacer));
+ height = gtk_widget_get_allocated_height (GTK_WIDGET (spacer));
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (spacer));
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
+ gtk_render_background (context, cr, 0, 0, width, height);
+ gtk_style_context_restore (context);
+
+ cairo_set_line_width (cr, 1.0);
+
+ if (priv->view_background_set)
+ {
+ gdk_cairo_set_source_rgba (cr, &container->priv->view_background);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+ }
+
+ if (priv->view_margin_background_set)
+ {
+ gdk_cairo_set_source_rgba (cr, &container->priv->view_margin_background);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+ }
+
+ if (priv->view_line_margin_fg_set)
+ {
+ gdk_cairo_set_source_rgba (cr, &container->priv->view_line_margin_fg);
+ cairo_move_to (cr, width - 0.5, 0);
+ cairo_line_to (cr, width - 0.5, height);
+ cairo_stroke (cr);
+ }
+
+ return FALSE;
+}
+
+static void
+gedit_view_centering_remove (GtkContainer *container,
+ GtkWidget *child)
+{
+ GeditViewCenteringPrivate *priv;
+
+ g_assert (GEDIT_IS_VIEW_CENTERING (container));
+
+ priv = GEDIT_VIEW_CENTERING (container)->priv;
+
+ if (priv->sourceview == child)
+ {
+ gtk_container_remove (GTK_CONTAINER (priv->scrolled_window), priv->sourceview);
+ g_object_remove_weak_pointer (G_OBJECT (priv->sourceview), (gpointer *)&priv->sourceview);
+ priv->sourceview = NULL;
+ priv->view_context = NULL;
+ }
+ else
+ {
+ GTK_CONTAINER_CLASS (gedit_view_centering_parent_class)->remove (container, child);
+ }
+}
+
+static void
+gedit_view_centering_add (GtkContainer *container,
+ GtkWidget *child)
+{
+ GeditViewCenteringPrivate *priv;
+ GtkTextBuffer *buffer;
+ GtkSourceStyleScheme *scheme;
+
+ g_assert (GEDIT_IS_VIEW_CENTERING (container));
+
+ priv = GEDIT_VIEW_CENTERING (container)->priv;
+
+ if (GEDIT_IS_VIEW (child))
+ {
+ if (priv->sourceview)
+ {
+ gedit_view_centering_remove (container, priv->sourceview);
+ }
+
+ priv->sourceview = child;
+ g_object_add_weak_pointer (G_OBJECT (child), (gpointer *)&priv->sourceview);
+ gtk_container_add (GTK_CONTAINER (priv->scrolled_window), child);
+
+ priv->view_context = gtk_widget_get_style_context (child);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->sourceview));
+ scheme = gtk_source_buffer_get_style_scheme (GTK_SOURCE_BUFFER (buffer));
+ get_spacer_colors (GEDIT_VIEW_CENTERING (container), scheme);
+
+ g_signal_connect (priv->sourceview,
+ "notify::right-margin-position",
+ G_CALLBACK (on_view_right_margin_position_changed),
+ container);
+
+ g_signal_connect (priv->sourceview,
+ "notify::show-right-margin",
+ G_CALLBACK (on_view_right_margin_visibility_changed),
+ container);
+
+ g_signal_connect (priv->view_context,
+ "changed",
+ G_CALLBACK (on_view_context_changed),
+ container);
+
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+ else
+ {
+ GTK_CONTAINER_CLASS (gedit_view_centering_parent_class)->add (container, child);
+ }
+}
+
+static gboolean
+on_spacer_scroll_event (GtkWidget *widget,
+ GdkEvent *event,
+ GeditViewCentering *container)
+{
+ GdkEventScroll *new_scroll_event;
+
+ new_scroll_event = (GdkEventScroll *)gdk_event_copy (event);
+ g_object_unref (new_scroll_event->window);
+
+ new_scroll_event->window = g_object_ref (gtk_widget_get_window (container->priv->sourceview));
+ new_scroll_event->send_event = TRUE;
+
+ new_scroll_event->x = 0;
+ new_scroll_event->y = 0;
+ new_scroll_event->x_root = 0;
+ new_scroll_event->y_root = 0;
+
+ gtk_main_do_event ((GdkEvent *)new_scroll_event);
+ gdk_event_free ((GdkEvent *)new_scroll_event);
+
+ return TRUE;
+}
+
+static void
+gedit_view_centering_size_allocate (GtkWidget *widget,
+ GtkAllocation *alloc)
+{
+ GeditViewCenteringPrivate *priv;
+ GtkTextView *view;
+ gint container_width;
+ gint gutter_width;
+ gint text_width;
+ gint spacer_width;
+ gint current_spacer_width;
+ GdkWindow *gutter_window;
+
+ g_assert (GEDIT_IS_VIEW_CENTERING (widget));
+
+ priv = GEDIT_VIEW_CENTERING (widget)->priv;
+
+ view = GTK_TEXT_VIEW (priv->sourceview);
+
+ if (view)
+ {
+ container_width = alloc->width;
+
+ gutter_window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_LEFT);
+ gutter_width = (gutter_window) ? gdk_window_get_width (gutter_window) : 0;
+
+ text_width = priv->view_text_width;
+ spacer_width = MAX (0, container_width - text_width - gutter_width) / 2;
+
+ g_object_get(priv->spacer, "width-request", ¤t_spacer_width, NULL);
+
+ if (current_spacer_width != spacer_width)
+ {
+ g_object_set(priv->spacer, "width-request", spacer_width, NULL);
+ }
+ }
+
+ GTK_WIDGET_CLASS (gedit_view_centering_parent_class)->size_allocate (widget, alloc);
+}
+
+static void
+gedit_view_centering_finalize (GObject *object)
+{
+ GeditViewCentering *container = GEDIT_VIEW_CENTERING (object);
+ GeditViewCenteringPrivate *priv = container->priv;
+
+ if (priv->sourceview)
+ {
+ gedit_view_centering_remove (GTK_CONTAINER (container), priv->sourceview);
+ }
+
+ G_OBJECT_CLASS (gedit_view_centering_parent_class)->finalize (object);
+}
+
+static void
+gedit_view_centering_class_init (GeditViewCenteringClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ gobject_class->finalize = gedit_view_centering_finalize;
+
+ widget_class->size_allocate = gedit_view_centering_size_allocate;
+
+ container_class->add = gedit_view_centering_add;
+ container_class->remove = gedit_view_centering_remove;
+}
+
+static void
+gedit_view_centering_init (GeditViewCentering *container)
+{
+ GeditViewCenteringPrivate *priv;
+
+ container->priv = gedit_view_centering_get_instance_private (container);
+ priv = container->priv;
+ priv->view_text_width = 0;
+
+ priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ priv->spacer = gtk_drawing_area_new ();
+ priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+
+ gtk_container_add (GTK_CONTAINER (container), priv->box);
+ gtk_box_pack_start (GTK_BOX (priv->box), priv->spacer, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->box), priv->scrolled_window, TRUE, TRUE, 0);
+
+ gtk_widget_set_no_show_all (GTK_WIDGET (priv->spacer), TRUE);
+ gtk_widget_show_all (GTK_WIDGET (priv->box));
+
+ g_signal_connect_swapped (priv->spacer, "draw",
+ G_CALLBACK (on_spacer_draw),
+ container);
+
+ gtk_widget_add_events(GTK_WIDGET(priv->spacer), GDK_SCROLL_MASK);
+ g_signal_connect (priv->spacer, "scroll-event",
+ G_CALLBACK (on_spacer_scroll_event),
+ container);
+}
+
+/**
+ * gedit_view_centering_set_centered:
+ * @container: a #GeditViewCentering.
+ * @centered: whether to center the sourceview child or not.
+ *
+ * If @centered is %TRUE, the sourceview child is centered
+ * horizontally on the #GeditViewCentering container.
+ **/
+void
+gedit_view_centering_set_centered (GeditViewCentering *container,
+ gboolean centered)
+{
+ g_return_if_fail (GEDIT_IS_VIEW_CENTERING (container));
+
+ container->priv->centered = centered != FALSE;
+
+ on_view_right_margin_visibility_changed (GEDIT_VIEW (container->priv->sourceview), NULL, container);
+}
+
+/**
+ * gedit_view_centering_get_centered:
+ * @container: a #GeditViewCentering.
+ *
+ * Return whether the #GtkSourceView child is centered or not.
+ *
+ * Return value: %TRUE if the #GtkSourceView child is centered
+ * horizontally on the #GeditViewCentering container.
+ **/
+gboolean
+gedit_view_centering_get_centered (GeditViewCentering *container)
+{
+ g_return_val_if_fail (GEDIT_IS_VIEW_CENTERING (container), FALSE);
+
+ return container->priv->centered;
+}
+
+GeditViewCentering *
+gedit_view_centering_new (void)
+{
+ return g_object_new (GEDIT_TYPE_VIEW_CENTERING,
+ NULL);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-view-centering.h b/gedit/gedit-view-centering.h
new file mode 100644
index 000000000..1d7218969
--- /dev/null
+++ b/gedit/gedit-view-centering.h
@@ -0,0 +1,67 @@
+/*
+ * gedit-view-centering.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Sébastien Lafargue
+ * Copyright (C) 2015 - Sébastien Wilmet
+ *
+ * Gedit is free software; you can redistribute this file and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Gedit 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef GEDIT_VIEW_CENTERING_H
+#define GEDIT_VIEW_CENTERING_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_VIEW_CENTERING (gedit_view_centering_get_type())
+#define GEDIT_VIEW_CENTERING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GEDIT_TYPE_VIEW_CENTERING, GeditViewCentering))
+#define GEDIT_VIEW_CENTERING_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GEDIT_TYPE_VIEW_CENTERING, GeditViewCentering const))
+#define GEDIT_VIEW_CENTERING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_VIEW_CENTERING,
GeditViewCenteringClass))
+#define GEDIT_IS_VIEW_CENTERING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GEDIT_TYPE_VIEW_CENTERING))
+#define GEDIT_IS_VIEW_CENTERING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_VIEW_CENTERING))
+#define GEDIT_VIEW_CENTERING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_VIEW_CENTERING,
GeditViewCenteringClass))
+
+typedef struct _GeditViewCentering GeditViewCentering;
+typedef struct _GeditViewCenteringClass GeditViewCenteringClass;
+typedef struct _GeditViewCenteringPrivate GeditViewCenteringPrivate;
+
+struct _GeditViewCentering
+{
+ GtkBin parent;
+
+ GeditViewCenteringPrivate *priv;
+};
+
+struct _GeditViewCenteringClass
+{
+ GtkBinClass parent_class;
+};
+
+GType gedit_view_centering_get_type (void) G_GNUC_CONST;
+
+GeditViewCentering * gedit_view_centering_new (void);
+
+void gedit_view_centering_set_centered (GeditViewCentering *container,
+ gboolean centered);
+
+gboolean gedit_view_centering_get_centered (GeditViewCentering *container);
+
+G_END_DECLS
+
+#endif /* GEDIT_VIEW_CENTERING_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-view-frame.c b/gedit/gedit-view-frame.c
index f41734c47..67c067a41 100644
--- a/gedit/gedit-view-frame.c
+++ b/gedit/gedit-view-frame.c
@@ -3,7 +3,7 @@
* This file is part of gedit
*
* Copyright (C) 2010 - Ignacio Casal Quinteiro
- * Copyright (C) 2013, 2019 - Sébastien Wilmet
+ * Copyright (C) 2013 - Sébastien Wilmet
*
* gedit is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
#include <glib/gi18n.h>
#include <stdlib.h>
+#include "gedit-view-centering.h"
#include "gedit-debug.h"
#include "gedit-utils.h"
#include "gedit-settings.h"
@@ -53,7 +54,11 @@ struct _GeditViewFrame
{
GtkOverlay parent_instance;
+ GSettings *editor_settings;
+
GeditView *view;
+ GeditViewCentering *view_centering;
+ GtkFrame *map_frame;
SearchMode search_mode;
@@ -159,6 +164,7 @@ gedit_view_frame_dispose (GObject *object)
gtk_source_file_set_mount_operation_factory (file, NULL, NULL, NULL);
}
+ g_clear_object (&frame->editor_settings);
g_clear_object (&frame->entry_tag);
g_clear_object (&frame->search_settings);
g_clear_object (&frame->old_search_settings);
@@ -213,7 +219,7 @@ hide_search_widget (GeditViewFrame *frame,
frame->start_mark);
gtk_text_buffer_place_cursor (buffer, &iter);
- tepl_view_scroll_to_cursor (TEPL_VIEW (frame->view));
+ gedit_view_scroll_to_cursor (frame->view);
}
if (frame->start_mark != NULL)
@@ -297,7 +303,7 @@ finish_search (GeditViewFrame *frame,
if (found || (entry_text[0] == '\0'))
{
- tepl_view_scroll_to_cursor (TEPL_VIEW (frame->view));
+ gedit_view_scroll_to_cursor (frame->view);
set_search_state (frame, SEARCH_STATE_NORMAL);
}
@@ -1061,6 +1067,7 @@ update_goto_line (GeditViewFrame *frame)
gchar **split_text = NULL;
const gchar *text;
GtkTextIter iter;
+ GeditDocument *doc;
entry_text = gtk_entry_get_text (GTK_ENTRY (frame->search_entry));
@@ -1116,8 +1123,11 @@ update_goto_line (GeditViewFrame *frame)
g_strfreev (split_text);
- moved = tepl_view_goto_line (TEPL_VIEW (frame->view), line);
- moved_offset = tepl_view_goto_line_offset (TEPL_VIEW (frame->view), line, line_offset);
+ doc = get_document (frame);
+ moved = gedit_document_goto_line (doc, line);
+ moved_offset = gedit_document_goto_line_offset (doc, line, line_offset);
+
+ gedit_view_scroll_to_cursor (frame->view);
if (!moved || !moved_offset)
{
@@ -1428,6 +1438,8 @@ gedit_view_frame_class_init (GeditViewFrameClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/gedit/ui/gedit-view-frame.ui");
gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, view);
+ gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, view_centering);
+ gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, map_frame);
gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, revealer);
gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, search_entry);
gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, go_up_button);
@@ -1454,6 +1466,13 @@ gedit_view_frame_init (GeditViewFrame *frame)
gtk_widget_init_template (GTK_WIDGET (frame));
+ frame->editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
+ g_settings_bind (frame->editor_settings,
+ GEDIT_SETTINGS_DISPLAY_OVERVIEW_MAP,
+ frame->map_frame,
+ "visible",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
+
doc = get_document (frame);
file = gedit_document_get_file (doc);
@@ -1551,6 +1570,14 @@ gedit_view_frame_new (void)
return g_object_new (GEDIT_TYPE_VIEW_FRAME, NULL);
}
+GeditViewCentering *
+gedit_view_frame_get_view_centering (GeditViewFrame *frame)
+{
+ g_return_val_if_fail (GEDIT_IS_VIEW_FRAME (frame), NULL);
+
+ return frame->view_centering;
+}
+
GeditView *
gedit_view_frame_get_view (GeditViewFrame *frame)
{
diff --git a/gedit/gedit-view-frame.h b/gedit/gedit-view-frame.h
index 78ac469d1..d2e550840 100644
--- a/gedit/gedit-view-frame.h
+++ b/gedit/gedit-view-frame.h
@@ -24,6 +24,7 @@
#include <gtk/gtk.h>
#include "gedit-document.h"
#include "gedit-view.h"
+#include "gedit-view-centering.h"
G_BEGIN_DECLS
@@ -32,6 +33,9 @@ G_DECLARE_FINAL_TYPE (GeditViewFrame, gedit_view_frame, GEDIT, VIEW_FRAME, GtkOv
GeditViewFrame *gedit_view_frame_new (void);
+GeditViewCentering
+ *gedit_view_frame_get_view_centering (GeditViewFrame *frame);
+
GeditView *gedit_view_frame_get_view (GeditViewFrame *frame);
void gedit_view_frame_popup_search (GeditViewFrame *frame);
diff --git a/gedit/gedit-view.c b/gedit/gedit-view.c
index 0c730c989..035e599ab 100644
--- a/gedit/gedit-view.c
+++ b/gedit/gedit-view.c
@@ -24,16 +24,21 @@
#include "gedit-view-activatable.h"
#include "gedit-plugins-engine.h"
#include "gedit-debug.h"
+#include "gedit-pango.h"
#include "gedit-utils.h"
#include "gedit-settings.h"
+#define GEDIT_VIEW_SCROLL_MARGIN 0.02
+
struct _GeditViewPrivate
{
+ GeditDocument *current_document;
PeasExtensionSet *extensions;
gchar *direct_save_uri;
- TeplSignalGroup *file_signal_group;
+ GtkCssProvider *css_provider;
+ PangoFontDescription *font_desc;
};
enum
@@ -50,7 +55,7 @@ enum
static guint signals[N_SIGNALS];
-G_DEFINE_TYPE_WITH_PRIVATE (GeditView, gedit_view, TEPL_TYPE_VIEW)
+G_DEFINE_TYPE_WITH_PRIVATE (GeditView, gedit_view, GTK_SOURCE_TYPE_VIEW)
static void
update_editable (GeditView *view)
@@ -73,23 +78,46 @@ file_read_only_notify_cb (GtkSourceFile *file,
update_editable (view);
}
+static void
+current_document_removed (GeditView *view)
+{
+ if (view->priv->current_document != NULL)
+ {
+ GtkSourceFile *file;
+
+ file = gedit_document_get_file (view->priv->current_document);
+
+ g_signal_handlers_disconnect_by_func (file,
+ file_read_only_notify_cb,
+ view);
+
+ g_object_unref (view->priv->current_document);
+ view->priv->current_document = NULL;
+ }
+}
+
static void
buffer_changed (GeditView *view)
{
- GeditDocument *doc;
GtkSourceFile *file;
+ GtkTextBuffer *buffer;
- doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
- file = gedit_document_get_file (doc);
+ current_document_removed (view);
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ if (!GEDIT_IS_DOCUMENT (buffer))
+ {
+ return;
+ }
- tepl_signal_group_clear (&view->priv->file_signal_group);
- view->priv->file_signal_group = tepl_signal_group_new (G_OBJECT (file));
+ view->priv->current_document = g_object_ref (GEDIT_DOCUMENT (buffer));
- tepl_signal_group_add (view->priv->file_signal_group,
- g_signal_connect (file,
- "notify::read-only",
- G_CALLBACK (file_read_only_notify_cb),
- view));
+ file = gedit_document_get_file (view->priv->current_document);
+ g_signal_connect_object (file,
+ "notify::read-only",
+ G_CALLBACK (file_read_only_notify_cb),
+ view,
+ 0);
update_editable (view);
}
@@ -106,7 +134,7 @@ static void
gedit_view_init (GeditView *view)
{
GtkTargetList *target_list;
- GtkStyleContext *style_context;
+ GtkStyleContext *context;
gedit_debug (DEBUG_VIEW);
@@ -140,8 +168,13 @@ gedit_view_init (GeditView *view)
NULL);
/* CSS stuff */
- style_context = gtk_widget_get_style_context (GTK_WIDGET (view));
- gtk_style_context_add_class (style_context, "gedit-view");
+ context = gtk_widget_get_style_context (GTK_WIDGET (view));
+ gtk_style_context_add_class (context, "gedit-view");
+
+ view->priv->css_provider = gtk_css_provider_new ();
+ gtk_style_context_add_provider (context,
+ GTK_STYLE_PROVIDER (view->priv->css_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
static void
@@ -150,7 +183,8 @@ gedit_view_dispose (GObject *object)
GeditView *view = GEDIT_VIEW (object);
g_clear_object (&view->priv->extensions);
- tepl_signal_group_clear (&view->priv->file_signal_group);
+
+ current_document_removed (view);
/* Disconnect notify buffer because the destroy of the textview will set
* the buffer to NULL, and we call get_buffer in the notify which would
@@ -160,26 +194,10 @@ gedit_view_dispose (GObject *object)
*/
g_signal_handlers_disconnect_by_func (view, buffer_notify_cb, NULL);
- G_OBJECT_CLASS (gedit_view_parent_class)->dispose (object);
-}
-
-static void
-update_font (GeditView *view)
-{
- GeditSettings *settings;
- gchar *selected_font;
-
- settings = _gedit_settings_get_singleton ();
- selected_font = _gedit_settings_get_selected_font (settings);
- tepl_utils_override_font (GTK_WIDGET (view), selected_font);
- g_free (selected_font);
-}
+ g_clear_object (&view->priv->css_provider);
+ g_clear_pointer (&view->priv->font_desc, pango_font_description_free);
-static void
-fonts_changed_cb (GeditSettings *settings,
- GeditView *view)
-{
- update_font (view);
+ G_OBJECT_CLASS (gedit_view_parent_class)->dispose (object);
}
static void
@@ -188,18 +206,27 @@ gedit_view_constructed (GObject *object)
GeditView *view = GEDIT_VIEW (object);
GeditSettings *settings;
GSettings *editor_settings;
+ gboolean use_default_font;
G_OBJECT_CLASS (gedit_view_parent_class)->constructed (object);
settings = _gedit_settings_get_singleton ();
editor_settings = _gedit_settings_peek_editor_settings (settings);
- update_font (view);
- g_signal_connect_object (settings,
- "fonts-changed",
- G_CALLBACK (fonts_changed_cb),
- view,
- 0);
+ use_default_font = g_settings_get_boolean (editor_settings, GEDIT_SETTINGS_USE_DEFAULT_FONT);
+
+ if (use_default_font)
+ {
+ gedit_view_set_font (view, TRUE, NULL);
+ }
+ else
+ {
+ gchar *editor_font;
+
+ editor_font = g_settings_get_string (editor_settings, GEDIT_SETTINGS_EDITOR_FONT);
+ gedit_view_set_font (view, FALSE, editor_font);
+ g_free (editor_font);
+ }
g_settings_bind (editor_settings, GEDIT_SETTINGS_DISPLAY_LINE_NUMBERS,
view, "show-line-numbers",
@@ -720,4 +747,217 @@ gedit_view_new (GeditDocument *doc)
NULL);
}
+void
+gedit_view_cut_clipboard (GeditView *view)
+{
+ GtkTextBuffer *buffer;
+ GtkClipboard *clipboard;
+
+ gedit_debug (DEBUG_VIEW);
+
+ g_return_if_fail (GEDIT_IS_VIEW (view));
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
+ GDK_SELECTION_CLIPBOARD);
+
+ gtk_text_buffer_cut_clipboard (buffer,
+ clipboard,
+ gtk_text_view_get_editable (GTK_TEXT_VIEW (view)));
+
+ gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
+ gtk_text_buffer_get_insert (buffer),
+ GEDIT_VIEW_SCROLL_MARGIN,
+ FALSE,
+ 0.0,
+ 0.0);
+}
+
+void
+gedit_view_copy_clipboard (GeditView *view)
+{
+ GtkTextBuffer *buffer;
+ GtkClipboard *clipboard;
+
+ gedit_debug (DEBUG_VIEW);
+
+ g_return_if_fail (GEDIT_IS_VIEW (view));
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
+ GDK_SELECTION_CLIPBOARD);
+
+ gtk_text_buffer_copy_clipboard (buffer, clipboard);
+
+ /* on copy do not scroll, we are already on screen */
+}
+
+void
+gedit_view_paste_clipboard (GeditView *view)
+{
+ GtkTextBuffer *buffer;
+ GtkClipboard *clipboard;
+
+ gedit_debug (DEBUG_VIEW);
+
+ g_return_if_fail (GEDIT_IS_VIEW (view));
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
+ GDK_SELECTION_CLIPBOARD);
+
+ gtk_text_buffer_paste_clipboard (buffer,
+ clipboard,
+ NULL,
+ gtk_text_view_get_editable (GTK_TEXT_VIEW (view)));
+
+ gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
+ gtk_text_buffer_get_insert (buffer),
+ GEDIT_VIEW_SCROLL_MARGIN,
+ FALSE,
+ 0.0,
+ 0.0);
+}
+
+/**
+ * gedit_view_delete_selection:
+ * @view: a #GeditView
+ *
+ * Deletes the text currently selected in the #GtkTextBuffer associated
+ * to the view and scroll to the cursor position.
+ */
+void
+gedit_view_delete_selection (GeditView *view)
+{
+ GtkTextBuffer *buffer;
+
+ gedit_debug (DEBUG_VIEW);
+
+ g_return_if_fail (GEDIT_IS_VIEW (view));
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ gtk_text_buffer_delete_selection (buffer,
+ TRUE,
+ gtk_text_view_get_editable (GTK_TEXT_VIEW (view)));
+
+ gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
+ gtk_text_buffer_get_insert (buffer),
+ GEDIT_VIEW_SCROLL_MARGIN,
+ FALSE,
+ 0.0,
+ 0.0);
+}
+
+/**
+ * gedit_view_select_all:
+ * @view: a #GeditView
+ *
+ * Selects all the text.
+ */
+void
+gedit_view_select_all (GeditView *view)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start;
+ GtkTextIter end;
+
+ gedit_debug (DEBUG_VIEW);
+
+ g_return_if_fail (GEDIT_IS_VIEW (view));
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+ gtk_text_buffer_select_range (buffer, &start, &end);
+}
+
+/**
+ * gedit_view_scroll_to_cursor:
+ * @view: a #GeditView
+ *
+ * Scrolls the @view to the cursor position.
+ */
+void
+gedit_view_scroll_to_cursor (GeditView *view)
+{
+ GtkTextBuffer *buffer;
+
+ gedit_debug (DEBUG_VIEW);
+
+ g_return_if_fail (GEDIT_IS_VIEW (view));
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
+ gtk_text_buffer_get_insert (buffer),
+ 0.25,
+ FALSE,
+ 0.0,
+ 0.0);
+}
+
+static void
+update_css_provider (GeditView *view)
+{
+ gchar *str;
+ gchar *css;
+
+ g_assert (GEDIT_IS_VIEW (view));
+ g_assert (view->priv->font_desc != NULL);
+
+ str = gedit_pango_font_description_to_css (view->priv->font_desc);
+ css = g_strdup_printf ("textview { %s }", str ? str : "");
+ gtk_css_provider_load_from_data (view->priv->css_provider, css, -1, NULL);
+
+ g_free (css);
+ g_free (str);
+}
+
+/**
+ * gedit_view_set_font:
+ * @view: a #GeditView
+ * @default_font: whether to reset to the default font
+ * @font_name: the name of the font to use
+ *
+ * If @default_font is #TRUE, resets the font of the @view to the default font.
+ * Otherwise sets it to @font_name.
+ */
+void
+gedit_view_set_font (GeditView *view,
+ gboolean default_font,
+ const gchar *font_name)
+{
+ gedit_debug (DEBUG_VIEW);
+
+ g_return_if_fail (GEDIT_IS_VIEW (view));
+
+ g_clear_pointer (&view->priv->font_desc, pango_font_description_free);
+
+ if (default_font)
+ {
+ GeditSettings *settings;
+ gchar *font;
+
+ settings = _gedit_settings_get_singleton ();
+ font = gedit_settings_get_system_font (settings);
+
+ view->priv->font_desc = pango_font_description_from_string (font);
+ g_free (font);
+ }
+ else
+ {
+ g_return_if_fail (font_name != NULL);
+
+ view->priv->font_desc = pango_font_description_from_string (font_name);
+ }
+
+ g_return_if_fail (view->priv->font_desc != NULL);
+
+ update_css_provider (view);
+}
+
/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-view.h b/gedit/gedit-view.h
index c05d68553..7f2ae3ae2 100644
--- a/gedit/gedit-view.h
+++ b/gedit/gedit-view.h
@@ -22,8 +22,10 @@
#ifndef GEDIT_VIEW_H
#define GEDIT_VIEW_H
+#include <gtk/gtk.h>
+
#include <gedit/gedit-document.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
G_BEGIN_DECLS
@@ -40,7 +42,7 @@ typedef struct _GeditViewPrivate GeditViewPrivate;
struct _GeditView
{
- TeplView view;
+ GtkSourceView view;
/*< private >*/
GeditViewPrivate *priv;
@@ -48,7 +50,7 @@ struct _GeditView
struct _GeditViewClass
{
- TeplViewClass parent_class;
+ GtkSourceViewClass parent_class;
void (*drop_uris) (GeditView *view,
gchar **uri_list);
@@ -60,6 +62,22 @@ GType gedit_view_get_type (void);
GtkWidget * gedit_view_new (GeditDocument *doc);
+void gedit_view_cut_clipboard (GeditView *view);
+
+void gedit_view_copy_clipboard (GeditView *view);
+
+void gedit_view_paste_clipboard (GeditView *view);
+
+void gedit_view_delete_selection (GeditView *view);
+
+void gedit_view_select_all (GeditView *view);
+
+void gedit_view_scroll_to_cursor (GeditView *view);
+
+void gedit_view_set_font (GeditView *view,
+ gboolean default_font,
+ const gchar *font_name);
+
G_END_DECLS
#endif /* GEDIT_VIEW_H */
diff --git a/gedit/gedit-window-private.h b/gedit/gedit-window-private.h
index 60f8ba706..380f6bdc5 100644
--- a/gedit/gedit-window-private.h
+++ b/gedit/gedit-window-private.h
@@ -27,6 +27,7 @@
#include "gedit-message-bus.h"
#include "gedit-settings.h"
#include "gedit-multi-notebook.h"
+#include "gedit-open-document-selector.h"
G_BEGIN_DECLS
@@ -53,12 +54,15 @@ struct _GeditWindowPrivate
PeasExtensionSet *extensions;
/* Widgets for fullscreen mode */
+ GtkWidget *fullscreen_controls;
GtkWidget *fullscreen_eventbox;
- GtkRevealer *fullscreen_revealer;
GtkWidget *fullscreen_headerbar;
- GtkWidget *fullscreen_new_button;
GtkMenuButton *fullscreen_gear_button;
- GtkMenuButton *fullscreen_open_recent_button;
+
+ GtkWidget *fullscreen_new_button;
+ GtkWidget *fullscreen_open_button;
+ GtkWidget *fullscreen_open_document_popover;
+ GeditOpenDocumentSelector *fullscreen_open_document_selector;
/* statusbar and context ids for statusbar messages */
GtkWidget *statusbar;
@@ -79,7 +83,10 @@ struct _GeditWindowPrivate
GtkWidget *side_headerbar;
GtkWidget *headerbar;
- GtkWidget *new_button;
+ GtkWidget *open_document_popover;
+ GtkWidget *new_button;
+ GtkWidget *open_button;
+ GeditOpenDocumentSelector *open_document_selector;
GtkMenuButton *gear_button;
diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c
index 2f9a2076f..b08a1dbcc 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -28,11 +28,11 @@
#include <glib/gi18n.h>
#include <libpeas/peas-extension-set.h>
-#include <tepl/tepl.h>
#include "gedit-window-private.h"
#include "gedit-app.h"
#include "gedit-app-private.h"
+#include "gedit-recent.h"
#include "gedit-notebook.h"
#include "gedit-notebook-popup-menu.h"
#include "gedit-multi-notebook.h"
@@ -40,6 +40,7 @@
#include "gedit-tab.h"
#include "gedit-tab-private.h"
#include "gedit-view-frame.h"
+#include "gedit-view-centering.h"
#include "gedit-utils.h"
#include "gedit-commands.h"
#include "gedit-commands-private.h"
@@ -54,6 +55,11 @@
#include "gedit-status-menu-button.h"
#include "gedit-settings.h"
#include "gedit-menu-stack-switcher.h"
+#include "gedit-highlight-mode-selector.h"
+#include "gedit-open-document-selector.h"
+
+#define TAB_WIDTH_DATA "GeditWindowTabWidthData"
+#define FULLSCREEN_ANIMATION_SPEED 500
enum
{
@@ -158,9 +164,9 @@ save_window_state (GtkWidget *widget)
GeditWindow *window = GEDIT_WINDOW (widget);
if ((window->priv->window_state &
- (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
+ (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
{
- gtk_window_get_size (GTK_WINDOW (widget), &window->priv->width, &window->priv->height);
+ gtk_window_get_size (GTK_WINDOW (widget), &window->priv->width, &window->priv->height);
g_settings_set (window->priv->window_settings, GEDIT_SETTINGS_WINDOW_SIZE,
"(ii)", window->priv->width, window->priv->height);
@@ -231,8 +237,6 @@ gedit_window_dispose (GObject *object)
*/
remove_actions (window);
- window->priv->fullscreen_open_recent_button = NULL;
-
G_OBJECT_CLASS (gedit_window_parent_class)->dispose (object);
}
@@ -247,6 +251,22 @@ gedit_window_finalize (GObject *object)
G_OBJECT_CLASS (gedit_window_parent_class)->finalize (object);
}
+/* Center the view when the window is in fullscreen mode. */
+static void
+update_view_centering (GeditTab *tab,
+ gpointer user_data)
+{
+ GeditViewFrame *view_frame;
+ GeditViewCentering *view_centering;
+ gboolean is_fullscreen;
+
+ view_frame = _gedit_tab_get_view_frame (tab);
+ view_centering = gedit_view_frame_get_view_centering (view_frame);
+
+ is_fullscreen = GPOINTER_TO_BOOLEAN (user_data);
+ gedit_view_centering_set_centered (view_centering, is_fullscreen);
+}
+
static void
update_fullscreen (GeditWindow *window,
gboolean is_fullscreen)
@@ -267,6 +287,10 @@ update_fullscreen (GeditWindow *window,
}
}
+ gedit_multi_notebook_foreach_tab (window->priv->multi_notebook,
+ (GtkCallback)update_view_centering,
+ GBOOLEAN_TO_POINTER (is_fullscreen));
+
#ifndef OS_OSX
if (is_fullscreen)
{
@@ -312,7 +336,7 @@ gedit_window_configure_event (GtkWidget *widget,
if (gtk_widget_get_realized (widget) &&
(window->priv->window_state &
- (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
+ (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
{
save_window_state (widget);
}
@@ -454,6 +478,7 @@ gedit_window_class_init (GeditWindowClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_headerbar);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, headerbar);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, new_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, open_button);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, gear_button);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, hpaned);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_panel);
@@ -466,10 +491,11 @@ gedit_window_class_init (GeditWindowClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, language_button);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, tab_width_button);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, line_col_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_controls);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_eventbox);
- gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_revealer);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_headerbar);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_new_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_open_button);
gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_gear_button);
}
@@ -765,8 +791,48 @@ update_actions_sensitivity (GeditWindow *window)
}
static void
-language_chooser_show_cb (TeplLanguageChooser *language_chooser,
- GeditWindow *window)
+on_recent_chooser_item_activated (GeditOpenDocumentSelector *open_document_selector,
+ gchar *uri,
+ GeditWindow *window)
+{
+ GFile *location;
+ GeditView *active_view;
+
+ g_return_if_fail (GEDIT_WINDOW (window));
+ g_return_if_fail (GEDIT_OPEN_DOCUMENT_SELECTOR (open_document_selector));
+
+ /* TODO: get_current_file when exists */
+ location = g_file_new_for_uri (uri);
+
+ if (location)
+ {
+ GSList *locations = NULL;
+ GSList *loaded = NULL;
+
+ locations = g_slist_prepend (locations, (gpointer) location);
+ loaded = gedit_commands_load_locations (window, locations, NULL, 0, 0);
+
+ /* if it doesn't contain just 1 element */
+ if (!loaded || loaded->next)
+ {
+ gedit_recent_remove_if_local (location);
+ }
+
+ g_slist_free (locations);
+ g_slist_free (loaded);
+
+ g_object_unref (location);
+ }
+
+ /* Needed to close the popover when activating the same
+ * document as the current one */
+ active_view = gedit_window_get_active_view (window);
+ gtk_widget_grab_focus (GTK_WIDGET (active_view));
+}
+
+static void
+language_selector_show_cb (GeditHighlightModeSelector *selector,
+ GeditWindow *window)
{
GeditDocument *active_document;
@@ -776,14 +842,14 @@ language_chooser_show_cb (TeplLanguageChooser *language_chooser,
GtkSourceLanguage *language;
language = gedit_document_get_language (active_document);
- tepl_language_chooser_select_language (language_chooser, language);
+ gedit_highlight_mode_selector_select_language (selector, language);
}
}
static void
-language_activated_cb (TeplLanguageChooser *language_chooser,
- GtkSourceLanguage *language,
- GeditWindow *window)
+language_selected_cb (GeditHighlightModeSelector *selector,
+ GtkSourceLanguage *language,
+ GeditWindow *window)
{
GeditDocument *active_document;
@@ -793,13 +859,13 @@ language_activated_cb (TeplLanguageChooser *language_chooser,
gedit_document_set_language (active_document, language);
}
- gtk_widget_hide (window->priv->language_popover);
+ gtk_widget_hide (GTK_WIDGET (window->priv->language_popover));
}
static void
setup_statusbar (GeditWindow *window)
{
- TeplLanguageChooserWidget *language_chooser;
+ GeditHighlightModeSelector *selector;
gedit_debug (DEBUG_WINDOW);
@@ -829,20 +895,20 @@ setup_statusbar (GeditWindow *window)
gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->priv->language_button),
window->priv->language_popover);
- language_chooser = tepl_language_chooser_widget_new ();
+ selector = gedit_highlight_mode_selector_new ();
- g_signal_connect (language_chooser,
+ g_signal_connect (selector,
"show",
- G_CALLBACK (language_chooser_show_cb),
+ G_CALLBACK (language_selector_show_cb),
window);
- g_signal_connect (language_chooser,
- "language-activated",
- G_CALLBACK (language_activated_cb),
+ g_signal_connect (selector,
+ "language-selected",
+ G_CALLBACK (language_selected_cb),
window);
- gtk_container_add (GTK_CONTAINER (window->priv->language_popover), GTK_WIDGET (language_chooser));
- gtk_widget_show (GTK_WIDGET (language_chooser));
+ gtk_container_add (GTK_CONTAINER (window->priv->language_popover), GTK_WIDGET (selector));
+ gtk_widget_show (GTK_WIDGET (selector));
}
static GeditWindow *
@@ -1044,8 +1110,8 @@ set_title (GeditWindow *window)
{
gchar *tmp;
- tmp = tepl_utils_str_middle_truncate (name,
- MAX_TITLE_LENGTH);
+ tmp = gedit_utils_str_middle_truncate (name,
+ MAX_TITLE_LENGTH);
g_free (name);
name = tmp;
}
@@ -1063,8 +1129,8 @@ set_title (GeditWindow *window)
* we have a title long 99 + 20, but I think it's a rare enough
* case to be acceptable. It's justa darn title afterall :)
*/
- dirname = tepl_utils_str_middle_truncate (str,
- MAX (20, MAX_TITLE_LENGTH - len));
+ dirname = gedit_utils_str_middle_truncate (str,
+ MAX (20, MAX_TITLE_LENGTH - len));
g_free (str);
}
}
@@ -1690,88 +1756,84 @@ drop_uris_cb (GtkWidget *widget,
load_uris_from_drop (window, uri_list);
}
-static void
-update_fullscreen_revealer_state (GeditWindow *window)
+static gboolean
+on_fullscreen_controls_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event,
+ GeditWindow *window)
{
- gboolean open_recent_menu_is_active;
- gboolean hamburger_menu_is_active;
+ window->priv->in_fullscreen_eventbox = TRUE;
- open_recent_menu_is_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(window->priv->fullscreen_open_recent_button));
- hamburger_menu_is_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(window->priv->fullscreen_gear_button));
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), TRUE);
- gtk_revealer_set_reveal_child (window->priv->fullscreen_revealer,
- (window->priv->in_fullscreen_eventbox ||
- open_recent_menu_is_active ||
- hamburger_menu_is_active));
+ return FALSE;
}
static gboolean
-on_fullscreen_eventbox_enter_notify_event (GtkWidget *fullscreen_eventbox,
- GdkEventCrossing *event,
- GeditWindow *window)
+real_fullscreen_controls_leave_notify_event (gpointer data)
{
- window->priv->in_fullscreen_eventbox = TRUE;
- update_fullscreen_revealer_state (window);
+ GeditWindow *window = GEDIT_WINDOW (data);
+ gboolean hamburger_menu_state;
+ gboolean fullscreen_open_button_state;
- return GDK_EVENT_PROPAGATE;
-}
+ hamburger_menu_state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(window->priv->fullscreen_gear_button));
+ fullscreen_open_button_state =
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(window->priv->fullscreen_open_button));
-static gboolean
-on_fullscreen_eventbox_leave_notify_event (GtkWidget *fullscreen_eventbox,
- GdkEventCrossing *event,
- GeditWindow *window)
-{
- if (-1.0 <= event->y && event->y <= 0.0)
- {
- /* Ignore the event.
- *
- * Leave notify events are received with -1 <= y <= 0
- * coordinates, although the GeditWindow is in fullscreen mode
- * and when there are no screens above (it's maybe a bug in an
- * underlying library).
- * If we hide the headerbar when those events happen, then it
- * makes the headerbar to be shown/hidden a lot of time in a
- * short period of time, i.e. a "stuttering". In other words
- * lots of leave/enter events are received when moving the mouse
- * upwards on the screen when the mouse is already at the top.
- * The expected leave event has a positive event->y value being
- * >= to the height of the headerbar (approximately
- * 40 <= y <= 50). So clearly when we receive a leave event with
- * event->y <= 0, it means that the mouse has left the eventbox
- * on the wrong side.
- * The -1.0 <= event->y is there (instead of just <= 0.0) in the
- * case that there is another screen *above*, even if this
- * heuristic/workaround is not perfect in that case. But that
- * case is quite rare, so it's probably a good enough solution.
- *
- * Note that apparently the "stuttering" occurs only on an Xorg
- * session, not on Wayland (tested with GNOME).
- *
- * If you see a better solution...
- */
- return GDK_EVENT_PROPAGATE;
+ window->priv->in_fullscreen_eventbox = FALSE;
+
+ if (!hamburger_menu_state && !fullscreen_open_button_state)
+ {
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), FALSE);
}
- window->priv->in_fullscreen_eventbox = FALSE;
- update_fullscreen_revealer_state (window);
+ return G_SOURCE_REMOVE;
+}
+
+/* this idle is needed because the toggled signal from gear button is received
+ * after the leave event from the event box ( which is automatically triggered when user
+ * bring up the gear menu */
+static gboolean
+on_fullscreen_controls_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event,
+ GeditWindow *window)
+{
+ g_idle_add (real_fullscreen_controls_leave_notify_event, window);
return GDK_EVENT_PROPAGATE;
}
static void
-setup_fullscreen_eventbox (GeditWindow *window)
+fullscreen_controls_setup (GeditWindow *window)
{
- gtk_widget_set_size_request (window->priv->fullscreen_eventbox, -1, 1);
- gtk_widget_hide (window->priv->fullscreen_eventbox);
+ GeditWindowPrivate *priv = window->priv;
- g_signal_connect (window->priv->fullscreen_eventbox,
+ g_signal_connect (priv->fullscreen_eventbox,
"enter-notify-event",
- G_CALLBACK (on_fullscreen_eventbox_enter_notify_event),
+ G_CALLBACK (on_fullscreen_controls_enter_notify_event),
window);
- g_signal_connect (window->priv->fullscreen_eventbox,
+ g_signal_connect (priv->fullscreen_eventbox,
"leave-notify-event",
- G_CALLBACK (on_fullscreen_eventbox_leave_notify_event),
+ G_CALLBACK (on_fullscreen_controls_leave_notify_event),
+ window);
+
+ gtk_widget_set_size_request (GTK_WIDGET (window->priv->fullscreen_eventbox), -1, 1);
+ gtk_widget_hide (window->priv->fullscreen_eventbox);
+
+ priv->fullscreen_open_document_popover = gtk_popover_new (priv->fullscreen_open_button);
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (priv->fullscreen_open_button),
+ priv->fullscreen_open_document_popover);
+
+ window->priv->fullscreen_open_document_selector = gedit_open_document_selector_new (window);
+
+ gtk_container_add (GTK_CONTAINER (priv->fullscreen_open_document_popover),
+ GTK_WIDGET (priv->fullscreen_open_document_selector));
+
+ gtk_widget_show_all (GTK_WIDGET (priv->fullscreen_open_document_selector));
+
+ g_signal_connect (window->priv->fullscreen_open_document_selector,
+ "file-activated",
+ G_CALLBACK (on_recent_chooser_item_activated),
window);
}
@@ -1885,7 +1947,7 @@ on_tab_added (GeditMultiNotebook *multi,
G_CALLBACK (bracket_matched_cb),
window);
g_signal_connect (doc,
- "tepl-cursor-moved",
+ "cursor-moved",
G_CALLBACK (update_cursor_position_statusbar),
window);
g_signal_connect (doc,
@@ -2144,10 +2206,23 @@ on_notebook_removed (GeditMultiNotebook *mnb,
}
static void
-on_fullscreen_toggle_button_toggled (GtkToggleButton *fullscreen_toggle_button,
- GeditWindow *window)
+on_fullscreen_gear_button_toggled (GtkToggleButton *fullscreen_gear_button,
+ GeditWindow *window)
{
- update_fullscreen_revealer_state (window);
+ gboolean button_active = gtk_toggle_button_get_active (fullscreen_gear_button);
+
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls),
+ button_active || window->priv->in_fullscreen_eventbox);
+}
+
+static void
+on_fullscreen_file_menu_button_toggled (GtkMenuButton *fullscreen_open_button,
+ GeditWindow *window)
+{
+ gboolean button_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fullscreen_open_button));
+
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls),
+ button_active || window->priv->in_fullscreen_eventbox);
}
static void
@@ -2537,6 +2612,18 @@ window_unrealized (GtkWidget *window,
window);
}
+static void
+check_window_is_active (GeditWindow *window,
+ GParamSpec *property,
+ gpointer useless)
+{
+ if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN)
+ {
+ gtk_widget_set_visible (window->priv->fullscreen_eventbox,
+ gtk_window_is_active (GTK_WINDOW (window)));
+ }
+}
+
static void
extension_added (PeasExtensionSet *extensions,
PeasPluginInfo *info,
@@ -2608,76 +2695,6 @@ sync_fullscreen_actions (GeditWindow *window,
g_object_unref (action);
}
-static void
-init_amtk_application_window (GeditWindow *gedit_window)
-{
- AmtkApplicationWindow *amtk_window;
-
- amtk_window = amtk_application_window_get_from_gtk_application_window (GTK_APPLICATION_WINDOW
(gedit_window));
- amtk_application_window_set_statusbar (amtk_window, GTK_STATUSBAR (gedit_window->priv->statusbar));
-}
-
-static GtkWidget *
-create_open_buttons (GeditWindow *window,
- GtkMenuButton **open_recent_button)
-{
- GtkWidget *hbox;
- GtkStyleContext *style_context;
- GtkWidget *open_dialog_button;
- GtkWidget *my_open_recent_button;
- AmtkApplicationWindow *amtk_window;
- GtkWidget *recent_menu;
-
- /* It currently needs to be a GtkBox, not a GtkGrid, because GtkGrid and
- * GTK_STYLE_CLASS_LINKED doesn't work as expected in a RTL locale.
- * Probably a GtkGrid bug.
- */
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- style_context = gtk_widget_get_style_context (hbox);
- gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_LINKED);
-
- open_dialog_button = gtk_button_new_with_mnemonic (_("_Open"));
- gtk_widget_set_tooltip_text (open_dialog_button, _("Open a file"));
- gtk_actionable_set_action_name (GTK_ACTIONABLE (open_dialog_button), "win.open");
-
- my_open_recent_button = gtk_menu_button_new ();
- gtk_widget_set_tooltip_text (my_open_recent_button, _("Open a recently used file"));
-
- amtk_window = amtk_application_window_get_from_gtk_application_window (GTK_APPLICATION_WINDOW
(window));
- recent_menu = amtk_application_window_create_open_recent_menu (amtk_window);
- gtk_menu_button_set_popup (GTK_MENU_BUTTON (my_open_recent_button), recent_menu);
-
- gtk_container_add (GTK_CONTAINER (hbox), open_dialog_button);
- gtk_container_add (GTK_CONTAINER (hbox), my_open_recent_button);
- gtk_widget_show_all (hbox);
-
- if (open_recent_button != NULL)
- {
- *open_recent_button = GTK_MENU_BUTTON (my_open_recent_button);
- }
-
- return hbox;
-}
-
-static void
-init_open_buttons (GeditWindow *window)
-{
- gtk_container_add_with_properties (GTK_CONTAINER (window->priv->headerbar),
- create_open_buttons (window, NULL),
- "position", 0, /* The first on the left. */
- NULL);
-
- gtk_container_add_with_properties (GTK_CONTAINER (window->priv->fullscreen_headerbar),
- create_open_buttons (window,
&(window->priv->fullscreen_open_recent_button)),
- "position", 0, /* The first on the left. */
- NULL);
-
- g_signal_connect (GTK_TOGGLE_BUTTON (window->priv->fullscreen_open_recent_button),
- "toggled",
- G_CALLBACK (on_fullscreen_toggle_button_toggled),
- window);
-}
-
static void
gedit_window_init (GeditWindow *window)
{
@@ -2692,6 +2709,7 @@ gedit_window_init (GeditWindow *window)
window->priv->state = GEDIT_WINDOW_STATE_NORMAL;
window->priv->inhibition_cookie = 0;
window->priv->dispose_has_run = FALSE;
+ window->priv->fullscreen_controls = NULL;
window->priv->direct_save_uri = NULL;
window->priv->closed_docs_stack = NULL;
window->priv->editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
@@ -2705,8 +2723,6 @@ gedit_window_init (GeditWindow *window)
window->priv->message_bus = gedit_message_bus_new ();
gtk_widget_init_template (GTK_WIDGET (window));
- init_amtk_application_window (window);
- init_open_buttons (window);
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries,
@@ -2716,9 +2732,32 @@ gedit_window_init (GeditWindow *window)
window->priv->window_group = gtk_window_group_new ();
gtk_window_group_add_window (window->priv->window_group, GTK_WINDOW (window));
- setup_fullscreen_eventbox (window);
+ /* Setup file popover and file dialog */
+ window->priv->open_document_popover = gtk_popover_new (window->priv->open_button);
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->priv->open_button),
+ window->priv->open_document_popover);
+
+ window->priv->open_document_selector = gedit_open_document_selector_new (window);
+
+ gtk_container_add (GTK_CONTAINER (window->priv->open_document_popover),
+ GTK_WIDGET (window->priv->open_document_selector));
+
+ gtk_widget_show_all (GTK_WIDGET (window->priv->open_document_selector));
+
+ g_signal_connect (window->priv->open_document_selector,
+ "file-activated",
+ G_CALLBACK (on_recent_chooser_item_activated),
+ window);
+
+ fullscreen_controls_setup (window);
sync_fullscreen_actions (window, FALSE);
+ g_object_bind_property (gedit_open_document_selector_get_search_entry
(window->priv->open_document_selector),
+ "text",
+ gedit_open_document_selector_get_search_entry
(window->priv->fullscreen_open_document_selector),
+ "text",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
hamburger_menu = _gedit_app_get_hamburger_menu (GEDIT_APP (g_application_get_default ()));
if (hamburger_menu)
{
@@ -2733,9 +2772,14 @@ gedit_window_init (GeditWindow *window)
gtk_widget_set_no_show_all (GTK_WIDGET (window->priv->fullscreen_gear_button), TRUE);
}
+ g_signal_connect (GTK_TOGGLE_BUTTON (window->priv->fullscreen_open_button),
+ "toggled",
+ G_CALLBACK (on_fullscreen_file_menu_button_toggled),
+ window);
+
g_signal_connect (GTK_TOGGLE_BUTTON (window->priv->fullscreen_gear_button),
"toggled",
- G_CALLBACK (on_fullscreen_toggle_button_toggled),
+ G_CALLBACK (on_fullscreen_gear_button_toggled),
window);
/* Setup status bar */
@@ -2849,6 +2893,12 @@ gedit_window_init (GeditWindow *window)
G_CALLBACK (window_unrealized),
NULL);
+ /* Check if the window is active for fullscreen */
+ g_signal_connect (window,
+ "notify::is-active",
+ G_CALLBACK (check_window_is_active),
+ NULL);
+
gedit_debug_message (DEBUG_WINDOW, "Update plugins ui");
window->priv->extensions = peas_extension_set_new (PEAS_ENGINE (gedit_plugins_engine_get_default ()),
diff --git a/gedit/gedit.c b/gedit/gedit.c
index fcffdaca6..ee3769537 100644
--- a/gedit/gedit.c
+++ b/gedit/gedit.c
@@ -28,13 +28,12 @@
# include "gedit-app-win32.h"
#endif
+#include <glib.h>
#include <locale.h>
#include <libintl.h>
-#include <tepl/tepl.h>
#include "gedit-dirs.h"
#include "gedit-debug.h"
-#include "gedit-factory.h"
#include "gedit-settings.h"
#ifdef G_OS_WIN32
@@ -117,7 +116,6 @@ int
main (int argc, char *argv[])
{
GType type;
- GeditFactory *factory;
GeditApp *app;
gint status;
@@ -140,9 +138,6 @@ main (int argc, char *argv[])
gedit_dirs_init ();
setup_i18n ();
- tepl_init ();
- factory = gedit_factory_new ();
- tepl_abstract_factory_set_singleton (TEPL_ABSTRACT_FACTORY (factory));
app = g_object_new (type,
"application-id", "org.gnome.gedit",
@@ -167,7 +162,6 @@ main (int argc, char *argv[])
G_OBJECT (app)->ref_count);
}
- tepl_finalize ();
gedit_dirs_shutdown ();
#ifdef G_OS_WIN32
diff --git a/gedit/meson.build b/gedit/meson.build
index 9fc81468e..844b6bac8 100644
--- a/gedit/meson.build
+++ b/gedit/meson.build
@@ -8,6 +8,7 @@ libgedit_public_headers = [
'gedit-menu-extension.h',
'gedit-message-bus.h',
'gedit-message.h',
+ 'gedit-progress-info-bar.h',
'gedit-statusbar.h',
'gedit-tab.h',
'gedit-utils.h',
@@ -27,11 +28,13 @@ libgedit_public_sources = [
'gedit-menu-extension.c',
'gedit-message-bus.c',
'gedit-message.c',
+ 'gedit-progress-info-bar.c',
'gedit-statusbar.c',
'gedit-tab.c',
'gedit-utils.c',
'gedit-view-activatable.c',
'gedit-view.c',
+ 'gedit-view-centering.c',
'gedit-window-activatable.c',
'gedit-window.c',
]
@@ -45,30 +48,37 @@ libgedit_private_headers = [
'gedit-documents-panel.h',
'gedit-encoding-items.h',
'gedit-encodings-dialog.h',
- 'gedit-factory.h',
'gedit-file-chooser-dialog-gtk.h',
'gedit-file-chooser-dialog.h',
'gedit-file-chooser.h',
'gedit-file-chooser-open-dialog.h',
'gedit-file-chooser-open.h',
'gedit-file-chooser-open-native.h',
+ 'gedit-highlight-mode-dialog.h',
+ 'gedit-highlight-mode-selector.h',
'gedit-history-entry.h',
'gedit-io-error-info-bar.h',
'gedit-menu-stack-switcher.h',
+ 'gedit-metadata-manager.h',
'gedit-multi-notebook.h',
'gedit-notebook.h',
'gedit-notebook-popup-menu.h',
'gedit-notebook-stack-switcher.h',
+ 'gedit-open-document-selector.h',
+ 'gedit-open-document-selector-helper.h',
+ 'gedit-open-document-selector-store.h',
+ 'gedit-pango.h',
'gedit-plugins-engine.h',
'gedit-preferences-dialog.h',
'gedit-print-job.h',
'gedit-print-preview.h',
'gedit-recent.h',
- 'gedit-recent-osx.h',
'gedit-replace-dialog.h',
'gedit-settings.h',
'gedit-status-menu-button.h',
'gedit-tab-label.h',
+ 'gedit-tab-private.h',
+ 'gedit-view-centering.h',
'gedit-view-frame.h',
'gedit-window-private.h',
]
@@ -85,20 +95,26 @@ libgedit_private_sources = [
'gedit-documents-panel.c',
'gedit-encoding-items.c',
'gedit-encodings-dialog.c',
- 'gedit-factory.c',
'gedit-file-chooser.c',
'gedit-file-chooser-dialog.c',
'gedit-file-chooser-dialog-gtk.c',
'gedit-file-chooser-open.c',
'gedit-file-chooser-open-dialog.c',
'gedit-file-chooser-open-native.c',
+ 'gedit-highlight-mode-dialog.c',
+ 'gedit-highlight-mode-selector.c',
'gedit-history-entry.c',
'gedit-io-error-info-bar.c',
'gedit-menu-stack-switcher.c',
+ 'gedit-metadata-manager.c',
'gedit-multi-notebook.c',
'gedit-notebook.c',
'gedit-notebook-popup-menu.c',
'gedit-notebook-stack-switcher.c',
+ 'gedit-open-document-selector.c',
+ 'gedit-open-document-selector-helper.c',
+ 'gedit-open-document-selector-store.c',
+ 'gedit-pango.c',
'gedit-plugins-engine.c',
'gedit-preferences-dialog.c',
'gedit-print-job.c',
@@ -117,6 +133,7 @@ libgedit_link_args = []
libgedit_deps = [
deps_basic_list,
libgd_dep,
+ libxml_dep,
]
if host_machine.system() == 'darwin'
diff --git a/gedit/resources/css/gedit-style.css b/gedit/resources/css/gedit-style.css
index eb43a8233..7036567c4 100644
--- a/gedit/resources/css/gedit-style.css
+++ b/gedit/resources/css/gedit-style.css
@@ -14,6 +14,18 @@
padding: 12px;
}
+.gedit-map-frame:dir(ltr) border {
+ border-width: 0 0 0 1px;
+}
+
+.gedit-map-frame:dir(rtl) border {
+ border-width: 0 1px 0 0;
+}
+
+.open-document-selector-treeview {
+ padding: 3px 6px 3px 6px;
+}
+
statusbar frame {
border: none;
padding-left: 6px;
diff --git a/gedit/resources/css/gedit.adwaita.css b/gedit/resources/css/gedit.adwaita.css
index 784e72aa2..8377c62a9 100644
--- a/gedit/resources/css/gedit.adwaita.css
+++ b/gedit/resources/css/gedit.adwaita.css
@@ -1,3 +1,28 @@
+.open-document-selector-treeview:hover {
+ background-color: alpha(@theme_fg_color, 0.05);
+}
+
+.open-document-selector-treeview:selected:hover {
+ background-color: @theme_selected_bg_color;
+}
+
+/* Only normal state is handle */
+.open-document-selector-name-label {
+ color: @theme_fg_color;
+}
+
+/* Only normal state is handle */
+.open-document-selector-path-label {
+ color: @theme_unfocused_fg_color;
+ font-size: smaller;
+}
+
+/* Only normal state is handle */
+.open-document-selector-match {
+ color: shade (@theme_fg_color, 0.6);
+ background-color: alpha(@warning_color, 0.4);
+}
+
.gedit-document-panel {
background-color: @sidebar_bg;
}
diff --git a/gedit/resources/gedit.gresource.xml.in b/gedit/resources/gedit.gresource.xml.in
index a5905110e..b0a70c185 100644
--- a/gedit/resources/gedit.gresource.xml.in
+++ b/gedit/resources/gedit.gresource.xml.in
@@ -8,10 +8,14 @@
<file preprocess="xml-stripblanks">ui/gedit-replace-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/gedit-print-preview.ui</file>
<file preprocess="xml-stripblanks">ui/gedit-print-preferences.ui</file>
+ <file preprocess="xml-stripblanks">ui/gedit-progress-info-bar.ui</file>
<file preprocess="xml-stripblanks">ui/gedit-status-menu-button.ui</file>
<file preprocess="xml-stripblanks">ui/gedit-tab-label.ui</file>
<file preprocess="xml-stripblanks">ui/gedit-view-frame.ui</file>
+ <file preprocess="xml-stripblanks">ui/gedit-highlight-mode-dialog.ui</file>
+ <file preprocess="xml-stripblanks">ui/gedit-highlight-mode-selector.ui</file>
<file preprocess="xml-stripblanks">ui/gedit-window.ui</file>
+ <file preprocess="xml-stripblanks">ui/gedit-open-document-selector.ui</file>
<file preprocess="xml-stripblanks">ui/gedit-shortcuts.ui</file>
<file preprocess="xml-stripblanks">ui/gedit-statusbar.ui</file>
<file>css/gedit-style.css</file>
diff --git a/gedit/resources/ui/gedit-highlight-mode-dialog.ui
b/gedit/resources/ui/gedit-highlight-mode-dialog.ui
new file mode 100644
index 000000000..31b8690bd
--- /dev/null
+++ b/gedit/resources/ui/gedit-highlight-mode-dialog.ui
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.8 -->
+ <template class="GeditHighlightModeDialog" parent="GtkDialog">
+ <property name="width_request">300</property>
+ <property name="height_request">400</property>
+ <property name="can_focus">False</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Highlight Mode</property>
+ <property name="type_hint">dialog</property>
+ <property name="modal">True</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <property name="layout_style">end</property>
+ <property name="border_width">5</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok_button">
+ <property name="label" translatable="yes">_Select</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <property name="receives_default">True</property>
+ <property name="can_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GeditHighlightModeSelector" id="selector">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancel_button</action-widget>
+ <action-widget response="-5">ok_button</action-widget>
+ </action-widgets>
+ </template>
+</interface>
diff --git a/gedit/resources/ui/gedit-highlight-mode-selector.ui
b/gedit/resources/ui/gedit-highlight-mode-selector.ui
new file mode 100644
index 000000000..1aa5c950e
--- /dev/null
+++ b/gedit/resources/ui/gedit-highlight-mode-selector.ui
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.8 -->
+ <object class="GtkListStore" id="liststore">
+ <columns>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name lang -->
+ <column type="GtkSourceLanguage"/>
+ </columns>
+ </object>
+ <object class="GtkTreeModelFilter" id="treemodelfilter">
+ <property name="child_model">liststore</property>
+ </object>
+ <template class="GeditHighlightModeSelector" parent="GtkGrid">
+ <property name="width_request">300</property>
+ <property name="height_request">400</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <property name="row_spacing">3</property>
+ <property name="border_width">6</property>
+ <child>
+ <object class="GtkSearchEntry" id="entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="is_focus">False</property>
+ <property name="activates_default">True</property>
+ <property name="placeholder_text" translatable="yes">Search highlight mode…</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <property name="model">treemodelfilter</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="enable_search">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview_selection"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/gedit/resources/ui/gedit-open-document-selector.ui
b/gedit/resources/ui/gedit-open-document-selector.ui
new file mode 100644
index 000000000..9393ac46c
--- /dev/null
+++ b/gedit/resources/ui/gedit-open-document-selector.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <template class="GeditOpenDocumentSelector" parent="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">9</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="placeholder_box">
+ <property name="visible">False</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkBox" id="placeholder_inner_box">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkImage" id="placeholder_image">
+ <property name="visible">True</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ <property name="pixel_size">64</property>
+ <property name="can_focus">False</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="placeholder_label">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">No results</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled_window">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="headers_visible">False</property>
+ <property name="fixed_height_mode">True</property>
+ <property name="enable_grid_lines">horizontal</property>
+ <property name="enable_search">False</property>
+ <property name="activate_on_single_click">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="open_button">
+ <property name="label" translatable="yes">Other _Documents…</property>
+ <property name="use-underline">True</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Open another file</property>
+ <property name="margin-top">6</property>
+ <property name="action_name">win.open</property>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/gedit/resources/ui/gedit-preferences-dialog.ui b/gedit/resources/ui/gedit-preferences-dialog.ui
index f1eeed45c..1ce0755da 100644
--- a/gedit/resources/ui/gedit-preferences-dialog.ui
+++ b/gedit/resources/ui/gedit-preferences-dialog.ui
@@ -105,6 +105,21 @@
<property name="width">2</property>
</packing>
</child>
+ <child>
+ <object class="GtkCheckButton" id="display_overview_map_checkbutton">
+ <property name="label" translatable="yes">Display _overview map</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
<child>
<object class="GtkCheckButton" id="display_grid_checkbutton">
<property name="label" translatable="yes">Display _grid pattern</property>
@@ -116,7 +131,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">3</property>
+ <property name="top_attach">4</property>
<property name="width">2</property>
</packing>
</child>
@@ -630,8 +645,19 @@
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
- <object class="TeplStyleSchemeChooserWidget" id="schemes_list">
+ <object class="GtkScrolledWindow" id="schemes_scrolled_window">
<property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">etched-in</property>
+ <property name="min_content_height">200</property>
+ <child>
+ <object class="GtkSourceStyleSchemeChooserWidget" id="schemes_list">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
</object>
<packing>
<property name="left_attach">0</property>
diff --git a/gedit/resources/ui/gedit-progress-info-bar.ui b/gedit/resources/ui/gedit-progress-info-bar.ui
new file mode 100644
index 000000000..3f733e4b6
--- /dev/null
+++ b/gedit/resources/ui/gedit-progress-info-bar.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.6 -->
+ <template class="GeditProgressInfoBar" parent="GtkInfoBar">
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="message_type">other</property>
+ <child internal-child="content_area">
+ <object class="GtkBox" id="infobar-content_area1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-size">2</property>
+ <property name="icon_name">image-missing</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">label</property>
+ <property name="use_markup">True</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkProgressBar" id="progress">
+ <property name="height_request">15</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="infobar-action_area1">
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/gedit/resources/ui/gedit-view-frame.ui b/gedit/resources/ui/gedit-view-frame.ui
index ebf70b013..b61d82c3a 100644
--- a/gedit/resources/ui/gedit-view-frame.ui
+++ b/gedit/resources/ui/gedit-view-frame.ui
@@ -7,15 +7,33 @@
<property name="has_focus">False</property>
<property name="is_focus">False</property>
<child>
- <object class="GtkScrolledWindow" id="scrolled_window">
+ <object class="GtkGrid" id="grid">
<property name="visible">True</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="overlay_scrolling">False</property>
<child>
- <object class="GeditView" id="view">
+ <object class="GeditViewCentering" id="view_centering">
<property name="visible">True</property>
- <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GeditView" id="view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkFrame" id="map_frame">
+ <property name="visible">True</property>
+ <style>
+ <class name="gedit-map-frame"/>
+ </style>
+ <child>
+ <object class="GtkSourceMap" id="map">
+ <property name="visible">True</property>
+ <property name="view">view</property>
+ </object>
+ </child>
</object>
</child>
</object>
diff --git a/gedit/resources/ui/gedit-window.ui b/gedit/resources/ui/gedit-window.ui
index 0d131ad69..b6283dcf4 100644
--- a/gedit/resources/ui/gedit-window.ui
+++ b/gedit/resources/ui/gedit-window.ui
@@ -27,6 +27,50 @@
<object class="GtkHeaderBar" id="headerbar">
<property name="visible">True</property>
<property name="show_close_button">True</property>
+ <child>
+ <object class="GtkMenuButton" id="open_button">
+ <property name="visible">True</property>
+ <property name="tooltip_text" translatable="yes">Open a file</property>
+ <property name="valign">center</property>
+ <property name="use_popover">True</property>
+ <style>
+ <class name="text-button"/>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkBox" id="open_button_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="open_button_name">
+ <property name="label" translatable="yes">_Open</property>
+ <property name="use-underline">True</property>
+ <property name="visible">True</property>
+ <property name="valign">baseline</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="open_button_arrow">
+ <property name="visible">True</property>
+ <property name="valign">baseline</property>
+ <property name="icon_name">pan-down-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="open_button_a11y">
+ <property name="accessible-name" translatable="yes">Open</property>
+ <property name="accessible-description" translatable="yes">Open a file</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">start</property>
+ </packing>
+ </child>
<child>
<object class="GtkButton" id="new_button">
<property name="visible">True</property>
@@ -310,7 +354,7 @@
<property name="can_focus">False</property>
<property name="valign">start</property>
<child>
- <object class="GtkRevealer" id="fullscreen_revealer">
+ <object class="GtkRevealer" id="fullscreen_controls">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="reveal_child">False</property>
@@ -318,6 +362,47 @@
<child>
<object class="GtkHeaderBar" id="fullscreen_headerbar">
<property name="visible">True</property>
+ <child>
+ <object class="GtkMenuButton" id="fullscreen_open_button">
+ <property name="visible">True</property>
+ <property name="tooltip_text" translatable="yes">Open a file dialog</property>
+ <property name="valign">center</property>
+ <property name="use_popover">True</property>
+ <style>
+ <class name="text-button"/>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkBox" id="fullscreen_open_button_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_focus">False</property>
+ <property name="is_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="fullscreen_open_button_name">
+ <property name="label" translatable="yes">Open</property>
+ <property name="visible">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="fullscreen_open_button_arrow">
+ <property name="visible">True</property>
+ <property name="icon_name">pan-down-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="fullscreen_open_button_a11y">
+ <property name="accessible-name" translatable="yes">Open</property>
+ <property name="accessible-description" translatable="yes">Open a file</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">start</property>
+ </packing>
+ </child>
<child>
<object class="GtkButton" id="fullscreen_new_button">
<property name="visible">True</property>
diff --git a/help/C/gedit-tab-groups.page b/help/C/gedit-tab-groups.page
index a25fcb6e0..d7ed84e8b 100644
--- a/help/C/gedit-tab-groups.page
+++ b/help/C/gedit-tab-groups.page
@@ -24,8 +24,8 @@
<p>If you are working with multiple tabs in <app>gedit</app> you can group
them, making it easier to keep your opened files organized. Adding a new tab
group will divide the <app>gedit</app> window in two panes, open a new
- “Untitled File†in the new pane, and make it active. You can open files into
- that tab group and move tabs from one tab group to another.</p>
+ “Untitled Document†in the new pane, and make it active. You can open files
+ into that tab group and move tabs from one tab group to another.</p>
<section id="open-new-tab-group">
<title>Open a new tab group in the gedit window</title>
diff --git a/meson.build b/meson.build
index be77a885f..ef77bc8a8 100644
--- a/meson.build
+++ b/meson.build
@@ -40,13 +40,25 @@ libgd_subproject = subproject(
libgd_dep = libgd_subproject.get_variable('libgd_dep')
# Dependencies
-gio_dep = dependency('gio-2.0', version: '>= 2.64')
+glib_req = '>= 2.64'
+gtk_req = '>= 2.22'
+gtksourceview_req = '>= 4.0'
+libpeas_req = '>= 1.14.1'
+libxml_req = '>= 2.5.0'
+gspell_req = '>= 1.0'
+pygobject_req = '>= 3.0.0'
+
+gio_dep = dependency('gio-2.0', version: glib_req)
+libxml_dep = dependency('libxml-2.0', version: libxml_req)
+gspell_dep = dependency('gspell-1', version: gspell_req)
+
+python3 = python.find_installation('python3')
libgedit_public_deps = [
gio_dep,
- dependency('gtk+-3.0', version: '>= 3.22'),
- dependency('tepl-6', version: '>= 5.99.0'),
- dependency('libpeas-gtk-1.0'),
+ dependency('gtk+-3.0', version: gtk_req),
+ dependency('gtksourceview-4', version: gtksourceview_req),
+ dependency('libpeas-gtk-1.0', version: libpeas_req),
]
deps_basic_list = [
@@ -54,9 +66,6 @@ deps_basic_list = [
dependency('gobject-introspection-1.0'),
]
-gspell_dep = dependency('gspell-1', version: '>= 1.0')
-python3 = python.find_installation('python3')
-
# Configurations
config_h = configuration_data()
config_h.set_quoted('PACKAGE_STRING', 'gedit-@0@'.format(api_version))
@@ -65,6 +74,17 @@ config_h.set_quoted('LIBDIR', join_paths(get_option('prefix'), get_option('libdi
config_h.set_quoted('DATADIR', join_paths(get_option('prefix'), get_option('datadir')))
config_h.set_quoted('VERSION', meson.project_version())
+enable_gvfs_metadata = get_option('enable-gvfs-metadata')
+if enable_gvfs_metadata == 'yes' or (enable_gvfs_metadata == 'auto' and host_machine.system() == 'linux')
+ enable_gvfs_metadata = true
+else
+ enable_gvfs_metadata = false
+endif
+
+if enable_gvfs_metadata
+ config_h.set('ENABLE_GVFS_METADATA', 1)
+endif
+
configure_file(
output: 'config.h',
configuration: config_h
diff --git a/meson_options.txt b/meson_options.txt
index 4e842d1ea..33d03cb14 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -21,4 +21,11 @@ option(
description: 'Build user documentation'
)
+option(
+ 'enable-gvfs-metadata',
+ type: 'combo',
+ choices: ['yes', 'no', 'auto'], value: 'auto',
+ description: 'Enable using gvfs to store metadata'
+)
+
option('plugin_externaltools', type: 'boolean', value: true)
diff --git a/plugins/snippets/snippets/document.py b/plugins/snippets/snippets/document.py
index 003237d17..23df28091 100644
--- a/plugins/snippets/snippets/document.py
+++ b/plugins/snippets/snippets/document.py
@@ -162,13 +162,13 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
buf = self.view.get_buffer()
self.connect_signal(buf, 'changed', self.on_buffer_changed)
- self.connect_signal(buf, 'tepl-cursor-moved', self.on_buffer_cursor_moved)
+ self.connect_signal(buf, 'cursor-moved', self.on_buffer_cursor_moved)
self.connect_signal_after(buf, 'insert-text', self.on_buffer_insert_text)
def last_snippet_removed(self):
buf = self.view.get_buffer()
self.disconnect_signal(buf, 'changed')
- self.disconnect_signal(buf, 'tepl-cursor-moved')
+ self.disconnect_signal(buf, 'cursor-moved')
self.disconnect_signal(buf, 'insert-text')
def current_placeholder(self):
@@ -559,7 +559,7 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
self.goto_placeholder(current, None)
if len(self.active_snippets) > 0:
- self.block_signal(buf, 'tepl-cursor-moved')
+ self.block_signal(buf, 'cursor-moved')
buf.begin_user_action()
@@ -569,7 +569,7 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
# Insert the snippet
if len(self.active_snippets) == 0:
self.first_snippet_inserted()
- self.block_signal(buf, 'tepl-cursor-moved')
+ self.block_signal(buf, 'cursor-moved')
sn = s.insert_into(self, start)
self.active_snippets.append(sn)
@@ -585,7 +585,7 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
else:
self.goto_placeholder(self.active_placeholder, sn.placeholders[keys[0]])
- self.unblock_signal(buf, 'tepl-cursor-moved')
+ self.unblock_signal(buf, 'cursor-moved')
if sn in self.active_snippets:
# Check if we can get end_iter in view without moving the
diff --git a/plugins/spell/gedit-spell-plugin.c b/plugins/spell/gedit-spell-plugin.c
index 611677826..47d449433 100644
--- a/plugins/spell/gedit-spell-plugin.c
+++ b/plugins/spell/gedit-spell-plugin.c
@@ -30,8 +30,13 @@
#include "gedit-spell-app-activatable.h"
-#define GEDIT_METADATA_ATTRIBUTE_SPELL_LANGUAGE "gedit-spell-language"
-#define GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED "gedit-spell-enabled"
+#ifdef G_OS_WIN32
+#define GEDIT_METADATA_ATTRIBUTE_SPELL_LANGUAGE "spell-language"
+#define GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED "spell-enabled"
+#else
+#define GEDIT_METADATA_ATTRIBUTE_SPELL_LANGUAGE "metadata::gedit-spell-language"
+#define GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED "metadata::gedit-spell-enabled"
+#endif
#define SPELL_ENABLED_STR "1"
#define SPELL_BASE_SETTINGS "org.gnome.gedit.plugins.spell"
diff --git a/po/POTFILES.in b/po/POTFILES.in
index be8af499a..25ff2db1a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -16,19 +16,22 @@ gedit/gedit-documents-panel.c
gedit/gedit-encodings-combo-box.c
gedit/gedit-encoding-items.c
gedit/gedit-encodings-dialog.c
-gedit/gedit-factory.c
gedit/gedit-file-chooser.c
gedit/gedit-file-chooser-dialog-gtk.c
gedit/gedit-file-chooser-open.c
gedit/gedit-file-chooser-open-dialog.c
gedit/gedit-file-chooser-open-native.c
+gedit/gedit-highlight-mode-dialog.c
+gedit/gedit-highlight-mode-selector.c
gedit/gedit-io-error-info-bar.c
gedit/gedit-notebook.c
gedit/gedit-notebook-popup-menu.c
+gedit/gedit-open-document-selector.c
gedit/gedit-plugins-engine.c
gedit/gedit-preferences-dialog.c
gedit/gedit-print-job.c
gedit/gedit-print-preview.c
+gedit/gedit-progress-info-bar.c
gedit/gedit-replace-dialog.c
gedit/gedit-statusbar.c
gedit/gedit-tab.c
@@ -41,6 +44,9 @@ gedit/resources/gtk/menus-common.ui
gedit/resources/gtk/menus.ui
gedit/resources/gtk/menus-traditional.ui
gedit/resources/ui/gedit-encodings-dialog.ui
+gedit/resources/ui/gedit-highlight-mode-dialog.ui
+gedit/resources/ui/gedit-highlight-mode-selector.ui
+gedit/resources/ui/gedit-open-document-selector.ui
gedit/resources/ui/gedit-preferences-dialog.ui
gedit/resources/ui/gedit-print-preferences.ui
gedit/resources/ui/gedit-print-preview.ui
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]