diff --git a/README.md b/README.md index 526f8a8..c5ce5bc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,12 @@ # Cornea Cornea is a Python + Gtk application to take screenshots. + +# Notes +* Need python 2+ +* ```sudo apt-get install python3``` + +# Images +![1 Cornera interface. ](images/pic1.png) + +# TODO +* Create OCR feature... diff --git a/cornea.desktop b/cornea.desktop new file mode 100755 index 0000000..515f800 --- /dev/null +++ b/cornea.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Cornea +GenericName=A python screenshot application. +Comment=Take screenshots of your desktop. +Exec=/screenshot +Icon=/resources/cornea.png +Type=Application +StartupNotify=true +Categories=Utility; +MimeType=text/plain; +Terminal=false diff --git a/images/pic1.png b/images/pic1.png new file mode 100644 index 0000000..1e8361d Binary files /dev/null and b/images/pic1.png differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e89fc2a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +EasyProcess==0.2.7 +Pillow==6.1.0 +pycairo==1.18.1 +PyGObject==3.34.0 +pyscreenshot==0.5.1 +setproctitle==1.1.10 diff --git a/src/__main__.py b/src/__main__.py new file mode 100755 index 0000000..c4415bf --- /dev/null +++ b/src/__main__.py @@ -0,0 +1,53 @@ +#!/usr/bin/python3 + +# Gtk imports +import gi, faulthandler, signal +gi.require_version('Gtk', '3.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gdk as gdk +from gi.repository import GLib + +# Python imports +import inspect + +from setproctitle import setproctitle + +# Application imports +from utils import Settings, CrossClassSignals +from signal_classes import MainWindow, DrawingArea, MainMenuPopup + + +class Main: + def __init__(self): + setproctitle('Cornea') + GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit) + faulthandler.enable() # For better debug info + + settings = Settings() + builder = settings.returnBuilder() + + # Gets the methods from the classes and sets to handler. + # Then, builder connects to any signals it needs. + utilsClass = CrossClassSignals(settings) + classes = [MainWindow(settings, utilsClass), + DrawingArea(settings, utilsClass), + MainMenuPopup(settings, utilsClass)] + + handlers = {} + for c in classes: + methods = inspect.getmembers(c, predicate=inspect.ismethod) + handlers.update(methods) + + builder.connect_signals(handlers) + window = settings.createWindow() + window.show() + + + +if __name__ == "__main__": + try: + main = Main() + gtk.main() + except Exception as e: + print( repr(e) ) diff --git a/src/resources/Main_Window.glade b/src/resources/Main_Window.glade new file mode 100644 index 0000000..742fdf0 --- /dev/null +++ b/src/resources/Main_Window.glade @@ -0,0 +1,544 @@ + + + + + + False + True + True + False + False + center + + + + + + True + False + vertical + + + True + False + + + True + True + 0 + + + + + + + + + + + + + + True + False + gtk-copy + + + False + popup + mouse + menu + False + north-east + + + + + + True + False + + + True + False + vertical + True + + + Grab Region + True + True + True + grabRegionImage + True + + + + False + True + 0 + + + + + gtk-close + True + True + True + True + True + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + + + True + True + 1 + + + + + + + + + + + + + True + False + gtk-cancel + + + True + False + gtk-edit + + + True + False + gtk-undo + + + 60 + 1 + 10 + + + False + Cornea + center + 500 + 310 + pyCornea.png + center + + + + + + True + False + + + True + False + vertical + + + True + False + + + Entire screen + True + True + False + Take a screenshot of the entire screen. + 5 + True + True + + + + False + True + 0 + + + + + Active window + True + True + False + Take a screenshot of the active window. + 5 + 5 + True + True + entireScrnToggle + + + + False + True + 1 + + + + + Select a region + True + True + False + Select a region to be captured by clicking a point of the screen without releasing the mouse, dragging you mouse to the other corner of the region, and releasing the mouse button. + 5 + 5 + True + True + entireScrnToggle + + + + False + True + 2 + + + + + Select a monitor + True + True + False + Take a screenshot of the selected monitor. + 5 + 5 + True + True + entireScrnToggle + + + + False + True + 3 + + + + + False + True + 0 + + + + + True + False + 5 + 5 + + + True + False + Timeout + right + + + False + True + 0 + + + + + True + True + Delay in seconds before the screenshot is taken. + number + timeoutAdjustment + True + True + + + True + True + 1 + + + + + False + True + 1 + + + + + 312 + 312 + True + False + 0 + none + + + True + False + gtk-missing-image + + + + + False + True + 2 + + + + + True + True + 0 + + + + + True + False + vertical + + + Take Snapshot + True + True + True + picImage + True + + + + False + True + 0 + + + + + True + False + True + monitorStore + False + + + + + + Monitors + + + + 0 + + + + + + + False + True + 1 + + + + + 200 + True + True + 15 + in + + + True + True + fileStore + False + + + + + + + + + Images + True + descending + + + + 0 + + + + + + + + + True + True + 2 + + + + + gtk-close + True + True + True + True + True + + + + False + True + 3 + + + + + False + True + 2 + + + + + + + 320 + 150 + False + delayAmount + + + + True + False + vertical + + + True + False + + + True + True + True + + + True + True + 0 + + + + + Revert + True + True + True + revertImage + True + + + + False + True + 1 + + + + + False + True + 0 + + + + + Rename + True + True + True + renameImage + True + + + + False + True + 1 + + + + + gtk-open + True + True + True + True + True + + + + False + True + 2 + + + + + gtk-delete + True + True + True + True + True + + + + False + True + 3 + + + + + + diff --git a/src/resources/cornea.png b/src/resources/cornea.png new file mode 100644 index 0000000..9227703 Binary files /dev/null and b/src/resources/cornea.png differ diff --git a/src/resources/stylesheet.css b/src/resources/stylesheet.css new file mode 100644 index 0000000..5ad1098 --- /dev/null +++ b/src/resources/stylesheet.css @@ -0,0 +1,3 @@ +.regionWindow { + background-color: rgba(0, 0, 0, 0.0); +} diff --git a/src/screenshot b/src/screenshot new file mode 100755 index 0000000..b0046be --- /dev/null +++ b/src/screenshot @@ -0,0 +1,14 @@ +#!/bin/bash + +# set -o xtrace ## To debug scripts +# set -o errexit ## To exit on error +# set -o errunset ## To exit if a variable is referenced but not set + + +function main() { + SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + cd "${SCRIPTPATH}" + source "../venv/bin/activate" + python . +} +main $@; diff --git a/src/signal_classes/DrawingArea.py b/src/signal_classes/DrawingArea.py new file mode 100644 index 0000000..3696ec4 --- /dev/null +++ b/src/signal_classes/DrawingArea.py @@ -0,0 +1,180 @@ +# Gtk imports +import gi, cairo +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gdk as gdk +from gi.repository import GLib as glib + + +# Python imports +import threading, html + +import pyscreenshot as capture + +# Application imports + + + +def threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs).start() + + return wrapper + +class MouseButtons: + LEFT_BUTTON = 1 + RIGHT_BUTTON = 3 + + +class DrawingArea: + def __init__(self, settings, utilsClass): + self.settings = settings + self.utilsClass = utilsClass + self.builder = self.settings.returnBuilder() + + self.mainWindow = self.builder.get_object('Main_Window') + self.regionWindow = self.builder.get_object('Region_Window') + self.regionMenu = self.builder.get_object('regionMenu') + self.messageLabel = self.builder.get_object('messageLabel') + MONITOR = self.settings.getMonitorData() + + self.settings.setWindowData(self.regionWindow) + self.regionWindow.set_default_size(MONITOR[0].width, MONITOR[0].height) + self.regionWindow.set_size_request(MONITOR[0].width, MONITOR[0].height) + self.regionWindow.set_keep_above(True) + + self.DRAW_AREA = self.builder.get_object("selectionArea") + self.DRAW_AREA.add_events(gdk.EventMask.BUTTON_PRESS_MASK) + self.DRAW_AREA.add_events(gdk.EventMask.BUTTON_RELEASE_MASK) + self.DRAW_AREA.add_events(gdk.EventMask.BUTTON1_MOTION_MASK) + self.DRAW_AREA.connect("button-press-event", self.on_button_press) + self.DRAW_AREA.connect("button-release-event", self.on_button_release) + self.DRAW_AREA.connect("motion-notify-event", self.on_mouse_move) + self.DRAW_AREA.connect("draw", self.on_draw) + + area = self.settings.getMonitorData()[0] + self.SCREENSHOTS_DIR = self.settings.returnScreenshotsDir() + self.WIN_REC = [area.x, area.y, area.width, area.height] + self.coords = [[0.0, 0.0], [0.0, 0.0]] # point1 and point2 + self.BORDER_COLOR = [255, 0, 0, 0.84] + self.TRANS_COLOR = [0, 0, 0, 0.0] + self.BG_COLOR = [0, 0, 0, 0.4] + self.success = "#88cc27" + self.warning = "#ffa800" + self.error = "#ff0000" + self.rec = None + self.cr = None + + self.regionWindow.set_default_size(area.width, area.height) + self.regionWindow.set_size_request(area.width, area.height) + self.regionWindow.move(area.x, area.y) + self.regionWindow.set_resizable(False) + self.regionWindow.set_keep_above(True) + + + + def on_button_press(self, w, e): + self.messageLabel.set_markup("") + if e.type == gdk.EventType.BUTTON_PRESS and e.button == MouseButtons.LEFT_BUTTON: + self.coords[0] = [e.x, e.y] + self.regionMenu.hide() + + # This will reset draw area initially. No further use + if self.cr: + self.draw(self.cr, self.WIN_REC, self.BG_COLOR) + self.DRAW_AREA.queue_draw() + if e.type == gdk.EventType.BUTTON_PRESS and e.button == MouseButtons.RIGHT_BUTTON: + self.regionMenu.show() + + # Update second set of coords. + def on_mouse_move(self, w, e): + self.coords[1] = [e.x, e.y] + self.DRAW_AREA.queue_draw() + + @threaded + def on_button_release(self, w, e): + if e.type == gdk.EventType.BUTTON_RELEASE and e.button == MouseButtons.LEFT_BUTTON: + glib.idle_add(self.regionMenu.show) + + + @threaded + def grabRegion(self, widget): + glib.idle_add(self.regionMenu.hide) + glib.idle_add(self.mainWindow.hide) + self.boundingBoxGrab(self.rec[0], self.rec[1], self.rec[2], self.rec[3]) + glib.idle_add(self.regionMenu.show) + glib.idle_add(self.mainWindow.show) + self.utilsClass.refereshDirectoryList() + + @threaded + def returnToMainWindow(self, widget): + glib.idle_add(self.regionWindow.hide) + glib.idle_add(self.regionMenu.hide) + glib.idle_add(self.mainWindow.show) + + + def on_draw(self, wid, cr): + if not self.cr: self.cr = cr + # Reset the screen with transparent view + self.draw(cr, self.WIN_REC, self.BG_COLOR) + + point1 = self.coords[0] + point2 = self.coords[1] + x1 = point1[0] + y1 = point1[1] + x2 = point2[0] + y2 = point2[1] + w = x2 - x1 + h = y2 - y1 + + # Rectangle information for region and screen grab + self.rec = [int(x1), int(y1), int(x2), int(y2)] + # Draw the new selection region + self.selectionDraw(cr, [x1, y1, w, h], self.BORDER_COLOR, self.TRANS_COLOR) + + + def draw(self, cr, x1y1wh, rgba): + cr.set_source_rgba(rgba[0], rgba[1], rgba[2], rgba[3]) + cr.rectangle(x1y1wh[0], x1y1wh[1], x1y1wh[2], x1y1wh[3]) + cr.set_operator(1); + cr.fill() + + def selectionDraw(self, cr, x1y1wh, brdrcol, transclr): + # Clear the region + cr.set_source_rgba(transclr[0], transclr[1], transclr[2], transclr[3]) + cr.rectangle(x1y1wh[0], x1y1wh[1], x1y1wh[2], x1y1wh[3]) + cr.set_operator(0); + cr.fill() + + # Draw a border + cr.set_source_rgba(brdrcol[0], brdrcol[1], brdrcol[2], brdrcol[3]) + cr.rectangle(x1y1wh[0] - 2, x1y1wh[1] - 2, x1y1wh[2] + 4, x1y1wh[3] + 4) + cr.set_operator(1); + cr.stroke() + + # Actual region grab + def boundingBoxGrab(self, x1, y1, x2, y2): + self.utilsClass.sleep(0.4) + try: + temp = 0; + if x2 < x1: + temp = x1 + x1 = x2 + x2 = temp + + if y2 < y1: + temp = y1 + y1 = y2 + y2 = temp + + + self.utilsClass.boundingBoxGrab(x1, y1, x2, y2) + markup = "Grabbed region successfully..." + glib.idle_add(self.messageLabel.set_markup, markup) + except Exception as e: + print(e) + markup = "Oops..." + \ + "\n" + html.escape( str(e) ) + "" + glib.idle_add(self.messageLabel.set_markup, markup) diff --git a/src/signal_classes/MainMenuPopup.py b/src/signal_classes/MainMenuPopup.py new file mode 100644 index 0000000..7b857a1 --- /dev/null +++ b/src/signal_classes/MainMenuPopup.py @@ -0,0 +1,51 @@ +# Gtk imports + +# Python imports +import os, subprocess + +# Application imports + + +class MainMenuPopup: + def __init__(self, settings, utilsClass): + self.settings = settings + self.utilsClass = utilsClass + + self.builder = self.settings.returnBuilder() + self.fileNameEntry = self.builder.get_object("fileNameEntry") + self.SCREENSHOTS_DIR = self.settings.returnScreenshotsDir() + self.backupName = None + + + def renameFile(self, widget, data=None): + newName = self.fileNameEntry.get_text().strip() + oldFilePath = self.SCREENSHOTS_DIR + '/' + self.backupName + newFilePath = self.SCREENSHOTS_DIR + '/' + newName + try: + if os.path.isfile(oldFilePath) and newName: + os.rename(oldFilePath, newFilePath) + self.backupName = newName + self.utilsClass.refereshDirectoryList() + except Exception as e: + print(str(e)) + + def openFile(self, widget, data=None): + filePath = self.SCREENSHOTS_DIR + '/' + self.backupName + subprocess.Popen(['xdg-open', filePath], stdout=subprocess.PIPE) + + def deleteFile(self, widget, data=None): + try: + filePath = self.SCREENSHOTS_DIR + '/' + self.backupName + if os.path.isfile(filePath): + os.remove(filePath) + self.builder.get_object("mainMenu").popdown() + self.utilsClass.refereshDirectoryList() + except Exception as e: + print(str(e)) + + + def resetName(self, widget, data=None): + self.fileNameEntry.set_text(self.backupName) + + def setBackupVar(self, widget): + self.backupName = self.fileNameEntry.get_text() diff --git a/src/signal_classes/MainWindow.py b/src/signal_classes/MainWindow.py new file mode 100644 index 0000000..010258e --- /dev/null +++ b/src/signal_classes/MainWindow.py @@ -0,0 +1,153 @@ +# Gtk imports +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gdk as gdk +from gi.repository import GLib as glib + +# Python imports +import threading, subprocess, os +import pyscreenshot as capture + +# Application imports + + +def threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs).start() + + return wrapper + +class MouseButtons: + LEFT_BUTTON = 1 + RIGHT_BUTTON = 3 + + +class MainWindow: + def __init__(self, settings, utilsClass): + self.settings = settings + self.utilsClass = utilsClass + self.builder = self.settings.returnBuilder() + + self.mainWindow = self.builder.get_object('Main_Window') + self.regionWindow = self.builder.get_object('Region_Window') + self.monitorStore = self.builder.get_object("monitorStore") + self.MONITORS = self.settings.getMonitorData() + + # Not adding the reference monitor + 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.monitorStore.append([mon]) + i += 1 + + monitorsView = self.builder.get_object("monitorsView") + monitorsView.set_cursor(1) + + self.SCREENSHOTS_DIR = self.settings.returnScreenshotsDir() + self.utilsClass.refereshDirectoryList() + + + + def take_screenshot(self, widget): + active_radio = self.getActiveRadio() + active = active_radio.get_children()[0].get_text() + + if "Entire screen" in active: + self.getEntireScreen() + self.utilsClass.refereshDirectoryList() + if "Active window" in active: + self.getActiveWindow() + self.utilsClass.refereshDirectoryList() + if "Select a region" in active: + self.regionWindow.show_all() + if "Select a monitor" in active: + self.snapshotMonitor() + self.utilsClass.refereshDirectoryList() + + + def getEntireScreen(self): + self.utilsClass.sleep() + # childprocess=False needed to not crash program + im = capture.grab(childprocess=False) + im.save(self.utilsClass.generateScreenshotName()) + + def getActiveWindow(self): + self.utilsClass.sleep() + + 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(self.utilsClass.generateScreenshotName(), "png", (), ()) + + def snapshotMonitor(self): + monitorsView = self.builder.get_object("monitorsView") + iterator = monitorsView.get_selection().get_selected()[1] + path = self.monitorStore.get_path(iterator) + # Slot 0 is ref monitor. Need to add 1 to get proper slot + monitor = self.MONITORS[int(str(path)) + 1] + + self.utilsClass.sleep() + + x2 = monitor.x + monitor.width + y2 = monitor.y + monitor.height + self.utilsClass.boundingBoxGrab(monitor.x, monitor.y, x2, y2) + + def toggleRadioBttn(self, widget): + monitorsView = self.builder.get_object('monitorsView') + delayAmount = self.builder.get_object('delayAmount') + snapshotBttn = self.builder.get_object('snapshotBttn') + active = self.getActiveRadio().get_children()[0].get_text() + + self.regionWindow.hide() + monitorsView.set_sensitive(False) + delayAmount.set_sensitive(True) + snapshotBttn.set_sensitive(True) + delayAmount.set_value(0) + + if "Active window" in active: + delayAmount.set_value(4) + if "Select a region" in active: + delayAmount.set_sensitive(False) + if "Select a monitor" in active: + monitorsView.set_sensitive(True) + + def setImage(self, user_data): + # We need the refresh state for the files list b/c GtkTreeSelection + # is calling this method b/c caling this too quickly causes issues... + if self.utilsClass.returnRefreshingState() == False: + selected = user_data.get_selected()[1] + if selected: + fileNameEntry = self.builder.get_object("fileNameEntry") + imageView = self.builder.get_object("imageView") + file = self.builder.get_object("fileStore").get_value(selected, 0) + fullPath = self.SCREENSHOTS_DIR + "/" + file + + try: + if os.path.isfile(fullPath): + fileNameEntry.set_text(file) + pixbuf = gtk.Image.new_from_file(fullPath).get_pixbuf() + scaledPixBuf = pixbuf.scale_simple(480, 320, 2) # 2 = BILINEAR and is best by default + imageView.set_from_pixbuf(scaledPixBuf) + except Exception as e: + print(e) + + + + def getActiveRadio(self): + master_radio = self.builder.get_object('entireScrnToggle') + active_radio = next(( + radio for radio in master_radio.get_group() + if radio.get_active() + )) + return active_radio + + def showMainMenu(self, w, e): + if e.type == gdk.EventType.BUTTON_PRESS and e.button == MouseButtons.RIGHT_BUTTON: + self.builder.get_object("mainMenu").popup() + + def close(self, widget): + gtk.main_quit() diff --git a/src/signal_classes/__init__.py b/src/signal_classes/__init__.py new file mode 100644 index 0000000..4c9517c --- /dev/null +++ b/src/signal_classes/__init__.py @@ -0,0 +1,3 @@ +from .MainWindow import MainWindow +from .DrawingArea import DrawingArea +from .MainMenuPopup import MainMenuPopup diff --git a/src/utils/CrossClassSignals.py b/src/utils/CrossClassSignals.py new file mode 100644 index 0000000..7124714 --- /dev/null +++ b/src/utils/CrossClassSignals.py @@ -0,0 +1,96 @@ +# Gtk imports +from gi.repository import GLib as glib + +# Python imports +import os, threading, time, datetime + +import pyscreenshot as capture + +# Application imports + + + +def threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs).start() + + return wrapper + +class CrossClassSignals: + def __init__(self, settings): + self.settings = settings + self.builder = self.settings.returnBuilder() + self.SCREENSHOTS_DIR = self.settings.returnScreenshotsDir() + self.fileStore = self.builder.get_object("fileStore") + self.refreshingState = False + + + def returnRefreshingState(self): + return self.refreshingState + + def setRefreshingState(self, state): + self.refreshingState = state + + + @threaded + def refereshDirectoryList(self): + self.refreshingState = True + images = self.returnDirectoryList() + images.sort() + if len(images) != len(self.fileStore): + self.fileStore.clear() + for image in images: + glib.idle_add(self.addToStore, (image)) + + # self.fileStore.sort() + self.refreshingState = False + + + @threaded + def addToStore(self, image): + self.fileStore.append([image]) + + def returnDirectoryList(self): + files = [] + + for file in os.listdir(self.SCREENSHOTS_DIR): + if os.path.isfile(os.path.join(self.SCREENSHOTS_DIR, file)): + files.append(file) + + return files + + + def boundingBoxGrab(self, x1, y1, x2, y2): + # childprocess=False needed to not crash program + im = capture.grab(bbox=(x1, y1, x2, y2), childprocess=False) + im.save(self.generateScreenshotName()) + + def generateScreenshotName(self): + return self.SCREENSHOTS_DIR + '/scrshot_' + self.getTime() + '.png' + + def getTime(self): + now = datetime.datetime.now() + return now.strftime("%Y-%m-%d %H:%M:%S") + + def sleep(self, wait=None): + delayAmount = self.builder.get_object("delayAmount") + if not wait: + wait = delayAmount.get_value_as_int() + + time.sleep(wait) + + + def getClipboardData(self): + proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout=subprocess.PIPE) + retcode = proc.wait() + data = proc.stdout.read() + return data.decode("utf-8").strip() + + def setClipboardData(self, data): + proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE) + proc.stdin.write(data) + proc.stdin.close() + retcode = proc.wait() + + def close(self, widget): + gtk.main_quit() diff --git a/src/utils/Settings.py b/src/utils/Settings.py new file mode 100644 index 0000000..c20aefe --- /dev/null +++ b/src/utils/Settings.py @@ -0,0 +1,71 @@ +# Gtk imports +import gi, cairo +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gdk as gdk + +# Python imports +import os + +# Application imports + + +class Settings: + def __init__(self): + self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + "/" + self.builder = gtk.Builder() + self.builder.add_from_file(self.SCRIPT_PTH + "../resources/Main_Window.glade") + + # 'Filters' + self.images = ('.png', '.jpg', '.jpeg', '.gif') + HOME_PATH = os.path.expanduser('~') + self.SCREENSHOTS_DIR = HOME_PATH + "/" + ".screenshots" + + if not os.path.isdir(self.SCREENSHOTS_DIR): + os.mkdir(self.SCREENSHOTS_DIR) + + + def createWindow(self): + # Get window and connect signals + window = self.builder.get_object("Main_Window") + window.connect("delete-event", gtk.main_quit) + self.setWindowData(window) + return window + + def setWindowData(self, window): + screen = window.get_screen() + visual = screen.get_rgba_visual() + + if visual != None and screen.is_composited(): + window.set_visual(visual) + + # bind css file + cssProvider = gtk.CssProvider() + cssProvider.load_from_path(self.SCRIPT_PTH + '../resources/stylesheet.css') + screen = gdk.Screen.get_default() + styleContext = gtk.StyleContext() + styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER) + + def getMonitorData(self): + screen = self.builder.get_object("Main_Window").get_screen() + wdth = screen.get_width() + hght = screen.get_height() + mon0 = gdk.Rectangle() + mon0.width = wdth + mon0.height = hght + monitors = [] + + monitors.append(mon0) + for m in range(screen.get_n_monitors()): + monitors.append(screen.get_monitor_geometry(m)) + + return monitors + + + def returnBuilder(self): return self.builder + def returnScreenshotsDir(self): return self.SCREENSHOTS_DIR + + # Filter returns + def returnImagesFilter(self): return self.images diff --git a/src/utils/__init__.py b/src/utils/__init__.py new file mode 100644 index 0000000..6025f81 --- /dev/null +++ b/src/utils/__init__.py @@ -0,0 +1,2 @@ +from .Settings import Settings +from .CrossClassSignals import CrossClassSignals