diff --git a/fillscreen.py b/fillscreen.py
new file mode 100644
index 0000000..5225969
--- /dev/null
+++ b/fillscreen.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'C:\Users\lmahler\Desktop\Dump\02_Python\Grail\fillscreen.ui'
+#
+# Created by: PyQt4 UI code generator 4.11.4
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt4 import QtCore, QtGui
+
+try:
+    _fromUtf8 = QtCore.QString.fromUtf8
+except AttributeError:
+    def _fromUtf8(s):
+        return s
+
+try:
+    _encoding = QtGui.QApplication.UnicodeUTF8
+    def _translate(context, text, disambig):
+        return QtGui.QApplication.translate(context, text, disambig, _encoding)
+except AttributeError:
+    def _translate(context, text, disambig):
+        return QtGui.QApplication.translate(context, text, disambig)
+
+class Ui_View(object):
+    def setupUi(self, View):
+        View.setObjectName(_fromUtf8("View"))
+        View.resize(294, 166)
+        View.setWindowOpacity(0.3)
+        View.setStyleSheet(_fromUtf8(""))
+
+        self.retranslateUi(View)
+        QtCore.QMetaObject.connectSlotsByName(View)
+
+    def retranslateUi(self, View):
+        View.setWindowTitle(_translate("View", "Grail.exe", None))
+
diff --git a/fillscreen.ui b/fillscreen.ui
new file mode 100644
index 0000000..d3fa67e
--- /dev/null
+++ b/fillscreen.ui
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>View</class>
+ <widget class="QWidget" name="View">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>294</width>
+    <height>166</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Grail.exe</string>
+  </property>
+  <property name="windowOpacity">
+   <double>0.300000000000000</double>
+  </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/grail.py b/grail.py
new file mode 100644
index 0000000..23cef75
--- /dev/null
+++ b/grail.py
@@ -0,0 +1,386 @@
+"""
+#*********************************#
+#*           Grail               *#
+#*********************************#
+#*   Author: Lukas Mahler        *#
+#*   Copyright: (C)2018-2020     *#
+#*   Version: 0.5.0              *#
+#*   Date: 25.12.2020            *#
+#*********************************#
+# Instant Upload Screenshot-Tool  #
+# based on the idea of Gyazoo.    #
+# -> MS Windows only!             #
+#*********************************#
+"""
+
+__author__ = "Lukas Mahler"
+__copyright__ = "Copyright 2018-2021"
+__version__ = "0.5.1"
+__date__ = "16.01.2021"
+__email__ = "lm@ankerlab.de"
+__status__ = "Development"
+
+
+try:
+    # Defaults
+    import os
+    import sys
+    import webbrowser
+    from io import BytesIO
+    from shutil import rmtree
+    from getpass import getpass
+    from tempfile import gettempdir
+    from socket import create_connection
+    from configparser import ConfigParser
+    from time import gmtime, strftime, sleep
+
+    # GUI
+    from PyQt4 import QtGui, QtCore, Qt
+    from PyQt4.QtCore import QProcess, QPoint
+    from fillscreen import Ui_View
+
+    # Customs
+    import win32gui
+    import win32clipboard
+    import paramiko
+    from desktopmagic.screengrab_win32 import getRectAsImage
+
+except ImportError as e:
+    print("ERROR: Missing Module |||", e)
+    sleep(10)
+    os.system("PAUSE>NUL")
+    sys.exit()
+
+
+###################################################################################################
+###################################################################################################
+
+
+class Fillscreen(QtGui.QWidget, Ui_View):
+
+    def __init__(self, parent=None):
+        QtGui.QWidget.__init__(self, parent)
+
+        ###############################################################################################
+        ###############################################################################################
+
+        # Bastelstüble wegen Transparentem Window welches aber den Input auf unterliegendes blockieren soll
+
+        # self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
+        # self.setBackgroundRole(QtGui.QPalette.Base)
+        # self.setAttribute(Qt.Qt.WA_NoSystemBackground, True)
+        self.setWindowFlags(
+            QtCore.Qt.WindowStaysOnTopHint |
+            QtCore.Qt.FramelessWindowHint |
+            QtCore.Qt.X11BypassWindowManagerHint
+        )
+        # self.istransparent = True
+
+        self.setupUi(self)
+
+        # self.setWindowOpacity(0.3)
+        # Qcolor = "rgba(255, 255, 255, 0)"
+        # self.setStyleSheet("background-color:{0}".format(Qcolor))
+
+        ###############################################################################################
+        ###############################################################################################
+
+        # Change Cursor to select tool on Startup
+        self.change_cursor()
+        self.begin = QtCore.QPoint()
+        self.end = QtCore.QPoint()
+        self.startingpoint = QtCore.QPoint()
+        self.endpoint = QtCore.QPoint()
+
+    def showFullscreen(self):
+        self.showMaximized()
+
+    # https://stackoverflow.com/a/44468898/5593051
+    def paintEvent(self, event):
+        qp = QtGui.QPainter(self)
+        # br = QtGui.QBrush(QtGui.QColor(100, 10, 10, 40))
+        qp.setPen(QtGui.QPen(QtCore.Qt.red, 3))
+        qp.drawRect(QtCore.QRect(self.begin, self.end))
+
+    def mousePressEvent(self, event):
+        if event.button() == QtCore.Qt.RightButton:
+            print("DEBUG: Exiting on Right Click Request")
+            app.quit()
+        else:
+            self.begin = event.pos()
+            self.end = event.pos()
+            # self.startingpoint = event.pos()
+            self.startingpoint = get_real_pos()
+            # print("Startpoint:",self.startingpoint)
+            self.update()
+
+    def mouseMoveEvent(self, event):
+        self.end = event.pos()
+        self.update()
+
+    def mouseReleaseEvent(self, event):
+        self.begin = event.pos()
+        self.end = event.pos()
+        self.endpoint = event.pos()
+        self.endpoint = get_real_pos()
+        # print("Endpoint:",self.endpoint)
+        self.update()
+        do_screen(self.startingpoint, self.endpoint)
+        app.quit()
+
+    @staticmethod
+    def change_cursor():
+        # http://doc.qt.io/archives/qt-4.8/qcursor.html
+        QtGui.QApplication.setOverrideCursor(QtCore.Qt.CrossCursor)
+    # QtGui.QApplication.restoreOverrideCursor()
+
+
+###################################################################################################
+###################################################################################################	
+
+
+def read_ini(rootdir):
+    myini = {}
+    config = ConfigParser()
+    try:
+        config.read_file(open(rootdir+'settings.ini'))
+    except Exception as e:
+        print("ERROR: Couldn't locate a 'settings.ini' |||", e)
+        # Creating new blank ini
+        with open(rootdir+'settings.ini', 'w') as f:
+            txt = "[MAIN]\n" \
+                  "# MODE EITHER ONLINE OR OFFLINE\nMODE = OFFLINE\n\n\n" \
+                  "# IF MODE IS ONLINE PROVIDE THE SFTP INFO BELOW\n" \
+                  "[ONLINE]\n\n" \
+                  "# URL EITHER IS AN IP OR A FQDN\nURL = \n\n" \
+                  "# PORT IS THE SSH PORT\nPORT = 22\n\n" \
+                  "# THE TIME IN SECONDS TO TRY TO CONNECT\nTIMEOUT = 5\n\n" \
+                  "# YOUR SSH USER, THIS CAN BE BLANK TO GET ASKED INTERACTIVELY\nUSR = \nPASS = \n\n" \
+                  "# THE LOCAL SERVER PATH WHERE TO PUT THE SCREENSHOT\nPTH = ./Screens/\n\n" \
+                  "# THIS SHOULD BE THE FULL ONLINE URL\nWHERE = \n\n\n" \
+                  "# IF MODE IS OFFLINE YOU MAY CHANGE THE SETTINGS BELOW\n" \
+                  "[OFFLINE]\n\n" \
+                  "WHERE = "
+            f.write(txt)
+
+    mode = config.get('MAIN', 'MODE')
+    if mode == "ONLINE":
+        url = config.get('ONLINE', 'URL')
+        port = int(config.get('ONLINE', 'PORT'))
+        timeout = int(config.get('ONLINE', 'TIMEOUT'))
+        usr = config.get('ONLINE', 'USR')
+        passw = config.get('ONLINE', 'PASS')
+        pth = config.get('ONLINE', 'PTH')
+        where = config.get('ONLINE', 'WHERE')
+        myini.update(
+            mode    = mode,
+            URL     = url,
+            PORT    = port,
+            TIMEOUT = timeout,
+            USR     = usr,
+            PASS    = passw,
+            PTH     = pth,
+            WHERE   = where
+        )
+    elif mode == "OFFLINE":
+        where = config.get('OFFLINE', 'WHERE')
+        myini.update(
+            mode	= mode,
+            WHERE	= where
+        )
+    else:
+        print("ERROR: you seem to be having a corrupt or broken 'settings.ini' please recheck!")
+
+    return myini
+
+
+def get_real_pos():
+    flags, hcursor, (x, y) = win32gui.GetCursorInfo()
+    return {"x": x, "y": y}
+
+
+def calc_frame(startinspot, endspot):
+    # If dragging began from top
+    if startinspot['x'] < endspot['x']:
+        left = startinspot['x']
+        right = endspot['x']
+        top = startinspot['y']
+        bottom = endspot['y']
+    # If dragging began from bottom
+    else:
+        left = endspot['x']
+        right = startinspot['x']
+        top = endspot['y']
+        bottom = startinspot['y']
+
+    # print("DEBUG:  Start:",left,"x",top)
+    # print("DEBUG:  End  :",right,"x",bottom)
+
+    if abs(left-right) <= 10 and abs(top-bottom) <= 10:
+        coordinates = None
+    else:
+        coordinates = (left, top, right+1, bottom+1)
+
+    return coordinates
+
+
+def do_screen(start, end):
+    """ This Function somehow is the Brain now """
+    # QtGui.QPixmap.grabWindow(QtGui.QApplication.desktop().winId()).save('screenshot.jpg', 'jpg')
+    # Hide all windows to take a Screenshot of the underlying interface
+    for window in windows:
+        window.hide()
+    frame = calc_frame(start, end)
+    print("Took Snapshot on Coordinates:", frame)
+    # https://github.com/python-pillow/Pillow/issues/1547
+    # https://github.com/ludios/Desktopmagic/blob/master/desktopmagic/screengrab_win32.py
+    # im = ImageGrab.grab(bbox=frame)
+
+    if not frame:
+        print("ERROR: Screenshots below 5x5 px not allowed, exiting...")
+        sleep(5)
+        return
+
+    im = getRectAsImage(frame)
+    send_to_clipboard(im)
+    timestamp = strftime("%Y-%m-%d_%H.%M.%S")
+
+    tempdir = gettempdir()+"\\Screens"
+    # print("DEBUG:",tempdir)
+    if not os.path.exists(tempdir):
+        os.makedirs(tempdir)
+    tempsave = '{0}\\{1}.png'.format(tempdir, 'Screen_'+timestamp)
+    im.save(tempsave)
+
+    if settings['MODE'] == "ONLINE":
+        upload_to_url(tempsave)
+    else:
+        save_to_local(tempsave)
+
+    clean_temp(tempdir)
+
+
+# https://stackoverflow.com/questions/34322132/copy-image-to-clipboard-in-python3
+def send_to_clipboard(im=None):
+    if im:
+        output = BytesIO()
+        im.convert("RGB").save(output, "BMP")
+        data = output.getvalue()[14:]
+        output.close()
+        win32clipboard.OpenClipboard()
+        win32clipboard.EmptyClipboard()
+        win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
+        win32clipboard.CloseClipboard()
+        print("Copied to Clipboard")
+    else:
+        win32clipboard.EmptyClipboard()
+        print("Cleared Clipboard")
+
+
+# https://stackoverflow.com/questions/432385/sftp-in-python-platform-independent
+def upload_to_url(tempsave):
+
+    # SFTP INFO
+    url 	= settings['URL']
+    port 	= settings['PORT']
+    timeout = settings['TIMEOUT']
+    usr 	= settings['USR']
+    passw 	= settings['PASS']
+    pth		= settings['PTH'] + os.path.basename(tempsave)
+    where	= settings['WHERE'] + os.path.basename(tempsave)
+
+    # Test Connection first or go into fallback
+    try:
+        s = create_connection((url, port), timeout)
+        s.close()
+    except Exception as e:
+        print("ERROR: Connection failed. |||", e)
+        print("\nFalling back to local save...")
+        save_to_local(tempsave, fallback=1)
+        return
+
+    # If not provided ask for Username & Password
+    if not usr:
+        usr = input("Please provide your Username: ")
+
+    if not passw:
+        passw = getpass("Please provide the password for {0}: ".format(usr))
+
+    try:
+        transport = paramiko.Transport((url, port))
+        transport.connect(username=usr, password=passw)
+    except Exception as e:
+        print("ERROR: SSH2 negotiation or authentication failed. |||", e)
+        print("\nFalling back to local save...")
+        save_to_local(tempsave, fallback=1)
+        return
+
+    print("Starting to Upload...")
+    sftp = paramiko.SFTPClient.from_transport(transport)
+    sftp.put(tempsave, pth)
+    sftp.close()
+    transport.close()
+
+    print("Screen was Uploaded: URL: " + where)
+    open_url(where)
+
+
+def save_to_local(tempsave, fallback=None):
+
+    if not fallback:
+        where = settings['WHERE']
+    else:
+        print("    -> Did fallback!")
+        config = ConfigParser()
+        config.read_file(open(root+'_settings.ini'))
+        where = config.get('OFFLINE', 'WHERE')
+
+    if not where:
+        print("No local Screens folder provided, creating one...")
+        where = os.path.dirname(os.path.abspath(__file__))+"\\Screens"
+
+    print("OFFLINE MODE: Screenshot Folder:", where)
+
+    if not os.path.exists(where):
+        os.makedirs(where)
+
+    src = tempsave
+    dst = where + "\\" + os.path.basename(tempsave)
+    # print("Source:",src,"\nDestination:",dst)
+    os.rename(src, dst)
+
+
+def open_url(where):
+    webbrowser.open(where, new=0, autoraise=True)
+
+
+def clean_temp(tempdir):
+    if os.path.exists(tempdir):
+        print("Cleaning up the tempdir [", tempdir, "]...")
+        rmtree(tempdir, ignore_errors=True)
+
+
+###################################################################################################
+###################################################################################################
+
+
+if __name__ == '__main__':
+
+    root = os.path.dirname(os.path.abspath(__file__))+"\\"
+    settings = read_ini(root)
+    if os.path.exists(root+"qt.conf"):
+        try:
+            os.remove(root+"qt.conf")
+        except Exception as e:
+            print("DEBUG:", e)
+    app = QtGui.QApplication(sys.argv)
+    windows = []
+
+    # https://stackoverflow.com/questions/51058236/create-qt-windows-based-on-number-of-list-items
+    for i in range(QtGui.QApplication.desktop().screenCount()):
+        topLeft = QtGui.QApplication.desktop().screenGeometry(i).topLeft()
+        window = Fillscreen()
+        window.move(topLeft)
+        window.showFullscreen()
+        windows.append(window)
+    app.exec_()
diff --git a/grail_build.cfg b/grail_build.cfg
new file mode 100644
index 0000000..8c481a0
--- /dev/null
+++ b/grail_build.cfg
@@ -0,0 +1,11 @@
+[ship]
+param = --onefile --windowed
+icon = C:\Users\lukas\Desktop\Dump\08_Resources\camera.ico
+
+[debug]
+param = --onefile
+icon = C:\Users\lukas\Desktop\Dump\08_Resources\camera.ico
+
+[test]
+param = --onedir --noupx --add-binary msvcp140.dll;.
+icon = C:\Users\lukas\Desktop\Dump\08_Resources\camera.ico
\ No newline at end of file
diff --git a/selector.py b/selector.py
new file mode 100644
index 0000000..f6dfbcc
--- /dev/null
+++ b/selector.py
@@ -0,0 +1,105 @@
+"""
+This subfile to Grail handles window settings and calculations.
+-> Only works on MS Windows!
+"""
+
+__author__ = "Lukas Mahler"
+__copyright__ = "Copyright 2018-2020"
+__version__ = "1.0.0"
+__date__ = "25.11.2020"
+__email__ = "lm@ankerlab.de"
+__status__ = "Development"
+
+
+import win32api
+import win32gui
+
+
+def getCursorPos():
+    flags, hcursor, (x, y) = win32gui.GetCursorInfo()
+    return {"x": x, "y": y}
+
+
+def getMonitors():
+    monitors = []
+    for hMonitor, hdcMonitor, pyRect in win32api.EnumDisplayMonitors():
+        monitors.append(pyRect)
+    #print(monitors)
+    return monitors
+
+
+def getResolution(monitors):
+    resolutions = {}
+    index = 0
+    for monitor in monitors:
+        x_from	= monitor[0]
+        x_to	= monitor[2]
+        y_from	= monitor[1]
+        y_to	= monitor[3]
+        res_x = x_to - x_from
+        res_y = y_to - y_from
+        res = (res_x, res_y)
+        resolutions['Monitor'+str(index)] = res
+        index += 1
+
+    return resolutions
+
+
+def getScreenInfo():
+    return {"x": win32api.GetSystemMetrics(0), "y": win32api.GetSystemMetrics(1)}
+
+
+def getStartingpoint():
+    return getCursorPos()
+
+
+def getEndpoint():
+    return getCursorPos()
+
+
+def getRectangle():
+
+    # Source: https://stackoverflow.com/a/41930485/5593051
+    state_left = win32api.GetKeyState(0x01)  # Left button down = 0 or 1. Button up = -127 or -128
+    state_right = win32api.GetKeyState(0x02)  # Right button down = 0 or 1. Button up = -127 or -128
+
+    while True:
+        a = win32api.GetKeyState(0x01)
+        b = win32api.GetKeyState(0x02)
+
+        if a != state_left:  # Button state changed
+            state_left = a
+            if a < 0:
+                print('Left Button Pressed')
+                pos_start = getStartingpoint()
+            else:
+                print('Left Button Released')
+                pos_end = getEndpoint()
+                break
+
+    print(pos_start)
+    print(pos_end)
+
+    calcScreenshotFrame(pos_start, pos_end)
+
+
+def calcScreenshotFrame(pos_start, pos_end):
+    # If dragging began from top
+    if pos_start['x'] < pos_end['x']:
+        left = pos_start['x']
+        right = pos_end['x']
+        top = pos_start['y']
+        bottom = pos_end['y']
+    # If dragging began from bottom
+    else:
+        left = pos_end['x']
+        right = pos_start['x']
+        top = pos_end['y']
+        bottom = pos_start['y']
+
+    print("Screenshot needs to be taken from: x:", left, "->", right, "and y:", top, "->", bottom)
+
+
+if __name__ == '__main__':
+    print("This is a Subfile from grail, it can't be executed on its own.")
+    exit()