#!/usr/bin/env python3.5 # Copyright 2017 Digital # # This file is part of DigiLib. # # DigiLib 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 3 of the License, or # (at your option) any later version. # # DigiLib 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 DigiLib. If not, see . # ## Imports # Python Libraries import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import Gdk import logging import logging.config import os import pprint import random import string import sys import time import yaml # My libraries import digilib.misc ## Logging log = logging.getLogger(__name__+".gui") ## Global Variables ## Classes class LabelName(Gtk.Label): def __init__(self, *args,**kwargs): super(LabelName, self).__init__(*args,**kwargs) self.set_css_name("namelabel") self.set_halign(Gtk.Align(2)) class LabelValue(Gtk.Label): """docstring for LabelValue""" def __init__(self, *args,**kwargs): super(LabelValue, self).__init__(*args,**kwargs) self.set_css_name("valuelabel") self.set_halign(Gtk.Align(1)) class InfoFrame(Gtk.Frame): """docstring for InfoFrame.""" def __init__(self,**kwargs): super(InfoFrame, self).__init__(**kwargs) self.lines = { # id:{ # "layout": layout, # "widgets": [label_name,label_value,widget], # "update_func":widget_update_func # } } self.current_line_no = 0 # self.layout = Gtk.Grid(halign=Gtk.Align(1)) self.layout = Gtk.Grid() self.layout.set_row_spacing(10) self.layout.set_column_spacing(5) self.layout.set_column_homogeneous(False) self.layout.set_hexpand(True) self.add(self.layout) def add_line( self, identifier, name, value, unit=None, widget=None, widget_update_func=None ): if id in self.lines.keys(): raise ValueError( "Identifiers must be uniqe, but '" +identifier +"' already exists!" ) self.lines[identifier] = { "layout":None, "wname":None, "wvalue":None, "wunit":None, "wextra":None, "update_func":None } self.lines[identifier]["update_func"] = widget_update_func # if there is a widget and an update function was passed then update it if widget_update_func == True: self.lines[identifier]["update_func"] = widget.set_value if self.lines[identifier]["update_func"]: self.lines[identifier]["update_func"](value) layout = Gtk.Box() layout.set_spacing(5) layout.set_homogeneous(False) self.lines[identifier]["layout"] = layout # create the labels for the name and value field and also for the unit # field if an unit was specified label_name = LabelName(name) self.lines[identifier]["wname"] = label_name self.layout.attach(label_name,0,self.current_line_no,1,1) label_value = LabelValue(value) self.lines[identifier]["wvalue"] = label_value layout.add(label_value) if unit: label_unit = LabelValue(unit) self.lines[identifier]["wunit"] = label_unit layout.add(label_unit) if widget: self.lines[identifier]["wextra"] = widget layout.add(widget) self.layout.attach(layout,1,self.current_line_no,1,1) self.current_line_no += 1 def update_name(self,identifier,name): self.lines[identifier]["wname"].set_label(name) def update_unit(self,identifier,unit): self.lines[identifier]["wunit"].set_label(unit) def update_value(self,identifier,value): self.lines[identifier]["wvalue"].set_label(str(value)) if self.lines[identifier]["update_func"]: self.lines[identifier]["update_func"](value) print(1) # class ChildGrid(Gtk.Grid): # def __init__(self): # super(ChildGrid,self).__init__() # self.prepare() # def prepare(self): # pass # # class ChildScrollBase(Gtk.ScrolledWindow): # def __init__(self): # super(ChildScroll,self).__init__() # self.prepare() # def prepare(self): # pass class ChildConsole(Gtk.Grid): scroll = True history_list = [] history_position = -1 def __init__(self,get_client): super(ChildConsole,self).__init__() self.get_client = get_client self.set_css_name("tab_console") self.prepare() self.button_send.connect("clicked",self.on_entry_activated) self.entry_cmd.connect("activate",self.on_entry_activated) self.entry_cmd.connect("key-press-event",self.on_keypress) def prepare(self): self.scroll_mark = Gtk.TextMark(name="scroll_mark") self.text_buffer_log = Gtk.TextBuffer() self.text_view_log = Gtk.TextView(hexpand=True,vexpand=True) self.text_view_log.set_buffer(self.text_buffer_log) self.text_view_log.set_editable(False) self.text_view_log.set_cursor_visible(False) self.text_view_log.props.pixels_above_lines = 2 self.text_view_log.props.pixels_below_lines = 2 self.text_view_log.props.right_margin = 2 self.text_view_log.props.left_margin = 6 # self.text_view_log.set_hexpand(True) # self.text_view_log.set_vexpand(True) self.scrolled_window = Gtk.ScrolledWindow() self.entry_cmd = Gtk.Entry(hexpand=True) # self.entry_cmd.set_cursor_hadjustment(Gtk.Align(2)) # self.entry_cmd.set_hexpand(True) self.button_send = Gtk.Button(label="send") # self.button_send.set_label("send") self.scrolled_window.add(self.text_view_log) self.attach(self.scrolled_window,0,1,2,1) self.attach(self.entry_cmd,0,2,1,1) self.attach(self.button_send,1,2,1,1) def add_msg(self,text,sender_name="Server"): for line in text.splitlines(): if sender_name: line = sender_name+":"+line self.text_buffer_log.insert( self.text_buffer_log.get_end_iter(), "\n"+line.rstrip() ) self.scroll_down(None) if self.scroll: self.scroll_down(None) def add_msg_threadsafe(self,*args,**kwargs): Gdk.threads_enter() self.add_msg(*args,**kwargs) Gdk.threads_leave() def send(self,text): client = self.get_client() if client: if client.is_connected: client.send(text) def scroll_down(self,*args): self.scroll = True self.text_buffer_log.add_mark( self.scroll_mark, self.text_buffer_log.get_end_iter() ) self.text_view_log.scroll_to_mark( mark=self.scroll_mark, # No idea what these arguments do, but they work. within_margin=0.0, use_align=True, xalign=0.5, yalign=0.5 ) self.text_buffer_log.delete_mark(self.scroll_mark) def toggle_scroll(self,*args): self.scroll = not self.scroll def get_entry_text(self): text = self.entry_cmd.get_text() self.entry_cmd.set_text("") return text def on_entry_activated(self,widget): text = self.get_entry_text() if text.strip(): self.history_position = -1 if len(self.history_list) == 0: self.history_list.insert(0,text) else: if self.history_list[0] != text: self.history_list.insert(0,text) self.add_msg(text,"you") self.send(text) def on_keypress(self,widget,event): if not widget == self.entry_cmd: lgui.debug("exiting keypress event function because the widget was \ not self.entry_cmd") return True if event.keyval == Gdk.KEY_Up: # Up if self.history_position < len(self.history_list)-1: self.history_position += 1 text = self.history_list[self.history_position] self.entry_cmd.set_text(text) self.entry_cmd.set_position(len(text)) return True elif event.keyval == Gdk.KEY_Down: # Down text = self.entry_cmd.get_text() if self.history_position == -1 and text != "": self.entry_cmd.set_text("") elif self.history_position == 0: self.history_position = -1 self.entry_cmd.set_text("") elif self.history_position > 0: self.history_position -= 1 text = self.history_list[self.history_position] self.entry_cmd.set_text(text) self.entry_cmd.set_position(len(text)) return True class ChildOverview(Gtk.ScrolledWindow): def __init__(self): super(ChildOverview,self).__init__() self.set_css_name("tab_overview") self.layout = Gtk.Grid() self.layout.set_column_homogeneous(True) self.add(self.layout) class ChildControl(Gtk.Grid): def __init__(self): super(ChildControl,self).__init__() self.label = Gtk.Label() self.label.set_markup("Another fancy self.label") self.add(self.label) class ChildSettings(Gtk.Grid): def __init__(self): super(ChildSettings,self).__init__() self.label = Gtk.Label() self.label.set_markup("Another fancy self.label") self.add(self.label) class WindowBase(Gtk.Window): def __init__(self,title="Don't Panic!"): super(Gtk.Window,self).__init__(title=title) self.pressed_keys = [] self.key_shortcuts = [] self.connect("delete-event",self.on_delete_event) self.connect("key-press-event",self.on_key_press_event) self.connect("key-release-event",self.on_key_release_event) def keystring_to_gkd(self, keys): key_list = keys.split(" ") known_keys = [] unknown_keys = [] for k in key_list: if "KEY_"+k in dir(Gdk): known_keys.append(eval("Gdk.KEY_"+k)) else: unknown_keys.append(k) if unknown_keys: raise ValueError("Unknown Keys: "+", ".join(unknown_keys)) else: return known_keys def add_key_shortcut(self,keys,func=None,args=[],kwargs={}): key_list = self.keystring_to_gkd(keys) for ks in self.key_shortcuts: if key_list == ks[0]: self.key_shortcuts.remove(ks) break self.key_shortcuts.append([key_list,func,args,kwargs]) def remove_key_shortcut(self,keys): key_list = self.keystring_to_gkd(keys) for ks in self.key_shortcuts: if key_list == ks[0]: self.key_shortcuts.remove(ks) break def on_delete_event(self,*args): print(args) Gtk.main_quit() def on_key_release_event(self,widget,event): if event.keyval in self.pressed_keys: self.pressed_keys.remove(event.keyval) def on_key_press_event(self,widget,event): self.pressed_keys.append(event.keyval) for keys,func,args,kwargs in self.key_shortcuts: if keys == self.pressed_keys: func(*args,**kwargs) break def hello_world(self,*args): print("hello world") #