diff options
-rw-r--r-- | src/chat.py | 43 | ||||
-rw-r--r-- | src/gtk/chat.ui | 21 | ||||
-rw-r--r-- | src/gtk/custom_adwaita.xml | 188 | ||||
-rw-r--r-- | src/main.py | 8 | ||||
-rw-r--r-- | src/meson.build | 3 | ||||
-rw-r--r-- | src/message.py | 7 | ||||
-rw-r--r-- | src/style.css | 13 | ||||
-rwxr-xr-x | src/weegtk.in | 1 |
8 files changed, 270 insertions, 14 deletions
diff --git a/src/chat.py b/src/chat.py index 3ee0438..1635faa 100644 --- a/src/chat.py +++ b/src/chat.py @@ -16,7 +16,9 @@ # along with this program. If not, see <https://www.gnu.org/licenses/>. # # SPDX-License-Identifier: GPL-3.0-or-later -from gi.repository import Adw, Gtk, Gio, GObject, GLib +import gi +gi.require_version("Spelling", "1") +from gi.repository import Adw, Gtk, Gdk, Gio, GObject, GLib, Spelling, GtkSource from .message import WeegtkMessage from .color import Color @@ -24,7 +26,9 @@ from weegtk import config from weegtk import netfile import json +import os +GObject.type_register(GtkSource.View) @Gtk.Template(resource_path='/com/fryzekconcepts/weegtk/gtk/chat.ui') class WeegtkChat(Adw.Bin): __gtype_name__ = 'WeegtkChat' @@ -65,6 +69,28 @@ class WeegtkChat(Adw.Bin): adj.connect("value-changed", self.scroll_changes) adj.connect("notify::upper", self.upper_notify) + # This is a bit of hack to have the raised color match in the gtk source editor + manager = GtkSource.StyleSchemeManager().get_default() + scheme = manager.get_scheme('CustomAdwaita') + buffer = self.text_entry.get_buffer() + buffer.set_style_scheme(scheme) + + sc_controller = Gtk.ShortcutController(propagation_phase=Gtk.PropagationPhase.CAPTURE) + action = Gtk.CallbackAction.new(self.entry_callback, self) + trigger = Gtk.ShortcutTrigger.parse_string("Return") + shortcut = Gtk.Shortcut(action=action, trigger=trigger) + sc_controller.add_shortcut(shortcut) + + self.add_controller(sc_controller) + + # Enable spell checking + self.checker = Spelling.Checker.get_default() + self.adapter = Spelling.TextBufferAdapter.new(self.text_entry.get_buffer(), self.checker) + self.extra_menu = self.adapter.get_menu_model() + self.text_entry.set_extra_menu(self.extra_menu) + self.text_entry.insert_action_group("spelling", self.adapter) + self.adapter.set_enabled(True) + # TODO figure out why style is not being taken from ui file self.add_css_class("view") @@ -125,7 +151,6 @@ class WeegtkChat(Adw.Bin): def setup_list_item(self, factory, list_item, *user_data): message = WeegtkMessage() list_item.set_child(message) - pass def bind_list_item(self, factory, list_item, *user_data): text = list_item.get_item().get_string() @@ -166,7 +191,10 @@ class WeegtkChat(Adw.Bin): last = self.model.get_string(count - 1) last_data = json.loads(last) if last_data["username"] == user: - msg_type = "message_append" + if msg_type == "system": + msg_type = "system_append" + else: + msg_type = "message_append" data = { "username": user, @@ -179,13 +207,18 @@ class WeegtkChat(Adw.Bin): # TODO clear chat buffer pass + @Gtk.Template.Callback() def entry_activate(self, *args): entry_buffer = self.text_entry.get_buffer() - text = entry_buffer.get_text() + text = entry_buffer.get_text(entry_buffer.get_start_iter(), entry_buffer.get_end_iter(), False) entry_buffer.set_text("", 0) self.emit("buffer_input", self.data['full_name'], text) + def entry_callback(self, *args): + self.entry_activate() + return True + def open_file_dialog(self, dialog, result, caller): try: file = dialog.open_finish(result) @@ -196,7 +229,7 @@ class WeegtkChat(Adw.Bin): conf = config.read() file_url = netfile.upload(file.get_path(), conf["upload"]["url"]) entry_buffer = self.text_entry.get_buffer() - entry_buffer.insert_text(self.text_entry.get_position(), file_url, -1) + entry_buffer.insert_at_cursor(file_url, -1) @Gtk.Template.Callback() def attach_file(self, *args): diff --git a/src/gtk/chat.ui b/src/gtk/chat.ui index fa4d77d..33cb41f 100644 --- a/src/gtk/chat.ui +++ b/src/gtk/chat.ui @@ -34,6 +34,7 @@ <property name="orientation">1</property> <style> <class name="navigation-sidebar"/> + <class name="messages"/> </style> <property name="tab-behavior">item</property> <property name="accessible-role">log</property> @@ -89,26 +90,36 @@ <object class="GtkButton"> <property name="icon-name">mail-attachment</property> <style> + <class name="raised"/> <class name="image-button"/> </style> <signal name="clicked" handler="attach_file"/> </object> </child> <child> - <object class="GtkEntry" id="text_entry"> + <object class="GtkScrolledWindow"> + <property name="max-content-height">10</property> + <property name="margin-start">5</property> + <property name="margin-end">5</property> <property name="halign">fill</property> <property name="hexpand">True</property> <property name="hexpand-set">True</property> - <property name="width-request">50</property> - <property name="margin-start">5</property> - <property name="margin-end">5</property> - <signal name="activate" handler="entry_activate"/> + <property name="vscrollbar-policy">GTK_POLICY_EXTERNAL</property> + <style> + <class name="entry-frame"/> + </style> + <property name="child"> + <object class="GtkSourceView" id="text_entry"> + <property name="valign">center</property> + </object> + </property> </object> </child> <child> <object class="GtkButton"> <property name="icon-name">mail-forward</property> <style> + <class name="raised"/> <class name="image-button"/> </style> <signal name="clicked" handler="entry_activate"/> diff --git a/src/gtk/custom_adwaita.xml b/src/gtk/custom_adwaita.xml new file mode 100644 index 0000000..c599df2 --- /dev/null +++ b/src/gtk/custom_adwaita.xml @@ -0,0 +1,188 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2020 Christian Hergert <christian@hergert.me> + + GtkSourceView is free software; you can redistribute it 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. + + GtkSourceView 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, see <http://www.gnu.org/licenses/>. + +--> +<style-scheme id="CustomAdwaita" _name="CustomAdwaita" version="1.0"> + <author>Christian Hergert</author> + <_description>An style scheme for Adwaita</_description> + + <metadata> + <property name="variant">light</property> + <property name="dark-variant">Adwaita-dark</property> + </metadata> + + <!-- Named Colors --> + <color name="blue_1" value="#99C1F1"/> + <color name="blue_2" value="#62A0EA"/> + <color name="blue_3" value="#3584E4"/> + <color name="blue_4" value="#1C71D8"/> + <color name="blue_5" value="#1A5FB4"/> + <color name="blue_6" value="#1B497E"/> + <color name="blue_7" value="#193D66"/> + <color name="brown_1" value="#CDAB8F"/> + <color name="brown_2" value="#B5835A"/> + <color name="brown_3" value="#986A44"/> + <color name="brown_4" value="#865E3C"/> + <color name="brown_5" value="#63452C"/> + <color name="chameleon_3" value="#4E9A06"/> + <color name="dark_1" value="#77767B"/> + <color name="dark_2" value="#5E5C64"/> + <color name="dark_3" value="#504E55"/> + <color name="dark_4" value="#3D3846"/> + <color name="dark_5" value="#241F31"/> + <color name="dark_6" value="#000000"/> + <color name="green_1" value="#8FF0A4"/> + <color name="green_2" value="#57E389"/> + <color name="green_3" value="#33D17A"/> + <color name="green_4" value="#2EC27E"/> + <color name="green_5" value="#26A269"/> + <color name="green_6" value="#1F7F56"/> + <color name="green_7" value="#1C6849"/> + <color name="light_1" value="#FFFFFF"/> + <color name="light_2" value="#FCFCFC"/> + <color name="light_3" value="#F6F5F4"/> + <color name="light_4" value="#DEDDDA"/> + <color name="light_5" value="#C0BFBC"/> + <color name="light_6" value="#B0AFAC"/> + <color name="light_7" value="#9A9996"/> + <color name="orange_1" value="#FFBE6F"/> + <color name="orange_2" value="#FFA348"/> + <color name="orange_3" value="#FF7800"/> + <color name="orange_4" value="#E66100"/> + <color name="orange_5" value="#C64600"/> + <color name="purple_1" value="#DC8ADD"/> + <color name="purple_2" value="#C061CB"/> + <color name="purple_3" value="#9141AC"/> + <color name="purple_4" value="#813D9C"/> + <color name="purple_5" value="#613583"/> + <color name="red_1" value="#F66151"/> + <color name="red_2" value="#ED333B"/> + <color name="red_3" value="#E01B24"/> + <color name="red_4" value="#C01C28"/> + <color name="red_5" value="#A51D2D"/> + <color name="teal_1" value="#93DDC2"/> + <color name="teal_2" value="#5BC8AF"/> + <color name="teal_3" value="#33B2A4"/> + <color name="teal_4" value="#26A1A2"/> + <color name="teal_5" value="#218787"/> + <color name="violet_2" value="#7D8AC7"/> + <color name="violet_3" value="#6362C8"/> + <color name="violet_4" value="#4E57BA"/> + <color name="yellow_1" value="#F9F06B"/> + <color name="yellow_2" value="#F8E45C"/> + <color name="yellow_3" value="#F6D32D"/> + <color name="yellow_4" value="#F5C211"/> + <color name="yellow_5" value="#E5A50A"/> + <color name="yellow_6" value="#D38B09"/> + <color name="raised" value="#EBEBEB"/> + + <!-- Global Styles --> + <style name="background-pattern" background="#FAFAFA"/> + <style name="bracket-match" bold="true"/> + <style name="current-line" background="raised"/> + <style name="current-line-number" background="light_3" foreground="light_7"/> + <style name="cursor" foreground="dark_1"/> + <style name="draw-spaces" foreground="light_6"/> + <style name="line-numbers" background="light_1" foreground="light_6"/> + <style name="map-overlay" background="dark_1"/> + <style name="right-margin" background="dark_1" foreground="dark_1"/> + <style name="search-match" background="#rgba(252,247,181,.5)" foreground="dark_4"/> + <style name="text" background="raised" foreground="dark_3"/> + + <!-- Defaults --> + <style name="def:base-n-integer" foreground="violet_4"/> + <style name="def:boolean" foreground="violet_4"/> + <style name="def:comment" foreground="dark_1"/> + <style name="def:constant" foreground="violet_4"/> + <style name="def:decimal" foreground="violet_4"/> + <style name="def:deletion" strikethrough="true"/> + <style name="def:doc-comment-element" foreground="dark_3"/> + <style name="def:emphasis" italic="true"/> + <style name="def:error" underline="error" underline-color="red_4"/> + <style name="def:floating-point" foreground="violet_4"/> + <style name="def:function" foreground="blue_4"/> + <style name="def:heading" foreground="teal_5" bold="true"/> + <style name="def:identifier" foreground="chameleon_3"/> + <style name="def:inline-code" foreground="violet_4"/> + <style name="def:link-destination" foreground="blue_3" italic="true" underline="low"/> + <style name="def:link-text" foreground="red_3"/> + <style name="def:list-marker" foreground="orange_5" bold="true"/> + <style name="def:net-address" foreground="blue_3" underline="low"/> + <style name="def:note" foreground="dark_4" background="#FCF7B5" bold="true"/> + <style name="def:number" foreground="violet_4"/> + <style name="def:preformatted-section" foreground="violet_4"/> + <style name="def:preprocessor" foreground="orange_5"/> + <style name="def:shebang" foreground="dark_1" bold="true"/> + <style name="def:special-char" foreground="red_2" bold="false"/> + <style name="def:statement" foreground="orange_5" bold="true"/> + <style name="def:string" foreground="teal_5"/> + <style name="def:strong-emphasis" bold="true"/> + <style name="def:type" foreground="teal_5" bold="true"/> + <style name="def:underlined" underline="single"/> + <style name="def:warning" underline="error" underline-color="yellow_4"/> + + <!-- C# --> + <style name="c-sharp:format" foreground="violet_4"/> + <style name="c-sharp:preprocessor" foreground="dark_2"/> + + <!-- C --> + <style name="c:printf" foreground="violet_4"/> + <style name="c:signal-name" foreground="red_4"/> + <style name="c:storage-class" foreground="teal_5" bold="true"/> + <style name="c:type-keyword" foreground="teal_5" bold="true"/> + + <!-- CSS --> + <style name="css:id-selector" foreground="teal_5" bold="true"/> + <style name="css:property-name" foreground="orange_5"/> + <style name="css:pseudo-selector" foreground="violet_4" bold="true"/> + <style name="css:selector-symbol" foreground="orange_5" bold="true"/> + <style name="css:type-selector" foreground="teal_5" bold="true"/> + <style name="css:vendor-specific" foreground="yellow_6"/> + + <!-- Diff --> + <style name="diff:added-line" foreground="teal_4"/> + <style name="diff:changed-line" foreground="orange_4"/> + <style name="diff:diff-file" foreground="violet_4"/> + <style name="diff:location" foreground="yellow_6"/> + <style name="diff:removed-line" foreground="red_1"/> + + <!-- Go --> + <style name="go:printf" foreground="violet_4"/> + + <!-- Python 2 --> + <style name="python:builtin-function" foreground="blue_4"/> + <style name="python:class-name" foreground="teal_5" bold="true"/> + <style name="python:module-handler" foreground="red_3"/> + + <!-- Rust --> + <style name="rust:attribute" foreground="violet_4"/> + <style name="rust:lifetime" foreground="orange_5" bold="false" italic="false"/> + <style name="rust:macro" foreground="violet_4" bold="false"/> + <style name="rust:scope" foreground="orange_5"/> + + <!-- Vala --> + <style name="vala:attributes" foreground="dark_2" bold="false"/> + + <!-- XML --> + <style name="xml:attribute-name" foreground="orange_5"/> + <style name="xml:attribute-value" foreground="violet_4"/> + <style name="xml:element-name" foreground="teal_5"/> + <style name="xml:namespace" foreground="yellow_6"/> + <style name="xml:processing-instruction" foreground="yellow_6" bold="true"/> + +</style-scheme> diff --git a/src/main.py b/src/main.py index ea387eb..91fed06 100644 --- a/src/main.py +++ b/src/main.py @@ -24,8 +24,9 @@ import traceback gi.require_version('Gtk', '4.0') gi.require_version('Adw', '1') +gi.require_version("Spelling", "1") -from gi.repository import Gtk, Gio, Adw +from gi.repository import Gtk, Gio, Adw, Spelling, GtkSource from .window import WeegtkWindow from weegtk import network @@ -56,6 +57,11 @@ class WeegtkApplication(Adw.Application): # https://gitlab.gnome.org/GNOME/gtk/-/issues/5917 self.pages = [] + # Add custom adwaita source theme so editing widget matches background + manager = GtkSource.StyleSchemeManager().get_default() + manager.append_search_path(f"{os.environ["WEEGTK_INSTALL_DIR"]}/weegtk") + manager.force_rescan() + conf = config.read() if config.str_to_bool(conf["relay"]["autoconnect"]): self.connect_to_weechat() diff --git a/src/meson.build b/src/meson.build index 081477c..d4fd452 100644 --- a/src/meson.build +++ b/src/meson.build @@ -38,7 +38,8 @@ weegtk_sources = [ 'relay/network.py', 'relay/protocol.py', 'relay/color.py', - 'relay/netfile.py' + 'relay/netfile.py', + 'gtk/custom_adwaita.xml' ] install_data(weegtk_sources, install_dir: moduledir) diff --git a/src/message.py b/src/message.py index db50829..0be93c2 100644 --- a/src/message.py +++ b/src/message.py @@ -65,7 +65,7 @@ class WeegtkMessage(Gtk.Box): else: self.avatar.set_text(data["username"]) - if data["type"] == "message_append": + if data["type"] in ["message_append", "system_append"]: self.avatar.set_visible(False) self.username.set_visible(False) @@ -80,7 +80,10 @@ class WeegtkMessage(Gtk.Box): msg = Gtk.Label(label=markuped, selectable=True, wrap=True, wrap_mode=Pango.WrapMode.WORD_CHAR, xalign=0, margin_top=margin, use_markup=True, - margin_start= padding_size if data["type"] == "message_append" else 0) + margin_start= padding_size if data["type"] in ["message_append", "system_append"] else 0) + + if data["type"] in ["system", "system_append"]: + msg.add_css_class("system-message") self.message_list.append(msg) diff --git a/src/style.css b/src/style.css index ae7eab8..363bf29 100644 --- a/src/style.css +++ b/src/style.css @@ -7,3 +7,16 @@ box.message { padding-top: 2px; padding-bottom: 2px; } + +.messages > row { + min-height: 0px; +} + +.system-message { + opacity: 0.6; +} + +.entry-frame { + border-radius: 9px; + background: #ebebeb; +} diff --git a/src/weegtk.in b/src/weegtk.in index 123a529..e0264c7 100755 --- a/src/weegtk.in +++ b/src/weegtk.in @@ -38,6 +38,7 @@ gettext.install('weegtk', localedir) if __name__ == '__main__': import gi + os.environ["WEEGTK_INSTALL_DIR"] = pkgdatadir from gi.repository import Gio resource = Gio.Resource.load(os.path.join(pkgdatadir, 'weegtk.gresource')) resource._register() |