Tree of tag thunar-4.20.2 (commit 11a519f) from https://gitlab.xfce.org/xfce/thunar. Upstream history is not included here to keep the repository small.
814 lines
26 KiB
C
814 lines
26 KiB
C
/* vi:set et ai sw=2 sts=2 ts=2: */
|
|
/*-
|
|
* Copyright (c) 2006 Benedikt Meurer <benny@xfce.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_MEMORY_H
|
|
#include <memory.h>
|
|
#endif
|
|
#ifdef HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_PCRE2
|
|
#define PCRE2_CODE_UNIT_WIDTH 8
|
|
#include <pcre2.h>
|
|
#endif
|
|
|
|
#include <libxfce4util/libxfce4util.h>
|
|
#include <thunar-sbr/thunar-sbr-replace-renamer.h>
|
|
|
|
|
|
|
|
/* Property identifiers */
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_CASE_SENSITIVE,
|
|
PROP_PATTERN,
|
|
PROP_REPLACEMENT,
|
|
PROP_REGEXP,
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
thunar_sbr_replace_renamer_finalize (GObject *object);
|
|
static void
|
|
thunar_sbr_replace_renamer_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
static void
|
|
thunar_sbr_replace_renamer_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
static void
|
|
thunar_sbr_replace_renamer_realize (GtkWidget *widget);
|
|
static gchar *
|
|
thunar_sbr_replace_renamer_process (ThunarxRenamer *renamer,
|
|
ThunarxFileInfo *file,
|
|
const gchar *text,
|
|
guint idx);
|
|
#ifdef HAVE_PCRE2
|
|
static gchar *
|
|
thunar_sbr_replace_renamer_pcre_exec (ThunarSbrReplaceRenamer *replace_renamer,
|
|
const gchar *text);
|
|
static void
|
|
thunar_sbr_replace_renamer_pcre_update (ThunarSbrReplaceRenamer *replace_renamer);
|
|
#endif
|
|
|
|
|
|
|
|
struct _ThunarSbrReplaceRenamerClass
|
|
{
|
|
ThunarxRenamerClass __parent__;
|
|
};
|
|
|
|
struct _ThunarSbrReplaceRenamer
|
|
{
|
|
ThunarxRenamer __parent__;
|
|
GtkWidget *pattern_entry;
|
|
gboolean case_sensitive;
|
|
gboolean regexp;
|
|
gchar *pattern;
|
|
gchar *replacement;
|
|
|
|
/* TRUE if PCRE is available and supports UTF-8 */
|
|
gint utf8_regexp_supported;
|
|
|
|
/* PCRE compiled pattern */
|
|
#ifdef HAVE_PCRE2
|
|
pcre2_code *pcre_pattern;
|
|
gint pcre_capture_count;
|
|
#endif
|
|
};
|
|
|
|
|
|
|
|
THUNARX_DEFINE_TYPE (ThunarSbrReplaceRenamer, thunar_sbr_replace_renamer, THUNARX_TYPE_RENAMER);
|
|
|
|
|
|
|
|
static void
|
|
thunar_sbr_replace_renamer_class_init (ThunarSbrReplaceRenamerClass *klass)
|
|
{
|
|
ThunarxRenamerClass *thunarxrenamer_class;
|
|
GtkWidgetClass *gtkwidget_class;
|
|
GObjectClass *gobject_class;
|
|
|
|
gobject_class = G_OBJECT_CLASS (klass);
|
|
gobject_class->finalize = thunar_sbr_replace_renamer_finalize;
|
|
gobject_class->get_property = thunar_sbr_replace_renamer_get_property;
|
|
gobject_class->set_property = thunar_sbr_replace_renamer_set_property;
|
|
|
|
gtkwidget_class = GTK_WIDGET_CLASS (klass);
|
|
gtkwidget_class->realize = thunar_sbr_replace_renamer_realize;
|
|
|
|
thunarxrenamer_class = THUNARX_RENAMER_CLASS (klass);
|
|
thunarxrenamer_class->process = thunar_sbr_replace_renamer_process;
|
|
|
|
/**
|
|
* ThunarSbrReplaceRenamer:case-sensitive:
|
|
*
|
|
* Whether to use case sensitive search and replace.
|
|
**/
|
|
g_object_class_install_property (gobject_class,
|
|
PROP_CASE_SENSITIVE,
|
|
g_param_spec_boolean ("case-sensitive",
|
|
"case-sensitive",
|
|
"case-sensitive",
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
/**
|
|
* ThunarSbrReplaceRenamer:pattern:
|
|
*
|
|
* The search pattern.
|
|
**/
|
|
g_object_class_install_property (gobject_class,
|
|
PROP_PATTERN,
|
|
g_param_spec_string ("pattern",
|
|
"pattern",
|
|
"pattern",
|
|
NULL,
|
|
G_PARAM_READWRITE));
|
|
|
|
/**
|
|
* ThunarSbrReplaceRenamer:replacement:
|
|
*
|
|
* The replacement text.
|
|
**/
|
|
g_object_class_install_property (gobject_class,
|
|
PROP_REPLACEMENT,
|
|
g_param_spec_string ("replacement",
|
|
"replacement",
|
|
"replacement",
|
|
NULL,
|
|
G_PARAM_READWRITE));
|
|
|
|
/**
|
|
* ThunarSbrReplaceRenamer:regexp:
|
|
*
|
|
* Whether to use regular expressions.
|
|
**/
|
|
g_object_class_install_property (gobject_class,
|
|
PROP_REGEXP,
|
|
g_param_spec_boolean ("regexp",
|
|
"regexp",
|
|
"regexp",
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_sbr_replace_renamer_init (ThunarSbrReplaceRenamer *replace_renamer)
|
|
{
|
|
AtkRelationSet *relations;
|
|
AtkRelation *relation;
|
|
AtkObject *object;
|
|
GtkWidget *grid;
|
|
GtkWidget *label;
|
|
GtkWidget *entry;
|
|
GtkWidget *button;
|
|
uint32_t pcre2_compiled_widths;
|
|
|
|
replace_renamer->utf8_regexp_supported = FALSE;
|
|
|
|
#ifdef HAVE_PCRE2
|
|
/* check if PCRE supports UTF-8 */
|
|
if (pcre2_config (PCRE2_CONFIG_COMPILED_WIDTHS, &pcre2_compiled_widths) >= 0)
|
|
{
|
|
/* bit0 indicates 8-bit support. bit1 and bit2 indicate 16-bit and 32-bit support respectively. */
|
|
if ((pcre2_compiled_widths & (1 << 0)) != 0)
|
|
replace_renamer->utf8_regexp_supported = TRUE;
|
|
}
|
|
#endif
|
|
|
|
grid = gtk_grid_new ();
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
|
|
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
|
gtk_box_pack_start (GTK_BOX (replace_renamer), grid, FALSE, FALSE, 0);
|
|
gtk_widget_show (grid);
|
|
|
|
label = gtk_label_new_with_mnemonic (_("_Search For:"));
|
|
gtk_label_set_xalign (GTK_LABEL (label), 1.0f);
|
|
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
|
|
gtk_widget_show (label);
|
|
|
|
replace_renamer->pattern_entry = gtk_entry_new ();
|
|
gtk_entry_set_activates_default (GTK_ENTRY (replace_renamer->pattern_entry), TRUE);
|
|
g_object_bind_property (G_OBJECT (replace_renamer->pattern_entry), "text", G_OBJECT (replace_renamer), "pattern", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
|
gtk_widget_set_tooltip_text (replace_renamer->pattern_entry, _("Enter the text to search for in the file names."));
|
|
gtk_widget_set_hexpand (replace_renamer->pattern_entry, TRUE);
|
|
gtk_grid_attach (GTK_GRID (grid), replace_renamer->pattern_entry, 1, 0, 1, 1);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), replace_renamer->pattern_entry);
|
|
gtk_widget_show (replace_renamer->pattern_entry);
|
|
|
|
/* set Atk label relation for the entry */
|
|
object = gtk_widget_get_accessible (replace_renamer->pattern_entry);
|
|
relations = atk_object_ref_relation_set (gtk_widget_get_accessible (label));
|
|
relation = atk_relation_new (&object, 1, ATK_RELATION_LABEL_FOR);
|
|
atk_relation_set_add (relations, relation);
|
|
g_object_unref (G_OBJECT (relation));
|
|
g_object_unref (relations);
|
|
|
|
button = gtk_check_button_new_with_mnemonic (_("Regular _Expression"));
|
|
g_object_bind_property (G_OBJECT (button), "active", G_OBJECT (replace_renamer), "regexp", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
|
gtk_widget_set_tooltip_text (button, _("If you enable this option, the pattern will be treated as a regular expression and "
|
|
"matched using the Perl-compatible regular expressions (PCRE). Check the documentation "
|
|
"for details about the regular expression syntax."));
|
|
gtk_grid_attach (GTK_GRID (grid), button, 2, 0, 1, 1);
|
|
gtk_widget_set_sensitive (button, replace_renamer->utf8_regexp_supported);
|
|
gtk_widget_show (button);
|
|
|
|
label = gtk_label_new_with_mnemonic (_("Replace _With:"));
|
|
gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
|
|
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
|
|
gtk_widget_show (label);
|
|
|
|
entry = gtk_entry_new ();
|
|
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
|
|
g_object_bind_property (G_OBJECT (entry), "text", G_OBJECT (replace_renamer), "replacement", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
|
gtk_widget_set_tooltip_text (entry, _("Enter the text that should be used as replacement for the pattern above."));
|
|
gtk_widget_set_hexpand (entry, TRUE);
|
|
gtk_grid_attach (GTK_GRID (grid), entry, 1, 1, 1, 1);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
|
|
gtk_widget_show (entry);
|
|
|
|
/* set Atk label relation for the entry */
|
|
object = gtk_widget_get_accessible (entry);
|
|
relations = atk_object_ref_relation_set (gtk_widget_get_accessible (label));
|
|
relation = atk_relation_new (&object, 1, ATK_RELATION_LABEL_FOR);
|
|
atk_relation_set_add (relations, relation);
|
|
g_object_unref (G_OBJECT (relation));
|
|
g_object_unref (relations);
|
|
|
|
button = gtk_check_button_new_with_mnemonic (_("C_ase Sensitive Search"));
|
|
g_object_bind_property (G_OBJECT (button), "active", G_OBJECT (replace_renamer), "case-sensitive", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
|
gtk_widget_set_tooltip_text (button, _("If you enable this option, the pattern will be searched in a case-sensitive manner. "
|
|
"The default is to use a case-insensitive search."));
|
|
gtk_grid_attach (GTK_GRID (grid), button, 2, 1, 1, 1);
|
|
gtk_widget_show (button);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_sbr_replace_renamer_finalize (GObject *object)
|
|
{
|
|
ThunarSbrReplaceRenamer *replace_renamer = THUNAR_SBR_REPLACE_RENAMER (object);
|
|
|
|
/* release the PCRE pattern (if any) */
|
|
#ifdef HAVE_PCRE2
|
|
if (G_UNLIKELY (replace_renamer->pcre_pattern != NULL))
|
|
pcre2_code_free (replace_renamer->pcre_pattern);
|
|
#endif
|
|
|
|
/* release the strings */
|
|
g_free (replace_renamer->replacement);
|
|
g_free (replace_renamer->pattern);
|
|
|
|
(*G_OBJECT_CLASS (thunar_sbr_replace_renamer_parent_class)->finalize) (object);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_sbr_replace_renamer_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ThunarSbrReplaceRenamer *replace_renamer = THUNAR_SBR_REPLACE_RENAMER (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_CASE_SENSITIVE:
|
|
g_value_set_boolean (value, thunar_sbr_replace_renamer_get_case_sensitive (replace_renamer));
|
|
break;
|
|
|
|
case PROP_PATTERN:
|
|
g_value_set_string (value, thunar_sbr_replace_renamer_get_pattern (replace_renamer));
|
|
break;
|
|
|
|
case PROP_REPLACEMENT:
|
|
g_value_set_string (value, thunar_sbr_replace_renamer_get_replacement (replace_renamer));
|
|
break;
|
|
|
|
case PROP_REGEXP:
|
|
g_value_set_boolean (value, thunar_sbr_replace_renamer_get_regexp (replace_renamer));
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_sbr_replace_renamer_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ThunarSbrReplaceRenamer *replace_renamer = THUNAR_SBR_REPLACE_RENAMER (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_CASE_SENSITIVE:
|
|
thunar_sbr_replace_renamer_set_case_sensitive (replace_renamer, g_value_get_boolean (value));
|
|
break;
|
|
|
|
case PROP_PATTERN:
|
|
thunar_sbr_replace_renamer_set_pattern (replace_renamer, g_value_get_string (value));
|
|
break;
|
|
|
|
case PROP_REPLACEMENT:
|
|
thunar_sbr_replace_renamer_set_replacement (replace_renamer, g_value_get_string (value));
|
|
break;
|
|
|
|
case PROP_REGEXP:
|
|
thunar_sbr_replace_renamer_set_regexp (replace_renamer, g_value_get_boolean (value));
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_sbr_replace_renamer_realize (GtkWidget *widget)
|
|
{
|
|
/* realize the widget */
|
|
(*GTK_WIDGET_CLASS (thunar_sbr_replace_renamer_parent_class)->realize) (widget);
|
|
|
|
#ifdef HAVE_PCRE2
|
|
/* update the PCRE pattern */
|
|
thunar_sbr_replace_renamer_pcre_update (THUNAR_SBR_REPLACE_RENAMER (widget));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
static gchar *
|
|
tsrr_replace (const gchar *text,
|
|
const gchar *pattern,
|
|
const gchar *replacement,
|
|
gboolean case_sensitive)
|
|
{
|
|
const gchar *p;
|
|
const gchar *t;
|
|
gunichar pc;
|
|
gunichar tc;
|
|
GString *result = g_string_sized_new (32);
|
|
|
|
while (*text != '\0')
|
|
{
|
|
/* compare the pattern to this part of the text */
|
|
for (p = pattern, t = text; *p != '\0' && *t != '\0'; p = g_utf8_next_char (p), t = g_utf8_next_char (t))
|
|
{
|
|
/* determine the next unichars */
|
|
pc = g_utf8_get_char (p);
|
|
tc = g_utf8_get_char (t);
|
|
|
|
/* check if the chars don't match */
|
|
if (pc != tc && (case_sensitive || g_unichar_toupper (pc) != g_unichar_toupper (tc)))
|
|
break;
|
|
}
|
|
|
|
/* check if the pattern matches */
|
|
if (G_UNLIKELY (*p == '\0'))
|
|
{
|
|
/* append the replacement to the result... */
|
|
g_string_append (result, replacement);
|
|
|
|
/* ...and skip to the text after the pattern */
|
|
text = t;
|
|
}
|
|
else
|
|
{
|
|
/* just append the text char */
|
|
g_string_append_unichar (result, g_utf8_get_char (text));
|
|
text = g_utf8_next_char (text);
|
|
}
|
|
}
|
|
|
|
return g_string_free (result, FALSE);
|
|
}
|
|
|
|
|
|
|
|
static gchar *
|
|
thunar_sbr_replace_renamer_process (ThunarxRenamer *renamer,
|
|
ThunarxFileInfo *file,
|
|
const gchar *text,
|
|
guint idx)
|
|
{
|
|
ThunarSbrReplaceRenamer *replace_renamer = THUNAR_SBR_REPLACE_RENAMER (renamer);
|
|
|
|
/* nothing to replace if we don't have a pattern */
|
|
if (G_UNLIKELY (replace_renamer->pattern == NULL || *replace_renamer->pattern == '\0'))
|
|
return g_strdup (text);
|
|
|
|
/* check if we should use regular expression */
|
|
if (G_UNLIKELY (replace_renamer->regexp))
|
|
{
|
|
#ifdef HAVE_PCRE2
|
|
/* check if the pattern failed to compile */
|
|
if (G_UNLIKELY (replace_renamer->pcre_pattern == NULL))
|
|
return g_strdup (text);
|
|
|
|
/* just execute the pattern */
|
|
return thunar_sbr_replace_renamer_pcre_exec (replace_renamer, text);
|
|
#endif
|
|
}
|
|
|
|
/* perform the replace operation */
|
|
return tsrr_replace (text, replace_renamer->pattern, replace_renamer->replacement, replace_renamer->case_sensitive);
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_PCRE2
|
|
static gchar *
|
|
thunar_sbr_replace_renamer_pcre_exec (ThunarSbrReplaceRenamer *replace_renamer,
|
|
const gchar *subject)
|
|
{
|
|
GString *result;
|
|
int error;
|
|
PCRE2_SIZE erroffset;
|
|
gchar output[1024];
|
|
pcre2_code *compiled_pattern;
|
|
PCRE2_SIZE outlen;
|
|
int n_substitutions; /* number of substitutions that were carried out */
|
|
|
|
result = g_string_sized_new (32);
|
|
|
|
compiled_pattern = pcre2_compile_8 ((PCRE2_SPTR) replace_renamer->pattern,
|
|
PCRE2_ZERO_TERMINATED,
|
|
0,
|
|
&error,
|
|
&erroffset,
|
|
0);
|
|
if (compiled_pattern == NULL)
|
|
return g_strdup (subject);
|
|
|
|
pcre2_jit_compile (compiled_pattern, PCRE2_JIT_COMPLETE);
|
|
|
|
outlen = sizeof (output) / sizeof (PCRE2_UCHAR);
|
|
|
|
n_substitutions = pcre2_substitute (compiled_pattern,
|
|
(PCRE2_SPTR) subject,
|
|
PCRE2_ZERO_TERMINATED,
|
|
0,
|
|
PCRE2_SUBSTITUTE_GLOBAL | PCRE2_SUBSTITUTE_EXTENDED,
|
|
0,
|
|
0,
|
|
(PCRE2_SPTR) replace_renamer->replacement,
|
|
PCRE2_ZERO_TERMINATED,
|
|
(PCRE2_UCHAR *) output,
|
|
&outlen);
|
|
|
|
if (n_substitutions < 0)
|
|
{
|
|
PCRE2_UCHAR buffer[256];
|
|
pcre2_get_error_message (error, buffer, sizeof (buffer));
|
|
g_warning ("PCRE2 substitution failed at offset %d: %s\n", (int) erroffset, buffer);
|
|
return g_strdup (subject);
|
|
}
|
|
|
|
pcre2_code_free (compiled_pattern);
|
|
|
|
for (size_t i = 0; i < outlen; i++)
|
|
g_string_append_c (result, output[i]);
|
|
|
|
return g_string_free (result, FALSE);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_sbr_replace_renamer_pcre_update (ThunarSbrReplaceRenamer *replace_renamer)
|
|
{
|
|
const gchar *error_message = NULL;
|
|
gchar *tooltip;
|
|
gchar *message;
|
|
glong offset;
|
|
gint error_offset = -1;
|
|
int error;
|
|
PCRE2_SIZE erroffset;
|
|
|
|
/* pre-compile the pattern if regexp is enabled */
|
|
if (G_UNLIKELY (replace_renamer->regexp))
|
|
{
|
|
/* release the previous pattern (if any) */
|
|
if (G_LIKELY (replace_renamer->pcre_pattern != NULL))
|
|
pcre2_code_free (replace_renamer->pcre_pattern);
|
|
|
|
/* try to compile the new pattern */
|
|
replace_renamer->pcre_pattern = pcre2_compile ((PCRE2_SPTR) replace_renamer->pattern, PCRE2_ZERO_TERMINATED, 0, &error, &erroffset, 0);
|
|
|
|
if (replace_renamer->pcre_pattern == NULL)
|
|
{
|
|
PCRE2_UCHAR buffer[256];
|
|
pcre2_get_error_message (error, buffer, sizeof (buffer));
|
|
g_warning ("PCRE2 compilation failed at offset %d: %s\n", (int) erroffset, buffer);
|
|
}
|
|
}
|
|
|
|
/* check if there was an error compiling the pattern */
|
|
if (G_UNLIKELY (error_message != NULL))
|
|
{
|
|
/* convert the message to UTF-8 */
|
|
message = g_locale_to_utf8 (error_message, -1, NULL, NULL, NULL);
|
|
if (G_LIKELY (message != NULL))
|
|
{
|
|
/* determine the UTF-8 char offset */
|
|
offset = g_utf8_pointer_to_offset (replace_renamer->pattern, replace_renamer->pattern + error_offset);
|
|
|
|
/* setup a tooltip with the error message */
|
|
tooltip = g_strdup_printf (_("Invalid regular expression, at character position %ld: %s"), offset, message);
|
|
gtk_widget_set_tooltip_text (replace_renamer->pattern_entry, tooltip);
|
|
g_free (tooltip);
|
|
}
|
|
g_free (message);
|
|
|
|
/* check if the entry is realized */
|
|
if (gtk_widget_get_realized (replace_renamer->pattern_entry))
|
|
{
|
|
/* highlight invalid input by using theme-specific colors */
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (replace_renamer->pattern_entry)), "error");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* check if the entry is realized */
|
|
if (gtk_widget_get_realized (replace_renamer->pattern_entry))
|
|
{
|
|
/* stop highlight of invalid input if any */
|
|
gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (replace_renamer->pattern_entry)), "error");
|
|
}
|
|
|
|
/* reset to default tooltip */
|
|
gtk_widget_set_tooltip_text (replace_renamer->pattern_entry, _("Enter the text to search for in the file names."));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_new:
|
|
*
|
|
* Allocates a new #ThunarSbrReplaceRenamer instance.
|
|
*
|
|
* Return value: the newly allocated #ThunarSbrReplaceRenamer.
|
|
**/
|
|
ThunarSbrReplaceRenamer *
|
|
thunar_sbr_replace_renamer_new (void)
|
|
{
|
|
return g_object_new (THUNAR_SBR_TYPE_REPLACE_RENAMER,
|
|
"name", _("Search & Replace"),
|
|
NULL);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_get_case_sensitive:
|
|
* @replace_renamer : a #ThunarSbrReplaceRenamer.
|
|
*
|
|
* Returns %TRUE if @replace_renamer<!---->s search should
|
|
* be case sensitive.
|
|
*
|
|
* Return value: %TRUE if @replace_renamer is case sensitive.
|
|
**/
|
|
gboolean
|
|
thunar_sbr_replace_renamer_get_case_sensitive (ThunarSbrReplaceRenamer *replace_renamer)
|
|
{
|
|
g_return_val_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer), FALSE);
|
|
return replace_renamer->case_sensitive;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_set_case_sensitive:
|
|
* @replace_renamer : a #ThunarSbrReplaceRenamer.
|
|
* @case_sensitive : %TRUE to use case sensitive search.
|
|
*
|
|
* If @case_sensitive is %TRUE the search of @replace_renamer
|
|
* will be case sensitive.
|
|
**/
|
|
void
|
|
thunar_sbr_replace_renamer_set_case_sensitive (ThunarSbrReplaceRenamer *replace_renamer,
|
|
gboolean case_sensitive)
|
|
{
|
|
g_return_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer));
|
|
|
|
/* normalize the value */
|
|
case_sensitive = !!case_sensitive;
|
|
|
|
/* check if we have a new setting */
|
|
if (G_LIKELY (replace_renamer->case_sensitive != case_sensitive))
|
|
{
|
|
/* apply the new value */
|
|
replace_renamer->case_sensitive = case_sensitive;
|
|
|
|
#ifdef HAVE_PCRE2
|
|
/* pre-compile the pattern */
|
|
thunar_sbr_replace_renamer_pcre_update (replace_renamer);
|
|
#endif
|
|
|
|
/* update the renamer */
|
|
thunarx_renamer_changed (THUNARX_RENAMER (replace_renamer));
|
|
|
|
/* notify listeners */
|
|
g_object_notify (G_OBJECT (replace_renamer), "case-sensitive");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_get_pattern:
|
|
* @replace_renamer : a #ThunarSbrReplaceRenamer.
|
|
*
|
|
* Returns the search pattern for @replace_renamer.
|
|
*
|
|
* Return value: the search pattern for @replace_renamer.
|
|
**/
|
|
const gchar *
|
|
thunar_sbr_replace_renamer_get_pattern (ThunarSbrReplaceRenamer *replace_renamer)
|
|
{
|
|
g_return_val_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer), NULL);
|
|
return replace_renamer->pattern;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_set_pattern:
|
|
* @replace_renamer : a #ThunarSbrReplaceRenamer.
|
|
* @pattern : the new pattern for @replace_renamer.
|
|
*
|
|
* Sets the search pattern of @replace_renamer to @pattern.
|
|
**/
|
|
void
|
|
thunar_sbr_replace_renamer_set_pattern (ThunarSbrReplaceRenamer *replace_renamer,
|
|
const gchar *pattern)
|
|
{
|
|
g_return_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer));
|
|
g_return_if_fail (g_utf8_validate (pattern, -1, NULL));
|
|
|
|
/* check if we have a new pattern */
|
|
if (g_strcmp0 (replace_renamer->pattern, pattern) != 0)
|
|
{
|
|
/* apply the new value */
|
|
g_free (replace_renamer->pattern);
|
|
replace_renamer->pattern = g_strdup (pattern);
|
|
|
|
#ifdef HAVE_PCRE2
|
|
/* pre-compile the pattern */
|
|
thunar_sbr_replace_renamer_pcre_update (replace_renamer);
|
|
#endif
|
|
|
|
/* update the renamer */
|
|
thunarx_renamer_changed (THUNARX_RENAMER (replace_renamer));
|
|
|
|
/* notify listeners */
|
|
g_object_notify (G_OBJECT (replace_renamer), "pattern");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_get_regexp:
|
|
* @replace_renamer : a #ThunarSbrReplaceRenamer.
|
|
*
|
|
* Returns %TRUE if @replace_renamer should use a regular
|
|
* expression.
|
|
*
|
|
* Return value: %TRUE if @replace_renamer uses a regexp.
|
|
**/
|
|
gboolean
|
|
thunar_sbr_replace_renamer_get_regexp (ThunarSbrReplaceRenamer *replace_renamer)
|
|
{
|
|
g_return_val_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer), FALSE);
|
|
return replace_renamer->regexp;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_set_regexp:
|
|
* @replace_renamer : a #ThunarSbrReplaceRenamer.
|
|
* @regexp : %TRUE to use regular expressions.
|
|
*
|
|
* If @regexp is %TRUE a regular expression should be used
|
|
* for @replace_renamer.
|
|
**/
|
|
void
|
|
thunar_sbr_replace_renamer_set_regexp (ThunarSbrReplaceRenamer *replace_renamer,
|
|
gboolean regexp)
|
|
{
|
|
g_return_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer));
|
|
|
|
/* normalize the value */
|
|
regexp = (!!regexp && replace_renamer->utf8_regexp_supported);
|
|
|
|
/* check if we have a new value */
|
|
if (G_LIKELY (replace_renamer->regexp != regexp))
|
|
{
|
|
/* apply the new value */
|
|
replace_renamer->regexp = regexp;
|
|
|
|
#ifdef HAVE_PCRE2
|
|
/* pre-compile the pattern */
|
|
thunar_sbr_replace_renamer_pcre_update (replace_renamer);
|
|
#endif
|
|
|
|
/* update the renamer */
|
|
thunarx_renamer_changed (THUNARX_RENAMER (replace_renamer));
|
|
|
|
/* notify listeners */
|
|
g_object_notify (G_OBJECT (replace_renamer), "regexp");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_get_replacement:
|
|
* @replace_renamer : a #ThunarSbrReplaceRenamer.
|
|
*
|
|
* Returns the replacement for the @replace_renamer.
|
|
*
|
|
* Return value: the replacement for @replace_renamer.
|
|
**/
|
|
const gchar *
|
|
thunar_sbr_replace_renamer_get_replacement (ThunarSbrReplaceRenamer *replace_renamer)
|
|
{
|
|
g_return_val_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer), NULL);
|
|
return replace_renamer->replacement;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_sbr_replace_renamer_set_replacement:
|
|
* @replace_renamer : a #ThunarSbrReplaceRenamer.
|
|
* @replacement : the new replacement.
|
|
*
|
|
* Sets the replacement of @replace_renamer to @replacement.
|
|
**/
|
|
void
|
|
thunar_sbr_replace_renamer_set_replacement (ThunarSbrReplaceRenamer *replace_renamer,
|
|
const gchar *replacement)
|
|
{
|
|
g_return_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer));
|
|
g_return_if_fail (g_utf8_validate (replacement, -1, NULL));
|
|
|
|
/* check if we have a new replacement */
|
|
if (g_strcmp0 (replace_renamer->replacement, replacement) != 0)
|
|
{
|
|
/* apply the setting */
|
|
g_free (replace_renamer->replacement);
|
|
replace_renamer->replacement = g_strdup (replacement);
|
|
|
|
/* update the renamer */
|
|
thunarx_renamer_changed (THUNARX_RENAMER (replace_renamer));
|
|
|
|
/* notify listeners */
|
|
g_object_notify (G_OBJECT (replace_renamer), "replacement");
|
|
}
|
|
}
|