<gh_stars>0
import gi, os, sys
import datetime
from codes import *

gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk, GObject, GdkPixbuf, Gdk, Pango
from pprint import pprint as pp

WORKINGDIR = os.getcwd()

class View(Gtk.Window):
    __gsignals__ = {
        'send': (GObject.SignalFlags.RUN_FIRST, None, (str,))
    }

    def __init__(self):
        Gtk.Window.__init__(self, title="Pychat")
        self.set_default_size(450, 700)
        self.set_resizable(False)

        self.create_layout()

        self.create_conversation_textview()
        self.create_message_entry()
        self.create_send_button()
        self.create_toolbar()
        self.create_about_link_button()

        self.apply_styles()

    # Styles
    def apply_styles(self):
        style_provider = Gtk.CssProvider()
        style_provider.load_from_path('/usr/share/PyChat/styles/main.css')
        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(),
            style_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

    # Creation of the layout and widgets
    def create_layout(self):
        self.grid = Gtk.Grid()
        self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.add(self.box)
        self.box.pack_start(self.grid, True, True, 0)

    def create_send_button(self):
        send_button = Gtk.Button(label="Send!", name="send_button")
        send_button.connect("clicked", self.on_send_button_clicked)
        self.grid.attach(send_button, 5, 2, 1, 1)

    def create_message_entry(self):
        self.message_entry = Gtk.Entry(name="message_entry")
        self.message_entry.set_text("")
        self.message_entry.connect("activate", self.on_enter_message_entry)
        self.grid.attach(self.message_entry, 0, 2, 5, 1)

    def create_conversation_textview(self):
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_hexpand(True)
        scrolledwindow.set_vexpand(True)
        self.grid.attach(scrolledwindow, 0, 1, 6, 1)

        self.textview = Gtk.TextView()
        self.textview.set_wrap_mode(Gtk.WrapMode.CHAR)
        self.textview.set_editable(False)

        self.textbuffer = self.textview.get_buffer()
        self.textbuffer.set_text("Welcome to Pychat!\n\nEnter :help to see a list of available commands.\nExample :open albert752@127.0.0.1:1234")
        scrolledwindow.add(self.textview)

        self.tag_bold = self.textbuffer.create_tag("bold", weight=Pango.Weight.BOLD)
        self.tag_italic = self.textbuffer.create_tag("italic", style=Pango.Style.ITALIC)
        self.tag_underline = self.textbuffer.create_tag("underline", underline=Pango.Underline.SINGLE)
        self.tag_found = self.textbuffer.create_tag("found", background="yellow")

    def create_toolbar(self):
        toolbar = Gtk.Box(spacing=5)
        self.grid.attach(toolbar, 0, 0, 6, 1)

        title_label = Gtk.Label()
        title_label.set_markup("<big>PyChat</big>")
        toolbar.pack_start(title_label, True, True, 0)

        self.search_entry = Gtk.Entry(name="message_entry")
        toolbar.pack_start(self.search_entry, True, True, 0)
        self.search_entry.connect("activate", self.on_search_clicked)

        button_search = Gtk.Button(label="Serach")
        button_search.connect("clicked", self.on_search_clicked)
        toolbar.pack_start(button_search, True, True, 0)

    def create_about_link_button(self):
        button = Gtk.LinkButton("https://github.com/albert752/Pychat", "© SevenFiveTwo - About", name="about")
        self.grid.attach(button,  0, 3, 1, 1)
        button.connect("clicked", self.about)

    # Widget handlers
    def on_send_button_clicked(self, widget):
        self.emit('send', self.message_entry.get_text())
        self.message_entry.set_text("")

    def on_enter_message_entry(self, widget):
        self.emit('send', self.message_entry.get_text())
        self.message_entry.set_text("")

    def on_save_button_clicked(self, widget):
        pass

    def on_close_button_clicked(self, widget):
        pass

    def on_search_clicked(self, widget):
        cursor_mark = self.textbuffer.get_insert()
        start = self.textbuffer.get_iter_at_mark(cursor_mark)
        if start.get_offset() == self.textbuffer.get_char_count():
            start = self.textbuffer.get_start_iter()

        def _handler(match_start, match_end):
            self.textbuffer.apply_tag(self.tag_found, match_start, match_end)
        self._search(self.search_entry.get_text(), start, _handler)

    def about(self, widget, data=None):

        APP_TITLE = "PyChat"
        APP_LICENCE = "MIT - More details at https://github.com/albert752/Pychat/blob/master/LICENSE"
        APP_COMMENTS = "A simple but powerful Py(thon) Chat"
        APP_COPYRIGHT = "albert752, jplanas98 and mefiso"
        HOME_PAGE = "https://github.com/albert752/Pychat/"
        APP_AUTHORS = ["albert752","jplanas98","mefiso"]

        about_dialog = Gtk.AboutDialog()
        dialog = about_dialog
        dialog.set_name(APP_TITLE)

        try:
            data = open('/usr/share/PyChat/LICENSE', 'r').read()
            dialog.set_license(data)
        except:
            dialog.set_license(APP_LICENCE)

        dialog.set_authors(APP_AUTHORS)
        dialog.set_comments(APP_COMMENTS)
        dialog.set_copyright(APP_COPYRIGHT)
        dialog.set_website(HOME_PAGE)
        dialog.run()
        dialog.destroy()

    # Updating methods
    def update(self, payload):

        if payload[0] == NEW_MESSAGE:
            handler = self.update_conversation_textview_message
            params = payload[1]
        elif payload[0] == STD_OUT:
            handler = self.update_conversation_textview_stdout
            params = payload[1]
        elif payload[0] == STD_ERR:
            handler = self.update_conversation_textview_stderr
            params = payload[1]

        GLib.idle_add(handler, params)
        GLib.idle_add(self._set_format_text)

    def update_conversation_textview_message(self, payload):
        self.textbuffer.insert(self.textbuffer.get_end_iter(), '\n*'+payload[0] + ' > *')
        self.textbuffer.insert(self.textbuffer.get_end_iter(), payload[1])

    def update_conversation_textview_stdout(self, payload):
        self.textbuffer.insert(self.textbuffer.get_end_iter(), '\n*[OK]:* ' + payload)

    def update_conversation_textview_stderr(self, payload):
        self.textbuffer.insert(self.textbuffer.get_end_iter(), '\n*[ER]:* ' + payload)

    # Private support methods
    def _set_format_text(self):
        self._set_style_text('*', self.tag_bold)
        self._set_style_text('_', self.tag_italic)
        self._set_style_text('-', self.tag_underline)
        self._search('*', self.textbuffer.get_start_iter(), self.textbuffer.delete)
        self._search('_', self.textbuffer.get_start_iter(), self.textbuffer.delete)
        self._search('-', self.textbuffer.get_start_iter(), self.textbuffer.delete)

    def _set_style_text(self, text, tag, start=None):
        if start is None:
            start = self.textbuffer.get_start_iter()
        EOB = self.textbuffer.get_end_iter()

        match = start.forward_search(text, 0, EOB)

        if match is not None:
            start, end = match
            match = end.forward_search(text, 0, EOB)
            _, end = match
            self.textbuffer.apply_tag(tag, start, end)
            self._set_style_text(text, tag, start=end)

    def _search(self, text, start, handler):
        end = self.textbuffer.get_end_iter()
        match = start.forward_search(text, 0, end)

        if match is not None:
            match_start, match_end = match
            handler(match_start, match_end)
            self._search(text, match_end, handler)

import gi, os, sys
import datetime
from codes import *

gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk, GObject, GdkPixbuf, Gdk, Pango
from pprint import pprint as pp

WORKINGDIR = os.getcwd()

class View(Gtk.Window):
    __gsignals__ = {
        'send': (GObject.SignalFlags.RUN_FIRST, None, (str,))
    }

    def __init__(self):
        Gtk.Window.__init__(self, title="Pychat")
        self.set_default_size(450, 700)
        self.set_resizable(False)

        self.create_layout()

        self.create_conversation_textview()
        self.create_message_entry()
        self.create_send_button()
        self.create_toolbar()
        self.create_about_link_button()

        self.apply_styles()

    # Styles
    def apply_styles(self):
        style_provider = Gtk.CssProvider()
        style_provider.load_from_path('/usr/share/PyChat/styles/main.css')
        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(),
            style_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

    # Creation of the layout and widgets
    def create_layout(self):
        self.grid = Gtk.Grid()
        self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.add(self.box)
        self.box.pack_start(self.grid, True, True, 0)

    def create_send_button(self):
        send_button = Gtk.Button(label="Send!", name="send_button")
        send_button.connect("clicked", self.on_send_button_clicked)
        self.grid.attach(send_button, 5, 2, 1, 1)

    def create_message_entry(self):
        self.message_entry = Gtk.Entry(name="message_entry")
        self.message_entry.set_text("")
        self.message_entry.connect("activate", self.on_enter_message_entry)
        self.grid.attach(self.message_entry, 0, 2, 5, 1)

    def create_conversation_textview(self):
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_hexpand(True)
        scrolledwindow.set_vexpand(True)
        self.grid.attach(scrolledwindow, 0, 1, 6, 1)

        self.textview = Gtk.TextView()
        self.textview.set_wrap_mode(Gtk.WrapMode.CHAR)
        self.textview.set_editable(False)

        self.textbuffer = self.textview.get_buffer()
        self.textbuffer.set_text("Welcome to Pychat!\n\nEnter :help to see a list of available commands.\nExample :open albert752@127.0.0.1:1234")
        scrolledwindow.add(self.textview)

        self.tag_bold = self.textbuffer.create_tag("bold", weight=Pango.Weight.BOLD)
        self.tag_italic = self.textbuffer.create_tag("italic", style=Pango.Style.ITALIC)
        self.tag_underline = self.textbuffer.create_tag("underline", underline=Pango.Underline.SINGLE)
        self.tag_found = self.textbuffer.create_tag("found", background="yellow")

    def create_toolbar(self):
        toolbar = Gtk.Box(spacing=5)
        self.grid.attach(toolbar, 0, 0, 6, 1)

        title_label = Gtk.Label()
        title_label.set_markup("<big>PyChat</big>")
        toolbar.pack_start(title_label, True, True, 0)

        self.search_entry = Gtk.Entry(name="message_entry")
        toolbar.pack_start(self.search_entry, True, True, 0)
        self.search_entry.connect("activate", self.on_search_clicked)

        button_search = Gtk.Button(label="Serach")
        button_search.connect("clicked", self.on_search_clicked)
        toolbar.pack_start(button_search, True, True, 0)

    def create_about_link_button(self):
        button = Gtk.LinkButton("https://github.com/albert752/Pychat", "© SevenFiveTwo - About", name="about")
        self.grid.attach(button,  0, 3, 1, 1)
        button.connect("clicked", self.about)

    # Widget handlers
    def on_send_button_clicked(self, widget):
        self.emit('send', self.message_entry.get_text())
        self.message_entry.set_text("")

    def on_enter_message_entry(self, widget):
        self.emit('send', self.message_entry.get_text())
        self.message_entry.set_text("")

    def on_save_button_clicked(self, widget):
        pass

    def on_close_button_clicked(self, widget):
        pass

    def on_search_clicked(self, widget):
        cursor_mark = self.textbuffer.get_insert()
        start = self.textbuffer.get_iter_at_mark(cursor_mark)
        if start.get_offset() == self.textbuffer.get_char_count():
            start = self.textbuffer.get_start_iter()

        def _handler(match_start, match_end):
            self.textbuffer.apply_tag(self.tag_found, match_start, match_end)
        self._search(self.search_entry.get_text(), start, _handler)

    def about(self, widget, data=None):

        APP_TITLE = "PyChat"
        APP_LICENCE = "MIT - More details at https://github.com/albert752/Pychat/blob/master/LICENSE"
        APP_COMMENTS = "A simple but powerful Py(thon) Chat"
        APP_COPYRIGHT = "albert752, jplanas98 and mefiso"
        HOME_PAGE = "https://github.com/albert752/Pychat/"
        APP_AUTHORS = ["albert752","jplanas98","mefiso"]

        about_dialog = Gtk.AboutDialog()
        dialog = about_dialog
        dialog.set_name(APP_TITLE)

        try:
            data = open('/usr/share/PyChat/LICENSE', 'r').read()
            dialog.set_license(data)
        except:
            dialog.set_license(APP_LICENCE)

        dialog.set_authors(APP_AUTHORS)
        dialog.set_comments(APP_COMMENTS)
        dialog.set_copyright(APP_COPYRIGHT)
        dialog.set_website(HOME_PAGE)
        dialog.run()
        dialog.destroy()

    # Updating methods
    def update(self, payload):

        if payload[0] == NEW_MESSAGE:
            handler = self.update_conversation_textview_message
            params = payload[1]
        elif payload[0] == STD_OUT:
            handler = self.update_conversation_textview_stdout
            params = payload[1]
        elif payload[0] == STD_ERR:
            handler = self.update_conversation_textview_stderr
            params = payload[1]

        GLib.idle_add(handler, params)
        GLib.idle_add(self._set_format_text)

    def update_conversation_textview_message(self, payload):
        self.textbuffer.insert(self.textbuffer.get_end_iter(), '\n*'+payload[0] + ' > *')
        self.textbuffer.insert(self.textbuffer.get_end_iter(), payload[1])

    def update_conversation_textview_stdout(self, payload):
        self.textbuffer.insert(self.textbuffer.get_end_iter(), '\n*[OK]:* ' + payload)

    def update_conversation_textview_stderr(self, payload):
        self.textbuffer.insert(self.textbuffer.get_end_iter(), '\n*[ER]:* ' + payload)

    # Private support methods
    def _set_format_text(self):
        self._set_style_text('*', self.tag_bold)
        self._set_style_text('_', self.tag_italic)
        self._set_style_text('-', self.tag_underline)
        self._search('*', self.textbuffer.get_start_iter(), self.textbuffer.delete)
        self._search('_', self.textbuffer.get_start_iter(), self.textbuffer.delete)
        self._search('-', self.textbuffer.get_start_iter(), self.textbuffer.delete)

    def _set_style_text(self, text, tag, start=None):
        if start is None:
            start = self.textbuffer.get_start_iter()
        EOB = self.textbuffer.get_end_iter()

        match = start.forward_search(text, 0, EOB)

        if match is not None:
            start, end = match
            match = end.forward_search(text, 0, EOB)
            _, end = match
            self.textbuffer.apply_tag(tag, start, end)
            self._set_style_text(text, tag, start=end)

    def _search(self, text, start, handler):
        end = self.textbuffer.get_end_iter()
        match = start.forward_search(text, 0, end)

        if match is not None:
            match_start, match_end = match
            handler(match_start, match_end)
            self._search(text, match_end, handler)
# Styles # Creation of the layout and widgets # Widget handlers # Updating methods # Private support methods