added content and structured others

This commit is contained in:
maximstewart 2021-02-21 00:36:31 -06:00
parent 06ca6a91ae
commit 8cfd143c93
58 changed files with 1865 additions and 0 deletions

View File

@ -0,0 +1,15 @@
// Open the Orders page in Amazon.
// Run the script for each page you wish to calculate total of.
elms = document.querySelectorAll("#ordersContainer")[0].querySelectorAll(".a-row .a-size-base");
total = 0;
for (let i = 0; i < elms.length ; i++) {
value = elms[i].innerText;
if (value.includes("$")) {
total += parseInt(value.replace("$", ""), 10);
console.log(value);
}
}
console.log(total);

View File

@ -0,0 +1,39 @@
pos = 7 // Position to delete from. Note: 0 is the 1st video of the list; 1 is the 2nd, etc.
end = 5 // How many videos to delete?
// :: UI Timeouts :: (1000 equals 1 second.)
// Note: Your computer is a toaster or potato? Can't render UI changes quickly?
// Bump these up till the proper prompts show, then up the Interval Timer.
t1 = 800
t2 = 800
t3 = 800
// :: Interval Timer :: (1000 equals 1 second.)
// Note: Slow internet or bumped up the UI Timeouts?
// If slow internet, incrimint this by 1 second till things delete.
// If you bumped uo or down the UI Timeouts, add them up and add ~2000.
wait = 4000
i = 1 // Index to keep track of deletions. Don't change!
interval = setInterval(function () {
if (i == end)
clearInterval(interval)
elm = document.getElementsByClassName('style-scope ytcp-video-list-cell-video open-menu-button')[pos];
elm.click();
setTimeout(function () {
document.getElementById('text-item-4').click();
}, t1);
setTimeout(function () {
document.getElementById('delete-confirm-checkbox').click();
}, t2);
setTimeout(function () {
document.getElementById('delete-confirm-button').click();
}, t3);
i += 1
}, wait);

View File

@ -0,0 +1,39 @@
Reference Material:
https://developers.google.com/apps-script
# ---- Functions ---- #
function createSheetsFromRow() {
// getActiveSpreadsheet actually returns the whole SpreadSheet object whereas getActiveSheet returns a single "Sheet" or null object.
let spreadSheet = SpreadsheetApp.getActiveSpreadsheet(); // The "container" that holds all your Sheet objects
let activeSheet = SpreadsheetApp.getActiveSheet(); // The Sheet that is active in your SpreadSheet object
let sheetData = activeSheet.getDataRange().getValues(); // Get the active Sheet's data... aka Rows and Columns
for (var i in sheetData) {
if (i == 0) { continue; } // Keep from adding first row as sheet
let row = sheetData[i]; // Get row's data
let newSheetName = row[2]; // New sheet name is derived from 3rd column (2nd index) which is Agency column
let newSheet = spreadSheet.getSheetByName(newSheetName);
if (newSheet === null) { // If sheet doesn't exists, we create it
newSheet = spreadSheet.insertSheet(newSheetName);
}
newSheet.appendRow(row);
}
}
function deleteAllSheetsButForFirst() {
let spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
let sheets = spreadSheet.getSheets();
for (var i in sheets) {
if (i == 0) { continue; } // Keep from deleting first sheet
let sheet = sheets[i];
spreadSheet.deleteSheet(sheet);
}
}

View File

@ -0,0 +1,51 @@
#!/usr/bin/python3
# Gtk imports
import gi, faulthandler, signal
gi.require_version('Gtk', '3.0')
gi.require_version('WebKit2', '4.0')
from gi.repository import Gtk as gtk
from gi.repository import Gdk as gdk
from gi.repository import WebKit2 as webkit
from gi.repository import GLib
# Python imports
import inspect, faulthandler
# Application imports
from utils import Settings
from signal_classes import CrossClassSignals, WebviewSignals
class Main:
def __init__(self):
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
faulthandler.enable() # For better debug info
webkit.WebView() # Need one initialized for webview to work from glade file
builder = gtk.Builder()
settings = Settings()
settings.attachBuilder(builder)
# Gets the methods from the classes and sets to handler.
# Then, builder connects to any signals it needs.
classes = [CrossClassSignals(settings),
WebviewSignals(settings)]
handlers = {}
for c in classes:
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
builder.connect_signals(handlers)
window = settings.createWindow()
window.show_all()
if __name__ == "__main__":
try:
main = Main()
gtk.main()
except Exception as e:
print(e)

View File

@ -0,0 +1,12 @@
#!/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() {
# GTK_DEBUG=interactive python3 ./ChronosBrowser.py
python3 ./ChronosBrowser.py
}
main $@;

View File

@ -0,0 +1,39 @@
# Gtk imports
import gi
gi.require_version('WebKit2', '4.0')
from gi.repository import WebKit2 as webkit
# Python imports
# Application imports
class WebviewFactory:
def __init__(self):
self.index = -1
self.view_collection = []
def createWebview(self):
view = webkit.WebView()
self.view_collection.append(view)
self.index += 1
return view
def deleteWebview(self, index):
if (len(self.view_collection) - 1) > 0:
self.view_collection.pop(index)
self.index -= 1
return 0
else:
return 1
def get_index(self, index):
val = index
if val >= 0 and val < len(self.view_collection):
self.index = index
return self.view_collection[self.index]
def returnNotebookSize(self,):
return len(self.view_collection)

View File

@ -0,0 +1 @@
from factory.WebviewFactory import WebviewFactory

View File

@ -0,0 +1 @@
sudo apt-get -y install python3 pygobject3-devel webkitgtk3-devel ubuntu-restricted-extras gstreamer1.0-gtk3

View File

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkImage" id="addImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-add</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="deleteImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-delete</property>
</object>
<object class="GtkImage" id="homeImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Home</property>
<property name="stock">gtk-home</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="refreshImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-refresh</property>
<property name="icon_size">3</property>
</object>
<object class="GtkWindow" id="Window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Chronos Browser</property>
<property name="window_position">center</property>
<property name="default_width">800</property>
<property name="default_height">600</property>
<property name="gravity">center</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox" id="menuBar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">homeImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="loadHome" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Refresh...</property>
<property name="image">refreshImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="refreshPage" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkSearchEntry" id="webview_search">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Search...</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
<signal name="key-release-event" handler="runSearchWebview" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="show_border">False</property>
<property name="scrollable">True</property>
<property name="enable_popup">True</property>
<signal name="switch-page" handler="selecte_view" swapped="no"/>
<child>
<placeholder/>
</child>
<child type="tab">
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<placeholder/>
</child>
<child type="action-start">
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">deleteImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="delTab" swapped="no"/>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child type="action-end">
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">addImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="addTab" swapped="no"/>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@ -0,0 +1,3 @@
window {
}

View File

@ -0,0 +1,15 @@
# Gtk imports
# Python imports
# Application imports
class CrossClassSignals:
def __init__(self, settings):
self.settings = settings
self.builder = self.settings.returnBuilder()
def closePopup(self, widget, data=None):
widget.hide()

View File

@ -0,0 +1,98 @@
# Gtk imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk
# Python imports
# Application imports
from factory import WebviewFactory
class WebviewSignals:
def __init__(self, settings):
self.webviewFactory = WebviewFactory()
self.settings = settings
builder = settings.returnBuilder()
self.home_page = settings.returnWebHome()
self.webview_search = builder.get_object("webview_search")
self.notebook = builder.get_object("notebook")
self.page = None
self.index = 0
self.labelLen = settings.returnLabelLen()
self.addTab()
self.page = self.notebook.get_nth_page(0)
def addTab(self, widget=None, uri=None):
self.current_webview = self.createWebview()
self.addToNotebook(self.current_webview, uri)
def delTab(self, widget):
state = self.webviewFactory.deleteWebview(self.index)
if state == 0:
self.notebook.remove_page(self.index)
def selecte_view(self, widget, page, index):
self.current_webview = self.webviewFactory.get_index(index)
self.webview_search.set_text(self.current_webview.get_uri())
self.page = page
self.index = index
def createWebview(self):
webview = self.webviewFactory.createWebview()
webview.connect("create", self.webviewCreateSignal)
self.set_webview_settings(webview)
webview.load_uri(self.home_page)
webview.connect("load-changed", self.setUrlBar)
return webview
def runSearchWebview(self, widget, data=None):
query = widget.get_text().strip()
if data.keyval == 65293: # If enter key pressed
if "http://" in query or "https://" in query or "file://" in query:
self.current_webview.load_uri(query)
else:
query = '+'.join(query.split())
query = "http://www.google.com/search?q=" + query
self.current_webview.load_uri(query)
self.notebook.get_tab_label(self.page).set_text(query)
def refreshPage(self, widget, data=None):
self.current_webview.load_uri(self.current_webview.get_uri())
def loadHome(self, widget):
self.current_webview.load_uri(self.home_page)
def setUrlBar(self, widget, data=None):
uri = widget.get_uri()
self.webview_search.set_text(uri)
label = uri[0: self.labelLen] + "..."
self.notebook.get_tab_label(self.page).set_text(label)
def webviewCreateSignal(self, widget, eve):
uri = eve.get_request()
type = eve.get_navigation_type()
isRedirect = eve.is_redirect()
if isRedirect == False and type == 5: # Open in new tab
self.addTab(None, uri.get_uri())
def addToNotebook(self, view, uri=None):
webview_box = gtk.Box()
webview_box.pack_start(view, expand = True, fill = True, padding = 0)
webview_box.show_all()
if uri:
self.notebook.append_page(webview_box, gtk.Label(uri))
view.load_uri(uri)
else:
self.notebook.append_page(webview_box, gtk.Label(view.get_uri()))
def set_webview_settings(self, view):
self.settings.setDefaultWebviewSettings(view, view.get_settings())

View File

@ -0,0 +1,2 @@
from signal_classes.CrossClassSignals import CrossClassSignals
from signal_classes.WebviewSignals import WebviewSignals

View File

@ -0,0 +1,125 @@
# 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.builder = None
self.THUMB_GENERATOR = "ffmpegthumbnailer"
self.DEFAULTCOLOR = gdk.RGBA(0.0, 0.0, 0.0, 0.0) # ~#00000000
self.MOUSEOVERCOLOR = gdk.RGBA(0.0, 0.9, 1.0, 0.64) # ~#00e8ff
self.SELECTEDCOLOR = gdk.RGBA(0.4, 0.5, 0.1, 0.84)
self.webHome = 'http://webfm.com/'
self.labelLength = 25 - 3
self.vidsExtensionList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
self.imagesExtensionList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
def attachBuilder(self, builder):
self.builder = builder
self.builder.add_from_file("resources/ChronosBrowser.glade")
def createWindow(self):
# Get window and connect signals
window = self.builder.get_object("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('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):
monitors = []
for m in range(screen.get_n_monitors()):
monitors.append(screen.get_monitor_geometry(m))
for monitor in monitors:
print(str(monitor.width) + "x" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y))
return monitors
def returnBuilder(self): return self.builder
def returnWebHome(self): return self.webHome
def returnVidsExtensionList(self): return self.vidsExtensionList
def returnImagesExtensionList(self): return self.imagesExtensionList
def returnLabelLen(self): return self.labelLength
def setDefaultWebviewSettings(self, widget, settings=None):
# Usability
settings.set_property('enable-fullscreen', True)
settings.set_property('print-backgrounds', True)
settings.set_property('enable-frame-flattening', False)
settings.set_property('enable-plugins', True)
settings.set_property('enable-java', False)
settings.set_property('enable-resizable-text-areas', True)
settings.set_property('zoom-text-only', False)
settings.set_property('enable-smooth-scrolling', True)
settings.set_property('enable-back-forward-navigation-gestures', False)
settings.set_property('media-playback-requires-user-gesture', False)
settings.set_property('enable-tabs-to-links', True)
settings.set_property('enable-caret-browsing', False)
# Security
settings.set_property('user-agent','Mozilla/5.0 (X11; Generic; Linux x86-64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Safari/605.1.15')
settings.set_property('enable-private-browsing', False)
settings.set_property('enable-xss-auditor', True)
settings.set_property('enable-hyperlink-auditing', False)
settings.set_property('enable-site-specific-quirks', True)
settings.set_property('enable-offline-web-application-cache', True)
settings.set_property('enable-page-cache', True)
settings.set_property('allow-modal-dialogs', True)
settings.set_property('enable-html5-local-storage', True)
settings.set_property('enable-html5-database', True)
settings.set_property('allow-file-access-from-file-urls', True)
settings.set_property('allow-universal-access-from-file-urls', False)
settings.set_property('enable-dns-prefetching', False)
# Media stuff
settings.set_hardware_acceleration_policy(0)
# settings.set_property('hardware-acceleration-policy', 'on-demand')
settings.set_property('enable-webgl', True)
settings.set_property('enable-webaudio', True)
settings.set_property('enable-accelerated-2d-canvas', True)
settings.set_property('auto-load-images', True)
settings.set_property('enable-media-capabilities', True)
settings.set_property('enable-media-stream', True)
settings.set_property('enable-mediasource', True)
settings.set_property('enable-encrypted-media', True)
settings.set_property('media-playback-allows-inline', True)
# JS
settings.set_property('enable-javascript', True)
settings.set_property('enable-javascript-markup', True)
settings.set_property('javascript-can-access-clipboard', False)
settings.set_property('javascript-can-open-windows-automatically', False)
# Debugging
settings.set_property('enable-developer-extras', False)
settings.set_property('enable-write-console-messages-to-stdout', False)
settings.set_property('draw-compositing-indicators', False)
settings.set_property('enable-mock-capture-devices', False)
settings.set_property('enable-spatial-navigation', False)

View File

@ -0,0 +1 @@
from utils.Settings import Settings

View File

@ -0,0 +1,11 @@
[Desktop Entry]
Name=pyDarkness
GenericName=Darken a region or add highlighting over an area.
Comment=Darken a region or add highlighting over an area.
Exec=/home/abaddon/Portable_Apps/local_bin/DarkOverlay/src/darkness
Icon=/home/abaddon/Portable_Apps/local_bin/DarkOverlay/src/resources/darkness.png
Type=Application
StartupNotify=true
Categories=Utility;
MimeType=text/plain;
Terminal=false

View File

@ -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

View File

@ -0,0 +1,29 @@
# Python imports
import inspect
# Gtk imports
# Application imports
from utils import Settings
from signal_classes import CrossClassSignals
class Main:
def __init__(self, args):
settings = Settings()
builder = settings.returnBuilder()
# Gets the methods from the classes and sets to handler.
# Then, builder connects to any signals it needs.
classes = [CrossClassSignals(settings)]
handlers = {}
for c in classes:
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
builder.connect_signals(handlers)
window = settings.createWindow()
window.show()

View File

@ -0,0 +1,32 @@
#!/usr/bin/python3
# Python imports
import argparse
from setproctitle import setproctitle
# Gtk imports
import gi, faulthandler, signal
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk
from gi.repository import GLib
# Application imports
from __init__ import Main
if __name__ == "__main__":
try:
setproctitle('DarkOverlay')
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
faulthandler.enable() # For better debug info
parser = argparse.ArgumentParser()
# Add long and short arguments
parser.add_argument("--file", "-f", default="firefox", help="JUST SOME FILE ARG.")
# Read arguments (If any...)
args = parser.parse_args()
main = Main(args)
gtk.main()
except Exception as e:
print( repr(e) )

View File

@ -0,0 +1,13 @@
#!/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 )"
source "/home/abaddon/Portable_Apps/py-venvs/pycornia-venv/bin/activate"
python "${SCRIPTPATH}"
}
main $@;

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkApplicationWindow" id="Main_Window">
<property name="width_request">320</property>
<property name="height_request">220</property>
<property name="can_focus">False</property>
<property name="window_position">center</property>
<property name="default_width">600</property>
<property name="default_height">480</property>
<property name="icon">darkness.png</property>
<property name="skip_pager_hint">True</property>
<property name="decorated">False</property>
<property name="gravity">center</property>
<property name="has_resize_grip">True</property>
<property name="show_menubar">False</property>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSeparator" id="separator1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEventBox">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
<property name="above_child">True</property>
<signal name="button-press-event" handler="getStartCoords" swapped="no"/>
<signal name="button-release-event" handler="popupMenu" swapped="no"/>
<signal name="key-press-event" handler="keyActionToggle" swapped="no"/>
<signal name="key-release-event" handler="endKeyActionToggle" swapped="no"/>
<signal name="motion-notify-event" handler="onMotion" swapped="no"/>
<child>
<object class="GtkDrawingArea" id="drawArea">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="configure-event" handler="onConfigure" swapped="no"/>
<signal name="draw" handler="onDraw" swapped="no"/>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<style>
<class name="regionWindow"/>
</style>
</object>
<object class="GtkListStore" id="monitorStore">
<columns>
<!-- column-name Monitors -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkAdjustment" id="opacityAdjustment">
<property name="lower">0.01</property>
<property name="upper">1</property>
<property name="value">0.75</property>
<property name="step_increment">0.01</property>
<property name="page_increment">10</property>
<signal name="value-changed" handler="onOpacityChange" swapped="no"/>
</object>
<object class="GtkPopover" id="rClickMenu">
<property name="width_request">320</property>
<property name="height_request">220</property>
<property name="can_focus">False</property>
<property name="relative_to">separator1</property>
<property name="constrain_to">none</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkColorButton" id="brushColorProp">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_alpha">True</property>
<property name="rgba">rgb(0,0,0)</property>
<signal name="color-set" handler="onColorSet" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="label" translatable="yes">Opacity</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">opacityAdjustment</property>
<property name="climb_rate">0.01</property>
<property name="digits">2</property>
<property name="value">0.75</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="close_app" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -0,0 +1,3 @@
.regionWindow {
background-color: rgba(0, 0, 0, 0.0);
}

View File

@ -0,0 +1,187 @@
# Python imports
import threading, subprocess, os, cairo
# Gtk imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk
from gi.repository import Gdk as gdk
# Application imports
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class MouseButton:
LEFT_BUTTON = 1
MIDDLE_BUTTON = 2
RIGHT_BUTTON = 3
class StateController:
isDragging = False
isCtrlDown = False
class CrossClassSignals:
def __init__(self, settings):
self.settings = settings
self.builder = self.settings.returnBuilder()
self.window = self.builder.get_object("Main_Window")
self.drawArea = self.builder.get_object("drawArea")
self.brushColorProp = self.builder.get_object("brushColorProp")
self.wh = self.builder.get_object("wh")
self.xy = self.builder.get_object("xy")
self.opacityVal = 0.75
self.states = StateController()
self.area = None
self.states.isCtrlDown = False
self.states.isMouseHeld = False
self.doDrawBackground = True
self.surface = None
self.brush = None
self.aw = None # Draw area width
self.ah = None # Draw area height
rgba = self.brushColorProp.get_rgba()
self.brushColorVal = [rgba.red, rgba.green, rgba.blue, self.opacityVal]
self.startCoords = [0.0, 0.0]
self.w1 = 0.0
self.h1 = 0.0
self.window.set_keep_above(True)
def onConfigure(self, area, eve, data = None):
self.area = area
aw = area.get_allocated_width()
ah = area.get_allocated_height()
self.aw = aw
self.ah = ah
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, aw, ah)
self.brush = cairo.Context(self.surface)
self.drawBackground(self.brush, aw, ah)
return False
def onDraw(self, area, brush):
if self.surface is not None:
brush.set_source_surface(self.surface, 0.0, 0.0)
brush.paint()
else:
print("No surface info...")
return False
# Draw background white
def drawBackground(self, brush, aw, ah):
rgba = self.brushColorVal
brush.rectangle(0, 0, aw, ah) # x, y, width, height
brush.set_source_rgba(rgba[0], rgba[1], rgba[2], rgba[3]) # x, y, width, height
if not self.doDrawBackground: # If transparent or white
self.brush.set_operator(0);
brush.fill()
self.brush.set_operator(1); # reset the brush after filling bg...
def onColorSet(self, widget):
rgba = widget.get_rgba()
self.brushColorVal = [rgba.red, rgba.green, rgba.blue, self.opacityVal]
self.drawArea.queue_draw()
self.drawArea.emit("configure_event", gdk.Event())
def onOpacityChange(self, widget):
self.opacityVal = widget.get_value()
self.brushColorVal[3] = self.opacityVal
self.drawArea.queue_draw()
self.drawArea.emit("configure_event", gdk.Event())
def popupMenu(self, widget, eve):
self.states.isMouseHeld = False
if eve.type == gdk.EventType.BUTTON_RELEASE and eve.button == MouseButton.RIGHT_BUTTON:
self.builder.get_object("rClickMenu").popup()
def getStartCoords(self, widget, eve):
if eve.type == gdk.EventType.BUTTON_PRESS and eve.button == MouseButton.LEFT_BUTTON:
self.startCoords = [eve.x, eve.y] # Used for delta calculations
self.w1 = self.window.get_size()[0] # Ref window width
self.h1 = self.window.get_size()[1] # Ref window height
self.states.isMouseHeld = True # State check for when updating width 'n height
def keyActionToggle(self, widget, eve):
key_id = gdk.keyval_name(eve.keyval).upper()
if key_id in ["CONTROL_R", "CONTROL_L"]:
self.states.isCtrlDown = True
def endKeyActionToggle(self, widget, eve):
key_id = gdk.keyval_name(eve.keyval).upper()
if key_id in ["CONTROL_R", "CONTROL_L"]:
self.states.isCtrlDown = False
def onMotion(self, widget, eve):
if self.states.isMouseHeld:
if self.states.isCtrlDown is False:
px1 = self.window.get_position()[0] # Ref window x
py1 = self.window.get_position()[1] # Ref window y
# Getting deltas of movement inner to draw event box
x1 = self.startCoords[0]
y1 = self.startCoords[1]
x2 = eve.x
y2 = eve.y
px = 0
py = 0
# Calculate that to actual posion change
if x2 > x1: # Is growing
px = px1 + (x2 - x1)
else: # Is shrinking
px = px1 - (x1 - x2)
if y2 > y1: # Is growing
py = py1 + (y2 - y1)
else: # Is shrinking
py = py1 - (y1 - y2)
self.window.move(px, py)
if self.states.isCtrlDown:
x1 = self.startCoords[0]
y1 = self.startCoords[1]
x2 = eve.x
y2 = eve.y
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.window.resize(w, h)
def close_app(self, widget):
gtk.main_quit()

View File

@ -0,0 +1 @@
from .CrossClassSignals import CrossClassSignals

View File

@ -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

View File

@ -0,0 +1 @@
from .Settings import Settings

View File

@ -0,0 +1,151 @@
#!/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 GLib
# Python Imports
import os, threading, time
from setproctitle import setproctitle
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class Main:
def __init__(self):
setproctitle('PATH Edit Tool')
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
faulthandler.enable() # For better debug info
self.HOME = os.path.expanduser('~')
PREFERED_BASH_PATH = self.HOME + "/" + ".bash_paths"
SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + "/"
GLADE_FILE = "main.glade"
self.builder = gtk.Builder()
self.builder.add_from_file(SCRIPT_PTH + GLADE_FILE)
self.builder.connect_signals(self)
self.pathTreeView = self.builder.get_object("pathTreeView")
self.messageWidget = self.builder.get_object("messageWidget")
self.messageLabel = self.builder.get_object("messageLabel")
self.pathListStore = gtk.ListStore(str)
self.success = "#88cc27"
self.warning = "#ffa800"
self.error = "#ff0000"
self.selected = None
self.bashrcPath = ""
if os.path.isfile(PREFERED_BASH_PATH):
self.bashrcPath = PREFERED_BASH_PATH
else:
self.bashrcPath = self.HOME + "/" + ".bashrc"
self.setupTreeview()
self.loadPaths()
window = self.builder.get_object("Main_Window")
window.connect("delete-event", gtk.main_quit)
window.show()
def addEntry(self, widget):
toAddPathTxt = self.builder.get_object("toAddPathEntry").get_text().strip()
if os.path.isdir(toAddPathTxt):
self.pathListStore.append([toAddPathTxt])
else:
self.displayMessage(self.warning, "Not a directory!")
def deleteEntry(self, widget):
self.pathListStore.remove(self.selected)
def saveToBashrc(self, widget):
try:
paths = list()
iter = self.pathListStore.get_iter_first()
while iter != None:
pth = self.pathListStore.get_value(iter, 0)
pth = pth.replace(self.HOME, "$HOME")
paths.append(pth)
# paths.append(self.pathListStore.get_value(iter, 0))
iter = self.pathListStore.iter_next(iter)
toExport = "export PATH=\"" + ':'.join(paths) + "\"\n\n"
file = open(self.bashrcPath, mode='r')
for line in file:
if "export PATH=" in line:
continue
else:
toExport += line
file.close()
file = open(self.bashrcPath, mode='w')
file.write(toExport)
file.close()
self.displayMessage(self.success, "Successfully saved file!")
except Exception as e:
self.displayMessage(self.error, "Opening/Writing to file failed!")
print("Opening/Writing to file failed with the following:\n\n")
print(e)
def setSelected(self, user_data):
selected = user_data.get_selected()[1]
if selected:
self.selected = selected
def loadPaths(self):
pathsStr = os.getenv("PATH")
# If path exists in bashrc replace default selection...
file = open(self.bashrcPath, mode='r')
for line in file:
if "export PATH=" in line:
part = line.replace("export PATH=", "")
cleaned = part.replace("\"", "")
pathsStr = cleaned.strip()
# Split string into list/tuple and add parts to store
paths = pathsStr.split(":")
for path in paths:
self.pathListStore.append([path])
def setupTreeview(self):
renderer = gtk.CellRendererText()
pathColumn = gtk.TreeViewColumn(title="Paths", cell_renderer=renderer, text=0)
self.pathTreeView.append_column(pathColumn)
self.pathTreeView.set_model(self.pathListStore)
def displayMessage(self, type, text):
markup = "<span foreground='" + type + "'>" + text + "</span>"
self.messageLabel.set_markup(markup)
self.messageWidget.popup()
self.hideMessageTimed()
@threaded
def hideMessageTimed(self):
time.sleep(3)
GLib.idle_add(self.messageWidget.popdown)
if __name__ == '__main__':
main = Main()
gtk.main()

View File

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkImage" id="delImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-delete</property>
</object>
<object class="GtkImage" id="plusImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-add</property>
</object>
<object class="GtkWindow" id="Main_Window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Edit PATH App</property>
<property name="window_position">center</property>
<property name="default_width">480</property>
<property name="default_height">560</property>
<property name="icon_name">applications-accessories</property>
<property name="gravity">center</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSeparator" id="separator1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTreeView" id="pathTreeView">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection">
<signal name="changed" handler="setSelected" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkEntry" id="toAddPathEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="placeholder_text" translatable="yes">Path...</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Add path...</property>
<property name="image">plusImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="addEntry" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Delete...</property>
<property name="image">delImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="deleteEntry" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Save...</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="saveToBashrc" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkPopover" id="messageWidget">
<property name="width_request">320</property>
<property name="can_focus">False</property>
<property name="relative_to">separator1</property>
<property name="position">bottom</property>
<child>
<object class="GtkLabel" id="messageLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="justify">center</property>
<attributes>
<attribute name="scale" value="2"/>
</attributes>
</object>
</child>
</object>
</interface>

View File

@ -0,0 +1,53 @@
# Python Imports
import os
import sys
# Lib Imports
import typer
# Application Imports
app = typer.Typer()
@app.command()
def makeTitleCase(file: str):
if os.path.isdir(file) :
for f in os.listdir(file):
os.rename(f, f.title())
else:
os.rename(file, file.title())
@app.command()
def removeFromName(fsub: str, file: str):
if os.path.isdir(file) :
for f in os.listdir(file):
os.rename(f, f.replace(fsub, ''))
else:
os.rename(file, file.replace(fsub, ''))
@app.command()
def removeFromToName(fsub: str, tsub: str, file: str):
if os.path.isdir(file) :
for f in os.listdir(file):
startIndex = f.index(fsub) + 1
endIndex = f.index(tsub)
toRemove = f[startIndex:endIndex]
os.rename(f, f.replace(toRemove, ''))
else:
startIndex = file.index(fsub) + 1
endIndex = file.index(tsub)
toRemove = file[startIndex:endIndex]
os.rename(file, file.replace(toRemove, ''))
@app.command()
def replaceInName(fsub: str, tsub: str, file: str):
if os.path.isdir(file) :
for f in os.listdir(file):
os.rename(f, f.replace(fsub, tsub))
else:
os.rename(file, file.replace(fsub, tsub))

View File

@ -0,0 +1,7 @@
#!/usr/sbin/python
from __init__ import app
if __name__ == "__main__":
app()

View File

@ -0,0 +1,73 @@
# Python imports
import json
import asyncio
import time
# Lib imports
from kasa import Discover
# Application imports
class SmartDeviceManager:
def __init__(self):
self.BASE_IP = "192.168.0."
self.IPs = ["12", "13", "14", "15", "16", "17"]
self.devices = self.retrieve_devices()
def retrieve_devices(self):
devices = []
for ip in self.IPs:
device = self.get_device(self.BASE_IP + ip)
if device:
print("Device: {} is available...".format(device.alias))
print("{}".format(device.hw_info))
devices.append(device)
return devices
def set_device_on(self, device):
asyncio.run(device.turn_on())
def set_device_off(self, device):
asyncio.run(device.turn_off())
def set_led_on(self, device):
asyncio.run(device.set_led(True))
def set_led_off(self, device):
asyncio.run(device.set_led(False))
def set_device_alias(self, device, alias):
asyncio.run(device.set_alias(alias))
def update_info(self, device):
try:
asyncio.run(device.update())
except Exception as e:
pass
def get_device(self, addr):
try:
device = asyncio.run( Discover.discover_single(addr) )
self.update_info(device)
return device
except Exception as e:
print(repr(e))
return None
def pulsate(self, device, rate = 1):
state = "on"
while True:
if state == "on":
state = "off"
self.set_device_on(device)
else:
state = "on"
self.set_device_off(device)
time.sleep(rate)
if __name__ == '__main__':
SmartDeviceManager()

View File

@ -0,0 +1,288 @@
#!/usr/bin/env python3
# Python Imports
import sys
import enum
import argparse
# Lib Imports
from Xlib import display
from Xlib.ext import randr, xinerama
try:
from . import __version__
except ImportError:
__version__ = "N/A"
class Position(enum.Enum):
TOP = enum.auto()
BOTTOM = enum.auto()
LEFT = enum.auto()
RIGHT = enum.auto()
def __str__(self):
return self.name.lower()
@staticmethod
def from_str(pos):
try:
return Position[pos.upper()]
except KeyError:
raise ValueError(f"value '{pos}' not part of the Pos enum")
class Shape:
def __init__(self, major, minor):
if max(major, minor) > 1.0 or min(major, minor) < 0.0:
raise ValueError(f"Shape out of range [0,1]: major={major}, minor={minor}")
self.major = major
self.minor = minor
class Monitor:
def __init__(self, name, x, y, width, height):
self.name = name
self.x = x
self.y = y
self.width = width
self.height = height
DEFAULTS = {
"name": "Smart Position",
"shape": (1.0, 0.4),
"position": str(Position.LEFT),
}
class SmartPositioner:
def __init__(self, name: str, shape: Shape, pos: Position, positioner_argv: list = None):
self.positioner_argv = positioner_argv
self.display = display.Display()
self.screen = self.display.screen()
self.root = self.screen.root
# self.fakeWindow = self.screen.root.create_window(0, 0, 1, 1, 1, self.screen.root_depth)
self.name = name
self.shape = shape
self.pos = pos
self.id = None
self.monitors = []
self.printXineramaVersion()
self.generateMonitorList()
self.getActiveMonitor()
def on_keybind(self, _, be):
pass
# if be.binding.command == f"nop {self.name}":
# self.toggle()
def _get_instance(self):
pass
# tree = self.i3.get_tree()
# if self.id is None:
# matches = tree.find_instanced(self.name)
# instance = {m.window_instance: m for m in matches}.get(self.name, None)
# if instance is not None:
# self.id = instance.id
# else:
# instance = tree.find_by_id(self.id)
# return instance
def toggle(self):
scrSize = self.getScreenSize()
mPos = self.getMousePosition()
self.display.flush() # Needed in some instances to prompt XWindows
# kitty = self._get_instance()
# if kitty is None:
# self.spawn()
# else:
# focused_ws = self._get_focused_workspace()
# if focused_ws is None:
# print("no focused workspaces; ignoring toggle request")
# return
# if kitty.workspace().name == focused_ws.name: # kitty present on current WS; hide
# self.i3.command(f"[con_id={self.id}] floating enable, move scratchpad")
# else:
# self.fetch(focused_ws)
def getMousePosition(self):
data = self.screen.root.query_pointer()._data
return data["root_x"], data["root_y"]
def getActiveMonitor(self):
pos = self.getMousePosition()
for mon in self.monitors:
pass
def getScreenSize(self):
w = self.display.screen().width_in_pixels
h = self.display.screen().height_in_pixels
return w, h
def printXineramaVersion(self):
xinerama_version = self.display.xinerama_query_version()
print('Found XINERAMA version %s.%s' % (
xinerama_version.major_version,
xinerama_version.minor_version,
), file=sys.stderr)
def generateMonitorList(self):
print('Available screens:')
screens = xinerama.query_screens(self.root).screens
i = 1
for (idx, screen) in enumerate(screens):
x, y, w, h = screen.x, screen.y, screen.width, screen.height
print('screen %d: %s' % (idx, screen))
self.monitors.append( Monitor( "Monitor " + str(i), x, y, w, x ) )
i += 1
# resources = randr.get_screen_resources(self.root)
# for output in resources.outputs:
# params = self.display.xrandr_get_output_info(output, resources.config_timestamp)
# if not params.crtc:
# continue
# crtc = self.display.xrandr_get_crtc_info(params.crtc, resources.config_timestamp)
# self.monitors.append( Monitor(params.name, crtc.width, crtc.height) )
def spawn(self):
pass
# cmd_base = f"exec --no-startup-id kitty --name {self.name}"
# if self.positioner_argv is None:
# cmd = cmd_base
# else:
# argv = " ".join(self.positioner_argv)
# cmd = f"{cmd_base} {argv}"
# self.i3.command(cmd)
def on_spawned(self, _, we):
pass
# if we.container.window_instance == self.name:
# self.id = we.container.id
# self.i3.command(f"[con_id={we.container.id}] "
# "floating enable, "
# "border none, "
# "move scratchpad")
# self.fetch(self._get_focused_workspace())
def on_moved(self, _, we):
pass
# # Con is floating wrapper; the Kitty window/container is a child
# is_kitty = we.container.find_by_id(self.id)
# if not is_kitty:
# return
# focused_ws = self._get_focused_workspace()
# if focused_ws is None:
# return
# kitty = self._get_instance() # need "fresh" instance to capture destination WS
# kitty_ws = kitty.workspace()
# if (kitty_ws is None or kitty_ws.name == focused_ws.name or
# kitty_ws.name == "__i3_scratch"): # FIXME: fragile way to check if hidden?
# return
# self.fetch(kitty_ws, retrieve=False)
def _get_focused_workspace(self):
pass
# focused_workspaces = [w for w in self.i3.get_workspaces() if w.focused]
# if not len(focused_workspaces):
# return None
# return focused_workspaces[0]
def fetch(self, ws, retrieve=True):
pass
# if self.id is None:
# raise RuntimeError("Kitty instance ID not yet assigned")
#
# if self.pos in (Position.TOP, Position.BOTTOM):
# width = round(ws.rect.width * self.shape.major)
# height = round(ws.rect.height * self.shape.minor)
# x = ws.rect.x
# y = ws.rect.y if self.pos is Position.TOP else ws.rect.y + ws.rect.height - height
# else: # LEFT || RIGHT
# width = round(ws.rect.width * self.shape.minor)
# height = round(ws.rect.height * self.shape.major)
# x = ws.rect.x if self.pos is Position.LEFT else ws.rect.x + ws.rect.width - width
# y = ws.rect.y
#
# self.i3.command(f"[con_id={self.id}] "
# f"resize set {width}px {height}px, "
# f"{', move scratchpad, scratchpad show' if retrieve else ''}"
# f"move absolute position {x}px {y}px")
@staticmethod
def on_shutdown(_, se):
exit(0)
def _split_args(args):
try:
split = args.index("--")
return args[:split], args[split + 1:]
except ValueError:
return args, None
def _simple_fraction(arg):
arg = float(arg)
if not 0 <= arg <= 1:
raise argparse.ArgumentError("Argument needs to be a simple fraction, within"
"[0, 1]")
return arg
def _parse_args(argv, defaults):
ap = argparse.ArgumentParser(
description="SmartPositioner: Window position wrapper for programs. "
"Arguments following '--' are forwarded to the program instance")
ap.set_defaults(**defaults)
ap.add_argument("-v", "--version",
action="version",
version=f"%(prog)s {__version__}",
help="show %(prog)s's version number and exit")
ap.add_argument("-n", "--name",
help="name/tag connecting a Kitti3 bindsym with a Kitty instance. "
"Forwarded to Kitty on spawn and scanned for on i3 binding "
"events")
ap.add_argument("-p", "--position",
type=Position.from_str,
choices=list(Position),
help="Along which edge of the screen to align the Kitty window")
ap.add_argument("-s", "--shape",
type=_simple_fraction,
nargs=2,
help="shape of the terminal window major and minor dimensions as a "
"fraction [0, 1] of the screen size (note: i3bar is accounted "
"for such that a 1.0 1.0 shaped terminal would not overlap it)")
args = ap.parse_args(argv)
return args
def cli():
argv_positioner3, argv_positioner = _split_args(sys.argv[1:])
args = _parse_args(argv_positioner3, DEFAULTS)
positioner = SmartPositioner(
name=args.name,
shape=Shape(*args.shape),
pos=args.position,
positioner_argv=argv_positioner,
)
# positioner.loop()
if __name__ == "__main__":
cli()