Merge branch 'master' of github.com:rad4day/dotfiles
This commit is contained in:
commit
5b6ead4d23
@ -144,7 +144,7 @@ floating_modifier $mod
|
|||||||
# Screensaver || ThinkVantage
|
# Screensaver || ThinkVantage
|
||||||
bindsym XF86ScreenSaver exec xautolock -locknow
|
bindsym XF86ScreenSaver exec xautolock -locknow
|
||||||
bindsym XF86Battery exec xautolock -locknow
|
bindsym XF86Battery exec xautolock -locknow
|
||||||
bindsym XF86Launch1 exec "xautolock -locknow; sleep 1; xset dpms force off"
|
bindsym XF86Launch1 exec "xautolock -locknow; sync; systemctl suspend-then-hibernate"
|
||||||
|
|
||||||
# Lock screen
|
# Lock screen
|
||||||
bindsym $mod+Ctrl+l exec "xautolock -locknow; sleep 1; xset dpms force off"
|
bindsym $mod+Ctrl+l exec "xautolock -locknow; sleep 1; xset dpms force off"
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
function run {
|
|
||||||
if ! pgrep $1 ;
|
|
||||||
then
|
|
||||||
$@&
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
run compton
|
|
||||||
run kwalletd5
|
|
||||||
run xscreensaver -nosplash
|
|
||||||
nitrogen --restore &
|
|
||||||
|
|
||||||
# Programms
|
|
||||||
run nextcloud
|
|
||||||
#run telegram-desktop
|
|
||||||
#run discord
|
|
||||||
#run thunderbird
|
|
@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
|
|
||||||
class Dmenu(object):
|
|
||||||
def __init__(self, items: list):
|
|
||||||
with open(os.path.dirname(sys.argv[0]) + "/dmenu.json") as fp:
|
|
||||||
self._dmenu = json.load(fp)["dmenu"]
|
|
||||||
self._items = items
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
"""Returns (exitCode, stdout)"""
|
|
||||||
p1 = subprocess.run(
|
|
||||||
self._dmenu,
|
|
||||||
input="\n".join(self._items),
|
|
||||||
encoding="utf-8",
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
)
|
|
||||||
return (p1.returncode, p1.stdout)
|
|
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"dmenu": [
|
|
||||||
"dmenu",
|
|
||||||
"-i",
|
|
||||||
"-l",
|
|
||||||
"6",
|
|
||||||
"-x",
|
|
||||||
"550",
|
|
||||||
"-y",
|
|
||||||
"400",
|
|
||||||
"-w",
|
|
||||||
"500",
|
|
||||||
"-h",
|
|
||||||
"20",
|
|
||||||
"-dim",
|
|
||||||
"0.2",
|
|
||||||
"-p",
|
|
||||||
"Do",
|
|
||||||
"-fn",
|
|
||||||
"Inconsolata-14:normal",
|
|
||||||
"-nb",
|
|
||||||
"#3F3F3F",
|
|
||||||
"-nf",
|
|
||||||
"#DCDCCC",
|
|
||||||
"-sb",
|
|
||||||
"#1E2320",
|
|
||||||
"-sf",
|
|
||||||
"#F0DFAF"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,145 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
import json
|
|
||||||
import argparse
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from modules import Application, MPC
|
|
||||||
from Dmenu import Dmenu
|
|
||||||
|
|
||||||
del sys.path[0]
|
|
||||||
sys.path.insert(0, os.path.dirname(sys.argv[0]))
|
|
||||||
|
|
||||||
|
|
||||||
# CONFIG
|
|
||||||
loadModules = [Application(), MPC()]
|
|
||||||
|
|
||||||
con = sqlite3.connect(os.path.dirname(sys.argv[0]) + "/database.sqlite")
|
|
||||||
|
|
||||||
# ARGUMENTS PARSER
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Smart Dropdown Launcher for AwesomeWM")
|
|
||||||
parser.add_argument(
|
|
||||||
"--create",
|
|
||||||
dest="FLAG_CREATE",
|
|
||||||
action="store_const",
|
|
||||||
const=True,
|
|
||||||
default=False,
|
|
||||||
help="Force TABLE \
|
|
||||||
CREATION",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--build",
|
|
||||||
dest="FLAG_BUILD",
|
|
||||||
action="store_const",
|
|
||||||
const=True,
|
|
||||||
default=False,
|
|
||||||
help="Force Build \
|
|
||||||
the Database",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--truncate",
|
|
||||||
dest="FLAG_TRUNCATE",
|
|
||||||
action="store_const",
|
|
||||||
const=True,
|
|
||||||
default=False,
|
|
||||||
help="Truncate\
|
|
||||||
Database during build",
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
# Helper functions
|
|
||||||
|
|
||||||
|
|
||||||
def create_db():
|
|
||||||
command = "CREATE TABLE entries(`ID` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, `Name` TEXT, `json` TEXT, `hits` INTEGER NOT NULL DEFAULT 0, `disabled` INTEGER NOT NULL DEFAULT 0, `type` TEXT NOT NULL DEFAULT 'file', `file` TEXT);"
|
|
||||||
with con:
|
|
||||||
cur = con.cursor()
|
|
||||||
cur.execute(command)
|
|
||||||
con.commit()
|
|
||||||
|
|
||||||
|
|
||||||
def retrieve_db():
|
|
||||||
rows = []
|
|
||||||
with con:
|
|
||||||
con.row_factory = sqlite3.Row
|
|
||||||
cur = con.cursor()
|
|
||||||
cur.execute("SELECT * FROM entries;")
|
|
||||||
ro = cur.fetchall()
|
|
||||||
for r in ro:
|
|
||||||
r = dict(r)
|
|
||||||
r["json"] = json.loads(r["json"])
|
|
||||||
rows.append(r)
|
|
||||||
return rows
|
|
||||||
|
|
||||||
|
|
||||||
def build_db():
|
|
||||||
entries = {}
|
|
||||||
for mod in loadModules:
|
|
||||||
entries.update(mod.build_db())
|
|
||||||
for k, v in entries.items():
|
|
||||||
if "Exec" in v["json"]:
|
|
||||||
with con:
|
|
||||||
con.cursor().execute(
|
|
||||||
"INSERT INTO entries(Name, json, file, type, disabled) VALUES(?, ?, ?, ?, ?)",
|
|
||||||
(k, json.dumps(v["json"]), v["file"], v["type"], v["disabled"]),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def build_menu():
|
|
||||||
entries = []
|
|
||||||
db = retrieve_db()
|
|
||||||
for mod in loadModules:
|
|
||||||
entries += mod.build_menu([x for x in db if x["type"] == mod.db_type])
|
|
||||||
|
|
||||||
# sort by hits
|
|
||||||
return sorted(entries, key=lambda i: i[2], reverse=True)
|
|
||||||
|
|
||||||
|
|
||||||
def run_program(data):
|
|
||||||
with con:
|
|
||||||
cur = con.cursor()
|
|
||||||
cur.execute("UPDATE entries SET hits=? WHERE ID=?", (data[2] + 1, data[0]))
|
|
||||||
cur.execute("SELECT type FROM entries WHERE ID=?", (data[0],))
|
|
||||||
con.commit()
|
|
||||||
typ = dict(cur.fetchone())["type"]
|
|
||||||
for mod in loadModules:
|
|
||||||
if mod.db_type == typ:
|
|
||||||
mod.call(data[1])
|
|
||||||
|
|
||||||
|
|
||||||
if args.FLAG_CREATE:
|
|
||||||
with con:
|
|
||||||
con.cursor().execute("DROP TABLE IF EXISTS entries;")
|
|
||||||
create_db()
|
|
||||||
# set BUILD flag so the database gets rebuilt too
|
|
||||||
args.FLAG_BUILD = True
|
|
||||||
|
|
||||||
if args.FLAG_BUILD:
|
|
||||||
if args.FLAG_TRUNCATE:
|
|
||||||
with con:
|
|
||||||
con.cursor().execute("DELETE FROM entries")
|
|
||||||
con.cursor().execute("DELETE FROM sqlite_sequence WHERE name='entries'")
|
|
||||||
con.commit()
|
|
||||||
build_db()
|
|
||||||
|
|
||||||
entries = build_menu()
|
|
||||||
p1 = Dmenu([x[1] for x in entries]).run()
|
|
||||||
|
|
||||||
if p1[0] != 0:
|
|
||||||
# error on escape
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
selected = list(filter(lambda x: p1[1].strip().startswith(x[1]), entries))
|
|
||||||
if selected == []:
|
|
||||||
# -> terminal module? None-Type modules?
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# use actual user input
|
|
||||||
selected = (selected[0][0], p1[1].rstrip(), selected[0][2])
|
|
||||||
run_program(selected)
|
|
||||||
|
|
||||||
con.close()
|
|
@ -1,128 +0,0 @@
|
|||||||
from .Module import Module as _Module
|
|
||||||
import locale as _locale
|
|
||||||
import subprocess as _subprocess
|
|
||||||
import shlex as _shlex
|
|
||||||
from pathlib import Path as _Path
|
|
||||||
from os import listdir as _listdir
|
|
||||||
from os.path import isfile as _isfile, join as _join
|
|
||||||
|
|
||||||
|
|
||||||
class Application(_Module):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.db_type = "Application"
|
|
||||||
self._home = str(_Path.home())
|
|
||||||
self._lang = _locale.getlocale()[0].split("_")[0].strip()
|
|
||||||
self._dirs = ["/usr/share/applications", self._home + "/.local/share/applications"]
|
|
||||||
self._references = {}
|
|
||||||
|
|
||||||
def build_db(self):
|
|
||||||
"""Function which adds entries to the database.
|
|
||||||
returns dict with:
|
|
||||||
Name, json, disabled, type, "file" """
|
|
||||||
db = {}
|
|
||||||
for d in self._dirs:
|
|
||||||
for fi in _listdir(d):
|
|
||||||
if _isfile(_join(d, fi)):
|
|
||||||
fc = self._scan_file(_join(d, fi))
|
|
||||||
for k, v in fc.items():
|
|
||||||
db.update({k: {
|
|
||||||
"Name": k,
|
|
||||||
"json": v,
|
|
||||||
"disabled": (("NoDisplay" in v and v["NoDisplay"] == "true") or
|
|
||||||
("Hidden" in v and v["Hidden"] == "true")),
|
|
||||||
"file": v['file'],
|
|
||||||
"type": self.db_type
|
|
||||||
}})
|
|
||||||
return db
|
|
||||||
|
|
||||||
def update_db(self, database: dict):
|
|
||||||
"""Function which updates entries in the database.
|
|
||||||
returns dict with modified/deleted/added database entries"""
|
|
||||||
entries = self.build_db()
|
|
||||||
dbremove = []
|
|
||||||
# dbKey == id, dbValue dict of fileds
|
|
||||||
for dbKey, dbValue in database:
|
|
||||||
if dbValue["type"] == self.db_type:
|
|
||||||
if dbValue["Name"] not in entries:
|
|
||||||
dbremove.append(dbKey)
|
|
||||||
else:
|
|
||||||
# update all values managed by this module
|
|
||||||
for k, v in entries[dbValue["Name"]]:
|
|
||||||
dbValue[k] = v
|
|
||||||
# remove no more existing entries
|
|
||||||
for i in dbremove:
|
|
||||||
database.pop(i)
|
|
||||||
return database
|
|
||||||
|
|
||||||
def build_menu(self, items: dict):
|
|
||||||
"""Builds the menu entries.
|
|
||||||
return list of tuples (id, name, hits)"""
|
|
||||||
# we only get entries of our app type so no problem here
|
|
||||||
# json is already unjsonified
|
|
||||||
NAME_PREFIX="run "
|
|
||||||
NAME_POSTFIX=" (%PATH%)"
|
|
||||||
entries = []
|
|
||||||
for r in items:
|
|
||||||
identifier=(NAME_PREFIX + r['Name'] + NAME_POSTFIX).replace("%PATH%", r['json']['Exec'])
|
|
||||||
entries.append((r['ID'], identifier, r['hits']))
|
|
||||||
if ("Terminal" not in r["json"]):
|
|
||||||
r['json']["Terminal"] = "false"
|
|
||||||
self._references[identifier] = (r['json']["Exec"], r['json']["Terminal"], r['file'], r['Name'])
|
|
||||||
|
|
||||||
return entries
|
|
||||||
|
|
||||||
def call(self, cmd: str):
|
|
||||||
"""Handles the selected entry"""
|
|
||||||
# find the entry
|
|
||||||
reference = list(filter(lambda x: cmd.startswith(x), self._references.keys()))
|
|
||||||
entry = reference[0]
|
|
||||||
cmd = cmd.replace(entry, "").lstrip()
|
|
||||||
# Just call the program
|
|
||||||
_subprocess.Popen(_shlex.split(self._expand_fieldcodes(self._references[entry][0], cmd, reference)),
|
|
||||||
encoding="utf-8",
|
|
||||||
shell=(self._references[entry][1] == "true"))
|
|
||||||
|
|
||||||
def _scan_file(self, fi):
|
|
||||||
entries = {}
|
|
||||||
with open(fi, encoding="utf-8", mode="r") as f:
|
|
||||||
data = {}
|
|
||||||
for line in f:
|
|
||||||
line = line.strip()
|
|
||||||
if line.startswith("["): # and line.rstrip() != "[Desktop Entry]":
|
|
||||||
data["header"] = line.strip("[]")
|
|
||||||
if "Name" in data and "Exec" in data:
|
|
||||||
data['file'] = fi
|
|
||||||
entries[data["Name"]] = data
|
|
||||||
data = {}
|
|
||||||
if "=" in line:
|
|
||||||
s = line.split("=")
|
|
||||||
if "[" in s[0] and "]" in s[0]:
|
|
||||||
if "[" + self._lang + "]" in s[0]:
|
|
||||||
data[s[0].replace("[" + self._lang + "]", "").strip()] = s[1]
|
|
||||||
elif s[0] != "Name" or "Name" not in data.keys():
|
|
||||||
data[s[0]] = s[1]
|
|
||||||
|
|
||||||
if "Name" in data:
|
|
||||||
data['file'] = fi
|
|
||||||
entries[data["Name"]] = data
|
|
||||||
return entries
|
|
||||||
|
|
||||||
def _expand_fieldcodes(self, entry: str, cmd: str, reference):
|
|
||||||
fieldcodes = ['%f', '%F', '%u', '%U', '%i', '%c', '%k'] # todo implement %i as expand icon-key
|
|
||||||
for fc in range(0, len(fieldcodes)):
|
|
||||||
fieldcodes[fc] = fieldcodes[fc] in entry
|
|
||||||
if True in fieldcodes:
|
|
||||||
if '%k' in entry:
|
|
||||||
entry = entry.replace('%k', '"' + reference[2] + "'")
|
|
||||||
if '%c' in entry:
|
|
||||||
entry = entry.replace('%c', '"' + reference[3] + "'")
|
|
||||||
if '%i' in entry:
|
|
||||||
entry = entry.replace(' %i', "")
|
|
||||||
if '%f' in entry or '%F' in entry or '%u' in entry or '%U' in entry:
|
|
||||||
entry = entry.replace('%f', cmd)
|
|
||||||
entry = entry.replace('%F', cmd)
|
|
||||||
entry = entry.replace('%u', cmd)
|
|
||||||
entry = entry.replace('%U', cmd)
|
|
||||||
cmd = ""
|
|
||||||
return (entry + " " + cmd).rstrip()
|
|
@ -1,118 +0,0 @@
|
|||||||
from .Module import Module as _Module
|
|
||||||
import locale as _locale
|
|
||||||
from pathlib import Path as _Path
|
|
||||||
from Dmenu import Dmenu
|
|
||||||
import subprocess as _subprocess
|
|
||||||
|
|
||||||
|
|
||||||
class MPC(_Module):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.db_type = "MPC"
|
|
||||||
self._home = str(_Path.home())
|
|
||||||
self._lang = _locale.getlocale()[0].split("_")[0].strip()
|
|
||||||
self._dirs = ["/usr/share/applications", self._home + "/.local/share/applications"]
|
|
||||||
self.replace = True
|
|
||||||
|
|
||||||
def build_db(self):
|
|
||||||
"""Function which adds entries to the database.
|
|
||||||
returns dict with:
|
|
||||||
Name, json, disabled, type, "file" """
|
|
||||||
|
|
||||||
# we only add an generic Submenu entry.
|
|
||||||
db = {"Media Player Control [MPC]": {
|
|
||||||
"Name": "Media Player Control [MPC]",
|
|
||||||
"json": "",
|
|
||||||
"disabled": False,
|
|
||||||
"file": "none",
|
|
||||||
"type": self.db_type
|
|
||||||
}}
|
|
||||||
return db
|
|
||||||
|
|
||||||
def update_db(self, database: dict):
|
|
||||||
"""Function which updates entries in the database.
|
|
||||||
returns dict with modified/deleted/added database entries"""
|
|
||||||
return self.build_db()
|
|
||||||
|
|
||||||
def build_menu(self, items: dict):
|
|
||||||
"""Builds the menu entries.
|
|
||||||
return list of tuples (id, name, hits)"""
|
|
||||||
# we only get entries of our app type so no problem here
|
|
||||||
# json is already unjsonified
|
|
||||||
entries = []
|
|
||||||
for r in items:
|
|
||||||
entries.append((r['ID'], r['Name'], r['hits']))
|
|
||||||
|
|
||||||
return entries
|
|
||||||
|
|
||||||
def gatherInfo(self):
|
|
||||||
out = {}
|
|
||||||
infoprocess = _subprocess.run("mpc", stdout=_subprocess.PIPE, shell=True)
|
|
||||||
info = infoprocess.stdout.decode("utf8").split("\n")
|
|
||||||
if len(info) == 4:
|
|
||||||
status = [x.split(":") for x in info[2].split(" ")]
|
|
||||||
|
|
||||||
out["song"] = info[0]
|
|
||||||
out["playing"] = "[playing]" in info[1]
|
|
||||||
|
|
||||||
else:
|
|
||||||
status = [x.split(":") for x in info[0].split(" ")]
|
|
||||||
|
|
||||||
out["replace"] = self.replace
|
|
||||||
status = [x for x in status if len(x) == 2]
|
|
||||||
|
|
||||||
for i in status:
|
|
||||||
i[0] = i[0].strip()
|
|
||||||
i[1] = i[1].strip()
|
|
||||||
if i[1] == "off":
|
|
||||||
out[i[0]] = False
|
|
||||||
elif i[1] == "on":
|
|
||||||
out[i[0]] = True
|
|
||||||
else:
|
|
||||||
out[i[0]] = i[1]
|
|
||||||
return out
|
|
||||||
|
|
||||||
def buildStatusMenu(self):
|
|
||||||
info = self.gatherInfo()
|
|
||||||
if info["replace"]:
|
|
||||||
playlists = ['MODE: REPLACE']
|
|
||||||
else:
|
|
||||||
playlists = ['MODE: APPEND']
|
|
||||||
|
|
||||||
if info["random"]:
|
|
||||||
playlists += ['RANDOM: on']
|
|
||||||
else:
|
|
||||||
playlists += ['RANDOM: off']
|
|
||||||
|
|
||||||
return (len(playlists), playlists)
|
|
||||||
|
|
||||||
def handleStatusMenu(self, text: str):
|
|
||||||
if text.startswith("MODE: "):
|
|
||||||
self.replace = not self.replace
|
|
||||||
elif text.startswith("RANDOM: "):
|
|
||||||
_subprocess.run("mpc random", shell=True)
|
|
||||||
|
|
||||||
def call(self, cmd: str):
|
|
||||||
"""Handles the selected entry"""
|
|
||||||
# our menu entry was selected, time to create and show the submenu
|
|
||||||
while True:
|
|
||||||
infolen, playlists = self.buildStatusMenu()
|
|
||||||
|
|
||||||
playprocess = _subprocess.run("mpc lsplaylists", stdout=_subprocess.PIPE, shell=True)
|
|
||||||
playlists += playprocess.stdout.decode("utf8").split("\n")
|
|
||||||
menu = Dmenu(playlists)
|
|
||||||
ex = menu.run()
|
|
||||||
|
|
||||||
if ex[0] == 0:
|
|
||||||
if ex[1].rstrip() in playlists[0:infolen]:
|
|
||||||
self.handleStatusMenu(ex[1].rstrip())
|
|
||||||
continue
|
|
||||||
# user selected an entry
|
|
||||||
# mpc clear(?) -> mpc load ex[1] -> mpc play
|
|
||||||
command = "mpc load '" + ex[1].rstrip() + "'"
|
|
||||||
if self.replace:
|
|
||||||
command = "mpc clear; " + command + "; mpc play"
|
|
||||||
_subprocess.run(command, shell=True)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
break
|
|
@ -1,25 +0,0 @@
|
|||||||
class Module(object):
|
|
||||||
"""Abstract class, implement: build_db, update_db, build_menu, call"""
|
|
||||||
|
|
||||||
def __init__(self, obj):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def build_db():
|
|
||||||
"""Function which adds entries to the database.
|
|
||||||
returns dict with:
|
|
||||||
Name, json, disabled, type, "file" """
|
|
||||||
raise NotImplementedError("Should have implemented this")
|
|
||||||
|
|
||||||
def update_db(database: dict):
|
|
||||||
"""Function which updates entries in the database.
|
|
||||||
returns dict with modified/deleted/added database entries"""
|
|
||||||
raise NotImplementedError("Should have implemented this")
|
|
||||||
|
|
||||||
def build_menu(items: dict):
|
|
||||||
"""Builds the menu entries.
|
|
||||||
return list of tuples (id, name, hits)"""
|
|
||||||
raise NotImplementedError("Should have implemented this")
|
|
||||||
|
|
||||||
def call(entry: str):
|
|
||||||
"""Handles the selected entry"""
|
|
||||||
raise NotImplementedError("Should have implemented this")
|
|
@ -1,2 +0,0 @@
|
|||||||
from .Application import Application
|
|
||||||
from .MPC import MPC
|
|
Loading…
Reference in New Issue
Block a user