From 734bd26b77908cd33724498ee9ffdcd6e8dad498 Mon Sep 17 00:00:00 2001 From: ItsZariep Date: Wed, 10 Sep 2025 09:19:09 -0600 Subject: [PATCH] migrate textsize, bracketcompletion and joinlines migrate textsize, bracketcompletion and joinlines from Python to C because libpeas is kinda broken on Python --- .../bracket-complete/bracketcompletion.plugin | 105 ------ .../bracket-complete/bracketcompletion.py | 318 ------------------ plugins/bracket-complete/bracketcompletion.c | 233 +++++++++++++ .../bracketcompletion.plugin.desktop.in | 9 + plugins/bracket-complete/meson.build | 28 +- plugins/joinlines/joinlines.c | 212 ++++++++++++ plugins/joinlines/joinlines.plugin.desktop.in | 2 +- plugins/joinlines/joinlines/__init__.py | 91 ----- plugins/joinlines/meson.build | 19 +- plugins/textsize/meson.build | 17 +- plugins/textsize/textsize.c | 293 ++++++++++++++++ plugins/textsize/textsize.plugin.desktop.in | 2 +- plugins/textsize/textsize/__init__.py | 234 ------------- plugins/textsize/textsize/documenthelper.py | 117 ------- plugins/textsize/textsize/signals.py | 69 ---- 15 files changed, 805 insertions(+), 944 deletions(-) delete mode 100644 plugins/bracket-complete/bracket-complete/bracketcompletion.plugin delete mode 100644 plugins/bracket-complete/bracket-complete/bracketcompletion.py create mode 100644 plugins/bracket-complete/bracketcompletion.c create mode 100644 plugins/bracket-complete/bracketcompletion.plugin.desktop.in create mode 100644 plugins/joinlines/joinlines.c delete mode 100644 plugins/joinlines/joinlines/__init__.py create mode 100644 plugins/textsize/textsize.c delete mode 100644 plugins/textsize/textsize/__init__.py delete mode 100644 plugins/textsize/textsize/documenthelper.py delete mode 100644 plugins/textsize/textsize/signals.py diff --git a/plugins/bracket-complete/bracket-complete/bracketcompletion.plugin b/plugins/bracket-complete/bracket-complete/bracketcompletion.plugin deleted file mode 100644 index 8075cebe..00000000 --- a/plugins/bracket-complete/bracket-complete/bracketcompletion.plugin +++ /dev/null @@ -1,105 +0,0 @@ -[Plugin] -Loader=python3 -Module=bracketcompletion -IAge=3 -Name[ar]=إكمال الأقواس -Name[be]=Дапаўненне дужак -Name[bs]=Zatvaranje zagrada -Name[ca]=Compleció dels claudàtors -Name[ca@valencia]=Compleció dels claudàtors -Name[cs]=Doplňování závorek -Name[da]=Klammefuldførelse -Name[de]=Klammern schließen -Name[el]=Συμπλήρωση αγκύλων -Name[en_GB]=Bracket Completion -Name[eo]=Krampo-kompletigo -Name[es]=Completar paréntesis -Name[et]=Sulgude lõpetamine -Name[eu]=Parentesien osaketa -Name[fi]=Sulkuparin täsmäys -Name[fr]=Complétion de parenthèses -Name[fur]=Completament parentesis -Name[gl]=Completar parénteses -Name[he]=התאמת סוגריים -Name[hr]=Dovršavanje zagrada -Name[hu]=Zárójel-kiegészítés -Name[id]=Penyelesaian Tanda Kurung -Name[it]=Completamento parentesi -Name[ja]=カッコの補完 -Name[kk]=Жақшаларды толықтыру -Name[ko]=각괄호 일치 -Name[lt]=Skliaustų užbaigimas -Name[lv]=Iekavu noslēgšana -Name[nl]=Haakjes-voltooiing -Name[oc]=Complecion de parentèsis -Name[pl]=Uzupełnianie nawiasów -Name[pt]=Conclusão de chavetas -Name[pt_BR]=Fechamento de parênteses -Name[ro]=Completare paranteze -Name[ru]=Дополнение скобок -Name[sk]=Dopĺňanie pravých zátvoriek -Name[sl]=Dopolnjevanje oklepajev -Name[sr]=Допуњавање заграда -Name[sr@latin]=Dopunjavanje zagrada -Name[sv]=Parenteskomplettering -Name[te]=బ్రాకెట్ ముగింపు -Name[th]=การเติมเต็มคู่วงเล็บ -Name[tr]=Parantez Tamamlama -Name[zh_CN]=括号补全 -Name[zh_TW]=括號補完 -Name=Bracket Completion -Description[ar]=يغلق الأقواس آليا. -Description[as]=বন্ধনী নিজেই যোগ কৰে । -Description[be]=Аўтаматычна дадае канцавыя дужкі. -Description[be@latin]=Aŭtamatyčna dadaje kancavyja dužki. -Description[bs]=Automatski dodaj zatvorene zagrade. -Description[ca]=Afegeix claudàtors de tancada automàticament. -Description[ca@valencia]=Afig claudàtors de tancada automàticament. -Description[cs]=Automaticky přidává zavírací závorky. -Description[da]=Tilføjer automatisk afsluttende klammer. -Description[de]=Fügt automatisch schließende Klammern hinzu. -Description[dz]=ཁ་བསྡམ་གུག་ཤད་ཚུ་ རང་བཞིན་གྱིས་ཁ་སྐོང་རྐྱབ་ཨིན། -Description[el]=Συμπληρώνει αυτόματα τις αγκύλες. -Description[en_CA]=Automatically adds closing brackets. -Description[en_GB]=Automatically adds closing brackets. -Description[eo]=Aŭtomate aldoni fermantajn krampojn. -Description[es]=Añadir automáticamente cierres de paréntesis. -Description[eu]=Automatikoki gehitzen ditu itxierako parentesiak. -Description[fi]=Lisää suluille pääte automaattisesti. -Description[fr]=Ajouter automatiquement les parenthèses fermantes. -Description[fur]=Al zonte in automatic lis parentesis sieradis. -Description[gl]=Engadir automaticamente peches de parénteses. -Description[gu]=બંધ કરતા કૌંસો ઓપોઆપ ઉમેરાય છે. -Description[he]=הוספת סוגר לסגירה. -Description[hr]=Automatski zatvara zagrade. -Description[hu]=Automatikusan hozzáadja a záró zárójeleket. -Description[id]=Otomatis menambah kurung tutup. -Description[it]=Aggiunge automaticamente le parentesi di chiusura -Description[ja]=終わり括弧を自動的に追加します -Description[kk]=Жабатын жақшаны автоматты түрде қосады. -Description[ko]=자동으로 닫는 각괄호를 추가합니다. -Description[lt]=Automatiškai prideda užveriančius skliaustus. -Description[lv]=Automātiski pievieno aizverošās iekavas. -Description[mr]=स्वयं बंद करण्याजोगी ब्रॅकेट समावेष करा. -Description[nl]=Voegt automatisch ‘haakjes sluiten’ toe. -Description[oc]=Apondre automaticament las parentèsis tampantas. -Description[or]=ବନ୍ଦହୋଇଥିବା ବନ୍ଧନିଗୁଡ଼ିକୁ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଯୋଗକରନ୍ତୁ। -Description[pl]=Automatycznie dodaje nawiasy zamykające. -Description[pt]=Adiciona automaticamente fecho de chavetas. -Description[pt_BR]=Fecha parênteses automaticamente. -Description[ro]=Adaugă automat paranteze închise. -Description[ru]=Автоматическое добавление закрывающей скобки. -Description[sk]=Automatické pridávanie pravých zátvoriek. -Description[sl]=Samodejno doda zaklepaje -Description[sr]=Сам додаје затварајуће заграде. -Description[sr@latin]=Sam dodaje zatvarajuće zagrade. -Description[sv]=Lägger automatiskt till avslutande parenteser. -Description[th]=เติมวงเล็บปิดโดยอัตโนมัติ -Description[tr]=Parantez kapanışını kendiliğinden ekler. -Description[vi]=Tự động thêm dấu ngoặc đóng. -Description[zh_CN]=自动添加闭合括号。 -Description[zh_TW]=自動加入關閉用括號。 -Description=Automatically adds closing brackets. -Authors=Hrutvik Suthar -Copyright=Copyright @ 2020 Hrutvik Suthar -Version=1.0 diff --git a/plugins/bracket-complete/bracket-complete/bracketcompletion.py b/plugins/bracket-complete/bracket-complete/bracketcompletion.py deleted file mode 100644 index 5b85bf20..00000000 --- a/plugins/bracket-complete/bracket-complete/bracketcompletion.py +++ /dev/null @@ -1,318 +0,0 @@ -# -*- coding: utf-8 -*- -# -# bracketcompletion.py - Bracket completion plugin for Xed -# -# -# 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. - -import gi -gi.require_version('Peas', '1.0') -#gi.require_version('Xed', '3.0') -from gi.repository import GObject, Gdk, Xed - -common_brackets = { - '(' : ')', - '[' : ']', - '{' : '}', - '"' : '"', - "'" : "'", -} - -close_brackets = { - ')' : '(', - ']' : '[', - '}' : '{', -} - -language_brackets = { - 'changelog': { '<' : '>' }, - 'html': { '<' : '>' }, - 'ruby': { '|' : '|' }, - 'sh': { '`' : '`' }, - 'xml': { '<' : '>' }, - 'php': { '<' : '>' }, -} - - -class BracketCompletionPlugin(GObject.Object, Xed.ViewActivatable): - __gtype_name__ = "BracketCompletion" - - view = GObject.Property(type=Xed.View) - - def __init__(self): - GObject.Object.__init__(self) - - def do_activate(self): - self._doc = self.view.get_buffer() - self._last_iter = None - self._stack = [] - self._relocate_marks = True - self.update_language() - - # Add the markers to the buffer - insert = self._doc.get_iter_at_mark(self._doc.get_insert()) - self._mark_begin = self._doc.create_mark(None, insert, True) - self._mark_end = self._doc.create_mark(None, insert, False) - - self._handlers = [ - None, - None, - self.view.connect('notify::editable', self.on_notify_editable), - self._doc.connect('notify::language', self.on_notify_language), - None, - ] - self.update_active() - - def do_deactivate(self): - if self._handlers[0]: - self.view.disconnect(self._handlers[0]) - self.view.disconnect(self._handlers[1]) - self._doc.disconnect(self._handlers[4]) - self.view.disconnect(self._handlers[2]) - self._doc.disconnect(self._handlers[3]) - self._doc.delete_mark(self._mark_begin) - self._doc.delete_mark(self._mark_end) - - def update_active(self): - # Don't activate the feature if the buffer isn't editable or if - # there are no brackets for the language - active = self.view.get_editable() and \ - self._brackets is not None - - if active and self._handlers[0] is None: - self._handlers[0] = self.view.connect('event-after', - self.on_event_after) - self._handlers[1] = self.view.connect('key-press-event', - self.on_key_press_event) - self._handlers[4] = self._doc.connect('delete-range', - self.on_delete_range) - elif not active and self._handlers[0] is not None: - self.view.disconnect(self._handlers[0]) - self._handlers[0] = None - self.view.disconnect(self._handlers[1]) - self._handlers[1] = None - self._doc.disconnect(self._handlers[4]) - self._handlers[4] = None - - def update_language(self): - lang = self._doc.get_language() - if lang is None: - self._brackets = None - return - - lang_id = lang.get_id() - if lang_id in language_brackets: - self._brackets = language_brackets[lang_id] - # we populate the language-specific brackets with common ones lazily - self._brackets.update(common_brackets) - else: - self._brackets = common_brackets - - # get the corresponding keyvals - self._bracket_keyvals = set() - for b in self._brackets: - kv = Gdk.unicode_to_keyval(ord(b[-1])) - if (kv): - self._bracket_keyvals.add(kv) - for b in close_brackets: - kv = Gdk.unicode_to_keyval(ord(b[-1])) - if (kv): - self._bracket_keyvals.add(kv) - - def get_current_token(self): - end = self._doc.get_iter_at_mark(self._doc.get_insert()) - start = end.copy() - word = None - - if end.ends_word() or (end.inside_word() and not end.starts_word()): - start.backward_word_start() - word = self._doc.get_text(start, end) - - if not word and start.backward_char(): - word = start.get_char() - if word.isspace(): - word = None - - if word: - return word, start, end - else: - return None, None, None - - def get_next_token(self): - start = self._doc.get_iter_at_mark(self._doc.get_insert()) - end = start.copy() - word = None - - if start.ends_word() or (start.inside_word() and not start.starts_word()): - end.forward_word_end() - word = self._doc.get_text(start, end) - - if not word: - word = start.get_char() - if word.isspace(): - word = None - - if word: - return word, start, end - else: - return None, None, None - - def compute_indentation(self, cur): - """ - Compute indentation at the given iterator line - view : gtk.TextView - cur : gtk.TextIter - """ - start = self._doc.get_iter_at_line(cur.get_line()) - end = start.copy() - - c = end.get_char() - while c.isspace() and c not in ('\n', '\r') and end.compare(cur) < 0: - if not end.forward_char(): - break - c = end.get_char() - - if start.equal(end): - return '' - return start.get_slice(end) - - def on_notify_language(self, view, pspec): - self.update_language() - self.update_active() - - def on_notify_editable(self, view, pspec): - self.update_active() - - def on_key_press_event(self, view, event): - if event.state & (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK): - return False - - if event.keyval in (Gdk.KEY_Left, Gdk.KEY_Right): - self._stack = [] - - if event.keyval == Gdk.KEY_BackSpace: - self._stack = [] - - if self._last_iter == None: - return False - - iter1 = self._doc.get_iter_at_mark(self._doc.get_insert()) - iter1.backward_char() - self._doc.begin_user_action() - self._doc.delete(iter1, self._last_iter) - self._doc.end_user_action() - self._last_iter = None - return True - - if event.keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter) and \ - view.get_auto_indent() and self._last_iter != None: - # This code has barely been adapted from gtksourceview.c - # Note: it might break IM! - - mark = self._doc.get_insert() - iter1 = self._doc.get_iter_at_mark(mark) - - indent = self.compute_indentation(iter1) - indent = "\n" + indent - - # Insert new line and auto-indent. - self._doc.begin_user_action() - self._doc.insert(iter1, indent) - self._doc.insert(iter1, indent) - self._doc.end_user_action() - - # Leave the cursor where we want it to be - iter1.backward_chars(len(indent)) - self._doc.place_cursor(iter1) - self.view.scroll_mark_onscreen(mark) - - self._last_iter = None - return True - - self._last_iter = None - return False - - def on_event_after(self, view, event): - if event.type != Gdk.EventType.KEY_PRESS or \ - event.state & (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK) or \ - event.keyval not in self._bracket_keyvals: - return - - # Check if the insert mark is in the range of mark_begin to mark_end - # if not we free the stack - insert = self._doc.get_insert() - iter_begin = self._doc.get_iter_at_mark(self._mark_begin) - iter_end = self._doc.get_iter_at_mark(self._mark_end) - insert_iter = self._doc.get_iter_at_mark(insert) - if not iter_begin.equal(iter_end): - if not insert_iter.in_range(iter_begin, iter_end): - self._stack = [] - self._relocate_marks = True - - # Check if the word is not in our brackets - word, start, end = self.get_current_token() - - if word not in self._brackets and word not in close_brackets: - return - - # If we didn't insert brackets yet we insert them in the insert mark iter - if self._relocate_marks == True: - insert_iter = self._doc.get_iter_at_mark(insert) - self._doc.move_mark(self._mark_begin, insert_iter) - self._doc.move_mark(self._mark_end, insert_iter) - self._relocate_marks = False - - # Depending on having close bracket or a open bracket we get the opposed - # bracket - bracket = None - bracket2 = None - - if word not in close_brackets: - self._stack.append(word) - bracket = self._brackets[word] - else: - bracket2 = close_brackets[word] - - word2, _, _ = self.get_next_token() - - # Check to skip the closing bracket - # Example: word = ) and word2 = ) - if word == word2: - if bracket2 != None and self._stack != [] and \ - self._stack[len(self._stack) - 1] == bracket2: - self._stack.pop() - self._doc.handler_block(self._handlers[4]) - self._doc.delete(start, end) - self._doc.handler_unblock(self._handlers[4]) - end.forward_char() - self._doc.place_cursor(end) - return - - # Insert the closing bracket - if bracket != None: - self._doc.begin_user_action() - self._doc.insert(end, bracket) - self._doc.end_user_action() - - # Leave the cursor when we want it to be - self._last_iter = end.copy() - end.backward_chars(len(bracket)) - self._doc.place_cursor(end) - - def on_delete_range(self, doc, start, end): - self._stack = [] - -# ex:ts=4:et: diff --git a/plugins/bracket-complete/bracketcompletion.c b/plugins/bracket-complete/bracketcompletion.c new file mode 100644 index 00000000..22f10c02 --- /dev/null +++ b/plugins/bracket-complete/bracketcompletion.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include + +#define BRACKET_COMPLETION_TYPE (bracket_completion_get_type()) +G_DECLARE_FINAL_TYPE(BracketCompletion, bracket_completion, BRACKET, COMPLETION, GObject) + +struct _BracketCompletion +{ + GObject parent_instance; + XedView *view; + + GtkTextBuffer *buffer; + GtkTextMark *mark_begin; + GtkTextMark *mark_end; + GList *stack; + gboolean relocate_marks; + gulong handler_key_press; + gulong handler_editable; +}; + +static void xed_view_activatable_iface_init(XedViewActivatableInterface *iface); + +G_DEFINE_FINAL_TYPE_WITH_CODE(BracketCompletion, bracket_completion, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(XED_TYPE_VIEW_ACTIVATABLE, xed_view_activatable_iface_init)) + +enum +{ + PROP_0, + PROP_VIEW +}; + +static const gchar* get_closing_bracket(gchar c) +{ + switch (c) + { + case '(': return ")"; + case '[': return "]"; + case '{': return "}"; + case '"': return "\""; + case '\'': return "'"; + default: return NULL; + } +} + +static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + BracketCompletion *self = BRACKET_COMPLETION(user_data); + GtkTextIter iter; + + if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(self->view))) + { + return FALSE; + } + + gtk_text_buffer_get_iter_at_mark(self->buffer, &iter, gtk_text_buffer_get_insert(self->buffer)); + + if (event->keyval == GDK_KEY_BackSpace) + { + if (self->stack != NULL) + { + GList *last = g_list_last(self->stack); + g_free(last->data); + self->stack = g_list_delete_link(self->stack, last); + } + return FALSE; + } + + gchar key = gdk_keyval_to_unicode(event->keyval); + if (key == 0) + { + return FALSE; + } + + const gchar *closing = get_closing_bracket(key); + if (closing) + { + gtk_text_buffer_insert_at_cursor(self->buffer, closing, -1); + + gtk_text_buffer_get_iter_at_mark(self->buffer, &iter, gtk_text_buffer_get_insert(self->buffer)); + gtk_text_iter_backward_char(&iter); + gtk_text_buffer_place_cursor(self->buffer, &iter); + + /* Store the opening bracket */ + self->stack = g_list_append(self->stack, g_strdup_printf("%c", key)); + } + + return FALSE; +} + +static void on_notify_editable(GObject *obj, GParamSpec *pspec, gpointer user_data) +{ + BracketCompletion *self = BRACKET_COMPLETION(user_data); + gboolean editable = gtk_text_view_get_editable(GTK_TEXT_VIEW(self->view)); + + if (!editable) + { + g_list_free_full(self->stack, g_free); + self->stack = NULL; + } +} + +static void bracket_completion_activate(XedViewActivatable *activatable) +{ + BracketCompletion *self = BRACKET_COMPLETION(activatable); + GtkTextIter iter; + + self->buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self->view)); + + gtk_text_buffer_get_iter_at_mark(self->buffer, &iter, gtk_text_buffer_get_insert(self->buffer)); + self->mark_begin = gtk_text_buffer_create_mark(self->buffer, NULL, &iter, TRUE); + self->mark_end = gtk_text_buffer_create_mark(self->buffer, NULL, &iter, FALSE); + + self->handler_key_press = g_signal_connect(self->view, "key-press-event", + G_CALLBACK(on_key_press), self); + self->handler_editable = g_signal_connect(self->view, "notify::editable", + G_CALLBACK(on_notify_editable), self); +} + +static void bracket_completion_deactivate(XedViewActivatable *activatable) +{ + BracketCompletion *self = BRACKET_COMPLETION(activatable); + + if (self->handler_key_press != 0) + { + g_signal_handler_disconnect(self->view, self->handler_key_press); + self->handler_key_press = 0; + } + + if (self->handler_editable != 0) + { + g_signal_handler_disconnect(self->view, self->handler_editable); + self->handler_editable = 0; + } + + if (self->buffer) + { + if (self->mark_begin) + { + gtk_text_buffer_delete_mark(self->buffer, self->mark_begin); + self->mark_begin = NULL; + } + if (self->mark_end) + { + gtk_text_buffer_delete_mark(self->buffer, self->mark_end); + self->mark_end = NULL; + } + } + + g_list_free_full(self->stack, g_free); + self->stack = NULL; +} + +static void bracket_completion_get_property(GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) + { + BracketCompletion *self = BRACKET_COMPLETION(object); + switch (prop_id) + { + case PROP_VIEW: + g_value_set_object(value, self->view); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void bracket_completion_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + BracketCompletion *self = BRACKET_COMPLETION(object); + + switch (prop_id) + { + case PROP_VIEW: + self->view = XED_VIEW(g_value_get_object(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void bracket_completion_dispose(GObject *object) +{ + BracketCompletion *self = BRACKET_COMPLETION(object); + g_clear_object(&self->view); + G_OBJECT_CLASS(bracket_completion_parent_class)->dispose(object); +} + +static void bracket_completion_finalize(GObject *object) +{ + BracketCompletion *self = BRACKET_COMPLETION(object); + g_list_free_full(self->stack, g_free); + self->stack = NULL; + G_OBJECT_CLASS(bracket_completion_parent_class)->finalize(object); +} + +static void bracket_completion_init(BracketCompletion *self) +{ + self->stack = NULL; + self->relocate_marks = TRUE; + self->handler_key_press = 0; + self->handler_editable = 0; +} + +static void bracket_completion_class_init(BracketCompletionClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->get_property = bracket_completion_get_property; + object_class->set_property = bracket_completion_set_property; + object_class->dispose = bracket_completion_dispose; + object_class->finalize = bracket_completion_finalize; + + g_object_class_override_property(object_class, PROP_VIEW, "view"); +} + +static void xed_view_activatable_iface_init(XedViewActivatableInterface *iface) +{ + iface->activate = bracket_completion_activate; + iface->deactivate = bracket_completion_deactivate; +} + +G_MODULE_EXPORT void +peas_register_types(PeasObjectModule *module) +{ + peas_object_module_register_extension_type(module, + XED_TYPE_VIEW_ACTIVATABLE, + BRACKET_COMPLETION_TYPE); +} \ No newline at end of file diff --git a/plugins/bracket-complete/bracketcompletion.plugin.desktop.in b/plugins/bracket-complete/bracketcompletion.plugin.desktop.in new file mode 100644 index 00000000..1026ee89 --- /dev/null +++ b/plugins/bracket-complete/bracketcompletion.plugin.desktop.in @@ -0,0 +1,9 @@ +[Plugin] +Loader=python3 +Module=bracketcompletion +IAge=3 +_Name=Bracket Completion +_Description=Automatically adds closing brackets. +Authors=Hrutvik Suthar +Copyright=Copyright @ 2020 Hrutvik Suthar; @ 2025 ItsZariep +Version=2.0 diff --git a/plugins/bracket-complete/meson.build b/plugins/bracket-complete/meson.build index e5e8a5f5..50d916d9 100644 --- a/plugins/bracket-complete/meson.build +++ b/plugins/bracket-complete/meson.build @@ -1,4 +1,26 @@ -install_subdir( - 'bracket-complete', - install_dir: pluginslibdir +bracketcompletion_sources = files( + 'bracketcompletion.c' +) + +bracketcompletion_deps = [ + dependency('xed'), + dependency('gtk+-3.0'), + dependency('libpeas-1.0'), +] + +library( + 'bracketcompletion', + bracketcompletion_sources, + dependencies: bracketcompletion_deps, + install: true, + install_dir: join_paths(libdir, 'xed', 'plugins') +) + +bracketcompletion_desktop = custom_target( + 'bracketcompletion_desktop', + input: 'bracketcompletion.plugin.desktop.in', + output: 'bracketcompletion.plugin', + command: [intltool_merge, '-d', '-u', po_dir, '@INPUT@', '@OUTPUT@'], + install: true, + install_dir: pluginslibdir, ) diff --git a/plugins/joinlines/joinlines.c b/plugins/joinlines/joinlines.c new file mode 100644 index 00000000..28156993 --- /dev/null +++ b/plugins/joinlines/joinlines.c @@ -0,0 +1,212 @@ +#include +#include +#include +#include + +#define JOIN_LINES_TYPE (join_lines_get_type()) +G_DECLARE_FINAL_TYPE(JoinLines, join_lines, JOIN, LINES, GObject) + +struct _JoinLines +{ + GObject parent_instance; + XedView *view; + GtkTextBuffer *buffer; + gulong handler_key_press; +}; + +static void xed_view_activatable_iface_init(XedViewActivatableInterface *iface); + +G_DEFINE_FINAL_TYPE_WITH_CODE(JoinLines, join_lines, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(XED_TYPE_VIEW_ACTIVATABLE, xed_view_activatable_iface_init)) + +enum +{ + PROP_0, + PROP_VIEW +}; + +static void do_join_lines(JoinLines *self) +{ + GtkTextIter start, end; + GtkTextMark *end_mark; + + if (!self->buffer) + { + return; + } + + gtk_text_buffer_begin_user_action(self->buffer); + + if (!gtk_text_buffer_get_selection_bounds(self->buffer, &start, &end)) + { + gtk_text_buffer_get_iter_at_mark(self->buffer, &start, + gtk_text_buffer_get_insert(self->buffer)); + end = start; + gtk_text_iter_forward_line(&end); + } + + end_mark = gtk_text_buffer_create_mark(self->buffer, NULL, &end, FALSE); + + if (!gtk_text_iter_ends_line(&start)) + { + gtk_text_iter_forward_to_line_end(&start); + } + + while (gtk_text_iter_backward_char(&start)) + { + gunichar ch = gtk_text_iter_get_char(&start); + if (ch != ' ' && ch != '\t') + { + gtk_text_iter_forward_char(&start); + break; + } + } + + while (TRUE) + { + GtkTextIter iter_end; + gtk_text_buffer_get_iter_at_mark(self->buffer, &iter_end, end_mark); + + if (gtk_text_iter_compare(&start, &iter_end) >= 0) + { + break; + } + + GtkTextIter tmp_end = start; + while (1) + { + gunichar ch = gtk_text_iter_get_char(&tmp_end); + if (ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t') + { + gtk_text_iter_forward_char(&tmp_end); + } + else + { + break; + } + } + + gtk_text_buffer_delete(self->buffer, &start, &tmp_end); + gtk_text_buffer_insert(self->buffer, &start, " ", -1); + gtk_text_iter_forward_to_line_end(&start); + } + + gtk_text_buffer_delete_mark(self->buffer, end_mark); + gtk_text_buffer_end_user_action(self->buffer); +} + + +static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + JoinLines *self = JOIN_LINES(user_data); + + if ((event->state & GDK_CONTROL_MASK) && event->keyval == GDK_KEY_j) + { + do_join_lines(self); + return TRUE; + } + + return FALSE; +} + + +static void join_lines_activate(XedViewActivatable *activatable) +{ + JoinLines *self = JOIN_LINES(activatable); + + self->buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self->view)); + self->handler_key_press = g_signal_connect(self->view, "key-press-event", + G_CALLBACK(on_key_press), self); +} + +static void join_lines_deactivate(XedViewActivatable *activatable) +{ + JoinLines *self = JOIN_LINES(activatable); + + if (self->handler_key_press != 0) + { + g_signal_handler_disconnect(self->view, self->handler_key_press); + self->handler_key_press = 0; + } + + self->buffer = NULL; +} + + +static void join_lines_get_property(GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + JoinLines *self = JOIN_LINES(object); + switch (prop_id) + { + case PROP_VIEW: + g_value_set_object(value, self->view); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void join_lines_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + JoinLines *self = JOIN_LINES(object); + + switch (prop_id) + { + case PROP_VIEW: + self->view = XED_VIEW(g_value_get_object(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void join_lines_dispose(GObject *object) +{ + JoinLines *self = JOIN_LINES(object); + + if (self->handler_key_press != 0 && self->view != NULL) + { + g_signal_handler_disconnect(self->view, self->handler_key_press); + self->handler_key_press = 0; + } + + self->view = NULL; + self->buffer = NULL; + + G_OBJECT_CLASS(join_lines_parent_class)->dispose(object); +} + +static void join_lines_init(JoinLines *self) +{ + self->buffer = NULL; + self->handler_key_press = 0; +} + +static void join_lines_class_init(JoinLinesClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->get_property = join_lines_get_property; + object_class->set_property = join_lines_set_property; + object_class->dispose = join_lines_dispose; + + g_object_class_override_property(object_class, PROP_VIEW, "view"); +} + +static void xed_view_activatable_iface_init(XedViewActivatableInterface *iface) +{ + iface->activate = join_lines_activate; + iface->deactivate = join_lines_deactivate; +} + +G_MODULE_EXPORT void +peas_register_types(PeasObjectModule *module) +{ + peas_object_module_register_extension_type(module, + XED_TYPE_VIEW_ACTIVATABLE, + JOIN_LINES_TYPE); +} diff --git a/plugins/joinlines/joinlines.plugin.desktop.in b/plugins/joinlines/joinlines.plugin.desktop.in index 659d6c82..d382002c 100644 --- a/plugins/joinlines/joinlines.plugin.desktop.in +++ b/plugins/joinlines/joinlines.plugin.desktop.in @@ -5,6 +5,6 @@ IAge=3 _Name=Join Lines _Description=Join several lines Icon=gnome-mime-text-x-python -Authors=Steve Frécinaux ;André Homeyer;Linux Mint team +Authors=Steve Frécinaux ;André Homeyer;ItsZariep;Linux Mint team Copyright=Copyright @ 2006-2007 Steve Frécinaux, André Homeyer Builtin=true diff --git a/plugins/joinlines/joinlines/__init__.py b/plugins/joinlines/joinlines/__init__.py deleted file mode 100644 index 486b2012..00000000 --- a/plugins/joinlines/joinlines/__init__.py +++ /dev/null @@ -1,91 +0,0 @@ -from gi.repository import GObject, Gtk, Xed - -import gettext -gettext.install("xed") - -MENU_PATH = "/MenuBar/ViewMenu/ViewOps_1" - -class JoinLinesPlugin(GObject.Object, Xed.WindowActivatable): - __gtype_name__ = "JoinLinesPlugin" - - window = GObject.property(type=Xed.Window) - - def __init__(self): - GObject.Object.__init__(self) - - def do_activate(self): - self._views = {} - - self._insert_menu() - - def _insert_menu(self): - manager = self.window.get_ui_manager() - - self._action_group = Gtk.ActionGroup(name="XedJoinLinesPluginActions") - self._action_group.add_actions( - [("JoinLinesAction", None, _("_Join Lines"), "J", - _("Join the selected lines"), - lambda w: self.join_lines(w))]) - - manager.insert_action_group(self._action_group) - - self._ui_id = manager.new_merge_id() - - manager.add_ui(self._ui_id, - MENU_PATH, - "JoinLinesAction", - "JoinLinesAction", - Gtk.UIManagerItemType.MENUITEM, - False) - - def do_update_state(self): - self._action_group.set_sensitive(self.window.get_active_document() != None) - - def do_deactivate(self): - self._remove_menu() - - - def _remove_menu(self): - manager = self.window.get_ui_manager() - manager.remove_ui(self._ui_id) - manager.remove_action_group(self._action_group) - manager.ensure_update() - - def join_lines(self, w): - doc = self.window.get_active_document() - if doc is None: - return - - doc.begin_user_action() - - # If there is a selection use it, otherwise join the - # next line - try: - start, end = doc.get_selection_bounds() - except ValueError: - start = doc.get_iter_at_mark(doc.get_insert()) - end = start.copy() - end.forward_line() - - end_mark = doc.create_mark(None, end) - - if not start.ends_line(): - start.forward_to_line_end() - - # Include trailing spaces in the chunk to be removed - while start.backward_char() and start.get_char() in ('\t', ' '): - pass - start.forward_char() - - while doc.get_iter_at_mark(end_mark).compare(start) == 1: - end = start.copy() - while end.get_char() in ('\r', '\n', ' ', '\t'): - end.forward_char() - doc.delete(start, end) - - doc.insert(start, ' ') - start.forward_to_line_end() - - doc.delete_mark(end_mark) - doc.end_user_action() - diff --git a/plugins/joinlines/meson.build b/plugins/joinlines/meson.build index 09426af6..6af07b5a 100644 --- a/plugins/joinlines/meson.build +++ b/plugins/joinlines/meson.build @@ -1,9 +1,22 @@ -install_subdir( +joinlines_sources = files( + 'joinlines.c' +) + +joinlines_deps = [ + dependency('xed'), + dependency('gtk+-3.0'), + dependency('libpeas-1.0'), +] + +library( 'joinlines', - install_dir: pluginslibdir + joinlines_sources, + dependencies: joinlines_deps, + install: true, + install_dir: join_paths(libdir, 'xed', 'plugins') ) -textsize_desktop = custom_target( +joinlines_desktop = custom_target( 'joinlines_desktop', input: 'joinlines.plugin.desktop.in', output: 'joinlines.plugin', diff --git a/plugins/textsize/meson.build b/plugins/textsize/meson.build index a3270a3b..71ef2105 100644 --- a/plugins/textsize/meson.build +++ b/plugins/textsize/meson.build @@ -1,6 +1,19 @@ -install_subdir( +textsize_sources = files( + 'textsize.c' +) + +textsize_deps = [ + dependency('xed'), + dependency('gtk+-3.0'), + dependency('libpeas-1.0'), +] + +library( 'textsize', - install_dir: pluginslibdir + textsize_sources, + dependencies: textsize_deps, + install: true, + install_dir: join_paths(libdir, 'xed', 'plugins') ) textsize_desktop = custom_target( diff --git a/plugins/textsize/textsize.c b/plugins/textsize/textsize.c new file mode 100644 index 00000000..e3d1cdf8 --- /dev/null +++ b/plugins/textsize/textsize.c @@ -0,0 +1,293 @@ +#include +#include +#include +#include + +#define MAX_FONT_SIZE 64 +#define MIN_FONT_SIZE 4 + +#define TEXT_ZOOM_TYPE (text_zoom_get_type()) +G_DECLARE_FINAL_TYPE(TextZoom, text_zoom, TEXT, ZOOM, GObject) + +struct _TextZoom +{ + GObject parent_instance; + XedView *view; + gulong handler_scroll; + gulong handler_key; +}; + +static void xed_view_activatable_iface_init(XedViewActivatableInterface *iface); + +G_DEFINE_FINAL_TYPE_WITH_CODE(TextZoom, text_zoom, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(XED_TYPE_VIEW_ACTIVATABLE, xed_view_activatable_iface_init)) + +enum +{ + PROP_0, + PROP_VIEW +}; + +static void +set_font_size(GtkTextView *view, int delta, gboolean reset) +{ + PangoFontDescription *default_desc = + g_object_get_data(G_OBJECT(view), "zoom-default-font"); + gint *default_size_ptr = + g_object_get_data(G_OBJECT(view), "zoom-default-size"); + gint *current_size_ptr = + g_object_get_data(G_OBJECT(view), "zoom-current-size"); + + if (!default_desc) + { + GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET(view)); + PangoFontDescription *font_desc = NULL; + + gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, + "font", &font_desc, NULL); + + if (font_desc) + { + default_desc = pango_font_description_copy(font_desc); + pango_font_description_free(font_desc); + } + else + { + default_desc = pango_font_description_from_string("Monospace 10"); + } + + g_object_set_data_full(G_OBJECT(view), "zoom-default-font", + default_desc, (GDestroyNotify)pango_font_description_free); + + gint default_size = pango_font_description_get_size(default_desc) / PANGO_SCALE; + if (default_size == 0) + { + default_size = 10; // Fallback size + } + + default_size_ptr = g_new(gint, 1); + *default_size_ptr = default_size; + g_object_set_data_full(G_OBJECT(view), "zoom-default-size", + default_size_ptr, g_free); + + current_size_ptr = g_new(gint, 1); + *current_size_ptr = default_size; + g_object_set_data_full(G_OBJECT(view), "zoom-current-size", + current_size_ptr, g_free); + } + + gint current_size; + if (reset) + { + current_size = *default_size_ptr; + } + else + { + current_size = *current_size_ptr + delta; + if (current_size < MIN_FONT_SIZE) + { + current_size = MIN_FONT_SIZE; + } + if (current_size > MAX_FONT_SIZE) + { + current_size = MAX_FONT_SIZE; + } + } + + *current_size_ptr = current_size; + + PangoFontDescription *desc = pango_font_description_copy(default_desc); + pango_font_description_set_size(desc, current_size * PANGO_SCALE); + + // Use CSS provider instead of the deprecated gtk_widget_override_font + GtkCssProvider *provider = gtk_css_provider_new(); + gchar *css_data = g_strdup_printf( + "textview { font-family: %s; font-size: %dpt; }", + pango_font_description_get_family(desc) ? pango_font_description_get_family(desc) : "monospace", + current_size); + + gtk_css_provider_load_from_data(provider, css_data, -1, NULL); + + GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET(view)); + gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + + g_free(css_data); + g_object_unref(provider); + pango_font_description_free(desc); +} + +static gboolean +on_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer user_data) +{ + guint state = event->state & gtk_accelerator_get_default_mod_mask(); + + if (state == GDK_CONTROL_MASK) + { + switch (event->direction) + { + case GDK_SCROLL_UP: + set_font_size(GTK_TEXT_VIEW(widget), +1, FALSE); + return TRUE; + case GDK_SCROLL_DOWN: + set_font_size(GTK_TEXT_VIEW(widget), -1, FALSE); + return TRUE; + case GDK_SCROLL_SMOOTH: + if (event->delta_y < 0) + { + set_font_size(GTK_TEXT_VIEW(widget), +1, FALSE); + } + else if (event->delta_y > 0) + { + set_font_size(GTK_TEXT_VIEW(widget), -1, FALSE); + } + return TRUE; + default: + break; + } + } + return FALSE; +} + +static gboolean +on_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + if ((event->state & GDK_CONTROL_MASK) != 0) + { + switch (event->keyval) + { + case GDK_KEY_plus: + case GDK_KEY_KP_Add: + case GDK_KEY_equal: + set_font_size(GTK_TEXT_VIEW(widget), +1, FALSE); + return TRUE; + case GDK_KEY_minus: + case GDK_KEY_KP_Subtract: + set_font_size(GTK_TEXT_VIEW(widget), -1, FALSE); + return TRUE; + case GDK_KEY_0: + case GDK_KEY_KP_0: + set_font_size(GTK_TEXT_VIEW(widget), 0, TRUE); + return TRUE; + } + } + return FALSE; +} + +static void +text_zoom_activate(XedViewActivatable *activatable) +{ + TextZoom *self = TEXT_ZOOM(activatable); + + gtk_widget_set_can_focus(GTK_WIDGET(self->view), TRUE); + gtk_widget_add_events(GTK_WIDGET(self->view), + GDK_SCROLL_MASK | GDK_KEY_PRESS_MASK); + + self->handler_scroll = g_signal_connect(self->view, "scroll-event", + G_CALLBACK(on_scroll_event), self); + self->handler_key = g_signal_connect(self->view, "key-press-event", + G_CALLBACK(on_key_press_event), self); +} + +static void +text_zoom_deactivate(XedViewActivatable *activatable) +{ + TextZoom *self = TEXT_ZOOM(activatable); + + if (self->handler_scroll) + { + g_signal_handler_disconnect(self->view, self->handler_scroll); + } + if (self->handler_key) + { + g_signal_handler_disconnect(self->view, self->handler_key); + } + + self->handler_scroll = 0; + self->handler_key = 0; +} + +static void +text_zoom_get_property(GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + TextZoom *self = TEXT_ZOOM(object); + switch (prop_id) + { + case PROP_VIEW: + g_value_set_object(value, self->view); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +text_zoom_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + TextZoom *self = TEXT_ZOOM(object); + + switch (prop_id) + { + case PROP_VIEW: + self->view = XED_VIEW(g_value_get_object(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +text_zoom_dispose(GObject *object) +{ + TextZoom *self = TEXT_ZOOM(object); + + if (self->handler_scroll && self->view) + g_signal_handler_disconnect(self->view, self->handler_scroll); + if (self->handler_key && self->view) + g_signal_handler_disconnect(self->view, self->handler_key); + + self->handler_scroll = 0; + self->handler_key = 0; + self->view = NULL; + + G_OBJECT_CLASS(text_zoom_parent_class)->dispose(object); +} + +static void +text_zoom_class_init(TextZoomClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->get_property = text_zoom_get_property; + object_class->set_property = text_zoom_set_property; + object_class->dispose = text_zoom_dispose; + + g_object_class_override_property(object_class, PROP_VIEW, "view"); +} + +static void +text_zoom_init(TextZoom *self) +{ + self->view = NULL; + self->handler_scroll = 0; + self->handler_key = 0; +} + +static void +xed_view_activatable_iface_init(XedViewActivatableInterface *iface) +{ + iface->activate = text_zoom_activate; + iface->deactivate = text_zoom_deactivate; +} + +G_MODULE_EXPORT void +peas_register_types(PeasObjectModule *module) +{ + peas_object_module_register_extension_type(module, + XED_TYPE_VIEW_ACTIVATABLE, + TEXT_ZOOM_TYPE); +} diff --git a/plugins/textsize/textsize.plugin.desktop.in b/plugins/textsize/textsize.plugin.desktop.in index 5ce2e653..5c4469fc 100644 --- a/plugins/textsize/textsize.plugin.desktop.in +++ b/plugins/textsize/textsize.plugin.desktop.in @@ -5,6 +5,6 @@ IAge=3 _Name=Text Size _Description=Allow controlling the zoom levels of the text Icon=gnome-mime-text-x-python -Authors=Steve Frécinaux ;Linux Mint team +Authors=Steve Frécinaux ;ItsZariep ;Linux Mint team Copyright=Copyright © 2017 by the authors Builtin=true \ No newline at end of file diff --git a/plugins/textsize/textsize/__init__.py b/plugins/textsize/textsize/__init__.py deleted file mode 100644 index f3286bb4..00000000 --- a/plugins/textsize/textsize/__init__.py +++ /dev/null @@ -1,234 +0,0 @@ -# -*- coding: utf-8 -*- -# -# __init__.py - Text size plugin -# -# Copyright (C) 2008 - Konstantin Mikhaylov -# Copyright (C) 2009 - Wouter Bolsterlee -# Copyright (C) 2010 - Ignacio Casal Quinteiro -# Copyright (C) 2010 - Jesse van den Kieboom -# Copyright (C) 2017 - Linux Mint team -# -# 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. - -from gi.repository import GObject, Gio, Gtk, Gdk, Xed -from .documenthelper import DocumentHelper - -import gettext -gettext.install("xed") - -MENU_PATH = "/MenuBar/ViewMenu/ViewOps_1" - -class TextSizePlugin(GObject.Object, Xed.WindowActivatable): - __gtype_name__ = "TextSizePlugin" - - window = GObject.Property(type=Xed.Window) - - def __init__(self): - GObject.Object.__init__(self) - - def do_activate(self): - self._views = {} - - # Insert menu items - self._insert_menu() - - # Insert document helpers - for view in self.window.get_views(): - self.add_document_helper(view) - - self.window.connect('tab-added', self.on_tab_added) - self.window.connect('tab-removed', self.on_tab_removed) - - self._accel_group = Gtk.AccelGroup() - self.window.add_accel_group(self._accel_group) - - self._proxy_callback_map = { - 'LargerTextAction': self.on_larger_text_accel, - 'SmallerTextAction': self.on_smaller_text_accel, - 'NormalSizeAction': self.on_normal_size_accel - } - - self._proxy_mappings = [] - self._init_proxy_accels() - self._accel_map_handler_id = Gtk.AccelMap.get().connect('changed', self.on_accel_map_changed) - - def _install_proxy(self, action): - if not isinstance(action, Gtk.Action): - action = self._action_group.get_action(str(action)) - - if not action: - return - - entry = Gtk.AccelMap.lookup_entry(action.get_accel_path()) - - if not entry: - return - - mapping = { - Gdk.KEY_KP_Equal: Gdk.KEY_equal, - Gdk.KEY_plus: Gdk.KEY_equal, - Gdk.KEY_KP_Add: Gdk.KEY_equal, - Gdk.KEY_KP_Subtract: Gdk.KEY_minus, - Gdk.KEY_KP_0: Gdk.KEY_0, - } - - for extra_accel in mapping.keys(): - if mapping[extra_accel] == entry[1].accel_key: - key = extra_accel - mod = entry[1].accel_mods - - callback = self._proxy_callback_map[action.get_name()] - - self._accel_group.connect(key, mod, Gtk.AccelFlags.LOCKED, callback) - self._proxy_mappings.append((key, mod)) - - def _init_proxy_accels(self): - self._install_proxy('LargerTextAction') - self._install_proxy('SmallerTextAction') - self._install_proxy('NormalSizeAction') - - def do_deactivate(self): - # Remove any installed menu items - self._remove_menu() - - for view in self.window.get_views(): - self.remove_document_helper(view) - - self.window.remove_accel_group(self._accel_group) - - Gtk.AccelMap.get().disconnect(self._accel_map_handler_id) - - self._accel_group = None - self._action_group = None - - def _insert_menu(self): - # Get the GtkUIManager - manager = self.window.get_ui_manager() - - # Create a new action group - self._action_group = Gtk.ActionGroup(name="XedTextSizePluginActions") - self._action_group.add_actions([("LargerTextAction", None, _("_Larger Text"), - "equal", None, - self.on_larger_text_activate), - ("SmallerTextAction", None, _("S_maller Text"), - "minus", None, - self.on_smaller_text_activate), - ("NormalSizeAction", None, _("_Normal size"), - "0", None, - self.on_normal_size_activate)]) - - # Insert the action group - manager.insert_action_group(self._action_group) - - self._ui_id = manager.new_merge_id(); - - manager.add_ui(self._ui_id, - MENU_PATH, - "LargerTextAction", - "LargerTextAction", - Gtk.UIManagerItemType.MENUITEM, - False) - - manager.add_ui(self._ui_id, - MENU_PATH, - "SmallerTextAction", - "SmallerTextAction", - Gtk.UIManagerItemType.MENUITEM, - False) - - manager.add_ui(self._ui_id, - MENU_PATH, - "NormalSizeAction", - "NormalSizeAction", - Gtk.UIManagerItemType.MENUITEM, - False) - - def _remove_menu(self): - # Get the GtkUIManager - manager = self.window.get_ui_manager() - - # Remove the ui - manager.remove_ui(self._ui_id) - - # Remove the action group - manager.remove_action_group(self._action_group) - - # Make sure the manager updates - manager.ensure_update() - - def do_update_state(self): - self._action_group.set_sensitive(self.window.get_active_document() != None) - - def get_helper(self, view): - if not hasattr(view, "textsize_document_helper"): - return None - return view.textsize_document_helper - - def add_document_helper(self, view): - if self.get_helper(view) != None: - return - - DocumentHelper(view) - - def remove_document_helper(self, view): - helper = self.get_helper(view) - - if helper != None: - helper.stop() - - def call_helper(self, cb): - view = self.window.get_active_view() - - if view: - cb(self.get_helper(view)) - - # Menu activate handlers - def on_larger_text_activate(self, action, user_data=None): - self.call_helper(lambda helper: helper.larger_text()) - - def on_smaller_text_activate(self, action, user_data=None): - self.call_helper(lambda helper: helper.smaller_text()) - - def on_normal_size_activate(self, action, user_data=None): - self.call_helper(lambda helper: helper.normal_size()) - - def on_larger_text_accel(self, group, accel, key, mod): - self.call_helper(lambda helper: helper.larger_text()) - - def on_smaller_text_accel(self, group, accel, key, mod): - self.call_helper(lambda helper: helper.smaller_text()) - - def on_normal_size_accel(self, group, accel, key, mod): - self.call_helper(lambda helper: helper.normal_size()) - - def on_tab_added(self, window, tab): - self.add_document_helper(tab.get_view()) - - def on_tab_removed(self, window, tab): - self.remove_document_helper(tab.get_view()) - - def _remap_proxy(self, action): - # Remove previous proxy - if item in self._proxy_mappings: - self._accel_group.disconnect_key(item[0], item[1]) - - self._install_proxy(action) - - def on_accel_map_changed(self, accelmap, path, key, mod): - for action in self._action_group.list_actions(): - if action.get_accel_path() == path: - self._remap_proxy(action) - return diff --git a/plugins/textsize/textsize/documenthelper.py b/plugins/textsize/textsize/documenthelper.py deleted file mode 100644 index 5329c340..00000000 --- a/plugins/textsize/textsize/documenthelper.py +++ /dev/null @@ -1,117 +0,0 @@ -# -*- coding: utf-8 -*- -# -# documenthelper.py - Document helper -# -# Copyright (C) 2010 - Jesse van den Kieboom -# Copyright (C) 2017 - Linux Mint team -# -# 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. - - -from .signals import Signals -from gi.repository import Gtk, Gdk, Pango - -MAX_FONT_SIZE = 30 -MIN_FONT_SIZE = 5 - -class DocumentHelper(Signals): - def __init__(self, view): - Signals.__init__(self) - - self._view = view - - self.connect_signal(self._view, 'scroll-event', self.on_scroll_event) - self.connect_signal(self._view, 'button-press-event', self.on_button_press_event) - - self._view.textsize_document_helper = self - - self._default_font = None - self._last_font = None - - def stop(self): - if self._default_font: - self._view.override_font(self._default_font) - - self.disconnect_signals(self._view) - - self._view.textsize_document_helper = None - - def update_default_font(self): - context = self._view.get_style_context() - description = context.get_font(context.get_state()).copy() - - if not self._last_font or description.hash() != self._last_font.hash(): - self._default_font = description - - def set_font_size(self, amount): - self.update_default_font() - - context = self._view.get_style_context() - description = context.get_font(context.get_state()).copy() - - buf = self._view.get_buffer() - size = description.get_size() / Pango.SCALE - - if size >= MAX_FONT_SIZE and amount == 1: - return; - if size <= MIN_FONT_SIZE and amount == -1: - return; - - description.set_size(max(1, (size + amount)) * Pango.SCALE) - - self._view.override_font(description) - self._last_font = description - - def larger_text(self): - self.set_font_size(1) - - def smaller_text(self): - self.set_font_size(-1) - - def normal_size(self): - self.update_default_font() - - buf = self._view.get_buffer() - - self._view.override_font(self._default_font) - self._last_font = self._default_font - - def on_scroll_event(self, view, event): - state = event.state & Gtk.accelerator_get_default_mod_mask() - - if state != Gdk.ModifierType.CONTROL_MASK: - return Gdk.EVENT_PROPAGATE - - if event.direction == Gdk.ScrollDirection.UP: - self.larger_text() - elif event.direction == Gdk.ScrollDirection.DOWN: - self.smaller_text() - elif event.direction == Gdk.ScrollDirection.SMOOTH: - if event.delta_y > 0: - self.smaller_text() - elif event.delta_y < 0: - self.larger_text() - - return Gdk.EVENT_STOP - - def on_button_press_event(self, view, event): - state = event.state & Gtk.accelerator_get_default_mod_mask() - - if state == Gdk.ModifierType.CONTROL_MASK and event.button == 2: - self.normal_size() - return Gdk.EVENT_STOP - else: - return Gdk.EVENT_PROPAGATE diff --git a/plugins/textsize/textsize/signals.py b/plugins/textsize/textsize/signals.py deleted file mode 100644 index 2996a129..00000000 --- a/plugins/textsize/textsize/signals.py +++ /dev/null @@ -1,69 +0,0 @@ -class Signals(object): - def __init__(self): - self._signals = {} - - def _connect(self, obj, name, handler, connector): - ret = self._signals.setdefault(obj, {}) - - hid = connector(name, handler) - ret.setdefault(name, []).append(hid) - - return hid - - def connect_signal(self, obj, name, handler): - return self._connect(obj, name, handler, obj.connect) - - def connect_signal_after(self, obj, name, handler): - return self._connect(obj, name, handler, obj.connect_after) - - def disconnect_signals(self, obj): - if obj not in self._signals: - return False - - for name in self._signals[obj]: - for hid in self._signals[obj][name]: - obj.disconnect(hid) - - del self._signals[obj] - return True - - def block_signal(self, obj, name): - if obj not in self._signals: - return False - - if name not in self._signals[obj]: - return False - - for hid in self._signals[obj][name]: - obj.handler_block(hid) - - return True - - def unblock_signal(self, obj, name): - if obj not in self._signals: - return False - - if name not in self._signals[obj]: - return False - - for hid in self._signals[obj][name]: - obj.handler_unblock(hid) - - return True - - def disconnect_signal(self, obj, name): - if obj not in self._signals: - return False - - if name not in self._signals[obj]: - return False - - for hid in self._signals[obj][name]: - obj.disconnect(hid) - - del self._signals[obj][name] - - if len(self._signals[obj]) == 0: - del self._signals[obj] - - return True \ No newline at end of file