Post New Code Cleanup
This commit is contained in:
3
src/core/__init__.py
Normal file
3
src/core/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Gtk Bound Signal Module
|
||||
"""
|
||||
3
src/core/containers/__init__.py
Normal file
3
src/core/containers/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Containers Module
|
||||
"""
|
||||
35
src/core/containers/core_widget.py
Normal file
35
src/core/containers/core_widget.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from .left_box import LeftBox
|
||||
from .right_box import RightBox
|
||||
|
||||
|
||||
|
||||
class CoreWidget(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(CoreWidget, self).__init__()
|
||||
|
||||
self._builder = settings.get_builder()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
self.add(LeftBox())
|
||||
self.add(RightBox())
|
||||
40
src/core/containers/left_box.py
Normal file
40
src/core/containers/left_box.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from ..widgets.radio_buttons import RadioButtons
|
||||
from ..widgets.delay_amount import DelayAmount
|
||||
from ..widgets.preview_image import PreviewPane
|
||||
from ..widgets.menu_popover import MenuPopover
|
||||
|
||||
|
||||
class LeftBox(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(LeftBox, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
menu = MenuPopover()
|
||||
delay_amount = DelayAmount()
|
||||
menu.set_relative_to(delay_amount)
|
||||
menu.set_position(Gtk.PositionType.BOTTOM)
|
||||
|
||||
self.add(RadioButtons())
|
||||
self.add(delay_amount)
|
||||
self.add(PreviewPane())
|
||||
35
src/core/containers/right_box.py
Normal file
35
src/core/containers/right_box.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from ..widgets.snapshot_button import SnapshotButton
|
||||
from ..widgets.monitor_list import MonitorList
|
||||
from ..widgets.images_list import ImagesList
|
||||
|
||||
|
||||
|
||||
class RightBox(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(RightBox, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
self.add(SnapshotButton())
|
||||
self.add(MonitorList())
|
||||
self.add(ImagesList())
|
||||
72
src/core/controller.py
Normal file
72
src/core/controller.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from .mixins.signals_mixins import SignalsMixins
|
||||
from .controller_data import ControllerData
|
||||
from .screenshot_controller import ScreenshotController
|
||||
from .containers.core_widget import CoreWidget
|
||||
|
||||
|
||||
|
||||
class Controller(SignalsMixins, ControllerData):
|
||||
def __init__(self, args, unknownargs):
|
||||
self.setup_controller_data()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
if args.no_plugins == "false":
|
||||
self.plugins.launch_plugins()
|
||||
|
||||
for arg in unknownargs + [args.new_tab,]:
|
||||
if os.path.isfile(arg):
|
||||
message = f"FILE|{arg}"
|
||||
event_system.emit("post_file_to_ipc", message)
|
||||
|
||||
if os.path.isdir(arg):
|
||||
message = f"DIR|{arg}"
|
||||
event_system.emit("post_file_to_ipc", message)
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
self.window.connect("focus-out-event", self.unset_keys_and_data)
|
||||
self.window.connect("key-press-event", self.on_global_key_press_controller)
|
||||
self.window.connect("key-release-event", self.on_global_key_release_controller)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
|
||||
event_system.subscribe("handle_dir_from_ipc", self.handle_dir_from_ipc)
|
||||
event_system.subscribe("tggl_top_main_menubar", self._tggl_top_main_menubar)
|
||||
|
||||
def _load_widgets(self):
|
||||
ScreenshotController()
|
||||
|
||||
def load_glade_file(self):
|
||||
self.builder = Gtk.Builder()
|
||||
# self.builder.add_from_file(settings.get_glade_file())
|
||||
self.builder.expose_object("main_window", self.window)
|
||||
|
||||
settings.set_builder(self.builder)
|
||||
self.core_widget = CoreWidget()
|
||||
|
||||
settings.register_signals_to_builder([self, self.core_widget])
|
||||
|
||||
def get_core_widget(self):
|
||||
return self.core_widget
|
||||
|
||||
def _tggl_top_main_menubar(self):
|
||||
print("_tggl_top_main_menubar > stub...")
|
||||
68
src/core/controller_data.py
Normal file
68
src/core/controller_data.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# Python imports
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from plugins.plugins_controller import PluginsController
|
||||
|
||||
|
||||
|
||||
class ControllerData:
|
||||
''' ControllerData contains most of the state of the app at ay given time. It also has some support methods. '''
|
||||
|
||||
def setup_controller_data(self) -> None:
|
||||
self.window = settings.get_main_window()
|
||||
self.builder = None
|
||||
self.core_widget = None
|
||||
self.was_midified_key = False
|
||||
self.ctrl_down = False
|
||||
self.shift_down = False
|
||||
self.alt_down = False
|
||||
|
||||
self.load_glade_file()
|
||||
self.plugins = PluginsController()
|
||||
|
||||
|
||||
def clear_console(self) -> None:
|
||||
''' Clears the terminal screen. '''
|
||||
os.system('cls' if os.name == 'nt' else 'clear')
|
||||
|
||||
def call_method(self, _method_name: str, data: type) -> type:
|
||||
'''
|
||||
Calls a method from scope of class.
|
||||
|
||||
Parameters:
|
||||
a (obj): self
|
||||
b (str): method name to be called
|
||||
c (*): Data (if any) to be passed to the method.
|
||||
Note: It must be structured according to the given methods requirements.
|
||||
|
||||
Returns:
|
||||
Return data is that which the calling method gives.
|
||||
'''
|
||||
method_name = str(_method_name)
|
||||
method = getattr(self, method_name, lambda data: f"No valid key passed...\nkey={method_name}\nargs={data}")
|
||||
return method(*data) if data else method()
|
||||
|
||||
def has_method(self, obj: type, method: type) -> type:
|
||||
''' Checks if a given method exists. '''
|
||||
return callable(getattr(obj, method, None))
|
||||
|
||||
def clear_children(self, widget: type) -> None:
|
||||
''' Clear children of a gtk widget. '''
|
||||
for child in widget.get_children():
|
||||
widget.remove(child)
|
||||
|
||||
def get_clipboard_data(self, encoding="utf-8") -> str:
|
||||
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout=subprocess.PIPE)
|
||||
retcode = proc.wait()
|
||||
data = proc.stdout.read()
|
||||
return data.decode(encoding).strip()
|
||||
|
||||
def set_clipboard_data(self, data: type, encoding="utf-8") -> None:
|
||||
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE)
|
||||
proc.stdin.write(data.encode(encoding))
|
||||
proc.stdin.close()
|
||||
retcode = proc.wait()
|
||||
3
src/core/mixins/__init__.py
Normal file
3
src/core/mixins/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Generic Mixins Module
|
||||
"""
|
||||
3
src/core/mixins/signals/__init__.py
Normal file
3
src/core/mixins/signals/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Signals module
|
||||
"""
|
||||
20
src/core/mixins/signals/ipc_signals_mixin.py
Normal file
20
src/core/mixins/signals/ipc_signals_mixin.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
|
||||
class IPCSignalsMixin:
|
||||
""" IPCSignalsMixin handle messages from another starting solarfm process. """
|
||||
|
||||
def print_to_console(self, message=None):
|
||||
print(message)
|
||||
|
||||
def handle_file_from_ipc(self, path: str) -> None:
|
||||
print(f"File From IPC: {path}")
|
||||
|
||||
def handle_dir_from_ipc(self, path: str) -> None:
|
||||
print(f"Dir From IPC: {path}")
|
||||
94
src/core/mixins/signals/keyboard_signals_mixin.py
Normal file
94
src/core/mixins/signals/keyboard_signals_mixin.py
Normal file
@@ -0,0 +1,94 @@
|
||||
# Python imports
|
||||
import re
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
valid_keyvalue_pat = re.compile(r"[a-z0-9A-Z-_\[\]\(\)\| ]")
|
||||
|
||||
|
||||
|
||||
class KeyboardSignalsMixin:
|
||||
""" KeyboardSignalsMixin keyboard hooks controller. """
|
||||
|
||||
# TODO: Need to set methods that use this to somehow check the keybindings state instead.
|
||||
def unset_keys_and_data(self, widget=None, eve=None):
|
||||
self.ctrl_down = False
|
||||
self.shift_down = False
|
||||
self.alt_down = False
|
||||
|
||||
def on_global_key_press_controller(self, eve, user_data):
|
||||
keyname = Gdk.keyval_name(user_data.keyval).lower()
|
||||
modifiers = Gdk.ModifierType(user_data.get_state() & ~Gdk.ModifierType.LOCK_MASK)
|
||||
|
||||
self.was_midified_key = True if modifiers != 0 else False
|
||||
|
||||
if keyname.replace("_l", "").replace("_r", "") in ["control", "alt", "shift"]:
|
||||
if "control" in keyname:
|
||||
self.ctrl_down = True
|
||||
if "shift" in keyname:
|
||||
self.shift_down = True
|
||||
if "alt" in keyname:
|
||||
self.alt_down = True
|
||||
|
||||
def on_global_key_release_controller(self, widget, event):
|
||||
""" Handler for keyboard events """
|
||||
keyname = Gdk.keyval_name(event.keyval).lower()
|
||||
modifiers = Gdk.ModifierType(event.get_state() & ~Gdk.ModifierType.LOCK_MASK)
|
||||
|
||||
if keyname.replace("_l", "").replace("_r", "") in ["control", "alt", "shift"]:
|
||||
should_return = self.was_midified_key and (self.ctrl_down or self.shift_down or self.alt_down)
|
||||
|
||||
if "control" in keyname:
|
||||
self.ctrl_down = False
|
||||
if "shift" in keyname:
|
||||
self.shift_down = False
|
||||
if "alt" in keyname:
|
||||
self.alt_down = False
|
||||
|
||||
# NOTE: In effect a filter after releasing a modifier and we have a modifier mapped
|
||||
if should_return:
|
||||
self.was_midified_key = False
|
||||
return
|
||||
|
||||
mapping = keybindings.lookup(event)
|
||||
logger.debug(f"on_global_key_release_controller > key > {keyname}")
|
||||
logger.debug(f"on_global_key_release_controller > keyval > {event.keyval}")
|
||||
logger.debug(f"on_global_key_release_controller > mapping > {mapping}")
|
||||
|
||||
if mapping:
|
||||
# See if in controller scope
|
||||
try:
|
||||
getattr(self, mapping)()
|
||||
return True
|
||||
except Exception:
|
||||
# Must be plugins scope, event call, OR we forgot to add method to controller scope
|
||||
if "||" in mapping:
|
||||
sender, eve_type = mapping.split("||")
|
||||
else:
|
||||
sender = ""
|
||||
eve_type = mapping
|
||||
|
||||
self.handle_key_event_system(sender, eve_type)
|
||||
else:
|
||||
logger.debug(f"on_global_key_release_controller > key > {keyname}")
|
||||
|
||||
if self.ctrl_down:
|
||||
if not keyname in ["1", "kp_1", "2", "kp_2", "3", "kp_3", "4", "kp_4"]:
|
||||
self.handle_key_event_system(None, mapping)
|
||||
else:
|
||||
...
|
||||
|
||||
def handle_key_event_system(self, sender, eve_type):
|
||||
event_system.emit(eve_type)
|
||||
|
||||
def keyboard_close_tab(self):
|
||||
...
|
||||
13
src/core/mixins/signals_mixins.py
Normal file
13
src/core/mixins/signals_mixins.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
from .signals.ipc_signals_mixin import IPCSignalsMixin
|
||||
from .signals.keyboard_signals_mixin import KeyboardSignalsMixin
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
|
||||
class SignalsMixins(KeyboardSignalsMixin, IPCSignalsMixin):
|
||||
...
|
||||
122
src/core/screenshot_controller.py
Normal file
122
src/core/screenshot_controller.py
Normal file
@@ -0,0 +1,122 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
import pyscreenshot as capture
|
||||
|
||||
# Application imports
|
||||
from .widgets.region.window import RegionWindow
|
||||
|
||||
|
||||
|
||||
class ScreenshotController:
|
||||
def __init__(self):
|
||||
super(ScreenshotController, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("grab_entire_screen", self.grab_entire_screen)
|
||||
event_system.subscribe("grab_active_window", self.grab_active_window)
|
||||
event_system.subscribe("pass_to_region_handler", self.pass_to_region_handler)
|
||||
event_system.subscribe("grab_region_hide", self._grab_region_hide)
|
||||
event_system.subscribe("grab_region", self._grab_region)
|
||||
event_system.subscribe("grab_selected_monitor", self.grab_selected_monitor)
|
||||
|
||||
def _load_widgets(self):
|
||||
RegionWindow()
|
||||
|
||||
|
||||
def grab_entire_screen(self):
|
||||
logger.info("Grabbing Entire Screen...")
|
||||
window = settings.get_main_window()
|
||||
|
||||
@daemon_threaded
|
||||
def do_grab():
|
||||
im = capture.grab(childprocess = False)
|
||||
im.save( settings.generate_screenshot_name() )
|
||||
GLib.idle_add(window.show)
|
||||
|
||||
window.hide()
|
||||
do_grab()
|
||||
|
||||
|
||||
def grab_active_window(self):
|
||||
logger.info("Grabbing Active Window...")
|
||||
|
||||
event_system.emit("grab_delay")
|
||||
screen = Gdk.get_default_root_window().get_screen()
|
||||
w = screen.get_active_window()
|
||||
pb = Gdk.pixbuf_get_from_window(w, *w.get_geometry())
|
||||
pb.savev(settings.generate_screenshot_name(), "png", (), ())
|
||||
|
||||
|
||||
def pass_to_region_handler(self):
|
||||
logger.info("Passing to Region Handler...")
|
||||
window = settings.get_main_window()
|
||||
window.hide()
|
||||
event_system.emit("show_region_window")
|
||||
|
||||
def _grab_region_hide(self, region_window):
|
||||
region_window.hide()
|
||||
window = settings.get_main_window()
|
||||
window.show()
|
||||
|
||||
def _grab_region(self, region_window):
|
||||
logger.info("Grabbing Selected Region...")
|
||||
x, y = region_window.get_position()
|
||||
w, h = region_window.get_size()
|
||||
x2 = x + w
|
||||
y2 = y + h
|
||||
|
||||
def show_region_window():
|
||||
# NOTE: No clue why showing window has it move outta prior place.
|
||||
# So, move back to original spot before showing...
|
||||
region_window.move(x, y)
|
||||
region_window.show()
|
||||
|
||||
@daemon_threaded
|
||||
def do_bounding_box_grab(x1, y1, x2, y2):
|
||||
while region_window.is_visible():
|
||||
...
|
||||
|
||||
im = capture.grab(bbox = (x1, y1, x2, y2), childprocess = False)
|
||||
im.save( settings.generate_screenshot_name() )
|
||||
GLib.idle_add(show_region_window)
|
||||
|
||||
region_window.hide()
|
||||
offset = 1
|
||||
do_bounding_box_grab(x - offset, y - offset, x2 + offset, y2 + offset)
|
||||
|
||||
|
||||
def grab_selected_monitor(self):
|
||||
logger.info("Grabbing Monitor...")
|
||||
|
||||
window = settings.get_main_window()
|
||||
monitor = event_system.emit_and_await("get_selected_monitor")
|
||||
x2 = monitor.x + monitor.width
|
||||
y2 = monitor.y + monitor.height
|
||||
|
||||
@daemon_threaded
|
||||
def do_bounding_box_grab(x1, y1, x2, y2):
|
||||
im = capture.grab(bbox = (x1, y1, x2, y2), childprocess = False)
|
||||
im.save( settings.generate_screenshot_name() )
|
||||
GLib.idle_add(window.show)
|
||||
|
||||
event_system.emit("grab_delay")
|
||||
window.hide()
|
||||
do_bounding_box_grab(monitor.x, monitor.y, x2, y2)
|
||||
3
src/core/widgets/__init__.py
Normal file
3
src/core/widgets/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Widgets Module
|
||||
"""
|
||||
61
src/core/widgets/delay_amount.py
Normal file
61
src/core/widgets/delay_amount.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# Python imports
|
||||
import time
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class DelayAmount(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(DelayAmount, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
self.set_margin_top(5)
|
||||
self.set_margin_bottom(5)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("set_grab_delay", self.set_grab_delay)
|
||||
event_system.subscribe("grab_delay", self.grab_delay)
|
||||
|
||||
def _load_widgets(self):
|
||||
label = Gtk.Label("Timeout: ")
|
||||
spinner = Gtk.SpinButton()
|
||||
|
||||
spinner.set_hexpand(True)
|
||||
spinner.set_numeric(True)
|
||||
spinner.set_snap_to_ticks(True)
|
||||
spinner.set_digits(0)
|
||||
spinner.set_range(0, 120)
|
||||
spinner.set_increments(1, 5)
|
||||
|
||||
self.add(label)
|
||||
self.add(spinner)
|
||||
|
||||
def set_grab_delay(self, wait = 0.0):
|
||||
delay_amount = self.get_children()[1]
|
||||
delay_amount.set_value(wait)
|
||||
|
||||
|
||||
def grab_delay(self, wait = None):
|
||||
delay_amount = self.get_children()[1]
|
||||
if not wait:
|
||||
wait = delay_amount.get_value_as_int()
|
||||
|
||||
time.sleep(wait)
|
||||
114
src/core/widgets/images_list.py
Normal file
114
src/core/widgets/images_list.py
Normal file
@@ -0,0 +1,114 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gio
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from mixins.tree_nixin import TreeMixin
|
||||
|
||||
|
||||
|
||||
class ImagesList(TreeMixin, Gtk.ScrolledWindow):
|
||||
def __init__(self):
|
||||
super(ImagesList, self).__init__()
|
||||
|
||||
self._tree_view = None
|
||||
self._store = None
|
||||
self._dir_watcher = None
|
||||
self._watch_dir = None
|
||||
|
||||
self._set_file_watcher()
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_size_request(200, -1)
|
||||
self.set_hexpand(False)
|
||||
self.set_vexpand(True)
|
||||
self.set_margin_top(15)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
scroll, self._store = self._create_treeview_widget("Images")
|
||||
|
||||
self._tree_view = scroll.get_children()[0]
|
||||
self._tree_view.connect("button-press-event", self._handle_clicks)
|
||||
self._tree_view.connect("row-activated", self._set_active_image)
|
||||
|
||||
self._tree_view.set_property("activate-on-single-click", True)
|
||||
|
||||
self.referesh_directory_list()
|
||||
self.add(scroll)
|
||||
|
||||
def _set_file_watcher(self):
|
||||
if settings.is_debug():
|
||||
logger.debug(f"Watcher Will Not Be Set...")
|
||||
return
|
||||
|
||||
images_dir = settings.get_screenshots_dir()
|
||||
self._watch_dir = Gio.File.new_for_uri(f"file://{images_dir}")
|
||||
self._dir_watcher = self._watch_dir.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, Gio.Cancellable())
|
||||
|
||||
self._dir_watcher.connect("changed", self._dir_watch_updates, ())
|
||||
|
||||
def _dir_watch_updates(self, file_monitor, file, other_file = None, eve_type = None, data = None):
|
||||
if eve_type in [Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED,
|
||||
Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN,
|
||||
Gio.FileMonitorEvent.MOVED_OUT]:
|
||||
|
||||
self._store.clear()
|
||||
self.referesh_directory_list()
|
||||
|
||||
def _set_active_image(self, tree_view = None, path = None, column = None):
|
||||
file = self.get_selected()
|
||||
event_system.emit("set_image_to_view", (file,))
|
||||
event_system.emit("set_revert_data", (file,))
|
||||
|
||||
def _handle_clicks(self, widget = None, eve = None):
|
||||
if eve.button == 1 and eve.type == 5:
|
||||
file = self.get_selected()
|
||||
event_system.emit("set_revert_data", (file,))
|
||||
event_system.emit("open_file")
|
||||
return
|
||||
|
||||
if eve.button == 1 and eve.type == 4:
|
||||
self._set_active_image()
|
||||
return
|
||||
|
||||
if eve.button == 3:
|
||||
file = self.get_selected()
|
||||
|
||||
event_system.emit("set_revert_data", (file,))
|
||||
event_system.emit("show_menu", (file,))
|
||||
return
|
||||
|
||||
@threaded
|
||||
def referesh_directory_list(self):
|
||||
images = settings.get_directory_list()
|
||||
images.sort()
|
||||
for image in images:
|
||||
GLib.idle_add(self.add_to_store, (image,))
|
||||
|
||||
def add_to_store(self, image):
|
||||
self._store.append(image)
|
||||
|
||||
def get_selected(self):
|
||||
model, treeiter = self._tree_view.get_selection().get_selected()
|
||||
if treeiter != None:
|
||||
return model[treeiter][0]
|
||||
|
||||
return None
|
||||
117
src/core/widgets/menu_popover.py
Normal file
117
src/core/widgets/menu_popover.py
Normal file
@@ -0,0 +1,117 @@
|
||||
# Python imports
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class MenuPopover(Gtk.Popover):
|
||||
def __init__(self):
|
||||
super(MenuPopover, self).__init__()
|
||||
|
||||
self._revert_name = None
|
||||
self._rename_entry = None
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_size_request(360, -1)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("set_revert_data", self.set_revert_data)
|
||||
event_system.subscribe("show_menu", self.show_menu)
|
||||
event_system.subscribe("open_file", self.open_file)
|
||||
|
||||
def _load_widgets(self):
|
||||
box = Gtk.Box()
|
||||
box2 = Gtk.Box()
|
||||
|
||||
self._rename_entry = Gtk.Entry()
|
||||
revert_button = Gtk.Button(label = "Revert")
|
||||
rename_button = Gtk.Button(label = "Rename")
|
||||
open_button = Gtk.Button(label = "Open")
|
||||
delete_button = Gtk.Button(label = "Delete")
|
||||
|
||||
revert_button.set_image( Gtk.Image.new_from_icon_name("gtk-undo", 4) )
|
||||
rename_button.set_image( Gtk.Image.new_from_icon_name("gtk-edit", 4) )
|
||||
open_button.set_image( Gtk.Image.new_from_icon_name("gtk-open", 4) )
|
||||
delete_button.set_image( Gtk.Image.new_from_icon_name("gtk-delete", 4) )
|
||||
|
||||
revert_button.set_always_show_image(True)
|
||||
rename_button.set_always_show_image(True)
|
||||
open_button.set_always_show_image(True)
|
||||
delete_button.set_always_show_image(True)
|
||||
box.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
box2.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
self._rename_entry.set_hexpand(True)
|
||||
|
||||
box2.add(self._rename_entry)
|
||||
box2.add(revert_button)
|
||||
box.add(box2)
|
||||
box.add(rename_button)
|
||||
box.add(open_button)
|
||||
box.add(delete_button)
|
||||
|
||||
revert_button.connect("clicked", self.revert_name)
|
||||
rename_button.connect("clicked", self.rename_file)
|
||||
open_button.connect("clicked", self.open_file)
|
||||
delete_button.connect("clicked", self.delete_file)
|
||||
|
||||
box.show_all()
|
||||
self.add(box)
|
||||
|
||||
|
||||
def set_revert_data(self, name):
|
||||
if not name in ("", None):
|
||||
self._revert_name = name
|
||||
self._rename_entry.set_text(name)
|
||||
|
||||
def show_menu(self, name):
|
||||
if not name in ("", None):
|
||||
self.set_revert_data(name)
|
||||
self.popup()
|
||||
|
||||
def revert_name(self, widget = None, data = None):
|
||||
self._rename_entry.set_text(self._revert_name)
|
||||
|
||||
def rename_file(self, widget, data=None):
|
||||
dir = settings.get_screenshots_dir()
|
||||
new_name = self._rename_entry.get_text().strip()
|
||||
|
||||
old_file_path = os.path.join(dir, self._revert_name)
|
||||
new_file_path = os.path.join(dir, new_name)
|
||||
|
||||
try:
|
||||
if os.path.isfile(old_file_path) and not new_name in ("", None):
|
||||
os.rename(old_file_path, new_file_path)
|
||||
self._revert_name = new_name
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
|
||||
def open_file(self, widget = None, data = None):
|
||||
dir = settings.get_screenshots_dir()
|
||||
file = os.path.join(dir, self._revert_name)
|
||||
subprocess.Popen(['xdg-open', file], stdout = subprocess.PIPE)
|
||||
|
||||
def delete_file(self, widget, data=None):
|
||||
try:
|
||||
dir = settings.get_screenshots_dir()
|
||||
file = os.path.join(dir, self._revert_name)
|
||||
if os.path.isfile(file):
|
||||
os.remove(file)
|
||||
self.popdown()
|
||||
event_system.emit("unset_image_preview")
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
68
src/core/widgets/monitor_list.py
Normal file
68
src/core/widgets/monitor_list.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from mixins.tree_nixin import TreeMixin
|
||||
|
||||
|
||||
|
||||
class MonitorList(TreeMixin, Gtk.Box):
|
||||
def __init__(self):
|
||||
super(MonitorList, self).__init__()
|
||||
|
||||
self.MONITORS: [] = None
|
||||
self._monitors_view = None
|
||||
self._store = None
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_hexpand(False)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("get_selected_monitor", self.get_selected_monitor)
|
||||
event_system.subscribe("set_monitor_sensitive", self.set_monitor_sensitive)
|
||||
|
||||
def _load_widgets(self):
|
||||
grid, self._store = self._create_treeview_widget("Monitors")
|
||||
self._monitors_view = grid.get_children()[0]
|
||||
|
||||
self._load_monitor_store()
|
||||
|
||||
self.set_monitor_sensitive()
|
||||
grid.set_hexpand(True)
|
||||
self.add(grid)
|
||||
|
||||
def _load_monitor_store(self):
|
||||
self.MONITORS = settings.get_monitor_data()
|
||||
i = 0
|
||||
for monitor in self.MONITORS:
|
||||
if i > 0:
|
||||
mon = str(monitor.width) + "x" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y)
|
||||
self._store.append([mon])
|
||||
i += 1
|
||||
|
||||
self._monitors_view.set_cursor(0)
|
||||
|
||||
def get_selected_monitor(self):
|
||||
iter = self._monitors_view.get_selection().get_selected()[1]
|
||||
path = self._store.get_path(iter)
|
||||
|
||||
# Slot 0 is ref monitor. Need to add 1 to get proper slot
|
||||
return self.MONITORS[int(str(path)) + 1]
|
||||
|
||||
def set_monitor_sensitive(self, isSensitive = False):
|
||||
self._monitors_view.set_sensitive(isSensitive)
|
||||
56
src/core/widgets/preview_image.py
Normal file
56
src/core/widgets/preview_image.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gio
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class PreviewPane(Gtk.AspectFrame):
|
||||
def __init__(self):
|
||||
super(PreviewPane, self).__init__()
|
||||
|
||||
self._preview_image = None
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_size_request(312, 312)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("set_image_to_view", self.set_image_to_view)
|
||||
event_system.subscribe("unset_image_preview", self.unset_image_preview)
|
||||
|
||||
def _load_widgets(self):
|
||||
self._preview_image = Gtk.Image()
|
||||
self.unset_image_preview()
|
||||
self.add(self._preview_image)
|
||||
|
||||
def set_image_to_view(self, image_file):
|
||||
if not image_file:
|
||||
return
|
||||
|
||||
images_dir = settings.get_screenshots_dir()
|
||||
path = os.path.join(images_dir, image_file)
|
||||
|
||||
pixbuf = Gtk.Image.new_from_file(path).get_pixbuf()
|
||||
scaledPixBuf = pixbuf.scale_simple(480, 320, 2) # 2 = BILINEAR and is best by default
|
||||
self._preview_image.set_from_pixbuf(scaledPixBuf)
|
||||
|
||||
def unset_image_preview(self):
|
||||
pixbuf = Gtk.Image.new_from_icon_name("gtk-missing-image", 4).get_pixbuf()
|
||||
self._preview_image.set_from_pixbuf(pixbuf)
|
||||
76
src/core/widgets/radio_buttons.py
Normal file
76
src/core/widgets/radio_buttons.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class RadioButtons(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(RadioButtons, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("get_screenshot_type", self._get_active_type)
|
||||
|
||||
def _load_widgets(self):
|
||||
radio_1 = Gtk.RadioButton(label = "Entire Screen")
|
||||
radio_2 = Gtk.RadioButton(label = "Active Window")
|
||||
radio_3 = Gtk.RadioButton(label = "Select Region")
|
||||
radio_4 = Gtk.RadioButton(label = "Select Monitor")
|
||||
|
||||
self.add(radio_1)
|
||||
self.add(radio_2)
|
||||
self.add(radio_3)
|
||||
self.add(radio_4)
|
||||
|
||||
self._setup_data()
|
||||
|
||||
def _setup_data(self):
|
||||
last_child = None
|
||||
for child in self.get_children():
|
||||
if last_child:
|
||||
child.join_group(last_child)
|
||||
else:
|
||||
last_child = child
|
||||
|
||||
child.connect("released", self._set_data_state)
|
||||
|
||||
def _get_active_type(self):
|
||||
group = self.get_children()[0].get_group()
|
||||
active_radio = [r for r in group if r.get_active()]
|
||||
return active_radio[0]
|
||||
|
||||
def _set_data_state(self, widget = None, eve = None):
|
||||
label = widget.get_label()
|
||||
isSensitive = False
|
||||
wait = 0.0
|
||||
|
||||
if label == "Entire Screen":
|
||||
...
|
||||
if label == "Active Window":
|
||||
wait = 4.0
|
||||
if label == "Select Region":
|
||||
...
|
||||
if label == "Select Monitor":
|
||||
isSensitive = True
|
||||
|
||||
event_system.emit("set_grab_delay", (wait,))
|
||||
event_system.emit("set_monitor_sensitive", (isSensitive,))
|
||||
3
src/core/widgets/region/__init__.py
Normal file
3
src/core/widgets/region/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Widgets Module
|
||||
"""
|
||||
177
src/core/widgets/region/body_grid.py
Normal file
177
src/core/widgets/region/body_grid.py
Normal file
@@ -0,0 +1,177 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class BodyGrid(Gtk.Grid):
|
||||
def __init__(self, window, gdk_window):
|
||||
super(BodyGrid, self).__init__()
|
||||
|
||||
self._gdk_window = gdk_window
|
||||
self._window = window
|
||||
self._is_dragging = False
|
||||
self._update_block = False
|
||||
self._drag_start_x = 0
|
||||
self._drag_start_y = 0
|
||||
self._current_x = 0
|
||||
self._current_y = 0
|
||||
self._w1 = 0.0
|
||||
self._h1 = 0.0
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("region-window")
|
||||
self.set_vexpand(True)
|
||||
self.set_hexpand(True)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
drag_button = Gtk.Button("")
|
||||
close_button = Gtk.Button("x")
|
||||
grab_button = Gtk.Button("Grab")
|
||||
bottom_right = Gtk.Button("")
|
||||
box2 = Gtk.Box()
|
||||
box3 = Gtk.Box()
|
||||
box4 = Gtk.Box()
|
||||
box5 = Gtk.Box()
|
||||
|
||||
ctx = drag_button.get_style_context()
|
||||
ctx.add_class("expand-button")
|
||||
ctx2 = bottom_right.get_style_context()
|
||||
ctx2.add_class("expand-button")
|
||||
|
||||
col, row = 1, 1
|
||||
self.attach(drag_button, col, row, 11, 1)
|
||||
col, row = 12, 1
|
||||
self.attach(close_button, col, row, 1, 1)
|
||||
col, row = 1, 2
|
||||
self.attach(box2, col, row, 5, 3)
|
||||
col, row = 1, 5
|
||||
self.attach(box3, col, row, 4, 1)
|
||||
col, row = 1, 12
|
||||
self.attach(box4, col, row, 3, 1)
|
||||
col, row = 5, 12
|
||||
self.attach(grab_button, col, row, 3, 1)
|
||||
col, row = 9, 12
|
||||
self.attach(box5, col, row, 3, 1)
|
||||
col, row = 12, 12
|
||||
self.attach(bottom_right, col, row, 1, 1)
|
||||
|
||||
close_button.set_vexpand(False)
|
||||
close_button.set_hexpand(False)
|
||||
box2.set_vexpand(True)
|
||||
box2.set_hexpand(True)
|
||||
box3.set_vexpand(True)
|
||||
box3.set_hexpand(True)
|
||||
box4.set_vexpand(False)
|
||||
box4.set_hexpand(True)
|
||||
box5.set_vexpand(False)
|
||||
box5.set_hexpand(True)
|
||||
|
||||
drag_button.connect("button-press-event", self._press_event)
|
||||
drag_button.connect("motion-notify-event", self._move_motion_event)
|
||||
drag_button.connect("button-release-event", self._release_event)
|
||||
close_button.connect("button-release-event", self._region_close)
|
||||
grab_button.connect("button-release-event", self._region_grab)
|
||||
bottom_right.connect("button-press-event", self._press_event)
|
||||
bottom_right.connect("motion-notify-event", self._resize_motion_event)
|
||||
bottom_right.connect("button-release-event", self._release_event)
|
||||
|
||||
|
||||
def _region_close(self, widget = None, eve = None):
|
||||
event_system.emit("grab_region_hide", (self._window,))
|
||||
|
||||
def _region_grab(self, widget = None, eve = None):
|
||||
event_system.emit("grab_region", (self._window,))
|
||||
|
||||
def _press_event(self, widget = None, eve = None):
|
||||
window = self.get_parent()
|
||||
cursor = Gdk.Cursor(Gdk.CursorType.CROSSHAIR)
|
||||
window.get_window().set_cursor(cursor)
|
||||
|
||||
self._is_dragging = True
|
||||
self._drag_start_x = eve.x_root
|
||||
self._drag_start_y = eve.y_root
|
||||
|
||||
if self._current_x == 0:
|
||||
self._current_x, self._current_y = self._window.get_position()
|
||||
|
||||
self._w1, self._h1 = self._window.get_size()
|
||||
|
||||
def _resize_motion_event(self, widget = None, eve = None):
|
||||
if self._update_block: return
|
||||
|
||||
x1 = self._drag_start_x
|
||||
y1 = self._drag_start_y
|
||||
x2 = eve.x_root
|
||||
y2 = eve.y_root
|
||||
w = 0
|
||||
h = 0
|
||||
|
||||
if x2 > x1: # Is growing
|
||||
w = self._w1 + (x2 - x1)
|
||||
else: # Is shrinking
|
||||
w = self._w1 - (x1 - x2)
|
||||
|
||||
if y2 > y1: # Is growing
|
||||
h = self._h1 + (y2 - y1)
|
||||
else: # Is shrinking
|
||||
h = self._h1 - (y1 - y2)
|
||||
|
||||
self._update_block = True
|
||||
self._window.resize(w, h)
|
||||
self._update_block = False
|
||||
|
||||
def _move_motion_event(self, widget = None, eve = None):
|
||||
if self._is_dragging:
|
||||
if eve.x_root > self._drag_start_x:
|
||||
self._current_x += (eve.x_root - self._drag_start_x)
|
||||
elif eve.x_root < self._drag_start_x:
|
||||
self._current_x -= (self._drag_start_x - eve.x_root)
|
||||
else:
|
||||
self._current_x = self._current_x
|
||||
|
||||
if eve.y_root > self._drag_start_y:
|
||||
self._current_y += (eve.y_root - self._drag_start_y)
|
||||
elif eve.y_root < self._drag_start_y:
|
||||
self._current_y -= (self._drag_start_y - eve.y_root)
|
||||
else:
|
||||
self._current_y = self._current_y
|
||||
|
||||
self._drag_start_x = eve.x_root
|
||||
self._drag_start_y = eve.y_root
|
||||
|
||||
self._update_block = True
|
||||
self._window.move(self._current_x, self._current_y)
|
||||
self._update_block = False
|
||||
|
||||
def _release_event(self, widget = None, eve = None):
|
||||
window = self.get_parent()
|
||||
watch_cursor = Gdk.Cursor(Gdk.CursorType.ARROW)
|
||||
window.get_window().set_cursor(watch_cursor)
|
||||
|
||||
self._is_dragging = False
|
||||
self._drag_start_x = 0
|
||||
self._drag_start_y = 0
|
||||
70
src/core/widgets/region/window.py
Normal file
70
src/core/widgets/region/window.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
import cairo
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
# Application imports
|
||||
from .body_grid import BodyGrid
|
||||
|
||||
|
||||
|
||||
class RegionWindow(Gtk.Window):
|
||||
def __init__(self):
|
||||
super(RegionWindow, self).__init__()
|
||||
|
||||
self._set_window_data()
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_default_size(600, 480)
|
||||
self.set_deletable(False)
|
||||
self.set_decorated(False)
|
||||
self.set_resizable(True)
|
||||
self.set_skip_pager_hint(True)
|
||||
self.set_skip_taskbar_hint(True)
|
||||
self.set_has_resize_grip(True)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("show_region_window", self._show_region_window)
|
||||
|
||||
def _load_widgets(self):
|
||||
gdk_window = self.get_screen().get_root_window()
|
||||
self.add( BodyGrid(self, gdk_window) )
|
||||
|
||||
def _set_window_data(self) -> None:
|
||||
screen = self.get_screen()
|
||||
visual = screen.get_rgba_visual()
|
||||
|
||||
if visual != None and screen.is_composited():
|
||||
self.set_visual(visual)
|
||||
self.set_app_paintable(True)
|
||||
self.connect("draw", self._area_draw)
|
||||
|
||||
# bind css file
|
||||
cssProvider = Gtk.CssProvider()
|
||||
cssProvider.load_from_path( settings.get_css_file() )
|
||||
screen = Gdk.Screen.get_default()
|
||||
styleContext = Gtk.StyleContext()
|
||||
styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
|
||||
|
||||
def _area_draw(self, widget: Gtk.ApplicationWindow, cr: cairo.Context) -> None:
|
||||
cr.set_source_rgba( *(0, 0, 0, 0.0) )
|
||||
cr.set_operator(cairo.OPERATOR_SOURCE)
|
||||
cr.paint()
|
||||
cr.set_operator(cairo.OPERATOR_OVER)
|
||||
|
||||
|
||||
def _show_region_window(self):
|
||||
self.show()
|
||||
48
src/core/widgets/snapshot_button.py
Normal file
48
src/core/widgets/snapshot_button.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class SnapshotButton(Gtk.Button):
|
||||
def __init__(self):
|
||||
super(SnapshotButton, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_always_show_image(True)
|
||||
self.set_image_position(Gtk.PositionType.LEFT)
|
||||
self.set_label("Take Snapshot")
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("clicked", self._take_snapshot)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
image = Gtk.Image.new_from_icon_name("gtk-media-play", 3)
|
||||
self.set_image(image)
|
||||
|
||||
def _take_snapshot(self, widget = None, eve = None):
|
||||
active = event_system.emit_and_await("get_screenshot_type").get_label()
|
||||
if "Entire Screen" in active:
|
||||
event_system.emit("grab_entire_screen")
|
||||
if "Active Window" in active:
|
||||
event_system.emit("grab_active_window")
|
||||
if "Select Region" in active:
|
||||
event_system.emit("pass_to_region_handler")
|
||||
if "Select Monitor" in active:
|
||||
event_system.emit("grab_selected_monitor")
|
||||
98
src/core/window.py
Normal file
98
src/core/window.py
Normal file
@@ -0,0 +1,98 @@
|
||||
# Python imports
|
||||
import time
|
||||
import signal
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
import cairo
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from core.controller import Controller
|
||||
|
||||
|
||||
|
||||
class ControllerStartExceptiom(Exception):
|
||||
...
|
||||
|
||||
|
||||
class Window(Gtk.ApplicationWindow):
|
||||
"""docstring for Window."""
|
||||
|
||||
def __init__(self, args, unknownargs):
|
||||
super(Window, self).__init__()
|
||||
|
||||
self._controller = None
|
||||
|
||||
self._set_window_data()
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
|
||||
settings.set_main_window(self)
|
||||
self._load_widgets(args, unknownargs)
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_default_size(settings.get_main_window_width(),
|
||||
settings.get_main_window_height())
|
||||
|
||||
self.set_size_request(settings.get_main_window_width(),
|
||||
settings.get_main_window_height())
|
||||
|
||||
self.set_title(f"{app_name}")
|
||||
self.set_icon_from_file( settings.get_window_icon() )
|
||||
self.set_gravity(5) # 5 = CENTER
|
||||
self.set_position(1) # 1 = CENTER, 4 = CENTER_ALWAYS
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("delete-event", self._tear_down)
|
||||
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._tear_down)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("tear_down", self._tear_down)
|
||||
|
||||
def _load_widgets(self, args, unknownargs):
|
||||
if settings.is_debug():
|
||||
self.set_interactive_debugging(True)
|
||||
|
||||
|
||||
self._controller = Controller(args, unknownargs)
|
||||
if not self._controller:
|
||||
raise ControllerStartException("Controller exited and doesn't exist...")
|
||||
|
||||
self.add( self._controller.get_core_widget() )
|
||||
|
||||
def _set_window_data(self) -> None:
|
||||
screen = self.get_screen()
|
||||
visual = screen.get_rgba_visual()
|
||||
|
||||
if visual != None and screen.is_composited():
|
||||
self.set_visual(visual)
|
||||
self.set_app_paintable(True)
|
||||
self.connect("draw", self._area_draw)
|
||||
|
||||
# bind css file
|
||||
cssProvider = Gtk.CssProvider()
|
||||
cssProvider.load_from_path( settings.get_css_file() )
|
||||
screen = Gdk.Screen.get_default()
|
||||
styleContext = Gtk.StyleContext()
|
||||
styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
|
||||
|
||||
def _area_draw(self, widget: Gtk.ApplicationWindow, cr: cairo.Context) -> None:
|
||||
cr.set_source_rgba( *settings.get_paint_bg_color() )
|
||||
cr.set_operator(cairo.OPERATOR_SOURCE)
|
||||
cr.paint()
|
||||
cr.set_operator(cairo.OPERATOR_OVER)
|
||||
|
||||
|
||||
def _tear_down(self, widget=None, eve=None):
|
||||
settings.clear_pid()
|
||||
time.sleep(event_sleep_time)
|
||||
Gtk.main_quit()
|
||||
Reference in New Issue
Block a user