Major refactor
This commit is contained in:
parent
80d8ccc2c9
commit
2c6df7c527
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 213 KiB |
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
PyInquirer
|
||||||
|
pyxdg
|
||||||
|
setproctitle
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Python imports
|
||||||
|
import builtins
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
class Builtins:
|
||||||
|
def dummy(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: Just reminding myself we can add to builtins two different ways...
|
||||||
|
# __builtins__.update({"event_system": Builtins()})
|
||||||
|
builtins.app_name = "Shellmen"
|
||||||
|
builtins.debug = False
|
||||||
|
builtins.trace_debug = False
|
232
src/__init__.py
232
src/__init__.py
|
@ -1,230 +1,20 @@
|
||||||
# Python imports
|
# Python imports
|
||||||
import os, subprocess, json
|
import os, inspect, time
|
||||||
|
|
||||||
from os.path import isdir, isfile, join
|
# Lib imports
|
||||||
from os import listdir
|
|
||||||
|
|
||||||
# Gtk imports
|
|
||||||
from xdg.DesktopEntry import DesktopEntry
|
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from core import Context
|
from utils import Settings
|
||||||
|
from signal_classes import Controller
|
||||||
|
from __builtins__ import Builtins
|
||||||
|
|
||||||
|
|
||||||
class Main(Context):
|
|
||||||
"""
|
|
||||||
This is the start class called from "__main__"
|
|
||||||
"""
|
|
||||||
def __init__(self, args):
|
|
||||||
"""
|
|
||||||
Initialize it all...
|
|
||||||
"""
|
|
||||||
super().__init__(args)
|
|
||||||
HOME_APPS = os.path.expanduser('~') + "/.local/share/applications/"
|
|
||||||
paths = ["/opt/", "/usr/share/applications/", HOME_APPS]
|
|
||||||
baseOptions = ["[ TO MAIN MENU ]", "Favorites"]
|
|
||||||
self.menuData = self.getDesktopFilesInfo(paths)
|
|
||||||
self.faves = self.loadFaves()
|
|
||||||
query = ""
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
self.clear()
|
|
||||||
group = self.call_method("mainMenu")["group"]
|
|
||||||
self.clear()
|
|
||||||
|
|
||||||
if "Search..." in group:
|
|
||||||
query = self.call_method("searchMenu")["query"]
|
|
||||||
if "[ Set Favorites ]" in group:
|
|
||||||
progsList = self.getSubgroup("Search...", "")
|
|
||||||
fixedProgsList = []
|
|
||||||
|
|
||||||
for prog in progsList:
|
|
||||||
fixedProgsList.append({'name': prog})
|
|
||||||
|
|
||||||
self.faves = self.call_method("setFavoritesMenu", [fixedProgsList])["setFaves"]
|
|
||||||
self.saveFaves(self.faves)
|
|
||||||
continue
|
|
||||||
if "[ Exit ]" in group:
|
|
||||||
break
|
|
||||||
|
|
||||||
progsList = ["[ TO MAIN MENU ]"]
|
|
||||||
progsList += self.getSubgroup(group, query)
|
|
||||||
entry = self.call_method("subMenu", [group, progsList])["prog"]
|
|
||||||
|
|
||||||
self.logger.debug(entry)
|
|
||||||
if entry not in baseOptions:
|
|
||||||
self.logger.info("[Executing Program] Group: {} Entry: {}".format(group, entry))
|
|
||||||
self.executeProgram(group, entry)
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.error(e)
|
|
||||||
|
|
||||||
|
|
||||||
def call_method(self, method_name, data = None):
|
class Main(Builtins):
|
||||||
mName = str(method_name)
|
def __init__(self, args, unknownargs):
|
||||||
method = getattr(self, mName, lambda data: "No valid key passed...\nkey= " + mName + "\nargs= " + data)
|
settings = Settings()
|
||||||
return method(data) if data else method()
|
controller = Controller(settings, args, unknownargs)
|
||||||
|
|
||||||
|
if not controller:
|
||||||
def loadFaves(self, data = None):
|
raise Exception("Controller exited and doesn't exist...")
|
||||||
configFolder = os.getenv("HOME") + "/.config/shellmen"
|
|
||||||
configFile = configFolder + "/favorites.json"
|
|
||||||
self.logger.info("[Opening saved favorites file: {}".format(configFile))
|
|
||||||
faves = []
|
|
||||||
|
|
||||||
if os.path.isdir(configFolder) == False:
|
|
||||||
os.mkdir(configFolder)
|
|
||||||
if os.path.isfile(configFile) == False:
|
|
||||||
open(configFile, 'a').close()
|
|
||||||
|
|
||||||
with open(configFile) as infile:
|
|
||||||
try:
|
|
||||||
faves = json.load(infile)
|
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
|
|
||||||
infile.close()
|
|
||||||
|
|
||||||
return faves
|
|
||||||
|
|
||||||
|
|
||||||
def saveFaves(self, data = None):
|
|
||||||
configFolder = os.getenv("HOME") + "/.config/shellmen"
|
|
||||||
configFile = configFolder + "/favorites.json"
|
|
||||||
with open(configFile, 'w') as outfile:
|
|
||||||
json.dump(data, outfile)
|
|
||||||
|
|
||||||
|
|
||||||
def getDesktopFilesInfo(self, paths):
|
|
||||||
menuObjs = {
|
|
||||||
"Accessories": [],
|
|
||||||
"Multimedia": [],
|
|
||||||
"Graphics": [],
|
|
||||||
"Game": [],
|
|
||||||
"Office": [],
|
|
||||||
"Development": [],
|
|
||||||
"Internet": [],
|
|
||||||
"Settings": [],
|
|
||||||
"System": [],
|
|
||||||
"Wine": [],
|
|
||||||
"Other": []
|
|
||||||
}
|
|
||||||
|
|
||||||
for path in paths:
|
|
||||||
if not "/opt/" in path:
|
|
||||||
self.listAndUpdateDesktopFiles(path, menuObjs);
|
|
||||||
else:
|
|
||||||
for folder in listdir(path):
|
|
||||||
try:
|
|
||||||
fPath = path + folder + "/"
|
|
||||||
self.listAndUpdateDesktopFiles(fPath, menuObjs);
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.debug(e)
|
|
||||||
|
|
||||||
return menuObjs
|
|
||||||
|
|
||||||
def listAndUpdateDesktopFiles(self, path, menuObjs):
|
|
||||||
for f in listdir(path):
|
|
||||||
fPath = path + f
|
|
||||||
if isfile(fPath) and f.endswith(".desktop"):
|
|
||||||
xdgObj = DesktopEntry(fPath)
|
|
||||||
|
|
||||||
title = xdgObj.getName()
|
|
||||||
groups = xdgObj.getCategories()
|
|
||||||
comment = xdgObj.getComment()
|
|
||||||
# icon = xdgObj.getIcon()
|
|
||||||
mainExec = xdgObj.getExec()
|
|
||||||
tryExec = xdgObj.getTryExec()
|
|
||||||
|
|
||||||
group = ""
|
|
||||||
if "Accessories" in groups or "Utility" in groups:
|
|
||||||
group = "Accessories"
|
|
||||||
elif "Multimedia" in groups or "Video" in groups or "Audio" in groups:
|
|
||||||
group = "Multimedia"
|
|
||||||
elif "Development" in groups:
|
|
||||||
group = "Development"
|
|
||||||
elif "Game" in groups:
|
|
||||||
group = "Game"
|
|
||||||
elif "Internet" in groups or "Network" in groups:
|
|
||||||
group = "Internet"
|
|
||||||
elif "Graphics" in groups:
|
|
||||||
group = "Graphics"
|
|
||||||
elif "Office" in groups:
|
|
||||||
group = "Office"
|
|
||||||
elif "System" in groups:
|
|
||||||
group = "System"
|
|
||||||
elif "Settings" in groups:
|
|
||||||
group = "Settings"
|
|
||||||
elif "Wine" in groups:
|
|
||||||
group = "Wine"
|
|
||||||
else:
|
|
||||||
group = "Other"
|
|
||||||
|
|
||||||
menuObjs[group].append( {"title": title, "groups": groups,
|
|
||||||
"comment": comment, "exec": mainExec,
|
|
||||||
"tryExec": tryExec, "fileName": f
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
def getSubgroup(self, group, query = ""):
|
|
||||||
desktopObjs = []
|
|
||||||
if "Search..." in group:
|
|
||||||
gkeys = self.menuData.keys()
|
|
||||||
for gkey in gkeys:
|
|
||||||
for opt in self.menuData[gkey]:
|
|
||||||
keys = opt.keys()
|
|
||||||
if "comment" in keys and len(opt["comment"]) > 0 :
|
|
||||||
if query.lower() in opt["comment"].lower():
|
|
||||||
desktopObjs.append( opt["title"] + " || " + opt["comment"] )
|
|
||||||
if query.lower() in opt["title"].lower() or query.lower() in opt["fileName"].lower():
|
|
||||||
desktopObjs.append( opt["title"] + " || " + opt["fileName"].replace(".desktop", "") )
|
|
||||||
elif "Favorites" in group:
|
|
||||||
desktopObjs = self.faves
|
|
||||||
else:
|
|
||||||
for opt in self.menuData[group]:
|
|
||||||
keys = opt.keys()
|
|
||||||
if "comment" in keys and len(opt["comment"]) > 0 :
|
|
||||||
desktopObjs.append( opt["title"] + " || " + opt["comment"] )
|
|
||||||
else:
|
|
||||||
desktopObjs.append( opt["title"] + " || " + opt["fileName"].replace(".desktop", "") )
|
|
||||||
|
|
||||||
return desktopObjs
|
|
||||||
|
|
||||||
|
|
||||||
def executeProgram(self, group, entry):
|
|
||||||
parts = entry.split("||")
|
|
||||||
program = parts[0].strip()
|
|
||||||
comment = parts[1].strip()
|
|
||||||
|
|
||||||
if "Search..." in group or "Favorites" in group:
|
|
||||||
gkeys = self.menuData.keys()
|
|
||||||
for gkey in gkeys:
|
|
||||||
self.pre_execute(self.menuData[gkey], program, comment)
|
|
||||||
else:
|
|
||||||
self.pre_execute(self.menuData[group], program, comment)
|
|
||||||
|
|
||||||
|
|
||||||
def pre_execute(self, options, program, comment):
|
|
||||||
for opt in options:
|
|
||||||
if program in opt["title"]:
|
|
||||||
keys = opt.keys()
|
|
||||||
if comment in opt["comment"] or comment in opt["fileName"]:
|
|
||||||
try:
|
|
||||||
self.execute(opt["tryExec"])
|
|
||||||
except Exception as e:
|
|
||||||
try:
|
|
||||||
if "exec" in keys and len(opt["exec"]):
|
|
||||||
self.execute(opt["exec"])
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.debug(e)
|
|
||||||
|
|
||||||
|
|
||||||
def execute(self, option):
|
|
||||||
DEVNULL = open(os.devnull, 'w')
|
|
||||||
command = option.split("%")[0]
|
|
||||||
self.logger.debug(command)
|
|
||||||
subprocess.Popen(command.split(), cwd=os.getenv("HOME"), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL)
|
|
||||||
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
os.system('cls' if os.name == 'nt' else 'clear')
|
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
|
||||||
# Python imports
|
# Python imports
|
||||||
import argparse
|
import argparse, faulthandler, traceback
|
||||||
|
from setproctitle import setproctitle
|
||||||
|
|
||||||
|
import tracemalloc
|
||||||
|
tracemalloc.start()
|
||||||
|
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from __init__ import Main
|
from __init__ import Main
|
||||||
|
@ -8,12 +18,19 @@ from __init__ import Main
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
|
# import web_pdb
|
||||||
|
# web_pdb.set_trace()
|
||||||
|
|
||||||
|
setproctitle('Shellmen')
|
||||||
|
faulthandler.enable() # For better debug info
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
# Add long and short arguments
|
# Add long and short arguments
|
||||||
parser.add_argument("--theme", "-t", default="default", help="The theme to use for the menu. (default, orange, red, purple, green)")
|
parser.add_argument("--theme", "-t", default="default", help="The theme to use for the menu. (default, orange, red, purple, green)")
|
||||||
|
|
||||||
# Read arguments (If any...)
|
# Read arguments (If any...)
|
||||||
args = parser.parse_args()
|
args, unknownargs = parser.parse_known_args()
|
||||||
main = Main(args)
|
|
||||||
|
Main(args, unknownargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print( repr(e) )
|
traceback.print_exc()
|
||||||
|
quit()
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
"""
|
|
||||||
Core module
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .mixins import StylesMixin
|
|
||||||
|
|
||||||
from .utils import Logger
|
|
||||||
from .Context import Context
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
# Python imports
|
||||||
|
import threading, subprocess
|
||||||
|
from os.path import isfile
|
||||||
|
from os import listdir
|
||||||
|
|
||||||
|
|
||||||
|
# Gtk imports
|
||||||
|
from xdg.DesktopEntry import DesktopEntry
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .mixins import *
|
||||||
|
from . import Menu, Controller_Data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def threaded(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class Controller(ProcessorMixin, Menu, Controller_Data):
|
||||||
|
def __init__(self, _settings, args, unknownargs):
|
||||||
|
super().__init__(_settings, args)
|
||||||
|
|
||||||
|
self.setup_controller_data(_settings)
|
||||||
|
|
||||||
|
base_options = ["[ TO MAIN MENU ]", "Favorites"]
|
||||||
|
self.menu_data = self.get_desktop_files_info(self.app_paths)
|
||||||
|
query = ""
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
self.clear_console()
|
||||||
|
group = self.call_method("main_menu")["group"]
|
||||||
|
self.clear_console()
|
||||||
|
|
||||||
|
if "Search..." in group:
|
||||||
|
query = self.call_method("search_menu")["query"]
|
||||||
|
if "[ Set Favorites ]" in group:
|
||||||
|
programs_list = self.get_sub_group("Search...", "")
|
||||||
|
fixed_programs_list = []
|
||||||
|
|
||||||
|
for prog in programs_list:
|
||||||
|
fixed_programs_list.append({'name': prog})
|
||||||
|
|
||||||
|
self.favorites = self.call_method("set_favorites_menu", [fixed_programs_list])["setFaves"]
|
||||||
|
self.save_faves(self.favorites)
|
||||||
|
continue
|
||||||
|
if "[ Exit ]" in group:
|
||||||
|
break
|
||||||
|
|
||||||
|
programs_list = ["[ TO MAIN MENU ]"]
|
||||||
|
programs_list += self.get_sub_group(group, query)
|
||||||
|
entry = self.call_method("sub_menu", [group, programs_list])["prog"]
|
||||||
|
|
||||||
|
self.logger.debug(entry)
|
||||||
|
if entry not in base_options:
|
||||||
|
self.logger.info(f"[Executing Program] Group: {group} Entry: {entry}")
|
||||||
|
self.execute_program(group, entry)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(e)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_desktop_files_info(self, paths):
|
||||||
|
menu_objects = {
|
||||||
|
"Accessories": [],
|
||||||
|
"Multimedia": [],
|
||||||
|
"Graphics": [],
|
||||||
|
"Game": [],
|
||||||
|
"Office": [],
|
||||||
|
"Development": [],
|
||||||
|
"Internet": [],
|
||||||
|
"Settings": [],
|
||||||
|
"System": [],
|
||||||
|
"Wine": [],
|
||||||
|
"Other": []
|
||||||
|
}
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
if not "/opt/" in path:
|
||||||
|
self.list_and_update_desktop_iles(path, menu_objects);
|
||||||
|
else:
|
||||||
|
for folder in listdir(path):
|
||||||
|
try:
|
||||||
|
full_path = f"{path}{folder}/"
|
||||||
|
self.list_and_update_desktop_iles(full_path, menu_objects);
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.debug(e)
|
||||||
|
|
||||||
|
return menu_objects
|
||||||
|
|
||||||
|
def list_and_update_desktop_iles(self, path, menu_objects):
|
||||||
|
try:
|
||||||
|
for f in listdir(path):
|
||||||
|
full_path = f"{path}{f}"
|
||||||
|
if isfile(full_path) and f.endswith(".desktop"):
|
||||||
|
xdg_object = DesktopEntry(full_path)
|
||||||
|
hidden = xdg_object.getHidden()
|
||||||
|
nodisplay = xdg_object.getNoDisplay()
|
||||||
|
type = xdg_object.getType()
|
||||||
|
groups = xdg_object.getCategories()
|
||||||
|
# Do not show those marked as hidden or not to display
|
||||||
|
if hidden or nodisplay:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if type == "Application" and groups != "":
|
||||||
|
title = xdg_object.getName()
|
||||||
|
comment = xdg_object.getComment()
|
||||||
|
# icon = xdg_object.getIcon()
|
||||||
|
mainExec = xdg_object.getExec()
|
||||||
|
tryExec = xdg_object.getTryExec()
|
||||||
|
|
||||||
|
group = ""
|
||||||
|
if "Accessories" in groups or "Utility" in groups:
|
||||||
|
group = "Accessories"
|
||||||
|
elif "Multimedia" in groups or "Video" in groups or "Audio" in groups:
|
||||||
|
group = "Multimedia"
|
||||||
|
elif "Development" in groups:
|
||||||
|
group = "Development"
|
||||||
|
elif "Game" in groups:
|
||||||
|
group = "Game"
|
||||||
|
elif "Internet" in groups or "Network" in groups:
|
||||||
|
group = "Internet"
|
||||||
|
elif "Graphics" in groups:
|
||||||
|
group = "Graphics"
|
||||||
|
elif "Office" in groups:
|
||||||
|
group = "Office"
|
||||||
|
elif "System" in groups:
|
||||||
|
group = "System"
|
||||||
|
elif "Settings" in groups:
|
||||||
|
group = "Settings"
|
||||||
|
elif "Wine" in groups:
|
||||||
|
group = "Wine"
|
||||||
|
else:
|
||||||
|
group = "Other"
|
||||||
|
|
||||||
|
menu_objects[group].append( {"title": title, "groups": groups,
|
||||||
|
"comment": comment, "exec": mainExec,
|
||||||
|
"tryExec": tryExec, "fileName": f
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.debug(e)
|
||||||
|
|
||||||
|
|
||||||
|
def get_sub_group(self, group, query = ""):
|
||||||
|
desktop_objects = []
|
||||||
|
if "Search..." in group:
|
||||||
|
group_keys = self.menu_data.keys()
|
||||||
|
for group_key in group_keys:
|
||||||
|
for opt in self.menu_data[group_key]:
|
||||||
|
keys = opt.keys()
|
||||||
|
if "comment" in keys and len(opt["comment"]) > 0 :
|
||||||
|
if query.lower() in opt["comment"].lower():
|
||||||
|
desktop_objects.append( opt["title"] + " || " + opt["comment"] )
|
||||||
|
if query.lower() in opt["title"].lower() or query.lower() in opt["fileName"].lower():
|
||||||
|
desktop_objects.append( opt["title"] + " || " + opt["fileName"].replace(".desktop", "") )
|
||||||
|
elif "Favorites" in group:
|
||||||
|
desktop_objects = self.favorites
|
||||||
|
else:
|
||||||
|
for opt in self.menu_data[group]:
|
||||||
|
keys = opt.keys()
|
||||||
|
if "comment" in keys and len(opt["comment"]) > 0 :
|
||||||
|
desktop_objects.append( opt["title"] + " || " + opt["comment"] )
|
||||||
|
else:
|
||||||
|
desktop_objects.append( opt["title"] + " || " + opt["fileName"].replace(".desktop", "") )
|
||||||
|
|
||||||
|
return desktop_objects
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def tear_down(self, widget=None, eve=None):
|
||||||
|
quit()
|
||||||
|
|
||||||
|
def get_clipboard_data(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 set_clipboard_data(self, data):
|
||||||
|
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE)
|
||||||
|
proc.stdin.write(data)
|
||||||
|
proc.stdin.close()
|
||||||
|
retcode = proc.wait()
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Python imports
|
||||||
|
import os, signal
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Controller_Data:
|
||||||
|
def clear_console(self):
|
||||||
|
os.system('cls' if os.name == 'nt' else 'clear')
|
||||||
|
|
||||||
|
def call_method(self, _method_name, data = None):
|
||||||
|
method_name = str(_method_name)
|
||||||
|
method = getattr(self, method_name, lambda data: f"No valid key passed...\nkey={method_name}\nargs={data}")
|
||||||
|
return method(data) if data else method()
|
||||||
|
|
||||||
|
def has_method(self, obj, name):
|
||||||
|
return callable(getattr(obj, name, None))
|
||||||
|
|
||||||
|
def setup_controller_data(self, _settings):
|
||||||
|
self.settings = _settings
|
||||||
|
self.logger = self.settings.get_logger()
|
||||||
|
self.app_paths = self.settings.get_app_paths()
|
||||||
|
self.favorites_path = self.settings.get_favorites_path()
|
||||||
|
self.favorites = self.settings.get_favorites()
|
||||||
|
|
||||||
|
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.tear_down)
|
|
@ -9,7 +9,6 @@ import json
|
||||||
from PyInquirer import style_from_dict, Token, prompt, Separator
|
from PyInquirer import style_from_dict, Token, prompt, Separator
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from .utils import Logger
|
|
||||||
from .mixins import StylesMixin
|
from .mixins import StylesMixin
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,67 +20,66 @@ GROUPS = [ "Search...", "Favorites", "Accessories", "Multimedia", "Graphics", "O
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class Context(StylesMixin):
|
class Menu(StylesMixin):
|
||||||
"""
|
"""
|
||||||
The menu class has sub methods that are called per run.
|
The menu class has sub methods that are called per run.
|
||||||
"""
|
"""
|
||||||
def __init__(self, args):
|
def __init__(self, settings, args):
|
||||||
"""
|
"""
|
||||||
Construct a new 'Menu' object which pulls in mixins.
|
Construct a new 'Menu' object which pulls in mixins.
|
||||||
:param args: The terminal passed arguments
|
:param args: The terminal passed arguments
|
||||||
|
|
||||||
:return: returns nothing
|
:return: returns nothing
|
||||||
"""
|
"""
|
||||||
self.logger = Logger().get_logger("MAIN")
|
self.logger = settings.get_logger()
|
||||||
# Set the theme
|
self.theme = self.call_method(args.theme)
|
||||||
self.theme = self.call_method(args.theme)
|
self.menu_data = None
|
||||||
self.menuData = None
|
|
||||||
|
|
||||||
|
|
||||||
def mainMenu(self, _grouplist = None):
|
def main_menu(self, _group_list = None):
|
||||||
"""
|
"""
|
||||||
Displays the main menu using the defined GROUPS list...
|
Displays the main menu using the defined GROUPS list...
|
||||||
"""
|
"""
|
||||||
grouplist = GROUPS if not _grouplist else _grouplist
|
group_list = GROUPS if not _group_list else _group_list
|
||||||
menu = {
|
menu = {
|
||||||
'type': 'list',
|
'type': 'list',
|
||||||
'name': 'group',
|
'name': 'group',
|
||||||
'message': '[ MAIN MENU ]',
|
'message': '[ MAIN MENU ]',
|
||||||
'choices': grouplist
|
'choices': group_list
|
||||||
}
|
}
|
||||||
|
|
||||||
return prompt(menu, style=self.theme)
|
return prompt(menu, style=self.theme)
|
||||||
|
|
||||||
|
|
||||||
def setFavoritesMenu(self, _grouplist = None):
|
def set_favorites_menu(self, _group_list = None):
|
||||||
GROUPS = [{'name': '[ TO MAIN MENU ]'}, {'name': 'This is a stub method for Favorites...'}]
|
GROUPS = [{'name': '[ TO MAIN MENU ]'}, {'name': 'This is a stub method for Favorites...'}]
|
||||||
grouplist = GROUPS if not _grouplist[0] else _grouplist[0]
|
group_list = GROUPS if not _group_list[0] else _group_list[0]
|
||||||
menu = {
|
menu = {
|
||||||
'type': 'checkbox',
|
'type': 'checkbox',
|
||||||
'qmark': '>',
|
'qmark': '>',
|
||||||
'message': 'Select Favorites',
|
'message': 'Select Favorites',
|
||||||
'name': 'setFaves',
|
'name': 'setFaves',
|
||||||
'choices': grouplist
|
'choices': group_list
|
||||||
}
|
}
|
||||||
|
|
||||||
return prompt(menu, style=self.theme)
|
return prompt(menu, style=self.theme)
|
||||||
|
|
||||||
|
|
||||||
def subMenu(self, data = ["NO GROUP NAME", "NO PROGRAMS PASSED IN"]):
|
def sub_menu(self, data = ["NO GROUP NAME", "NO PROGRAMS PASSED IN"]):
|
||||||
group = data[0]
|
group = data[0]
|
||||||
progList = data[1]
|
prog_list = data[1]
|
||||||
|
|
||||||
menu = {
|
menu = {
|
||||||
'type': 'list',
|
'type': 'list',
|
||||||
'name': 'prog',
|
'name': 'prog',
|
||||||
'message': '[ ' + group + ' ]',
|
'message': f'[ {group} ]',
|
||||||
'choices': progList
|
'choices': prog_list
|
||||||
}
|
}
|
||||||
|
|
||||||
return prompt(menu, style=self.theme)
|
return prompt(menu, style=self.theme)
|
||||||
|
|
||||||
|
|
||||||
def searchMenu(self):
|
def search_menu(self):
|
||||||
menu = {
|
menu = {
|
||||||
'type': 'input',
|
'type': 'input',
|
||||||
'name': 'query',
|
'name': 'query',
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""
|
||||||
|
Gtk Bound Signal Module
|
||||||
|
"""
|
||||||
|
from .mixins import *
|
||||||
|
from .Menu import Menu
|
||||||
|
from .Controller_Data import Controller_Data
|
||||||
|
from .Controller import Controller
|
|
@ -0,0 +1,43 @@
|
||||||
|
# Python imports
|
||||||
|
import os, subprocess
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessorMixin:
|
||||||
|
def execute_program(self, group, entry):
|
||||||
|
parts = entry.split("||")
|
||||||
|
program = parts[0].strip()
|
||||||
|
comment = parts[1].strip()
|
||||||
|
|
||||||
|
if "Search..." in group or "Favorites" in group:
|
||||||
|
group_keys = self.menu_data.keys()
|
||||||
|
for group_key in group_keys:
|
||||||
|
self.pre_execute(self.menu_data[group_key], program, comment)
|
||||||
|
else:
|
||||||
|
self.pre_execute(self.menu_data[group], program, comment)
|
||||||
|
|
||||||
|
|
||||||
|
def pre_execute(self, options, program, comment):
|
||||||
|
for opt in options:
|
||||||
|
if program in opt["title"]:
|
||||||
|
keys = opt.keys()
|
||||||
|
if comment in opt["comment"] or comment in opt["fileName"]:
|
||||||
|
try:
|
||||||
|
self.execute(opt["tryExec"])
|
||||||
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
if "exec" in keys and len(opt["exec"]):
|
||||||
|
self.execute(opt["exec"])
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.debug(e)
|
||||||
|
|
||||||
|
|
||||||
|
def execute(self, option):
|
||||||
|
DEVNULL = open(os.devnull, 'w')
|
||||||
|
command = option.split("%")[0]
|
||||||
|
self.logger.debug(command)
|
||||||
|
subprocess.Popen(command.split(), cwd=os.getenv("HOME"), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL)
|
|
@ -2,3 +2,4 @@
|
||||||
Mixins module
|
Mixins module
|
||||||
"""
|
"""
|
||||||
from .StylesMixin import StylesMixin
|
from .StylesMixin import StylesMixin
|
||||||
|
from .ProcessorMixin import ProcessorMixin
|
|
@ -5,8 +5,8 @@ import os, logging
|
||||||
|
|
||||||
|
|
||||||
class Logger:
|
class Logger:
|
||||||
def __init__(self):
|
def __init__(self, config_path):
|
||||||
pass
|
self._CONFIG_PATH = config_path
|
||||||
|
|
||||||
def get_logger(self, loggerName = "NO_LOGGER_NAME_PASSED", createFile = True):
|
def get_logger(self, loggerName = "NO_LOGGER_NAME_PASSED", createFile = True):
|
||||||
"""
|
"""
|
||||||
|
@ -42,8 +42,8 @@ class Logger:
|
||||||
log.addHandler(ch)
|
log.addHandler(ch)
|
||||||
|
|
||||||
if createFile:
|
if createFile:
|
||||||
folder = "core/logs"
|
folder = self._CONFIG_PATH
|
||||||
file = folder + "/shellmen.log"
|
file = f"{folder}/application.log"
|
||||||
|
|
||||||
if not os.path.exists(folder):
|
if not os.path.exists(folder):
|
||||||
os.mkdir(folder)
|
os.mkdir(folder)
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Python imports
|
||||||
|
import os, json
|
||||||
|
|
||||||
|
# Gtk imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from . import Logger
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Settings:
|
||||||
|
def __init__(self):
|
||||||
|
self._SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
self._USER_HOME = os.path.expanduser('~')
|
||||||
|
self._CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}"
|
||||||
|
self._FAVORITES_FILE = f"{self._CONFIG_PATH}/favorites.json"
|
||||||
|
self._HOME_APPS = f"{self._USER_HOME}/.local/share/applications/"
|
||||||
|
self._APP_PATHS = ["/opt/", "/usr/share/applications/", self._HOME_APPS]
|
||||||
|
|
||||||
|
self._logger = Logger(self._CONFIG_PATH).get_logger()
|
||||||
|
self._faves = []
|
||||||
|
|
||||||
|
if not os.path.exists(self._CONFIG_PATH):
|
||||||
|
os.mkdir(self._CONFIG_PATH)
|
||||||
|
self._logger = Logger(self._CONFIG_PATH).get_logger()
|
||||||
|
|
||||||
|
if not os.path.exists(self._FAVORITES_FILE):
|
||||||
|
open(self._FAVORITES_FILE, 'a').close()
|
||||||
|
|
||||||
|
|
||||||
|
with open(self._FAVORITES_FILE) as f:
|
||||||
|
try:
|
||||||
|
self._faves = json.load(f)
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def save_faves(self, data = None):
|
||||||
|
with open(self._FAVORITES_FILE, 'w') as f:
|
||||||
|
json.dump(data, f)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_logger(self): return self._logger
|
||||||
|
def get_favorites_path(self): return self._FAVORITES_FILE
|
||||||
|
def get_app_paths(self): return self._APP_PATHS
|
||||||
|
def get_favorites(self): return self._faves
|
|
@ -3,3 +3,4 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .Logger import Logger
|
from .Logger import Logger
|
||||||
|
from .Settings import Settings
|
Loading…
Reference in New Issue