Compare commits
31 Commits
619fae8a20
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 849e7611ca | |||
| 2c453bc621 | |||
| 530fe7c3ab | |||
| 5e5cc50ba8 | |||
| 22736147e6 | |||
| 4c25ce297c | |||
| 60b55da973 | |||
| 7c0d87fd20 | |||
| 4cd5a1f089 | |||
| 18dc71dcb0 | |||
| dd3e87f636 | |||
| cca007db76 | |||
| 33c0827ca2 | |||
| f2b33066af | |||
| fafc1a985f | |||
| e2e9dc8c1f | |||
| 25b6b5305b | |||
| 62debf9ece | |||
| cc5966dab2 | |||
| e82e4fb1eb | |||
| 48bac7e791 | |||
| b78fac0aa5 | |||
| bdb9c157f7 | |||
| a0f32a7c00 | |||
| b1096055b7 | |||
| ea62eb280c | |||
| cc8f62776d | |||
| 2389f1d414 | |||
| d81bf3815a | |||
| 1695f5bc5c | |||
| 1245951da9 |
@@ -3,11 +3,13 @@ A template project for Python with Gtk applications.
|
||||
|
||||
### Requirements
|
||||
* PyGObject (Gtk introspection library)
|
||||
* pygobject-stubs (For actually getting pylsp or python-language-server to auto complete in LSPs. Do if GTK3 --no-cache-dir --config-settings=config=Gtk3,Gdk3,Soup2)
|
||||
* pyxdg (Desktop ".desktop" file parser)
|
||||
* setproctitle (Define process title to search and kill more easily)
|
||||
* sqlmodel (SQL databases and is powered by Pydantic and SQLAlchemy)
|
||||
|
||||
### Note
|
||||
* pyrightconfig.json can prompt IDEs that use pyright lsp on where imports are located- look at venvPath and venv. "venvPath" is parent path of "venv" where "venv" is just the name of the folder under the parent path that is the python created venv.
|
||||
* Move respetive sub folder content under user_config to the same places in Linux. Though, user/share/<app name> can go to ~/.config folder if prefered.
|
||||
* In additiion, place the plugins folder in the same app folder you moved to /usr/share/<app name> or ~/.config/<app name> .
|
||||
There are a "\<change_me\>" strings and files that need to be set according to your app's name located at:
|
||||
@@ -20,4 +22,4 @@ There are a "\<change_me\>" strings and files that need to be set according to y
|
||||
|
||||
|
||||
For the user_config, after changing names and files, copy all content to their respective destinations.
|
||||
The logic follows Debian Dpkg packaging and its placement logic.
|
||||
The logic follows Debian Dpkg packaging and its placement logic.
|
||||
|
||||
@@ -1,2 +1,31 @@
|
||||
### Note
|
||||
Copy the example and rename it to your desired name. The Main class and passed in arguments are required. You don't necessarily need to use the passed in socket_id or event_system.
|
||||
Copy the example and rename it to your desired name. Plugins define a ui target slot with the 'ui_target' requests data but don't have to if not directly interacted with.
|
||||
Plugins must have a run method defined; though, you do not need to necessarily do anything within it. The run method implies that the passed in event system or other data is ready for the plugin to use.
|
||||
|
||||
|
||||
### Manifest Example (All are required even if empty.)
|
||||
```
|
||||
class Manifest:
|
||||
name: str = "Example Plugin"
|
||||
author: str = "John Doe"
|
||||
version: str = "0.0.1"
|
||||
support: str = ""
|
||||
requests: {} = {
|
||||
'pass_ui_objects': ["plugin_control_list"],
|
||||
'pass_events': "true",
|
||||
'bind_keys': []
|
||||
}
|
||||
pre_launch: bool = False
|
||||
```
|
||||
|
||||
|
||||
### Requests
|
||||
```
|
||||
requests: {} = {
|
||||
'pass_events': "true", # If empty or not present will be ignored.
|
||||
"pass_ui_objects": [""], # Request reference to a UI component. Will be passed back as array to plugin.
|
||||
'bind_keys': [f"{name}||send_message:<Control>f"],
|
||||
f"{name}||do_save:<Control>s"] # Bind keys with method and key pare using list. Must pass "name" like shown with delimiter to its right.
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
13
pyrightconfig.json
Normal file
13
pyrightconfig.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"reportUndefinedVariable": false,
|
||||
"reportUnusedVariable": false,
|
||||
"reportUnusedImport": true,
|
||||
"reportDuplicateImport": true,
|
||||
"executionEnvironments": [
|
||||
{
|
||||
"root": "./src/versions/solarfm-0.0.1/solarfm"
|
||||
}
|
||||
],
|
||||
"venvPath": ".",
|
||||
"venv": ".venv"
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
PyGObject
|
||||
pyxdg
|
||||
setproctitle
|
||||
sqlmodel
|
||||
PyGObject==3.40.1
|
||||
pygobject-stubs --no-cache-dir --config-settings=config=Gtk3,Gdk3,Soup2
|
||||
setproctitle==1.2.2
|
||||
pyxdg==0.27
|
||||
psutil==5.8.0
|
||||
pycryptodome==3.20.0
|
||||
sqlmodel==0.0.19
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Python imports
|
||||
import builtins
|
||||
import traceback
|
||||
import threading
|
||||
import sys
|
||||
|
||||
@@ -11,7 +12,7 @@ from libs.event_system import EventSystem
|
||||
from libs.endpoint_registry import EndpointRegistry
|
||||
from libs.keybindings import Keybindings
|
||||
from libs.logger import Logger
|
||||
from libs.settings_manager.manager import SettingsManager
|
||||
from libs.settings.manager import SettingsManager
|
||||
|
||||
|
||||
|
||||
@@ -31,11 +32,22 @@ def daemon_threaded_wrapper(fn):
|
||||
return thread
|
||||
return wrapper
|
||||
|
||||
def call_chain_wrapper(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
print()
|
||||
print()
|
||||
for line in traceback.format_stack():
|
||||
print( line.strip() )
|
||||
print()
|
||||
print()
|
||||
|
||||
return fn(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
# NOTE: Just reminding myself we can add to builtins two different ways...
|
||||
# __builtins__.update({"event_system": Builtins()})
|
||||
builtins.app_name = "<change_me>"
|
||||
builtins.APP_NAME = "<change_me>"
|
||||
|
||||
builtins.keybindings = Keybindings()
|
||||
builtins.event_system = EventSystem()
|
||||
@@ -46,12 +58,15 @@ builtins.settings_manager = SettingsManager()
|
||||
settings_manager.load_settings()
|
||||
|
||||
builtins.settings = settings_manager.settings
|
||||
builtins.logger = Logger(settings_manager.get_home_config_path(), \
|
||||
_ch_log_lvl=settings.debugging.ch_log_lvl, \
|
||||
_fh_log_lvl=settings.debugging.fh_log_lvl).get_logger()
|
||||
builtins.logger = Logger(
|
||||
settings_manager.get_home_config_path(), \
|
||||
_ch_log_lvl = settings.debugging.ch_log_lvl, \
|
||||
_fh_log_lvl = settings.debugging.fh_log_lvl
|
||||
).get_logger()
|
||||
|
||||
builtins.threaded = threaded_wrapper
|
||||
builtins.daemon_threaded = daemon_threaded_wrapper
|
||||
builtins.call_chain = call_chain_wrapper
|
||||
|
||||
|
||||
|
||||
@@ -60,6 +75,6 @@ def custom_except_hook(exc_type, exc_value, exc_traceback):
|
||||
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
||||
return
|
||||
|
||||
logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
|
||||
logger.error("Uncaught exception", exc_info = (exc_type, exc_value, exc_traceback))
|
||||
|
||||
sys.excepthook = custom_except_hook
|
||||
sys.excepthook = custom_except_hook
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""
|
||||
Start of package.
|
||||
"""
|
||||
Src Package.
|
||||
"""
|
||||
@@ -17,8 +17,9 @@ from app import Application
|
||||
|
||||
|
||||
|
||||
def main(args, unknownargs):
|
||||
setproctitle(f'{app_name}')
|
||||
def main():
|
||||
setproctitle(f'{APP_NAME}')
|
||||
settings_manager.set_start_load_time()
|
||||
|
||||
if args.debug == "true":
|
||||
settings_manager.set_debug(True)
|
||||
@@ -27,7 +28,9 @@ def main(args, unknownargs):
|
||||
settings_manager.set_trace_debug(True)
|
||||
|
||||
settings_manager.do_dirty_start_check()
|
||||
Application(args, unknownargs)
|
||||
|
||||
app = Application()
|
||||
app.run()
|
||||
|
||||
|
||||
|
||||
@@ -36,19 +39,20 @@ if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
# Add long and short arguments
|
||||
parser.add_argument("--debug", "-d", default="false", help="Do extra console messaging.")
|
||||
parser.add_argument("--trace-debug", "-td", default="false", help="Disable saves, ignore IPC lock, do extra console messaging.")
|
||||
parser.add_argument("--no-plugins", "-np", default="false", help="Do not load plugins.")
|
||||
parser.add_argument("--debug", "-d", default = "false", help = "Do extra console messaging.")
|
||||
parser.add_argument("--trace-debug", "-td", default = "false", help = "Disable saves, ignore IPC lock, do extra console messaging.")
|
||||
parser.add_argument("--no-plugins", "-np", default = "false", help = "Do not load plugins.")
|
||||
|
||||
parser.add_argument("--new-tab", "-nt", default="false", help="Opens a 'New Tab' if a handler is set for it.")
|
||||
parser.add_argument("--file", "-f", default="default", help="JUST SOME FILE ARG.")
|
||||
parser.add_argument("--new-tab", "-nt", default = "false", help = "Opens a 'New Tab' if a handler is set for it.")
|
||||
parser.add_argument("--file", "-f", default = "default", help = "JUST SOME FILE ARG.")
|
||||
|
||||
# Read arguments (If any...)
|
||||
args, unknownargs = parser.parse_known_args()
|
||||
settings_manager.set_starting_args( args, unknownargs )
|
||||
|
||||
try:
|
||||
faulthandler.enable() # For better debug info
|
||||
main(args, unknownargs)
|
||||
main()
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
quit()
|
||||
54
src/app.py
54
src/app.py
@@ -1,4 +1,5 @@
|
||||
# Python imports
|
||||
from contextlib import suppress
|
||||
import signal
|
||||
import os
|
||||
|
||||
@@ -19,27 +20,40 @@ class AppLaunchException(Exception):
|
||||
class Application:
|
||||
""" docstring for Application. """
|
||||
|
||||
def __init__(self, args, unknownargs):
|
||||
def __init__(self):
|
||||
super(Application, self).__init__()
|
||||
|
||||
if not settings_manager.is_trace_debug():
|
||||
self.load_ipc(args, unknownargs)
|
||||
|
||||
self.setup_debug_hook()
|
||||
Window(args, unknownargs).main()
|
||||
|
||||
|
||||
def load_ipc(self, args, unknownargs):
|
||||
ipc_server = IPCServer()
|
||||
def run(self):
|
||||
if not settings_manager.is_trace_debug():
|
||||
if not self.load_ipc():
|
||||
return
|
||||
|
||||
win = Window()
|
||||
win.start()
|
||||
|
||||
def load_ipc(self):
|
||||
args, \
|
||||
unknownargs = settings_manager.get_starting_args()
|
||||
ipc_server = IPCServer()
|
||||
|
||||
self.ipc_realization_check(ipc_server)
|
||||
if ipc_server.is_ipc_alive:
|
||||
return True
|
||||
|
||||
if not ipc_server.is_ipc_alive:
|
||||
for arg in unknownargs + [args.new_tab,]:
|
||||
if os.path.isfile(arg):
|
||||
message = f"FILE|{arg}"
|
||||
ipc_server.send_ipc_message(message)
|
||||
logger.warning(f"{app_name} IPC Server Exists: Have sent path(s) to it and closing...")
|
||||
for arg in unknownargs + [args.new_tab,]:
|
||||
if os.path.isfile(arg):
|
||||
message = f"FILE|{arg}"
|
||||
ipc_server.send_ipc_message(message)
|
||||
|
||||
raise AppLaunchException(f"{app_name} IPC Server Exists: Have sent path(s) to it and closing...")
|
||||
if os.path.isdir(arg):
|
||||
message = f"DIR|{arg}"
|
||||
ipc_server.send_ipc_message(message)
|
||||
|
||||
return False
|
||||
|
||||
def ipc_realization_check(self, ipc_server):
|
||||
try:
|
||||
@@ -47,18 +61,12 @@ class Application:
|
||||
except Exception:
|
||||
ipc_server.send_test_ipc_message()
|
||||
|
||||
try:
|
||||
ipc_server.create_ipc_listener()
|
||||
except Exception as e:
|
||||
...
|
||||
|
||||
def setup_debug_hook(self):
|
||||
try:
|
||||
# Typically: ValueError: signal only works in main thread
|
||||
with suppress(ValueError):
|
||||
# kill -SIGUSR2 <pid> from Linux/Unix or SIGBREAK signal from Windows
|
||||
signal.signal(
|
||||
vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR1"),
|
||||
vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"),
|
||||
debug_signal_handler
|
||||
)
|
||||
except ValueError:
|
||||
# Typically: ValueError: signal only works in main thread
|
||||
...
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""
|
||||
Core Module
|
||||
Core Package
|
||||
"""
|
||||
33
src/core/builder_wrapper.py
Normal file
33
src/core/builder_wrapper.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class BuilderWrapper(Gtk.Builder):
|
||||
"""docstring for BuilderWrapper."""
|
||||
|
||||
def __init__(self):
|
||||
super(BuilderWrapper, self).__init__()
|
||||
|
||||
self.objects = {}
|
||||
|
||||
def get_object(self, id: str, use_gtk: bool = True) -> any:
|
||||
if not use_gtk:
|
||||
return self.objects[id]
|
||||
|
||||
return super(BuilderWrapper, self).get_object(id)
|
||||
|
||||
def expose_object(self, id: str, object: any, use_gtk: bool = True) -> None:
|
||||
if not use_gtk:
|
||||
self.objects[id] = object
|
||||
else:
|
||||
super(BuilderWrapper, self).expose_object(id, object)
|
||||
|
||||
def dereference_object(self, id: str) -> None:
|
||||
del self.objects[id]
|
||||
@@ -1,3 +1,3 @@
|
||||
"""
|
||||
Containers Module
|
||||
"""
|
||||
Containers Package
|
||||
"""
|
||||
@@ -8,6 +8,7 @@ from gi.repository import Gtk
|
||||
# Application imports
|
||||
from .header_container import HeaderContainer
|
||||
from .body_container import BodyContainer
|
||||
from .footer_container import FooterContainer
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +23,7 @@ class BaseContainer(Gtk.Box):
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
@@ -33,12 +34,13 @@ class BaseContainer(Gtk.Box):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("update_transparency", self._update_transparency)
|
||||
event_system.subscribe("remove_transparency", self._remove_transparency)
|
||||
event_system.subscribe("update-transparency", self._update_transparency)
|
||||
event_system.subscribe("remove-transparency", self._remove_transparency)
|
||||
|
||||
def _load_widgets(self):
|
||||
self.add(HeaderContainer())
|
||||
self.add(BodyContainer())
|
||||
self.add(FooterContainer())
|
||||
|
||||
def _update_transparency(self):
|
||||
self.ctx.add_class(f"mw_transparency_{settings.theming.transparency}")
|
||||
|
||||
@@ -23,7 +23,7 @@ class BodyContainer(Gtk.Box):
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
|
||||
@@ -21,9 +21,15 @@ class CenterContainer(Gtk.Box):
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
self.set_hexpand(True)
|
||||
self.set_vexpand(True)
|
||||
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("center-container")
|
||||
|
||||
@@ -31,7 +37,6 @@ class CenterContainer(Gtk.Box):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
# event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
@@ -40,6 +45,9 @@ class CenterContainer(Gtk.Box):
|
||||
|
||||
button.connect("clicked", self._hello_world)
|
||||
|
||||
button.show()
|
||||
glade_box.show()
|
||||
|
||||
self.add(button)
|
||||
self.add(glade_box)
|
||||
self.add( WebkitUI() )
|
||||
|
||||
40
src/core/containers/footer_container.py
Normal file
40
src/core/containers/footer_container.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class FooterContainer(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(FooterContainer, self).__init__()
|
||||
|
||||
self.ctx = self.get_style_context()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
|
||||
self.set_hexpand(True)
|
||||
|
||||
self.ctx.add_class("footer-container")
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
@@ -6,7 +6,8 @@ gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from ..widgets.transparency_scale import TransparencyScale
|
||||
from ..widgets.controls.open_files_button import OpenFilesButton
|
||||
from ..widgets.controls.transparency_scale import TransparencyScale
|
||||
|
||||
|
||||
|
||||
@@ -21,26 +22,33 @@ class HeaderContainer(Gtk.Box):
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
|
||||
self.set_hexpand(True)
|
||||
|
||||
self.ctx.add_class("header-container")
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
event_system.subscribe("tggl-top-main-menubar", self.tggl_top_main_menubar)
|
||||
|
||||
|
||||
def _load_widgets(self):
|
||||
button = Gtk.Button(label = "Interactive Debug")
|
||||
button = Gtk.Button(label = "Interactive Debug")
|
||||
button.connect("clicked", self._interactive_debug)
|
||||
|
||||
self.add(TransparencyScale())
|
||||
self.add( OpenFilesButton() )
|
||||
self.add( TransparencyScale() )
|
||||
self.add(button)
|
||||
|
||||
def _interactive_debug(self, widget = None, eve = None):
|
||||
event_system.emit("load_interactive_debug")
|
||||
event_system.emit("load-interactive-debug")
|
||||
|
||||
def tggl_top_main_menubar(self):
|
||||
self.hide() if self.is_visible() else self.show_all()
|
||||
@@ -18,9 +18,14 @@ class LeftContainer(Gtk.Box):
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
self.set_vexpand(True)
|
||||
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("left-container")
|
||||
|
||||
@@ -28,8 +33,7 @@ class LeftContainer(Gtk.Box):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
# event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
...
|
||||
@@ -6,6 +6,7 @@ gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from ..widgets.vte_widget import VteWidget
|
||||
|
||||
|
||||
|
||||
@@ -18,9 +19,14 @@ class RightContainer(Gtk.Box):
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
self.set_vexpand(True)
|
||||
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("right-container")
|
||||
|
||||
@@ -28,8 +34,8 @@ class RightContainer(Gtk.Box):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
# event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
vte_widget = VteWidget()
|
||||
self.add( vte_widget )
|
||||
@@ -1,3 +1,3 @@
|
||||
"""
|
||||
Controllers Module
|
||||
Controllers Package
|
||||
"""
|
||||
@@ -1,5 +1,4 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
@@ -18,27 +17,20 @@ from .bridge_controller import BridgeController
|
||||
|
||||
|
||||
class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
|
||||
def __init__(self, args, unknownargs):
|
||||
self.setup_controller_data()
|
||||
""" docstring for BaseController. """
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self._setup_controller_data()
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_controllers()
|
||||
|
||||
if args.no_plugins == "false":
|
||||
self.plugins.launch_plugins()
|
||||
|
||||
for arg in unknownargs + [args.new_tab,]:
|
||||
if os.path.isfile(arg):
|
||||
message = f"FILE|{arg}"
|
||||
event_system.emit("post_file_to_ipc", message)
|
||||
|
||||
if os.path.isdir(arg):
|
||||
message = f"DIR|{arg}"
|
||||
event_system.emit("post_file_to_ipc", message)
|
||||
self._load_plugins_and_files()
|
||||
|
||||
logger.info(f"Made it past {self.__class__} loading...")
|
||||
settings_manager.set_end_load_time()
|
||||
settings_manager.log_load_time()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
@@ -50,20 +42,28 @@ class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
|
||||
self.window.connect("key-release-event", self.on_global_key_release_controller)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("shutting_down", lambda: print("Shutting down..."))
|
||||
event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
|
||||
event_system.subscribe("handle_dir_from_ipc", self.handle_dir_from_ipc)
|
||||
event_system.subscribe("tggl_top_main_menubar", self._tggl_top_main_menubar)
|
||||
event_system.subscribe("shutting-down", lambda: print("Shutting down..."))
|
||||
event_system.subscribe("handle-file-from-ipc", self.handle_file_from_ipc)
|
||||
event_system.subscribe("handle-dir-from-ipc", self.handle_dir_from_ipc)
|
||||
event_system.subscribe("tggl-top-main-menubar", self._tggl_top_main_menubar)
|
||||
|
||||
def _load_controllers(self):
|
||||
BridgeController()
|
||||
|
||||
def _load_plugins_and_files(self):
|
||||
args, unknownargs = settings_manager.get_starting_args()
|
||||
if args.no_plugins == "false":
|
||||
self.plugins_controller.pre_launch_plugins()
|
||||
self.plugins_controller.post_launch_plugins()
|
||||
|
||||
for file in settings_manager.get_starting_files():
|
||||
event_system.emit("post-file-to-ipc", file)
|
||||
|
||||
def _tggl_top_main_menubar(self):
|
||||
logger.debug("_tggl_top_main_menubar > stub...")
|
||||
|
||||
def setup_builder_and_container(self):
|
||||
self.builder = Gtk.Builder()
|
||||
self.builder.add_from_file(settings_manager.get_glade_file())
|
||||
def _load_glade_file(self):
|
||||
self.builder.add_from_file( settings_manager.get_glade_file() )
|
||||
self.builder.expose_object("main_window", self.window)
|
||||
|
||||
settings_manager.set_builder(self.builder)
|
||||
|
||||
@@ -7,23 +7,49 @@ from shutil import which
|
||||
|
||||
# Application imports
|
||||
from plugins.plugins_controller import PluginsController
|
||||
from ..builder_wrapper import BuilderWrapper
|
||||
|
||||
|
||||
|
||||
class BaseControllerData:
|
||||
''' BaseControllerData contains most of the state of the app at ay given time. It also has some support methods. '''
|
||||
|
||||
def setup_controller_data(self) -> None:
|
||||
self.window = settings_manager.get_main_window()
|
||||
self.builder = None
|
||||
self.base_container = None
|
||||
self.was_midified_key = False
|
||||
self.ctrl_down = False
|
||||
self.shift_down = False
|
||||
self.alt_down = False
|
||||
def _setup_controller_data(self) -> None:
|
||||
self.window = settings_manager.get_main_window()
|
||||
self.builder = BuilderWrapper()
|
||||
self.plugins_controller = PluginsController()
|
||||
|
||||
self.setup_builder_and_container()
|
||||
self.plugins = PluginsController()
|
||||
self.base_container = None
|
||||
self.was_midified_key = False
|
||||
self.ctrl_down = False
|
||||
self.shift_down = False
|
||||
self.alt_down = False
|
||||
|
||||
self._collect_files_dirs()
|
||||
self._load_glade_file()
|
||||
|
||||
|
||||
def _collect_files_dirs(self):
|
||||
args, \
|
||||
unknownargs = settings_manager.get_starting_args()
|
||||
files = []
|
||||
|
||||
for arg in unknownargs + [args.new_tab,]:
|
||||
if os.path.isdir( arg.replace("file://", "") ):
|
||||
files.append( f"DIR|{arg.replace('file://', '')}" )
|
||||
continue
|
||||
|
||||
# NOTE: If passing line number with file split against :
|
||||
if os.path.isfile( arg.replace("file://", "").split(":")[0] ):
|
||||
files.append( f"FILE|{arg.replace('file://', '')}" )
|
||||
continue
|
||||
|
||||
logger.info(f"Not a File: {arg}")
|
||||
|
||||
if len(files) == 0: return
|
||||
|
||||
settings_manager.set_is_starting_with_file(True)
|
||||
settings_manager.set_starting_files(files)
|
||||
|
||||
def get_base_container(self):
|
||||
return self.base_container
|
||||
@@ -59,25 +85,23 @@ class BaseControllerData:
|
||||
widget.remove(child)
|
||||
|
||||
def get_clipboard_data(self, encoding = "utf-8") -> str:
|
||||
if which("xclip"):
|
||||
command = ['xclip','-selection','clipboard']
|
||||
else:
|
||||
if not which("xclip"):
|
||||
logger.info('xclip not found...')
|
||||
return
|
||||
|
||||
command = ['xclip','-selection','clipboard']
|
||||
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout = subprocess.PIPE)
|
||||
retcode = proc.wait()
|
||||
data = proc.stdout.read()
|
||||
return data.decode(encoding).strip()
|
||||
|
||||
def set_clipboard_data(self, data: type, encoding = "utf-8") -> None:
|
||||
if which("xclip"):
|
||||
command = ['xclip','-selection','clipboard']
|
||||
else:
|
||||
if not which("xclip"):
|
||||
logger.info('xclip not found...')
|
||||
return
|
||||
|
||||
command = ['xclip','-selection','clipboard']
|
||||
proc = subprocess.Popen(command, stdin = subprocess.PIPE)
|
||||
proc.stdin.write(data.encode(encoding))
|
||||
proc.stdin.close()
|
||||
retcode = proc.wait()
|
||||
retcode = proc.wait()
|
||||
|
||||
@@ -10,8 +10,6 @@ import base64
|
||||
class BridgeController:
|
||||
def __init__(self):
|
||||
|
||||
self.opened_files = {}
|
||||
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
|
||||
@@ -20,19 +18,19 @@ class BridgeController:
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("handle_bridge_event", self.handle_bridge_event)
|
||||
event_system.subscribe("handle-bridge-event", self.handle_bridge_event)
|
||||
|
||||
|
||||
def handle_bridge_event(self, event):
|
||||
match event.topic:
|
||||
case "save":
|
||||
event_system.emit(f"handle_file_event_{event.originator}", (event,))
|
||||
event_system.emit(f"handle-file-event-{event.originator}", (event,))
|
||||
case "close":
|
||||
event_system.emit(f"handle_file_event_{event.originator}", (event,))
|
||||
event_system.emit(f"handle-file-event-{event.originator}", (event,))
|
||||
case "load_buffer":
|
||||
event_system.emit(f"handle_file_event_{event.originator}", (event,))
|
||||
event_system.emit(f"handle-file-event-{event.originator}", (event,))
|
||||
case "load_file":
|
||||
event_system.emit(f"handle_file_event_{event.originator}", (event,))
|
||||
event_system.emit(f"handle-file-event-{event.originator}", (event,))
|
||||
case "alert":
|
||||
content = base64.b64decode( event.content.encode() ).decode("utf-8")
|
||||
logger.info(f"\nMessage Topic: {event.topic}\nMessage Content: {content}")
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""
|
||||
Widgets Module
|
||||
"""
|
||||
Widgets Package
|
||||
"""
|
||||
110
src/core/widgets/clock_widget.py
Normal file
110
src/core/widgets/clock_widget.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# Python imports
|
||||
from datetime import datetime
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GObject
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class CalendarWidget(Gtk.Popover):
|
||||
def __init__(self):
|
||||
super(CalendarWidget, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
self.body = Gtk.Calendar()
|
||||
|
||||
self.body.show()
|
||||
self.add(self.body)
|
||||
|
||||
|
||||
class ClockWidget(Gtk.EventBox):
|
||||
def __init__(self):
|
||||
super(ClockWidget, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_size_request(180, -1)
|
||||
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("clock-widget")
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("button_release_event", self._toggle_cal_popover)
|
||||
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
self.calendar = CalendarWidget()
|
||||
self.label = Gtk.Label()
|
||||
|
||||
self.calendar.set_relative_to(self)
|
||||
|
||||
self.label.set_justify(Gtk.Justification.CENTER)
|
||||
self.label.set_margin_top(15)
|
||||
self.label.set_margin_bottom(15)
|
||||
self.label.set_margin_left(15)
|
||||
self.label.set_margin_right(15)
|
||||
|
||||
self._update_face()
|
||||
self.add(self.label)
|
||||
|
||||
GObject.timeout_add(59000, self._update_face)
|
||||
|
||||
def _update_face(self):
|
||||
dt_now = datetime.now()
|
||||
hours_mins_sec = dt_now.strftime("%I:%M %p")
|
||||
month_day_year = dt_now.strftime("%m/%d/%Y")
|
||||
time_str = hours_mins_sec + "\n" + month_day_year
|
||||
|
||||
self.label.set_label(time_str)
|
||||
|
||||
def _toggle_cal_popover(self, widget, eve):
|
||||
if (self.calendar.get_visible() == True):
|
||||
self.calendar.popdown()
|
||||
return
|
||||
|
||||
now = datetime.now()
|
||||
timeStr = now.strftime("%m/%d/%Y")
|
||||
parts = timeStr.split("/")
|
||||
month = int(parts[0]) - 1
|
||||
day = int(parts[1])
|
||||
year = int(parts[2])
|
||||
|
||||
self.calendar.body.select_day(day)
|
||||
self.calendar.body.select_month(month, year)
|
||||
|
||||
self.calendar.popup()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3
src/core/widgets/code/__init__.py
Normal file
3
src/core/widgets/code/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Code Package
|
||||
"""
|
||||
29
src/core/widgets/code/command_system.py
Normal file
29
src/core/widgets/code/command_system.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from .commands import *
|
||||
|
||||
|
||||
|
||||
class CommandSystem:
|
||||
def __init__(self):
|
||||
super(CommandSystem, self).__init__()
|
||||
|
||||
self.data: list = ()
|
||||
|
||||
|
||||
def set_data(self, *args, **kwargs):
|
||||
self.data = (args, kwargs)
|
||||
|
||||
def exec(self, command: str):
|
||||
if not command in globals(): return
|
||||
|
||||
# method = getattr(self, command, None)
|
||||
method = globals()[command]
|
||||
args, kwargs = self.data
|
||||
if kwargs:
|
||||
method.execute(*args, kwargs)
|
||||
else:
|
||||
method.execute(*args)
|
||||
12
src/core/widgets/code/commands/__init__.py
Normal file
12
src/core/widgets/code/commands/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"""
|
||||
Commands Package
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
|
||||
__all__ = [
|
||||
command.replace(".py", "") for command in os.listdir(
|
||||
os.path.dirname(__file__)
|
||||
) if "__init__" not in command
|
||||
]
|
||||
23
src/core/widgets/code/commands/close_file.py
Normal file
23
src/core/widgets/code/commands/close_file.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def execute(
|
||||
editor: GtkSource.View = None,
|
||||
buffer: GtkSource.Buffer= None
|
||||
):
|
||||
logger.debug("Close File Command")
|
||||
file = editor.files.new()
|
||||
buffer = editor.get_buffer()
|
||||
editor.set_buffer(file.buffer)
|
||||
|
||||
editor.files.remove_file(buffer)
|
||||
19
src/core/widgets/code/commands/line_down.py
Normal file
19
src/core/widgets/code/commands/line_down.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def execute(
|
||||
editor: GtkSource.View = None,
|
||||
buffer: GtkSource.Buffer= None
|
||||
):
|
||||
logger.debug("Line Up Command")
|
||||
editor.emit("move-lines", True)
|
||||
19
src/core/widgets/code/commands/line_up.py
Normal file
19
src/core/widgets/code/commands/line_up.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def execute(
|
||||
editor: GtkSource.View = None,
|
||||
buffer: GtkSource.Buffer= None
|
||||
):
|
||||
logger.debug("Line Up Command")
|
||||
editor.emit("move-lines", False)
|
||||
26
src/core/widgets/code/commands/new_file.py
Normal file
26
src/core/widgets/code/commands/new_file.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def execute(
|
||||
editor: GtkSource.View = None,
|
||||
buffer: GtkSource.Buffer= None
|
||||
):
|
||||
logger.debug("New File Command")
|
||||
file = editor.files.new()
|
||||
language = editor.language_manager \
|
||||
.guess_language("file.txt", None)
|
||||
|
||||
file.buffer.set_language(language)
|
||||
file.buffer.set_style_scheme(editor.syntax_theme)
|
||||
|
||||
editor.set_buffer(file.buffer)
|
||||
36
src/core/widgets/code/commands/open_files.py
Normal file
36
src/core/widgets/code/commands/open_files.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def execute(
|
||||
editor: GtkSource.View = None,
|
||||
buffer: GtkSource.Buffer= None
|
||||
):
|
||||
logger.debug("Open File(s) Command")
|
||||
gfiles = event_system.emit_and_await("open_files")
|
||||
if not gfiles: return
|
||||
|
||||
size = len(gfiles)
|
||||
for i, gfile in enumerate(gfiles):
|
||||
file = editor.files.new()
|
||||
file.set_path(gfile)
|
||||
|
||||
language = editor.language_manager \
|
||||
.guess_language(file.fname, None)
|
||||
file.ftype = language
|
||||
file.buffer.set_language(language)
|
||||
file.buffer.set_style_scheme(editor.syntax_theme)
|
||||
|
||||
if i == (size - 1):
|
||||
editor.set_buffer(file.buffer)
|
||||
|
||||
|
||||
18
src/core/widgets/code/commands/show_completion.py
Normal file
18
src/core/widgets/code/commands/show_completion.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def execute(
|
||||
editor: GtkSource.View = None,
|
||||
buffer: GtkSource.Buffer= None
|
||||
):
|
||||
logger.debug("Show Completion Command")
|
||||
61
src/core/widgets/code/completion_manager.py
Normal file
61
src/core/widgets/code/completion_manager.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from .custom_completion_providers.lsp_completion_provider import LSPCompletionProvider
|
||||
|
||||
|
||||
|
||||
class CompletionManager():
|
||||
def __init__(self, completer):
|
||||
super(CompletionManager, self).__init__()
|
||||
|
||||
self._completor = completer
|
||||
self._lsp_provider = LSPCompletionProvider()
|
||||
self._timeout_id = None
|
||||
|
||||
|
||||
def request_completion(self):
|
||||
if self._timeout_id:
|
||||
GLib.source_remove(self._timeout_id)
|
||||
|
||||
self._timeout_id = GLib.timeout_add(
|
||||
1000,
|
||||
self._process_request_completion
|
||||
)
|
||||
|
||||
def _process_request_completion(self):
|
||||
print('hello')
|
||||
|
||||
self._timeout_id = None
|
||||
return False
|
||||
|
||||
def _do_completion(self):
|
||||
if self._completor.get_providers():
|
||||
self._mach_completion()
|
||||
else:
|
||||
self._start_completion()
|
||||
|
||||
def _mach_completion(self):
|
||||
"""
|
||||
Note: Use IF providers were added to completion...
|
||||
"""
|
||||
self._completion.match(
|
||||
self._completion.create_context()
|
||||
)
|
||||
|
||||
def _start_completion(self):
|
||||
"""
|
||||
Note: Use IF NO providers have been added to completion...
|
||||
"""
|
||||
self._completion.start(
|
||||
[
|
||||
self._lsp_provider
|
||||
],
|
||||
self._completion.create_context()
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Custom Completion Providers Module
|
||||
"""
|
||||
@@ -0,0 +1,74 @@
|
||||
# Python imports
|
||||
import re
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GtkSource
|
||||
from gi.repository import GObject
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class ExampleCompletionProvider(GObject.GObject, GtkSource.CompletionProvider):
|
||||
"""
|
||||
This is a custom Completion Example Provider.
|
||||
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
|
||||
"""
|
||||
__gtype_name__ = 'CustomProvider'
|
||||
|
||||
def __init__(self):
|
||||
GObject.Object.__init__(self)
|
||||
|
||||
def do_get_name(self):
|
||||
""" Returns: a new string containing the name of the provider. """
|
||||
return _('ExampleProvider')
|
||||
|
||||
def do_match(self, context):
|
||||
""" Get whether the provider match the context of completion detailed in context. """
|
||||
# NOTE: True for debugging but context needs to normally get checked for actual usage needs.
|
||||
# TODO: Fix me
|
||||
return True
|
||||
|
||||
def do_populate(self, context):
|
||||
"""
|
||||
In this instance, it will do 2 things:
|
||||
1) always provide Hello World! (Not ideal but an option so its in the example)
|
||||
2) Utilizes the Gtk.TextIter from the TextBuffer to determine if there is a jinja
|
||||
example of '{{ custom.' if so it will provide you with the options of foo and bar.
|
||||
If selected it will insert foo }} or bar }}, completing your syntax...
|
||||
|
||||
PLEASE NOTE the GtkTextIter Logic and regex are really rough and should be adjusted and tuned
|
||||
"""
|
||||
|
||||
proposals = [
|
||||
# GtkSource.CompletionItem(label='Hello World!', text = 'Hello World!', icon = None, info = None) # NOTE: Always proposed...
|
||||
]
|
||||
|
||||
# Gtk Versions differ on get_iter responses...
|
||||
end_iter = context.get_iter()
|
||||
if not isinstance(end_iter, Gtk.TextIter):
|
||||
_, end_iter = context.get_iter()
|
||||
|
||||
if end_iter:
|
||||
buf = end_iter.get_buffer()
|
||||
mov_iter = end_iter.copy()
|
||||
if mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY):
|
||||
mov_iter, _ = mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY)
|
||||
left_text = buf.get_text(mov_iter, end_iter, True)
|
||||
else:
|
||||
left_text = ''
|
||||
|
||||
if re.match(r'.*\{\{\s*custom\.$', left_text):
|
||||
proposals.append(
|
||||
GtkSource.CompletionItem(label='foo', text='foo }}') # optionally proposed based on left search via regex
|
||||
)
|
||||
proposals.append(
|
||||
GtkSource.CompletionItem(label='bar', text='bar }}') # optionally proposed based on left search via regex
|
||||
)
|
||||
|
||||
context.add_proposals(self, proposals, True)
|
||||
@@ -0,0 +1,117 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GtkSource
|
||||
from gi.repository import GObject
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
|
||||
"""
|
||||
This code is an LSP code completion plugin for Newton.
|
||||
# NOTE: Some code pulled/referenced from here --> https://github.com/isamert/gedi
|
||||
"""
|
||||
__gtype_name__ = 'LSPProvider'
|
||||
|
||||
def __init__(self):
|
||||
GObject.Object.__init__(self)
|
||||
|
||||
self._icon_theme = Gtk.IconTheme.get_default()
|
||||
|
||||
self.lsp_data = None
|
||||
|
||||
|
||||
def do_get_name(self):
|
||||
return "LSP Code Completion"
|
||||
|
||||
def get_iter_correctly(self, context):
|
||||
return context.get_iter()[1] if isinstance(context.get_iter(), tuple) else context.get_iter()
|
||||
|
||||
def do_match(self, context):
|
||||
return True
|
||||
|
||||
def do_get_priority(self):
|
||||
return 1
|
||||
|
||||
def do_get_activation(self):
|
||||
return GtkSource.CompletionActivation.USER_REQUESTED
|
||||
|
||||
|
||||
def do_populate(self, context, items = []):
|
||||
self.lsp_data
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# def do_populate(self, context, items = []):
|
||||
# if hasattr(self._source_view, "completion_items"):
|
||||
# items = self._source_view.completion_items
|
||||
|
||||
# proposals = []
|
||||
# for item in items:
|
||||
# proposals.append( self.create_completion_item(item) )
|
||||
|
||||
# context.add_proposals(self, proposals, True)
|
||||
|
||||
# def get_icon_for_type(self, _type):
|
||||
# try:
|
||||
# return self._theme.load_icon(icon_names[_type.lower()], 16, 0)
|
||||
# except:
|
||||
# ...
|
||||
|
||||
# try:
|
||||
# return self._theme.load_icon(Gtk.STOCK_ADD, 16, 0)
|
||||
# except:
|
||||
# ...
|
||||
|
||||
# return None
|
||||
|
||||
# def create_completion_item(self, item):
|
||||
# comp_item = GtkSource.CompletionItem.new()
|
||||
# keys = item.keys()
|
||||
# comp_item.set_label(item["label"])
|
||||
|
||||
# if "insertText" in keys:
|
||||
# comp_item.set_text(item["insertText"])
|
||||
|
||||
# if "additionalTextEdits" in keys:
|
||||
# comp_item.additionalTextEdits = item["additionalTextEdits"]
|
||||
|
||||
# return comp_item
|
||||
|
||||
|
||||
# def create_completion_item(self, item):
|
||||
# comp_item = GtkSource.CompletionItem.new()
|
||||
# comp_item.set_label(item.label)
|
||||
|
||||
# if item.textEdit:
|
||||
# if isinstance(item.textEdit, dict):
|
||||
# comp_item.set_text(item.textEdit["newText"])
|
||||
# else:
|
||||
# comp_item.set_text(item.textEdit)
|
||||
# else:
|
||||
# comp_item.set_text(item.insertText)
|
||||
|
||||
# comp_item.set_icon( self.get_icon_for_type(item.kind) )
|
||||
# comp_item.set_info(item.documentation)
|
||||
|
||||
# return comp_item
|
||||
@@ -0,0 +1,108 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GtkSource
|
||||
from gi.repository import GObject
|
||||
|
||||
import jedi
|
||||
from jedi.api import Script
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
# FIXME: Find real icon names...
|
||||
icon_names = {
|
||||
'import': '',
|
||||
'module': '',
|
||||
'class': '',
|
||||
'function': '',
|
||||
'statement': '',
|
||||
'param': ''
|
||||
}
|
||||
|
||||
|
||||
class Jedi:
|
||||
def get_script(file, doc_text):
|
||||
return Script(code = doc_text, path = file)
|
||||
|
||||
|
||||
class PythonCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
|
||||
"""
|
||||
This code is A python code completion plugin for Newton.
|
||||
# NOTE: Some code pulled/referenced from here --> https://github.com/isamert/gedi
|
||||
"""
|
||||
__gtype_name__ = 'PythonProvider'
|
||||
|
||||
def __init__(self, file):
|
||||
GObject.Object.__init__(self)
|
||||
self._theme = Gtk.IconTheme.get_default()
|
||||
self._file = file
|
||||
|
||||
def do_get_name(self):
|
||||
return "Python Code Completion"
|
||||
|
||||
def get_iter_correctly(self, context):
|
||||
return context.get_iter()[1] if isinstance(context.get_iter(), tuple) else context.get_iter()
|
||||
|
||||
def do_match(self, context):
|
||||
iter = self.get_iter_correctly(context)
|
||||
iter.backward_char()
|
||||
|
||||
buffer = iter.get_buffer()
|
||||
if buffer.get_context_classes_at_iter(iter) != ['no-spell-check']:
|
||||
return False
|
||||
|
||||
ch = iter.get_char()
|
||||
# NOTE: Look to re-add or apply supprting logic to use spaces
|
||||
# As is it slows down the editor in certain contexts...
|
||||
# if not (ch in ('_', '.', ' ') or ch.isalnum()):
|
||||
if not (ch in ('_', '.') or ch.isalnum()):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def do_get_priority(self):
|
||||
return 1
|
||||
|
||||
def do_get_activation(self):
|
||||
return GtkSource.CompletionActivation.INTERACTIVE
|
||||
|
||||
def do_populate(self, context):
|
||||
# TODO: Maybe convert async?
|
||||
it = self.get_iter_correctly(context)
|
||||
buffer = it.get_buffer()
|
||||
proposals = []
|
||||
|
||||
doc_text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), False)
|
||||
iter_cursor = buffer.get_iter_at_mark(buffer.get_insert())
|
||||
linenum = iter_cursor.get_line() + 1
|
||||
charnum = iter_cursor.get_line_index()
|
||||
|
||||
def create_generator():
|
||||
for completion in Jedi.get_script(self._file, doc_text).complete(line = linenum, column = None, fuzzy = False):
|
||||
comp_item = GtkSource.CompletionItem.new()
|
||||
comp_item.set_label(completion.name)
|
||||
comp_item.set_text(completion.name)
|
||||
comp_item.set_icon(self.get_icon_for_type(completion.type))
|
||||
comp_item.set_info(completion.docstring())
|
||||
yield comp_item
|
||||
|
||||
for item in create_generator():
|
||||
proposals.append(item)
|
||||
|
||||
context.add_proposals(self, proposals, True)
|
||||
|
||||
def get_icon_for_type(self, _type):
|
||||
try:
|
||||
return self._theme.load_icon(icon_names[_type.lower()], 16, 0)
|
||||
except:
|
||||
try:
|
||||
return self._theme.load_icon(Gtk.STOCK_ADD, 16, 0)
|
||||
except:
|
||||
return None
|
||||
127
src/core/widgets/code/key_mapper.py
Normal file
127
src/core/widgets/code/key_mapper.py
Normal file
@@ -0,0 +1,127 @@
|
||||
# Python imports
|
||||
import copy
|
||||
import json
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gdk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class NoKeyState:
|
||||
held: dict = {}
|
||||
released: dict = {}
|
||||
|
||||
class CtrlKeyState:
|
||||
held: dict = {}
|
||||
released: dict = {}
|
||||
|
||||
class ShiftKeyState:
|
||||
held: dict = {}
|
||||
released: dict = {}
|
||||
|
||||
class AltKeyState:
|
||||
held: dict = {}
|
||||
released: dict = {}
|
||||
|
||||
class CtrlShiftKeyState:
|
||||
held: dict = {}
|
||||
released: dict = {}
|
||||
|
||||
class CtrlAltKeyState:
|
||||
held: dict = {}
|
||||
released: dict = {}
|
||||
|
||||
class AltShiftKeyState:
|
||||
held: dict = {}
|
||||
released: dict = {}
|
||||
|
||||
class CtrlShiftAltKeyState:
|
||||
held: dict = {}
|
||||
released: dict = {}
|
||||
|
||||
|
||||
|
||||
class KeyMapper:
|
||||
def __init__(self):
|
||||
super(KeyMapper, self).__init__()
|
||||
|
||||
self.state = NoKeyState
|
||||
self._map = {
|
||||
NoKeyState: NoKeyState(),
|
||||
NoKeyState | CtrlKeyState : CtrlKeyState(),
|
||||
NoKeyState | ShiftKeyState: ShiftKeyState(),
|
||||
NoKeyState | AltKeyState : AltKeyState(),
|
||||
NoKeyState | CtrlKeyState | ShiftKeyState : CtrlShiftKeyState(),
|
||||
NoKeyState | CtrlKeyState | AltKeyState : CtrlAltKeyState(),
|
||||
NoKeyState | AltKeyState | ShiftKeyState : AltShiftKeyState(),
|
||||
NoKeyState | CtrlKeyState | ShiftKeyState | AltKeyState: CtrlShiftAltKeyState(),
|
||||
}
|
||||
|
||||
self.load_map()
|
||||
|
||||
|
||||
def load_map(self):
|
||||
self.states = copy.deepcopy(self._map)
|
||||
bindings_file = f"{settings_manager.get_home_config_path()}/code-key-bindings.json"
|
||||
|
||||
with open(bindings_file, 'r') as f:
|
||||
data = json.load(f)["keybindings"]
|
||||
|
||||
for command in data:
|
||||
press_state = "held" if "held" in data[command] else "released"
|
||||
keyname = data[command][press_state]
|
||||
|
||||
state = NoKeyState
|
||||
if "<Control>" in keyname:
|
||||
state = state | CtrlKeyState
|
||||
if "<Shift>" in keyname:
|
||||
state = state | ShiftKeyState
|
||||
if "<Alt>" in keyname:
|
||||
state = state | AltKeyState
|
||||
|
||||
keyname = keyname.replace("<Control>", "") \
|
||||
.replace("<Shift>", "") \
|
||||
.replace("<Alt>", "")
|
||||
|
||||
getattr(self.states[state], press_state)[keyname] = command
|
||||
|
||||
def re_map(self):
|
||||
self.states = copy.deepcopy(self._map)
|
||||
|
||||
def _key_press_event(self, eve):
|
||||
keyname = Gdk.keyval_name(eve.keyval)
|
||||
print(keyname)
|
||||
|
||||
self._set_key_state(eve)
|
||||
if keyname in self.states[self.state].held:
|
||||
return self.states[self.state].held[keyname]
|
||||
|
||||
def _key_release_event(self, eve):
|
||||
keyname = Gdk.keyval_name(eve.keyval)
|
||||
|
||||
self._set_key_state(eve)
|
||||
if keyname in self.states[self.state].released:
|
||||
return self.states[self.state].released[keyname]
|
||||
|
||||
def _set_key_state(self, eve):
|
||||
modifiers = Gdk.ModifierType(eve.get_state() & ~Gdk.ModifierType.LOCK_MASK)
|
||||
is_control = True if modifiers & Gdk.ModifierType.CONTROL_MASK else False
|
||||
is_shift = True if modifiers & Gdk.ModifierType.SHIFT_MASK else False
|
||||
|
||||
try:
|
||||
is_alt = True if modifiers & Gdk.ModifierType.ALT_MASK else False
|
||||
except Exception:
|
||||
is_alt = True if modifiers & Gdk.ModifierType.MOD1_MASK else False
|
||||
|
||||
self.state = NoKeyState
|
||||
if is_control:
|
||||
self.state = self.state | CtrlKeyState
|
||||
if is_shift:
|
||||
self.state = self.state | ShiftKeyState
|
||||
if is_alt:
|
||||
self.state = self.state | AltKeyState
|
||||
|
||||
40
src/core/widgets/code/source_buffer.py
Normal file
40
src/core/widgets/code/source_buffer.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('GtkSource', '4')
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class SourceBuffer(GtkSource.Buffer):
|
||||
def __init__(self):
|
||||
super(SourceBuffer, self).__init__()
|
||||
|
||||
self._handler_ids = []
|
||||
|
||||
|
||||
def set_signals(
|
||||
self,
|
||||
_changed,
|
||||
_mark_set,
|
||||
_insert_text,
|
||||
_modified_changed,
|
||||
):
|
||||
|
||||
self._handler_ids = [
|
||||
self.connect("changed", _changed),
|
||||
self.connect("mark-set", _mark_set),
|
||||
self.connect("insert-text", _insert_text),
|
||||
self.connect("modified-changed", _modified_changed)
|
||||
]
|
||||
|
||||
def clear_signals(self):
|
||||
for handle_id in self._handler_ids:
|
||||
self.disconnect(handle_id)
|
||||
|
||||
def __del__(self):
|
||||
for handle_id in self._handler_ids:
|
||||
self.disconnect(handle_id)
|
||||
77
src/core/widgets/code/source_file.py
Normal file
77
src/core/widgets/code/source_file.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GtkSource
|
||||
from gi.repository import Gio
|
||||
|
||||
# Application imports
|
||||
from .source_buffer import SourceBuffer
|
||||
|
||||
|
||||
|
||||
class SourceFile(GtkSource.File):
|
||||
def __init__(self):
|
||||
super(SourceFile, self).__init__()
|
||||
|
||||
self.encoding: str = "UTF-8"
|
||||
self.fname: str = "buffer"
|
||||
self.fpath: str = "buffer"
|
||||
self.ftype: str = "buffer"
|
||||
|
||||
self.buffer: SourceBuffer = SourceBuffer()
|
||||
|
||||
self._set_signals()
|
||||
|
||||
|
||||
def set_path(self, gfile: Gio.File.new_for_path):
|
||||
if not gfile: return
|
||||
|
||||
self.set_location(gfile)
|
||||
|
||||
self.fpath = gfile.get_parent().get_path(),
|
||||
self.fname = gfile.get_basename()
|
||||
data = gfile.load_bytes()[0].get_data().decode("UTF-8")
|
||||
|
||||
self.buffer.insert_at_cursor(data)
|
||||
|
||||
def _set_signals(self):
|
||||
self.buffer.set_signals(
|
||||
self._changed,
|
||||
self._mark_set,
|
||||
self._insert_text,
|
||||
self._modified_changed
|
||||
)
|
||||
|
||||
def _insert_text(
|
||||
self,
|
||||
buffer: SourceBuffer,
|
||||
location: Gtk.TextIter,
|
||||
text: str,
|
||||
length: int
|
||||
):
|
||||
logger.info("SourceFile._insert_text")
|
||||
|
||||
def _changed(self, buffer: SourceBuffer):
|
||||
logger.info("SourceFile._changed")
|
||||
|
||||
def _mark_set(
|
||||
self,
|
||||
buffer: SourceBuffer,
|
||||
location: Gtk.TextIter,
|
||||
mark: Gtk.TextMark
|
||||
):
|
||||
# logger.info("SourceFile._mark_set")
|
||||
...
|
||||
|
||||
def _modified_changed(self,buffer: SourceBuffer):
|
||||
logger.info("SourceFile._modified_changed")
|
||||
|
||||
def close(self):
|
||||
del self.buffer
|
||||
36
src/core/widgets/code/source_files_manager.py
Normal file
36
src/core/widgets/code/source_files_manager.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from .source_file import SourceFile
|
||||
from .source_buffer import SourceBuffer
|
||||
|
||||
|
||||
|
||||
class SourceFilesManager(list):
|
||||
def __init__(self):
|
||||
super(SourceFilesManager, self).__init__()
|
||||
|
||||
|
||||
def new(self):
|
||||
file = SourceFile()
|
||||
super().append(file)
|
||||
|
||||
return file
|
||||
|
||||
def append(self, file: SourceFile):
|
||||
if not file: return
|
||||
|
||||
super().append(file)
|
||||
|
||||
def remove_file(self, buffer: SourceBuffer):
|
||||
if not buffer: return
|
||||
|
||||
for file in self:
|
||||
if not buffer == file.buffer: continue
|
||||
self.remove(file)
|
||||
|
||||
file.close()
|
||||
del file
|
||||
break
|
||||
115
src/core/widgets/code/view.py
Normal file
115
src/core/widgets/code/view.py
Normal file
@@ -0,0 +1,115 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
from .source_files_manager import SourceFilesManager
|
||||
from .completion_manager import CompletionManager
|
||||
from .command_system import CommandSystem
|
||||
from .key_mapper import KeyMapper
|
||||
|
||||
|
||||
class SourceView(GtkSource.View):
|
||||
def __init__(self):
|
||||
super(SourceView, self).__init__()
|
||||
|
||||
self.key_mapper = KeyMapper()
|
||||
|
||||
self._setup_styles()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styles(self):
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("source-view")
|
||||
|
||||
self.set_vexpand(True)
|
||||
|
||||
self.set_show_line_marks(True)
|
||||
self.set_show_line_numbers(True)
|
||||
self.set_smart_backspace(True)
|
||||
self.set_indent_on_tab(True)
|
||||
self.set_insert_spaces_instead_of_tabs(True)
|
||||
self.set_auto_indent(True)
|
||||
self.set_monospace(True)
|
||||
self.set_tab_width(4)
|
||||
self.set_show_right_margin(True)
|
||||
self.set_right_margin_position(80)
|
||||
self.set_background_pattern(0) # 0 = None, 1 = Grid
|
||||
self.set_highlight_current_line(True)
|
||||
|
||||
def _setup_signals(self):
|
||||
# self.connect("show-completion", self._show_completion)
|
||||
self.map_id = self.connect("map", self._init_map)
|
||||
|
||||
# self.connect("focus", self._on_widget_focus)
|
||||
# self.connect("focus-in-event", self._focus_in_event)
|
||||
|
||||
# self.connect("drag-data-received", self._on_drag_data_received)
|
||||
self.connect("key-press-event", self._key_press_event)
|
||||
self.connect("key-release-event", self._key_release_event)
|
||||
# self.connect("button-press-event", self._button_press_event)
|
||||
# self.connect("button-release-event", self._button_release_event)
|
||||
# self.connect("scroll-event", self._scroll_event)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def _init_map(self, view):
|
||||
def _first_show_init():
|
||||
self.disconnect(self.map_id)
|
||||
del self.map_id
|
||||
|
||||
self._handle_first_show()
|
||||
|
||||
return False
|
||||
|
||||
# GLib.timeout_add(1000, _first_show_init)
|
||||
GLib.idle_add(_first_show_init)
|
||||
|
||||
def _handle_first_show(self):
|
||||
self.language_manager = GtkSource.LanguageManager()
|
||||
self.style_scheme_manager = GtkSource.StyleSchemeManager()
|
||||
self.command = CommandSystem()
|
||||
self.files = SourceFilesManager()
|
||||
self.completion = CompletionManager(
|
||||
self.get_completion()
|
||||
)
|
||||
|
||||
self.style_scheme_manager.append_search_path(f"{settings_manager.get_home_config_path()}/code_styles")
|
||||
self.syntax_theme = self.style_scheme_manager.get_scheme("penguins-in-space")
|
||||
|
||||
self.command.set_data(self, self.get_buffer())
|
||||
self.exec_command("new_file")
|
||||
|
||||
def _key_press_event(self, view, eve):
|
||||
command = self.key_mapper._key_press_event(eve)
|
||||
if not command: return False
|
||||
|
||||
self.exec_command(command)
|
||||
return True
|
||||
|
||||
def _key_release_event(self, view, eve):
|
||||
command = self.key_mapper._key_release_event(eve)
|
||||
if not command: return False
|
||||
|
||||
self.exec_command(command)
|
||||
return True
|
||||
|
||||
def _show_completion(self, view):
|
||||
self.completion.request_completion()
|
||||
|
||||
def exec_command(self, command: str):
|
||||
self.command.exec(command)
|
||||
3
src/core/widgets/controls/__init__.py
Normal file
3
src/core/widgets/controls/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Widgets.Controls Package
|
||||
"""
|
||||
83
src/core/widgets/controls/open_files_button.py
Normal file
83
src/core/widgets/controls/open_files_button.py
Normal file
@@ -0,0 +1,83 @@
|
||||
# Python imports
|
||||
from contextlib import suppress
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gio
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class OpenFilesButton(Gtk.Button):
|
||||
"""docstring for OpenFilesButton."""
|
||||
|
||||
def __init__(self):
|
||||
super(OpenFilesButton, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_label("Open File(s)...")
|
||||
self.set_image( Gtk.Image.new_from_icon_name("gtk-open", 4) )
|
||||
self.set_always_show_image(True)
|
||||
self.set_image_position(1) # Left - 0, Right = 1
|
||||
self.set_hexpand(False)
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("button-release-event", self._open_files)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("open_files", self._open_files)
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def _open_files(self, widget = None, eve = None, gfile = None):
|
||||
start_dir = None
|
||||
_gfiles = []
|
||||
|
||||
if gfile and gfile.query_exists():
|
||||
start_dir = gfile.get_parent()
|
||||
|
||||
chooser = Gtk.FileChooserDialog("Open File(s)...", None,
|
||||
Gtk.FileChooserAction.OPEN,
|
||||
(
|
||||
Gtk.STOCK_CANCEL,
|
||||
Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_OPEN,
|
||||
Gtk.ResponseType.OK
|
||||
)
|
||||
)
|
||||
|
||||
chooser.set_select_multiple(True)
|
||||
|
||||
with suppress(Exception):
|
||||
folder = widget.get_current_file().get_parent() if not start_dir else start_dir
|
||||
chooser.set_current_folder( folder.get_path() )
|
||||
|
||||
response = chooser.run()
|
||||
if not response == Gtk.ResponseType.OK:
|
||||
chooser.destroy()
|
||||
return _gfiles
|
||||
|
||||
filenames = chooser.get_filenames()
|
||||
if not filenames:
|
||||
chooser.destroy()
|
||||
return _gfiles
|
||||
|
||||
for file in filenames:
|
||||
path = file if os.path.isabs(file) else os.path.abspath(file)
|
||||
_gfiles.append( Gio.File.new_for_path(path) )
|
||||
|
||||
chooser.destroy()
|
||||
|
||||
logger.debug(_gfiles)
|
||||
return _gfiles
|
||||
72
src/core/widgets/controls/save_as_button.py
Normal file
72
src/core/widgets/controls/save_as_button.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gio
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class SaveAsButton(Gtk.Button):
|
||||
def __init__(self):
|
||||
super(SaveAsButton, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_label("Save As")
|
||||
self.set_image( Gtk.Image.new_from_icon_name("gtk-save-as", 4) )
|
||||
self.set_always_show_image(True)
|
||||
self.set_image_position(1) # Left - 0, Right = 1
|
||||
self.set_hexpand(False)
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("released", self._save_as)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("save-as", self._save_as)
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def _save_as(self, widget = None, eve = None, gfile = None):
|
||||
start_dir = None
|
||||
_gfile = None
|
||||
|
||||
chooser = Gtk.FileChooserDialog("Save File As...", None,
|
||||
Gtk.FileChooserAction.SAVE,
|
||||
(
|
||||
Gtk.STOCK_CANCEL,
|
||||
Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_SAVE_AS,
|
||||
Gtk.ResponseType.OK
|
||||
)
|
||||
)
|
||||
|
||||
# chooser.set_select_multiple(False)
|
||||
|
||||
response = chooser.run()
|
||||
if not response == Gtk.ResponseType.OK:
|
||||
chooser.destroy()
|
||||
return _gfile
|
||||
|
||||
file = chooser.get_filename()
|
||||
if not file:
|
||||
chooser.destroy()
|
||||
return _gfile
|
||||
|
||||
path = file if os.path.isabs(file) else os.path.abspath(file)
|
||||
_gfile = Gio.File.new_for_path(path)
|
||||
|
||||
chooser.destroy()
|
||||
|
||||
logger.debug(f"File To Save As: {_gfile}")
|
||||
return _gfile
|
||||
@@ -37,12 +37,12 @@ class TransparencyScale(Gtk.Scale):
|
||||
def _load_widgets(self):
|
||||
adjust = self.get_adjustment()
|
||||
adjust.set_lower(0)
|
||||
adjust.set_upper(99)
|
||||
adjust.set_upper(100)
|
||||
adjust.set_value(settings.theming.transparency)
|
||||
adjust.set_step_increment(1.0)
|
||||
|
||||
def _update_transparency(self, range):
|
||||
event_system.emit("remove_transparency")
|
||||
event_system.emit("remove-transparency")
|
||||
tp = int(range.get_value())
|
||||
settings.theming.transparency = tp
|
||||
event_system.emit("update_transparency")
|
||||
event_system.emit("update-transparency")
|
||||
35
src/core/widgets/pager_widget.py
Normal file
35
src/core/widgets/pager_widget.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Wnck', '3.0')
|
||||
from gi.repository import Wnck
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class PagerWidget:
|
||||
def __init__(self):
|
||||
super(PagerWidget, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def get_widget(self):
|
||||
return Wnck.Pager.new()
|
||||
54
src/core/widgets/task_list_widget.py
Normal file
54
src/core/widgets/task_list_widget.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Wnck', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Wnck
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class TaskListWidget(Gtk.ScrolledWindow):
|
||||
def __init__(self):
|
||||
super(TaskListWidget, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_hexpand(False)
|
||||
self.set_size_request(180, -1)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
viewport = Gtk.Viewport()
|
||||
task_list = Wnck.Tasklist.new()
|
||||
vbox = Gtk.Box()
|
||||
|
||||
vbox.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
|
||||
task_list.set_scroll_enabled(False)
|
||||
task_list.set_button_relief(2) # 0 = normal relief, 2 = no relief
|
||||
task_list.set_grouping(1) # 0 = mever group, 1 auto group, 2 = always group
|
||||
|
||||
task_list.set_vexpand(True)
|
||||
task_list.set_include_all_workspaces(False)
|
||||
task_list.set_orientation(1) # 0 = horizontal, 1 = vertical
|
||||
|
||||
vbox.add(task_list)
|
||||
viewport.add(vbox)
|
||||
self.add(viewport)
|
||||
128
src/core/widgets/vte_widget.py
Normal file
128
src/core/widgets/vte_widget.py
Normal file
@@ -0,0 +1,128 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
gi.require_version('Vte', '2.91')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import Vte
|
||||
|
||||
# Application imports
|
||||
from libs.dto.event import Event
|
||||
|
||||
|
||||
|
||||
class VteWidgetException(Exception):
|
||||
...
|
||||
|
||||
|
||||
|
||||
class VteWidget(Vte.Terminal):
|
||||
"""
|
||||
https://stackoverflow.com/questions/60454326/how-to-implement-a-linux-terminal-in-a-pygtk-app-like-vscode-and-pycharm-has
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(VteWidget, self).__init__()
|
||||
|
||||
self.cd_cmd_prefix = ("cd".encode(), "cd ".encode())
|
||||
self.dont_process = False
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
self._do_session_spawn()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("vte-widget")
|
||||
|
||||
self.set_clear_background(False)
|
||||
self.set_enable_sixel(True)
|
||||
self.set_cursor_shape( Vte.CursorShape.IBEAM )
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("commit", self._commit)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("update_term_path", self.update_term_path)
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def _do_session_spawn(self):
|
||||
self.spawn_sync(
|
||||
Vte.PtyFlags.DEFAULT,
|
||||
settings_manager.get_home_path(),
|
||||
["/bin/bash"],
|
||||
[],
|
||||
GLib.SpawnFlags.DEFAULT,
|
||||
None, None,
|
||||
)
|
||||
|
||||
# Note: '-->:' is used as a delimiter to split on to get command actual.
|
||||
# !!! DO NOT REMOVE UNLESS CODE UPDATED ACCORDINGLY !!!
|
||||
startup_cmds = [
|
||||
"env -i /bin/bash --noprofile --norc\n",
|
||||
"export TERM='xterm-256color'\n",
|
||||
"export LC_ALL=C\n",
|
||||
"export XDG_RUNTIME_DIR='/run/user/1000'\n",
|
||||
"export DISPLAY=:0\n",
|
||||
f"export XAUTHORITY='{settings_manager.get_home_path()}/.Xauthority'\n",
|
||||
f"\nexport HOME='{settings_manager.get_home_path()}'\n",
|
||||
"export PS1='\\h@\\u \\W -->: '\n",
|
||||
"clear\n"
|
||||
]
|
||||
|
||||
for i in startup_cmds:
|
||||
self.run_command(i)
|
||||
|
||||
def _commit(self, terminal, text, size):
|
||||
if self.dont_process:
|
||||
self.dont_process = False
|
||||
return
|
||||
|
||||
if not text.encode() == "\r".encode(): return
|
||||
|
||||
text, attributes = self.get_text()
|
||||
|
||||
if not text: return
|
||||
|
||||
lines = text.strip().splitlines()
|
||||
command_ran = None
|
||||
|
||||
try:
|
||||
command_ran = lines[-1].split("-->:")[1].strip()
|
||||
except VteWidgetException as e:
|
||||
logger.debug(e)
|
||||
return
|
||||
|
||||
if not command_ran[0:3].encode() in self.cd_cmd_prefix:
|
||||
return
|
||||
|
||||
target_path = command_ran.split( command_ran[0:3] )[1]
|
||||
if target_path in (".", "./"): return
|
||||
|
||||
if not target_path:
|
||||
target_path = settings_manager.get_home_path()
|
||||
|
||||
event = Event("pty_path_updated", "", target_path)
|
||||
event_system.emit("handle_bridge_event", (event,))
|
||||
|
||||
def update_term_path(self, fpath: str):
|
||||
self.dont_process = True
|
||||
|
||||
cmds = [f"cd '{fpath}'\n", "clear\n"]
|
||||
for cmd in cmds:
|
||||
self.run_command(cmd)
|
||||
|
||||
def run_command(self, cmd: str):
|
||||
self.feed_child_binary(bytes(cmd, 'utf8'))
|
||||
@@ -1,3 +1,3 @@
|
||||
"""
|
||||
WebKit2 UI Module
|
||||
WebKit2 UI Package
|
||||
"""
|
||||
@@ -9,17 +9,14 @@ from gi.repository import Gdk
|
||||
from gi.repository import WebKit2
|
||||
|
||||
# Application imports
|
||||
from libs.data_types import Event
|
||||
|
||||
from libs.settings.other.webkit_ui_settings import WebkitUISettings
|
||||
from libs.dto.event import Event
|
||||
|
||||
|
||||
class WebkitUI(WebKit2.WebView):
|
||||
def __init__(self):
|
||||
super(WebkitUI, self).__init__()
|
||||
|
||||
# self.get_context().set_sandbox_enabled(False)
|
||||
|
||||
self._load_settings()
|
||||
self._setup_styling()
|
||||
self._subscribe_to_events()
|
||||
self._load_view()
|
||||
@@ -27,10 +24,6 @@ class WebkitUI(WebKit2.WebView):
|
||||
|
||||
self.show_all()
|
||||
|
||||
if settings_manager.is_debug():
|
||||
inspector = self.get_inspector()
|
||||
inspector.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_vexpand(True)
|
||||
@@ -38,8 +31,8 @@ class WebkitUI(WebKit2.WebView):
|
||||
self.set_background_color( Gdk.RGBA(0, 0, 0, 0.0) )
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe(f"ui_message", self.ui_message)
|
||||
|
||||
event_system.subscribe(f"ui-message", self.ui_message)
|
||||
|
||||
def _load_settings(self):
|
||||
self.set_settings( WebkitUISettings() )
|
||||
|
||||
@@ -54,7 +47,6 @@ class WebkitUI(WebKit2.WebView):
|
||||
|
||||
def _setup_content_manager(self):
|
||||
content_manager = self.get_user_content_manager()
|
||||
|
||||
content_manager.connect("script-message-received", self._process_js_message)
|
||||
content_manager.register_script_message_handler("backend")
|
||||
|
||||
@@ -64,45 +56,14 @@ class WebkitUI(WebKit2.WebView):
|
||||
|
||||
try:
|
||||
event = Event( **json.loads(message) )
|
||||
event_system.emit("handle_bridge_event", (event,))
|
||||
event_system.emit("handle-bridge-event", (event,))
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
|
||||
def ui_message(self, mtype, message):
|
||||
def ui_message(self, message, mtype):
|
||||
command = f"displayMessage('{message}', '{mtype}', '3')"
|
||||
self.run_javascript(command, None, None)
|
||||
|
||||
|
||||
class WebkitUISettings(WebKit2.Settings):
|
||||
def __init__(self):
|
||||
super(WebkitUISettings, self).__init__()
|
||||
|
||||
self._set_default_settings()
|
||||
|
||||
|
||||
# Note: Highly insecure setup but most "app" like setup I could think of.
|
||||
# Audit heavily any scripts/links ran/clicked under this setup!
|
||||
def _set_default_settings(self):
|
||||
# self.set_enable_xss_auditor(True)
|
||||
# self.set_enable_hyperlink_auditing(True)
|
||||
self.set_enable_xss_auditor(False)
|
||||
self.set_enable_hyperlink_auditing(False)
|
||||
self.set_enable_dns_prefetching(False)
|
||||
self.set_allow_file_access_from_file_urls(True)
|
||||
self.set_allow_universal_access_from_file_urls(True)
|
||||
# self.set_enable_java(True)
|
||||
|
||||
self.set_enable_page_cache(False)
|
||||
self.set_enable_offline_web_application_cache(False)
|
||||
self.set_enable_html5_local_storage(False)
|
||||
self.set_enable_html5_database(False)
|
||||
|
||||
self.set_print_backgrounds(False)
|
||||
self.set_enable_tabs_to_links(False)
|
||||
self.set_enable_fullscreen(True)
|
||||
self.set_enable_developer_extras(True)
|
||||
self.set_enable_webrtc(True)
|
||||
self.set_enable_webaudio(True)
|
||||
self.set_enable_accelerated_2d_canvas(True)
|
||||
|
||||
self.set_user_agent(f"Mozilla/5.0 {app_name}")
|
||||
def run_javascript(self, script, cancellable, callback):
|
||||
logger.debug(script)
|
||||
super().run_javascript(script, cancellable, callback)
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gdk', '3.0')
|
||||
gi.require_version('WebKit2', '4.0')
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import WebKit2
|
||||
|
||||
# Application imports
|
||||
from libs.settings_manager.other.webkit_ui_settings import WebkitUISettings
|
||||
|
||||
|
||||
class WebkitUI(WebKit2.WebView):
|
||||
def __init__(self):
|
||||
super(WebkitUI, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._subscribe_to_events()
|
||||
self._load_view()
|
||||
self._setup_content_manager()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_vexpand(True)
|
||||
self.set_hexpand(True)
|
||||
self.set_background_color( Gdk.RGBA(0, 0, 0, 0.0) )
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe(f"ui_message", self.ui_message)
|
||||
|
||||
def _load_settings(self):
|
||||
self.set_settings( WebkitUISettings() )
|
||||
|
||||
def _load_view(self):
|
||||
path = settings_manager.get_context_path()
|
||||
data = None
|
||||
|
||||
with open(f"{path}/index.html", "r") as f:
|
||||
data = f.read()
|
||||
|
||||
self.load_html(content = data, base_uri = f"file://{path}/")
|
||||
|
||||
def _setup_content_manager(self):
|
||||
content_manager = self.get_user_content_manager()
|
||||
content_manager.connect("script-message-received", self._process_js_message)
|
||||
content_manager.register_script_message_handler("backend")
|
||||
|
||||
def _process_js_message(self, user_content_manager, js_result):
|
||||
js_value = js_result.get_js_value()
|
||||
message = js_value.to_string()
|
||||
|
||||
try:
|
||||
event = Event( **json.loads(message) )
|
||||
event_system.emit("handle_bridge_event", (event,))
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
|
||||
def ui_message(self, message, mtype):
|
||||
command = f"displayMessage('{message}', '{mtype}', '3')"
|
||||
self.run_javascript(command, None, None)
|
||||
|
||||
@@ -10,7 +10,13 @@ from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
try:
|
||||
from gi.repository import GdkX11
|
||||
except ImportError:
|
||||
logger.debug("Could not import X11 gir module...")
|
||||
|
||||
# Application imports
|
||||
from libs.status_icon import StatusIcon
|
||||
from core.controllers.base_controller import BaseController
|
||||
|
||||
|
||||
@@ -23,26 +29,34 @@ class ControllerStartExceptiom(Exception):
|
||||
class Window(Gtk.ApplicationWindow):
|
||||
""" docstring for Window. """
|
||||
|
||||
def __init__(self, args, unknownargs):
|
||||
def __init__(self):
|
||||
super(Window, self).__init__()
|
||||
settings_manager.set_main_window(self)
|
||||
|
||||
self._controller = None
|
||||
self._status_icon = None
|
||||
self._controller = None
|
||||
|
||||
self.guake_key = settings_manager.get_guake_key()
|
||||
self.hidefunc = None
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets(args, unknownargs)
|
||||
self._load_widgets()
|
||||
|
||||
self._set_window_data()
|
||||
self._set_size_constraints()
|
||||
self._setup_window_toggle_event()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_title(f"{app_name}")
|
||||
self.set_title(f"{APP_NAME}")
|
||||
self.set_icon_from_file( settings_manager.get_window_icon() )
|
||||
self.set_decorated(True)
|
||||
self.set_skip_pager_hint(False)
|
||||
self.set_skip_taskbar_hint(False)
|
||||
self.set_gravity(5) # 5 = CENTER
|
||||
self.set_position(1) # 1 = CENTER, 4 = CENTER_ALWAYS
|
||||
|
||||
@@ -54,23 +68,33 @@ class Window(Gtk.ApplicationWindow):
|
||||
self.connect("focus-in-event", self._on_focus_in_event)
|
||||
self.connect("focus-out-event", self._on_focus_out_event)
|
||||
|
||||
self.connect("delete-event", self._tear_down)
|
||||
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._tear_down)
|
||||
self.connect("delete-event", self.stop)
|
||||
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.stop)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("tear_down", self._tear_down)
|
||||
event_system.subscribe("load_interactive_debug", self._load_interactive_debug)
|
||||
event_system.subscribe("tear-down", self.stop)
|
||||
event_system.subscribe("load-interactive-debug", self._load_interactive_debug)
|
||||
|
||||
def _load_widgets(self, args, unknownargs):
|
||||
def _load_widgets(self):
|
||||
if settings_manager.is_debug():
|
||||
self.set_interactive_debugging(True)
|
||||
|
||||
self._controller = BaseController(args, unknownargs)
|
||||
self._controller = BaseController()
|
||||
self._status_icon = StatusIcon()
|
||||
if not self._controller:
|
||||
raise ControllerStartException("BaseController exited and doesn't exist...")
|
||||
|
||||
self.add( self._controller.get_base_container() )
|
||||
|
||||
def _display_manager(self):
|
||||
""" Try to detect which display manager we are running under... """
|
||||
|
||||
import os
|
||||
if os.environ.get('WAYLAND_DISPLAY'):
|
||||
return 'WAYLAND'
|
||||
|
||||
return 'X11'
|
||||
|
||||
def _set_size_constraints(self):
|
||||
_window_x = settings.config.main_window_x
|
||||
_window_y = settings.config.main_window_y
|
||||
@@ -90,13 +114,12 @@ class Window(Gtk.ApplicationWindow):
|
||||
if visual and screen.is_composited() and settings.config.make_transparent == 0:
|
||||
self.set_visual(visual)
|
||||
self.set_app_paintable(True)
|
||||
self.connect("draw", self._area_draw)
|
||||
# self.connect("draw", self._area_draw)
|
||||
|
||||
# bind css file
|
||||
cssProvider = Gtk.CssProvider()
|
||||
cssProvider.load_from_path( settings_manager.get_css_file() )
|
||||
screen = Gdk.Screen.get_default()
|
||||
styleContext = Gtk.StyleContext()
|
||||
cssProvider.load_from_path( settings_manager.get_css_file() )
|
||||
styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
|
||||
|
||||
def _area_draw(self, widget: Gtk.ApplicationWindow, cr: cairo.Context) -> None:
|
||||
@@ -107,17 +130,62 @@ class Window(Gtk.ApplicationWindow):
|
||||
|
||||
|
||||
def _on_focus_in_event(self, widget, event):
|
||||
event_system.emit("pause_dnd_signals")
|
||||
event_system.emit("pause-dnd-signals")
|
||||
|
||||
def _on_focus_out_event(self, widget, event):
|
||||
event_system.emit("listen_dnd_signals")
|
||||
event_system.emit("listen-dnd-signals")
|
||||
|
||||
def _load_interactive_debug(self):
|
||||
self.set_interactive_debugging(True)
|
||||
|
||||
def _setup_window_toggle_event(self) -> None:
|
||||
hidebound = None
|
||||
if not self.guake_key or not self._display_manager() == 'X11':
|
||||
return
|
||||
|
||||
def _tear_down(self, widget = None, eve = None):
|
||||
event_system.emit("shutting_down")
|
||||
try:
|
||||
import gi
|
||||
gi.require_version('Keybinder', '3.0')
|
||||
from gi.repository import Keybinder
|
||||
|
||||
Keybinder.init()
|
||||
Keybinder.set_use_cooked_accelerators(False)
|
||||
except (ImportError, ValueError) as e:
|
||||
logger.warning(e)
|
||||
logger.warning('Unable to load Keybinder module. This means the hide_window shortcut will be unavailable')
|
||||
|
||||
return
|
||||
|
||||
# Attempt to grab a global hotkey for hiding the window.
|
||||
# If we fail, we'll never hide the window, iconifying instead.
|
||||
try:
|
||||
hidebound = Keybinder.bind(self.guake_key, self._on_toggle_window, self)
|
||||
except (KeyError, NameError) as e:
|
||||
logger.warning(e)
|
||||
|
||||
if not hidebound:
|
||||
logger.debug('Unable to bind hide_window key, another instance/window has it.')
|
||||
self.hidefunc = self.iconify
|
||||
else:
|
||||
self.hidefunc = self.hide
|
||||
|
||||
def _on_toggle_window(self, data, window):
|
||||
"""Handle a request to hide/show the window"""
|
||||
if not window.get_property('visible'):
|
||||
window.show()
|
||||
# Note: Needed to properly grab widget focus when set_skip_taskbar_hint set to True
|
||||
window.present()
|
||||
# NOTE: Need here to enforce sticky after hide and reshow.
|
||||
window.stick()
|
||||
else:
|
||||
self.hidefunc()
|
||||
|
||||
|
||||
def start(self):
|
||||
Gtk.main()
|
||||
|
||||
def stop(self, widget = None, eve = None):
|
||||
event_system.emit("shutting-down")
|
||||
|
||||
size = self.get_size()
|
||||
pos = self.get_position()
|
||||
@@ -130,6 +198,3 @@ class Window(Gtk.ApplicationWindow):
|
||||
|
||||
settings_manager.clear_pid()
|
||||
Gtk.main_quit()
|
||||
|
||||
def main(self):
|
||||
Gtk.main()
|
||||
@@ -1,3 +1,3 @@
|
||||
"""
|
||||
Utils module
|
||||
"""
|
||||
Libs Package
|
||||
"""
|
||||
@@ -1,5 +0,0 @@
|
||||
"""
|
||||
Dasta Class module
|
||||
"""
|
||||
|
||||
from .event import Event
|
||||
6
src/libs/db/__init__.py
Normal file
6
src/libs/db/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
"""
|
||||
DB Package
|
||||
"""
|
||||
|
||||
from .models import User
|
||||
from .db import DB
|
||||
@@ -18,7 +18,7 @@ def debug_signal_handler(signal, frame):
|
||||
rpdb2.start_embedded_debugger("foobar", True, True)
|
||||
rpdb2.setbreak(depth=1)
|
||||
return
|
||||
except StandardError:
|
||||
except Exception:
|
||||
...
|
||||
|
||||
try:
|
||||
@@ -26,7 +26,7 @@ def debug_signal_handler(signal, frame):
|
||||
logger.debug("\n\nStarting embedded rconsole debugger...\n\n")
|
||||
rconsole.spawn_server()
|
||||
return
|
||||
except StandardError as ex:
|
||||
except Exception as ex:
|
||||
...
|
||||
|
||||
try:
|
||||
@@ -34,7 +34,15 @@ def debug_signal_handler(signal, frame):
|
||||
logger.debug("\n\nStarting PuDB debugger...\n\n")
|
||||
set_trace(paused = True)
|
||||
return
|
||||
except StandardError as ex:
|
||||
except Exception as ex:
|
||||
...
|
||||
|
||||
try:
|
||||
import ipdb
|
||||
logger.debug("\n\nStarting IPDB debugger...\n\n")
|
||||
ipdb.set_trace()
|
||||
return
|
||||
except Exception as ex:
|
||||
...
|
||||
|
||||
try:
|
||||
@@ -42,11 +50,11 @@ def debug_signal_handler(signal, frame):
|
||||
logger.debug("\n\nStarting embedded PDB debugger...\n\n")
|
||||
pdb.Pdb(skip=['gi.*']).set_trace()
|
||||
return
|
||||
except StandardError as ex:
|
||||
except Exception as ex:
|
||||
...
|
||||
|
||||
try:
|
||||
import code
|
||||
code.interact()
|
||||
except StandardError as ex:
|
||||
logger.debug(f"{ex}, returning to normal program flow...")
|
||||
except Exception as ex:
|
||||
logger.debug(f"{ex}, returning to normal program flow...")
|
||||
5
src/libs/dto/__init__.py
Normal file
5
src/libs/dto/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""
|
||||
Dasta Class Package
|
||||
"""
|
||||
|
||||
from .event import Event
|
||||
@@ -13,17 +13,17 @@ from .singleton import Singleton
|
||||
|
||||
|
||||
class IPCServer(Singleton):
|
||||
""" Create a listener so that other {app_name} instances send requests back to existing instance. """
|
||||
""" Create a listener so that other {APP_NAME} instances send requests back to existing instance. """
|
||||
def __init__(self, ipc_address: str = '127.0.0.1', conn_type: str = "socket"):
|
||||
self.is_ipc_alive = False
|
||||
self._ipc_port = 4848
|
||||
self._ipc_port = 0 # Use 0 to let Listener chose port
|
||||
self._ipc_address = ipc_address
|
||||
self._conn_type = conn_type
|
||||
self._ipc_authkey = b'' + bytes(f'{app_name}-ipc', 'utf-8')
|
||||
self._ipc_authkey = b'' + bytes(f'{APP_NAME}-ipc', 'utf-8')
|
||||
self._ipc_timeout = 15.0
|
||||
|
||||
if conn_type == "socket":
|
||||
self._ipc_address = f'/tmp/{app_name}-ipc.sock'
|
||||
self._ipc_address = f'/tmp/{APP_NAME}-ipc.sock'
|
||||
elif conn_type == "full_network":
|
||||
self._ipc_address = '0.0.0.0'
|
||||
elif conn_type == "full_network_unsecured":
|
||||
@@ -35,7 +35,7 @@ class IPCServer(Singleton):
|
||||
self._subscribe_to_events()
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("post_file_to_ipc", self.send_ipc_message)
|
||||
event_system.subscribe("post-file-to-ipc", self.send_ipc_message)
|
||||
|
||||
|
||||
def create_ipc_listener(self) -> None:
|
||||
@@ -56,36 +56,43 @@ class IPCServer(Singleton):
|
||||
@daemon_threaded
|
||||
def _run_ipc_loop(self, listener) -> None:
|
||||
# NOTE: Not thread safe if using with Gtk. Need to import GLib and use idle_add
|
||||
while True:
|
||||
while self.is_ipc_alive:
|
||||
try:
|
||||
conn = listener.accept()
|
||||
start_time = time.perf_counter()
|
||||
self._handle_ipc_message(conn, start_time)
|
||||
except EOFError as e:
|
||||
logger.debug( repr(e) )
|
||||
except Exception as e:
|
||||
logger.debug( repr(e) )
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
listener.close()
|
||||
|
||||
def _handle_ipc_message(self, conn, start_time) -> None:
|
||||
while True:
|
||||
while self.is_ipc_alive:
|
||||
msg = conn.recv()
|
||||
logger.debug(msg)
|
||||
|
||||
if "FILE|" in msg:
|
||||
file = msg.split("FILE|")[1].strip()
|
||||
if file:
|
||||
event_system.emit("handle_file_from_ipc", file)
|
||||
event_system.emit("handle-file-from-ipc", file)
|
||||
|
||||
conn.close()
|
||||
break
|
||||
|
||||
if "DIR|" in msg:
|
||||
file = msg.split("DIR|")[1].strip()
|
||||
if file:
|
||||
event_system.emit("handle_dir_from_ipc", file)
|
||||
event_system.emit("handle-dir-from-ipc", file)
|
||||
|
||||
conn.close()
|
||||
break
|
||||
|
||||
|
||||
if msg in ['close connection', 'close server']:
|
||||
if msg in ['close connection', 'close server', 'Empty Data...']:
|
||||
conn.close()
|
||||
break
|
||||
|
||||
@@ -129,4 +136,4 @@ class IPCServer(Singleton):
|
||||
logger.error("IPC Socket no longer valid.... Removing.")
|
||||
os.unlink(self._ipc_address)
|
||||
except Exception as e:
|
||||
logger.error( repr(e) )
|
||||
logger.error( repr(e) )
|
||||
@@ -1,3 +1,3 @@
|
||||
"""
|
||||
Utils/Mixins module
|
||||
Libs.Mixins Package
|
||||
"""
|
||||
@@ -67,4 +67,4 @@ class DnDMixin:
|
||||
|
||||
files.append(gfile)
|
||||
|
||||
event_system.emit('set_pre_drop_dnd', (files,))
|
||||
event_system.emit('set-pre-drop-dnd', (files,))
|
||||
@@ -1,6 +1,8 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
|
||||
@@ -8,13 +10,22 @@
|
||||
|
||||
|
||||
class IPCSignalsMixin:
|
||||
""" IPCSignalsMixin handle messages from another starting solarfm process. """
|
||||
""" IPCSignalsMixin handle messages from another starting {APP_NAME} process. """
|
||||
|
||||
def print_to_console(self, message=None):
|
||||
def print_to_console(self, message = None):
|
||||
logger.debug(message)
|
||||
|
||||
def handle_file_from_ipc(self, path: str) -> None:
|
||||
logger.debug(f"File From IPC: {path}")
|
||||
def handle_file_from_ipc(self, fpath: str) -> None:
|
||||
logger.debug(f"File From IPC: {fpath}")
|
||||
GLib.idle_add(
|
||||
self.broadcast_message, "handle-file", (fpath,)
|
||||
)
|
||||
|
||||
def handle_dir_from_ipc(self, path: str) -> None:
|
||||
logger.debug(f"Dir From IPC: {path}")
|
||||
def handle_dir_from_ipc(self, fpath: str) -> None:
|
||||
logger.debug(f"Dir From IPC: {fpath}")
|
||||
GLib.idle_add(
|
||||
self.broadcast_message, "handle-folder", (fpath,)
|
||||
)
|
||||
|
||||
def broadcast_message(self, message_type: str = "none", data: () = ()) -> None:
|
||||
event_system.emit(message_type, data)
|
||||
@@ -68,11 +68,11 @@ class KeyboardSignalsMixin:
|
||||
if mapping:
|
||||
self.handle_mapped_key_event(mapping)
|
||||
else:
|
||||
self.handle_as_key_event_scope(mapping)
|
||||
self.handle_as_key_event_scope(keyname)
|
||||
|
||||
def handle_mapped_key_event(self, mapping):
|
||||
try:
|
||||
self.handle_as_controller_scope()
|
||||
self.handle_as_controller_scope(mapping)
|
||||
except Exception:
|
||||
self.handle_as_plugin_scope(mapping)
|
||||
|
||||
@@ -86,13 +86,11 @@ class KeyboardSignalsMixin:
|
||||
sender = ""
|
||||
eve_type = mapping
|
||||
|
||||
self.handle_as_key_event_system(sender, eve_type)
|
||||
|
||||
def handle_as_key_event_scope(self, mapping):
|
||||
logger.debug(f"on_global_key_release_controller > key > {keyname}")
|
||||
self.handle_key_event_system(sender, eve_type)
|
||||
|
||||
def handle_as_key_event_scope(self, keyname):
|
||||
if self.ctrl_down and not keyname in ["1", "kp_1", "2", "kp_2", "3", "kp_3", "4", "kp_4"]:
|
||||
self.handle_key_event_system(None, mapping)
|
||||
self.handle_key_event_system(None, keyname)
|
||||
|
||||
def handle_key_event_system(self, sender, eve_type):
|
||||
event_system.emit(eve_type)
|
||||
4
src/libs/settings/__init__.py
Normal file
4
src/libs/settings/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
Settings Package
|
||||
"""
|
||||
from .manager import SettingsManager
|
||||
@@ -1,5 +1,6 @@
|
||||
# Python imports
|
||||
import inspect
|
||||
import time
|
||||
import json
|
||||
import zipfile
|
||||
|
||||
@@ -22,35 +23,35 @@ class MissingConfigError(Exception):
|
||||
|
||||
class SettingsManager(StartCheckMixin, Singleton):
|
||||
def __init__(self):
|
||||
self._SCRIPT_PTH = path.dirname(path.realpath(__file__))
|
||||
self._USER_HOME = path.expanduser('~')
|
||||
self._HOME_CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}"
|
||||
self._USR_PATH = f"/usr/share/{app_name.lower()}"
|
||||
self._USR_CONFIG_FILE = f"{self._USR_PATH}/settings.json"
|
||||
self._SCRIPT_PTH: str = path.dirname(path.realpath(__file__))
|
||||
self._USER_HOME: str = path.expanduser('~')
|
||||
self._HOME_CONFIG_PATH: str = f"{self._USER_HOME}/.config/{APP_NAME.lower()}"
|
||||
self._USR_PATH: str = f"/usr/share/{APP_NAME.lower()}"
|
||||
self._USR_CONFIG_FILE: str = f"{self._USR_PATH}/settings.json"
|
||||
|
||||
self._CONTEXT_PATH = f"{self._HOME_CONFIG_PATH}/context_path"
|
||||
self._PLUGINS_PATH = f"{self._HOME_CONFIG_PATH}/plugins"
|
||||
self._DEFAULT_ICONS = f"{self._HOME_CONFIG_PATH}/icons"
|
||||
self._CONFIG_FILE = f"{self._HOME_CONFIG_PATH}/settings.json"
|
||||
self._GLADE_FILE = f"{self._HOME_CONFIG_PATH}/Main_Window.glade"
|
||||
self._CSS_FILE = f"{self._HOME_CONFIG_PATH}/stylesheet.css"
|
||||
self._KEY_BINDINGS_FILE = f"{self._HOME_CONFIG_PATH}/key-bindings.json"
|
||||
self._PID_FILE = f"{self._HOME_CONFIG_PATH}/{app_name.lower()}.pid"
|
||||
self._UI_WIDEGTS_PATH = f"{self._HOME_CONFIG_PATH}/ui_widgets"
|
||||
self._CONTEXT_MENU = f"{self._HOME_CONFIG_PATH}/contexct_menu.json"
|
||||
self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png"
|
||||
self._CONTEXT_PATH: str = f"{self._HOME_CONFIG_PATH}/context_path"
|
||||
self._PLUGINS_PATH: str = f"{self._HOME_CONFIG_PATH}/plugins"
|
||||
self._DEFAULT_ICONS: str = f"{self._HOME_CONFIG_PATH}/icons"
|
||||
self._CONFIG_FILE: str = f"{self._HOME_CONFIG_PATH}/settings.json"
|
||||
self._GLADE_FILE: str = f"{self._HOME_CONFIG_PATH}/Main_Window.glade"
|
||||
self._CSS_FILE: str = f"{self._HOME_CONFIG_PATH}/stylesheet.css"
|
||||
self._KEY_BINDINGS_FILE: str = f"{self._HOME_CONFIG_PATH}/key-bindings.json"
|
||||
self._PID_FILE: str = f"{self._HOME_CONFIG_PATH}/{APP_NAME.lower()}.pid"
|
||||
self._UI_WIDEGTS_PATH: str = f"{self._HOME_CONFIG_PATH}/ui_widgets"
|
||||
self._CONTEXT_MENU: str = f"{self._HOME_CONFIG_PATH}/contexct_menu.json"
|
||||
self._WINDOW_ICON: str = f"{self._DEFAULT_ICONS}/{APP_NAME.lower()}.png"
|
||||
|
||||
# self._USR_CONFIG_FILE = f"{self._USR_PATH}/settings.json"
|
||||
# self._PLUGINS_PATH = f"plugins"
|
||||
# self._CONFIG_FILE = f"settings.json"
|
||||
# self._GLADE_FILE = f"Main_Window.glade"
|
||||
# self._CSS_FILE = f"stylesheet.css"
|
||||
# self._KEY_BINDINGS_FILE = f"key-bindings.json"
|
||||
# self._PID_FILE = f"{app_name.lower()}.pid"
|
||||
# self._WINDOW_ICON = f"{app_name.lower()}.png"
|
||||
# self._UI_WIDEGTS_PATH = f"ui_widgets"
|
||||
# self._CONTEXT_MENU = f"contexct_menu.json"
|
||||
# self._DEFAULT_ICONS = f"icons"
|
||||
# self._USR_CONFIG_FILE: str = f"{self._USR_PATH}/settings.json"
|
||||
# self._PLUGINS_PATH: str = f"plugins"
|
||||
# self._CONFIG_FILE: str = f"settings.json"
|
||||
# self._GLADE_FILE: str = f"Main_Window.glade"
|
||||
# self._CSS_FILE: str = f"stylesheet.css"
|
||||
# self._KEY_BINDINGS_FILE: str = f"key-bindings.json"
|
||||
# self._PID_FILE: str = f"{APP_NAME.lower()}.pid"
|
||||
# self._WINDOW_ICON: str = f"{APP_NAME.lower()}.png"
|
||||
# self._UI_WIDEGTS_PATH: str = f"ui_widgets"
|
||||
# self._CONTEXT_MENU: str = f"contexct_menu.json"
|
||||
# self._DEFAULT_ICONS: str = f"icons"
|
||||
|
||||
|
||||
# with zipfile.ZipFile("files.zip", mode="r", allowZip64=True) as zf:
|
||||
@@ -79,7 +80,7 @@ class SettingsManager(StartCheckMixin, Singleton):
|
||||
if not path.exists(self._CSS_FILE):
|
||||
raise MissingConfigError("Unable to find the application Stylesheet file.")
|
||||
if not path.exists(self._WINDOW_ICON):
|
||||
self._WINDOW_ICON = f"{self._USR_PATH}/icons/{app_name.lower()}.png"
|
||||
self._WINDOW_ICON = f"{self._USR_PATH}/icons/{APP_NAME.lower()}.png"
|
||||
if not path.exists(self._WINDOW_ICON):
|
||||
raise MissingConfigError("Unable to find the application icon.")
|
||||
if not path.exists(self._UI_WIDEGTS_PATH):
|
||||
@@ -90,7 +91,9 @@ class SettingsManager(StartCheckMixin, Singleton):
|
||||
|
||||
try:
|
||||
with open(self._KEY_BINDINGS_FILE) as file:
|
||||
bindings = json.load(file)["keybindings"]
|
||||
bindings = json.load(file)["keybindings"]
|
||||
self._guake_key = bindings["guake_key"]
|
||||
|
||||
keybindings.configure(bindings)
|
||||
except Exception as e:
|
||||
print( f"Settings Manager: {self._KEY_BINDINGS_FILE}\n\t\t{repr(e)}" )
|
||||
@@ -102,23 +105,25 @@ class SettingsManager(StartCheckMixin, Singleton):
|
||||
print( f"Settings Manager: {self._CONTEXT_MENU}\n\t\t{repr(e)}" )
|
||||
|
||||
|
||||
self.settings: Settings = None
|
||||
self._main_window = None
|
||||
self._builder = None
|
||||
self.PAINT_BG_COLOR = (0, 0, 0, 0.0)
|
||||
self.settings: Settings = None
|
||||
self._main_window = None
|
||||
self._builder = None
|
||||
self.PAINT_BG_COLOR: tuple = (0, 0, 0, 0.0)
|
||||
|
||||
self._trace_debug = False
|
||||
self._debug = False
|
||||
self._dirty_start = False
|
||||
self._trace_debug: bool = False
|
||||
self._debug: bool = False
|
||||
self._dirty_start: bool = False
|
||||
self._passed_in_file: bool = False
|
||||
self._starting_files: list = []
|
||||
|
||||
|
||||
def register_signals_to_builder(self, classes=None):
|
||||
def register_signals_to_builder(self, classes = None):
|
||||
handlers = {}
|
||||
|
||||
for c in classes:
|
||||
methods = None
|
||||
try:
|
||||
methods = inspect.getmembers(c, predicate=inspect.ismethod)
|
||||
methods = inspect.getmembers(c, predicate = inspect.ismethod)
|
||||
handlers.update(methods)
|
||||
except Exception as e:
|
||||
...
|
||||
@@ -128,7 +133,6 @@ class SettingsManager(StartCheckMixin, Singleton):
|
||||
def set_main_window(self, window): self._main_window = window
|
||||
def set_builder(self, builder) -> any: self._builder = builder
|
||||
|
||||
|
||||
def get_monitor_data(self) -> list:
|
||||
screen = self._main_window.get_screen()
|
||||
monitors = []
|
||||
@@ -152,29 +156,46 @@ class SettingsManager(StartCheckMixin, Singleton):
|
||||
def get_home_config_path(self) -> str: return self._HOME_CONFIG_PATH
|
||||
def get_window_icon(self) -> str: return self._WINDOW_ICON
|
||||
def get_home_path(self) -> str: return self._USER_HOME
|
||||
def get_starting_files(self) -> list: return self._starting_files
|
||||
def get_guake_key(self) -> tuple: return self._guake_key
|
||||
|
||||
def get_starting_args(self):
|
||||
return self.args, self.unknownargs
|
||||
|
||||
def set_main_window_x(self, x: int = 0): self.settings.config.main_window_x = x
|
||||
def set_main_window_y(self, y: int = 0): self.settings.config.main_window_y = y
|
||||
def set_main_window_width(self, width: int = 800): self.settings.config.main_window_width = width
|
||||
def set_main_window_height(self, height: int = 600): self.settings.config.main_window_height = height
|
||||
def set_main_window_min_width(self, width: int = 720): self.settings.config.main_window_min_width = width
|
||||
def set_main_window_min_height(self, height: int = 480): self.settings.config.main_window_min_height = height
|
||||
def set_starting_files(self, files: list): self._starting_files = files
|
||||
def set_start_load_time(self): self._start_load_time = time.perf_counter()
|
||||
def set_end_load_time(self): self._end_load_time = time.perf_counter()
|
||||
|
||||
def set_starting_args(self, args, unknownargs):
|
||||
self.args = args
|
||||
self.unknownargs = unknownargs
|
||||
|
||||
def set_trace_debug(self, trace_debug: bool):
|
||||
self._trace_debug = trace_debug
|
||||
|
||||
def set_debug(self, debug: bool):
|
||||
self._debug = debug
|
||||
|
||||
def set_is_starting_with_file(self, is_passed_in_file: bool = False):
|
||||
self._passed_in_file = is_passed_in_file
|
||||
|
||||
def is_trace_debug(self) -> str: return self._trace_debug
|
||||
def is_debug(self) -> str: return self._debug
|
||||
def is_starting_with_file(self) -> bool: return self._passed_in_file
|
||||
|
||||
def call_method(self, target_class = None, _method_name = None, data = None):
|
||||
def log_load_time(self): logger.info( f"Load Time: {self._end_load_time - self._start_load_time}" )
|
||||
|
||||
def call_method(self, target_class: any = None, _method_name: str = "", data: any = None):
|
||||
method_name = str(_method_name)
|
||||
method = getattr(target_class, method_name, lambda data: f"No valid key passed...\nkey={method_name}\nargs={data}")
|
||||
return method(data) if data else method()
|
||||
|
||||
def set_main_window_x(self, x = 0): self.settings.config.main_window_x = x
|
||||
def set_main_window_y(self, y = 0): self.settings.config.main_window_y = y
|
||||
def set_main_window_width(self, width = 800): self.settings.config.main_window_width = width
|
||||
def set_main_window_height(self, height = 600): self.settings.config.main_window_height = height
|
||||
def set_main_window_min_width(self, width = 720): self.settings.config.main_window_min_width = width
|
||||
def set_main_window_min_height(self, height = 480): self.settings.config.main_window_min_height = height
|
||||
|
||||
def set_trace_debug(self, trace_debug):
|
||||
self._trace_debug = trace_debug
|
||||
|
||||
def set_debug(self, debug):
|
||||
self._debug = debug
|
||||
|
||||
|
||||
def load_settings(self):
|
||||
if not path.exists(self._CONFIG_FILE):
|
||||
self.settings = Settings()
|
||||
@@ -1,8 +1,8 @@
|
||||
"""
|
||||
Options module
|
||||
Settings.Options Package
|
||||
"""
|
||||
from .settings import Settings
|
||||
from .config import Config
|
||||
from .filters import Filters
|
||||
from .theming import Theming
|
||||
from .debugging import Debugging
|
||||
from .debugging import Debugging
|
||||
3
src/libs/settings/other/__init__.py
Normal file
3
src/libs/settings/other/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Settings.Other Package
|
||||
"""
|
||||
@@ -39,4 +39,4 @@ class WebkitUISettings(WebKit2.Settings):
|
||||
self.set_enable_webaudio(True)
|
||||
self.set_enable_accelerated_2d_canvas(True)
|
||||
|
||||
self.set_user_agent(f"{app_name}")
|
||||
self.set_user_agent(f"{APP_NAME}")
|
||||
@@ -41,7 +41,7 @@ class StartCheckMixin:
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
except OSError:
|
||||
print(f"{app_name} PID file exists but PID is irrelevant; starting dirty...")
|
||||
print(f"{APP_NAME} PID file exists but PID is irrelevant; starting dirty...")
|
||||
self._dirty_start = True
|
||||
return False
|
||||
|
||||
@@ -53,7 +53,7 @@ class StartCheckMixin:
|
||||
self._print_pid(pid)
|
||||
|
||||
def _print_pid(self, pid):
|
||||
print(f"{app_name} PID: {pid}")
|
||||
print(f"{APP_NAME} PID: {pid}")
|
||||
|
||||
def _clean_pid(self):
|
||||
os.unlink(self._PID_FILE)
|
||||
@@ -1,4 +0,0 @@
|
||||
"""
|
||||
Settings module
|
||||
"""
|
||||
from .manager import SettingsManager
|
||||
@@ -1,3 +0,0 @@
|
||||
"""
|
||||
Settings Other module
|
||||
"""
|
||||
@@ -12,13 +12,11 @@ class SingletonError(Exception):
|
||||
|
||||
|
||||
class Singleton:
|
||||
ccount = 0
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
obj = super(Singleton, cls).__new__(cls)
|
||||
cls.ccount += 1
|
||||
if cls._instance:
|
||||
raise SingletonError(f"'{cls.__name__}' is a Singleton. Cannot create a new instance...")
|
||||
|
||||
if cls.ccount == 2:
|
||||
raise SingletonError(f"Exceeded {cls.__name__} instantiation limit...")
|
||||
|
||||
return obj
|
||||
cls._instance = super(Singleton, cls).__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
67
src/libs/status_icon.py
Normal file
67
src/libs/status_icon.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('AppIndicator3', '0.1')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import AppIndicator3
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class StatusIcon():
|
||||
""" StatusIcon for Application to go to Status Tray. """
|
||||
|
||||
def __init__(self):
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
status_menu = Gtk.Menu()
|
||||
icon_theme = Gtk.IconTheme.get_default()
|
||||
check_menu_item = Gtk.CheckMenuItem.new_with_label("Update icon")
|
||||
quit_menu_item = Gtk.MenuItem.new_with_label("Quit")
|
||||
|
||||
# Create StatusNotifierItem
|
||||
self.indicator = AppIndicator3.Indicator.new(
|
||||
f"{APP_NAME}-statusicon",
|
||||
"gtk-info",
|
||||
AppIndicator3.IndicatorCategory.APPLICATION_STATUS)
|
||||
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
|
||||
|
||||
check_menu_item.connect("activate", self.check_menu_item_cb)
|
||||
quit_menu_item.connect("activate", self.quit_menu_item_cb)
|
||||
icon_theme.connect('changed', self.icon_theme_changed_cb)
|
||||
|
||||
self.indicator.set_menu(status_menu)
|
||||
status_menu.append(check_menu_item)
|
||||
status_menu.append(quit_menu_item)
|
||||
status_menu.show_all()
|
||||
|
||||
def update_icon(self, icon_name):
|
||||
self.indicator.set_icon(icon_name)
|
||||
|
||||
def check_menu_item_cb(self, widget, data = None):
|
||||
icon_name = "parole" if widget.get_active() else "gtk-info"
|
||||
self.update_icon(icon_name)
|
||||
|
||||
def icon_theme_changed_cb(self, theme):
|
||||
self.update_icon("gtk-info")
|
||||
|
||||
def quit_menu_item_cb(self, widget, data = None):
|
||||
event_system.emit("tear-down")
|
||||
@@ -15,13 +15,14 @@ class ManifestProcessor(Exception):
|
||||
|
||||
|
||||
class Plugin:
|
||||
path: str = None
|
||||
name: str = None
|
||||
author: str = None
|
||||
version: str = None
|
||||
support: str = None
|
||||
requests:{} = None
|
||||
reference: type = None
|
||||
path: str = None
|
||||
name: str = None
|
||||
author: str = None
|
||||
version: str = None
|
||||
support: str = None
|
||||
requests:{} = None
|
||||
reference: type = None
|
||||
pre_launch: bool = False
|
||||
|
||||
|
||||
class ManifestProcessor:
|
||||
@@ -46,23 +47,29 @@ class ManifestProcessor:
|
||||
plugin.support = self._manifest["support"]
|
||||
plugin.requests = self._manifest["requests"]
|
||||
|
||||
if "pre_launch" in self._manifest.keys():
|
||||
plugin.pre_launch = True if self._manifest["pre_launch"] == "true" else False
|
||||
|
||||
return plugin
|
||||
|
||||
def get_loading_data(self):
|
||||
loading_data = {}
|
||||
requests = self._plugin.requests
|
||||
keys = requests.keys()
|
||||
|
||||
if "pass_events" in keys:
|
||||
if "pass_events" in requests:
|
||||
if requests["pass_events"] in ["true"]:
|
||||
loading_data["pass_events"] = True
|
||||
|
||||
if "bind_keys" in keys:
|
||||
if isinstance(requests["bind_keys"], list):
|
||||
loading_data["bind_keys"] = requests["bind_keys"]
|
||||
|
||||
if "pass_ui_objects" in keys:
|
||||
if "pass_ui_objects" in requests:
|
||||
if isinstance(requests["pass_ui_objects"], list):
|
||||
loading_data["pass_ui_objects"] = [ self._builder.get_object(obj) for obj in requests["pass_ui_objects"] ]
|
||||
|
||||
if "bind_keys" in requests:
|
||||
if isinstance(requests["bind_keys"], list):
|
||||
loading_data["bind_keys"] = requests["bind_keys"]
|
||||
|
||||
return self._plugin, loading_data
|
||||
|
||||
def is_pre_launch(self):
|
||||
return self._plugin.pre_launch
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from os.path import isdir
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import Gio
|
||||
|
||||
# Application imports
|
||||
@@ -35,11 +36,23 @@ class PluginsController:
|
||||
|
||||
self._plugins_dir_watcher = None
|
||||
self._plugin_collection = []
|
||||
self._plugin_manifests = {}
|
||||
|
||||
self._load_manifests()
|
||||
|
||||
|
||||
def launch_plugins(self) -> None:
|
||||
def _load_manifests(self):
|
||||
logger.info(f"Loading manifests...")
|
||||
|
||||
for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]:
|
||||
manifest = ManifestProcessor(path, self._builder)
|
||||
self._plugin_manifests[path] = {
|
||||
"path": path,
|
||||
"folder": folder,
|
||||
"manifest": manifest
|
||||
}
|
||||
|
||||
self._set_plugins_watcher()
|
||||
self.load_plugins()
|
||||
|
||||
def _set_plugins_watcher(self) -> None:
|
||||
self._plugins_dir_watcher = Gio.File.new_for_path(self._plugins_path) \
|
||||
@@ -52,21 +65,47 @@ class PluginsController:
|
||||
Gio.FileMonitorEvent.MOVED_OUT]:
|
||||
self.reload_plugins(file)
|
||||
|
||||
def load_plugins(self, file: str = None) -> None:
|
||||
logger.info(f"Loading plugins...")
|
||||
def pre_launch_plugins(self) -> None:
|
||||
logger.info(f"Loading pre-launch plugins...")
|
||||
plugin_manifests: {} = {}
|
||||
|
||||
for key in self._plugin_manifests:
|
||||
target_manifest = self._plugin_manifests[key]["manifest"]
|
||||
if target_manifest.is_pre_launch():
|
||||
plugin_manifests[key] = self._plugin_manifests[key]
|
||||
|
||||
self._load_plugins(plugin_manifests, is_pre_launch = True)
|
||||
|
||||
def post_launch_plugins(self) -> None:
|
||||
logger.info(f"Loading post-launch plugins...")
|
||||
plugin_manifests: {} = {}
|
||||
|
||||
for key in self._plugin_manifests:
|
||||
target_manifest = self._plugin_manifests[key]["manifest"]
|
||||
if not target_manifest.is_pre_launch():
|
||||
plugin_manifests[key] = self._plugin_manifests[key]
|
||||
|
||||
self._load_plugins(plugin_manifests)
|
||||
|
||||
def _load_plugins(self, plugin_manifests: {} = {}, is_pre_launch: bool = False) -> None:
|
||||
parent_path = os.getcwd()
|
||||
|
||||
for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]:
|
||||
try:
|
||||
target = join(path, "plugin.py")
|
||||
manifest = ManifestProcessor(path, self._builder)
|
||||
for key in plugin_manifests:
|
||||
target_manifest = plugin_manifests[key]
|
||||
path, folder, manifest = target_manifest["path"], target_manifest["folder"], target_manifest["manifest"]
|
||||
|
||||
try:
|
||||
target = join(path, "plugin.py")
|
||||
if not os.path.exists(target):
|
||||
raise InvalidPluginException("Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load...")
|
||||
|
||||
plugin, loading_data = manifest.get_loading_data()
|
||||
module = self.load_plugin_module(path, folder, target)
|
||||
self.execute_plugin(module, plugin, loading_data)
|
||||
|
||||
if is_pre_launch:
|
||||
self.execute_plugin(module, plugin, loading_data)
|
||||
else:
|
||||
GLib.idle_add(self.execute_plugin, *(module, plugin, loading_data))
|
||||
except Exception as e:
|
||||
logger.info(f"Malformed Plugin: Not loading -->: '{folder}' !")
|
||||
logger.debug("Trace: ", traceback.print_exc())
|
||||
|
||||
10
user_config/usr/share/app_name/code-key-bindings.json
Normal file
10
user_config/usr/share/app_name/code-key-bindings.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"keybindings": {
|
||||
"show_completion" : { "released" : "<Control>space" },
|
||||
"line_up" : { "held" : "<Control>Up" },
|
||||
"line_down" : { "held" : "<Control>Down" },
|
||||
"new_file" : { "released" : "<Control>t" },
|
||||
"open_files" : { "released" : "<Control>o" },
|
||||
"close_file" : { "released" : "<Control>w" }
|
||||
}
|
||||
}
|
||||
100
user_config/usr/share/app_name/code_styles/catppuccin-frappe.xml
Normal file
100
user_config/usr/share/app_name/code_styles/catppuccin-frappe.xml
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Catppuccin Gedit theme based on Oblivion theme and Cappuccin for Visual Studio Code.
|
||||
-->
|
||||
|
||||
<style-scheme id="catppuccin_frappe" _name="Catppuccin frappe" version="1.0">
|
||||
|
||||
<author>sacerdos</author>
|
||||
<_description>Soothing pastel theme for Gedit</_description>
|
||||
|
||||
<!-- Catppuccin Palette -->
|
||||
<color name="frappe_rosewater" value="#f2d5cf"/>
|
||||
<color name="frappe_flamingo" value="#eebebe"/>
|
||||
<color name="frappe_pink" value="#f4b8e4"/>
|
||||
<color name="frappe_mauve" value="#ca9ee6"/>
|
||||
<color name="frappe_red" value="#e78284"/>
|
||||
<color name="frappe_maroon" value="#ea999c"/>
|
||||
<color name="frappe_peach" value="#ef9f76"/>
|
||||
<color name="frappe_yellow" value="#e5c890"/>
|
||||
<color name="frappe_green" value="#a6d189"/>
|
||||
<color name="frappe_teal" value="#81c8be"/>
|
||||
<color name="frappe_sky" value="#99d1db"/>
|
||||
<color name="frappe_sapphire" value="#85c1dc"/>
|
||||
<color name="frappe_blue" value="#8caaee"/>
|
||||
<color name="frappe_lavender" value="#babbf1"/>
|
||||
<color name="frappe_text" value="#c6d0f5"/>
|
||||
<color name="frappe_subtext1" value="#b5bfe2"/>
|
||||
<color name="frappe_subtext0" value="#a5adce"/>
|
||||
<color name="frappe_overlay2" value="#949cbb"/>
|
||||
<color name="frappe_overlay1" value="#838ba7"/>
|
||||
<color name="frappe_overlay0" value="#737994"/>
|
||||
<color name="frappe_surface2" value="#626880"/>
|
||||
<color name="frappe_surface1" value="#51576d"/>
|
||||
<color name="frappe_surface0" value="#51576d"/>
|
||||
<color name="frappe_base" value="#303446"/>
|
||||
<color name="frappe_mantle" value="#292c3c"/>
|
||||
<color name="frappe_crust" value="#232634"/>
|
||||
|
||||
<!-- Global Settings -->
|
||||
<style name="text" foreground="frappe_text" background = "frappe_base"/>
|
||||
<style name="selection" foreground="frappe_text" background="frappe_surface2"/>
|
||||
<style name="cursor" foreground="frappe_rosewater"/>
|
||||
<style name="secondary-cursor" foreground="frappe_rosewater"/>
|
||||
<style name="current-line" background="frappe_surface0"/>
|
||||
<style name="line-numbers" foreground="frappe_text" background="frappe_crust"/>
|
||||
<style name="draw-spaces" foreground="frappe_text"/>
|
||||
<style name="background-pattern" background="frappe_base"/>
|
||||
|
||||
<!-- Bracket Matching -->
|
||||
<style name="bracket-match" foreground="frappe_mauve"/>
|
||||
<style name="bracket-mismatch" foreground="frappe_text" background="frappe_peach"/>
|
||||
|
||||
<!-- Right Margin -->
|
||||
<style name="right-margin" foreground="frappe_text" background="frappe_crust"/>
|
||||
|
||||
<!-- Search Matching -->
|
||||
<style name="search-match" foreground="frappe_text" background="frappe_blue"/>
|
||||
|
||||
<!-- Comments -->
|
||||
<style name="def:comment" foreground="frappe_overlay0"/>
|
||||
<style name="def:shebang" foreground="frappe_overlay0" bold="true"/>
|
||||
<style name="def:doc-comment-element" italic="true"/>
|
||||
|
||||
<!-- Constants -->
|
||||
<style name="def:constant" foreground="frappe_green"/>
|
||||
<style name="def:string" foreground="frappe_green"/>
|
||||
<style name="def:special-char" foreground="frappe_lavender"/>
|
||||
<style name="def:special-constant" foreground="frappe_lavender"/>
|
||||
<style name="def:floating-point" foreground="frappe_lavender"/>
|
||||
|
||||
<!-- Identifiers -->
|
||||
<style name="def:identifier" foreground="frappe_blue"/>
|
||||
|
||||
<!-- Statements -->
|
||||
<style name="def:statement" foreground="frappe_sapphire" bold="true"/>
|
||||
|
||||
<!-- Types -->
|
||||
<style name="def:type" foreground="frappe_maroon" bold="true"/>
|
||||
|
||||
<!-- Markup -->
|
||||
<style name="def:emphasis" italic="true"/>
|
||||
<style name="def:strong-emphasis" foreground="frappe_yellow" bold="true"/>
|
||||
<style name="def:inline-code" foreground="frappe_green"/>
|
||||
<style name="def:insertion" underline="single"/>
|
||||
<style name="def:deletion" strikethrough="true"/>
|
||||
<style name="def:link-text" foreground="frappe_rosewater"/>
|
||||
<style name="def:link-symbol" foreground="frappe_blue" bold="true"/>
|
||||
<style name="def:link-destination" foreground="frappe_blue" italic="true" underline="single"/>
|
||||
<style name="def:heading" foreground="frappe_teal" bold="true"/>
|
||||
<style name="def:thematic-break" foreground="frappe_green" bold="true"/>
|
||||
<style name="def:preformatted-section" foreground="frappe_green"/>
|
||||
<style name="def:list-marker" foreground="frappe_teal" bold="true"/>
|
||||
|
||||
<!-- Others -->
|
||||
<style name="def:preprocessor" foreground="frappe_teal"/>
|
||||
<style name="def:error" foreground="frappe_maroon" bold="true"/>
|
||||
<style name="def:warning" foreground="frappe_peach"/>
|
||||
<style name="def:note" foreground="frappe_blue" bold="true"/>
|
||||
<style name="def:net-address" italic="true" underline="single"/>
|
||||
</style-scheme>
|
||||
100
user_config/usr/share/app_name/code_styles/catppuccin-latte.xml
Normal file
100
user_config/usr/share/app_name/code_styles/catppuccin-latte.xml
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Catppuccin Gedit theme based on Oblivion theme and Cappuccin for Visual Studio Code.
|
||||
-->
|
||||
|
||||
<style-scheme id="catppuccin_latte" _name="Catppuccin latte" version="1.0">
|
||||
|
||||
<author>sacerdos</author>
|
||||
<_description>Soothing pastel theme for Gedit</_description>
|
||||
|
||||
<!-- Catppuccin Palette -->
|
||||
<color name="latte_rosewater" value="#dc8a78"/>
|
||||
<color name="latte_flamingo" value="#dd7878"/>
|
||||
<color name="latte_pink" value="#ea76cb"/>
|
||||
<color name="latte_mauve" value="#8839ef"/>
|
||||
<color name="latte_red" value="#d20f39"/>
|
||||
<color name="latte_maroon" value="#e64553"/>
|
||||
<color name="latte_peach" value="#fe640b"/>
|
||||
<color name="latte_yellow" value="#df8e1d"/>
|
||||
<color name="latte_green" value="#40a02b"/>
|
||||
<color name="latte_teal" value="#179299"/>
|
||||
<color name="latte_sky" value="#04a5e5"/>
|
||||
<color name="latte_sapphire" value="#209fb5"/>
|
||||
<color name="latte_blue" value="#1e66f5"/>
|
||||
<color name="latte_lavender" value="#7287fd"/>
|
||||
<color name="latte_text" value="#4c4f69"/>
|
||||
<color name="latte_subtext1" value="#5c5f77"/>
|
||||
<color name="latte_subtext0" value="#6c6f85"/>
|
||||
<color name="latte_overlay2" value="#7c7f93"/>
|
||||
<color name="latte_overlay1" value="#8c8fa1"/>
|
||||
<color name="latte_overlay0" value="#9ca0b0"/>
|
||||
<color name="latte_surface2" value="#acb0be"/>
|
||||
<color name="latte_surface1" value="#bcc0cc"/>
|
||||
<color name="latte_surface0" value="#ccd0da"/>
|
||||
<color name="latte_base" value="#eff1f5"/>
|
||||
<color name="latte_mantle" value="#e6e9ef"/>
|
||||
<color name="latte_crust" value="#dce0e8"/>
|
||||
|
||||
<!-- Global Settings -->
|
||||
<style name="text" foreground="latte_text" background = "latte_base"/>
|
||||
<style name="selection" foreground="latte_text" background="latte_surface2"/>
|
||||
<style name="cursor" foreground="latte_rosewater"/>
|
||||
<style name="secondary-cursor" foreground="latte_rosewater"/>
|
||||
<style name="current-line" background="latte_surface0"/>
|
||||
<style name="line-numbers" foreground="latte_text" background="latte_crust"/>
|
||||
<style name="draw-spaces" foreground="latte_text"/>
|
||||
<style name="background-pattern" background="latte_base"/>
|
||||
|
||||
<!-- Bracket Matching -->
|
||||
<style name="bracket-match" foreground="latte_mauve"/>
|
||||
<style name="bracket-mismatch" foreground="latte_text" background="latte_peach"/>
|
||||
|
||||
<!-- Right Margin -->
|
||||
<style name="right-margin" foreground="latte_text" background="latte_crust"/>
|
||||
|
||||
<!-- Search Matching -->
|
||||
<style name="search-match" foreground="latte_text" background="latte_blue"/>
|
||||
|
||||
<!-- Comments -->
|
||||
<style name="def:comment" foreground="latte_overlay0"/>
|
||||
<style name="def:shebang" foreground="latte_overlay0" bold="true"/>
|
||||
<style name="def:doc-comment-element" italic="true"/>
|
||||
|
||||
<!-- Constants -->
|
||||
<style name="def:constant" foreground="latte_green"/>
|
||||
<style name="def:string" foreground="latte_green"/>
|
||||
<style name="def:special-char" foreground="latte_lavender"/>
|
||||
<style name="def:special-constant" foreground="latte_lavender"/>
|
||||
<style name="def:floating-point" foreground="latte_lavender"/>
|
||||
|
||||
<!-- Identifiers -->
|
||||
<style name="def:identifier" foreground="latte_blue"/>
|
||||
|
||||
<!-- Statements -->
|
||||
<style name="def:statement" foreground="latte_sapphire" bold="true"/>
|
||||
|
||||
<!-- Types -->
|
||||
<style name="def:type" foreground="latte_maroon" bold="true"/>
|
||||
|
||||
<!-- Markup -->
|
||||
<style name="def:emphasis" italic="true"/>
|
||||
<style name="def:strong-emphasis" foreground="latte_yellow" bold="true"/>
|
||||
<style name="def:inline-code" foreground="latte_green"/>
|
||||
<style name="def:insertion" underline="single"/>
|
||||
<style name="def:deletion" strikethrough="true"/>
|
||||
<style name="def:link-text" foreground="latte_rosewater"/>
|
||||
<style name="def:link-symbol" foreground="latte_blue" bold="true"/>
|
||||
<style name="def:link-destination" foreground="latte_blue" italic="true" underline="single"/>
|
||||
<style name="def:heading" foreground="latte_teal" bold="true"/>
|
||||
<style name="def:thematic-break" foreground="latte_green" bold="true"/>
|
||||
<style name="def:preformatted-section" foreground="latte_green"/>
|
||||
<style name="def:list-marker" foreground="latte_teal" bold="true"/>
|
||||
|
||||
<!-- Others -->
|
||||
<style name="def:preprocessor" foreground="latte_teal"/>
|
||||
<style name="def:error" foreground="latte_maroon" bold="true"/>
|
||||
<style name="def:warning" foreground="latte_peach"/>
|
||||
<style name="def:note" foreground="latte_blue" bold="true"/>
|
||||
<style name="def:net-address" italic="true" underline="single"/>
|
||||
</style-scheme>
|
||||
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Catppuccin Gedit theme based on Oblivion theme and Cappuccin for Visual Studio Code.
|
||||
-->
|
||||
|
||||
<style-scheme id="catppuccin_macchiato" _name="Catppuccin macchiato" version="1.0">
|
||||
|
||||
<author>sacerdos</author>
|
||||
<_description>Soothing pastel theme for Gedit</_description>
|
||||
|
||||
<!-- Catppuccin Palette -->
|
||||
<color name="macchiato_rosewater" value="#f4dbd6"/>
|
||||
<color name="macchiato_flamingo" value="#f0c6c6"/>
|
||||
<color name="macchiato_pink" value="#f5bde6"/>
|
||||
<color name="macchiato_mauve" value="#c6a0f6"/>
|
||||
<color name="macchiato_red" value="#ed8796"/>
|
||||
<color name="macchiato_maroon" value="#ee99a0"/>
|
||||
<color name="macchiato_peach" value="#f5a97f"/>
|
||||
<color name="macchiato_yellow" value="#eed49f"/>
|
||||
<color name="macchiato_green" value="#a6da95"/>
|
||||
<color name="macchiato_teal" value="#8bd5ca"/>
|
||||
<color name="macchiato_sky" value="#91d7e3"/>
|
||||
<color name="macchiato_sapphire" value="#7dc4e4"/>
|
||||
<color name="macchiato_blue" value="#8aadf4"/>
|
||||
<color name="macchiato_lavender" value="#b7bdf8"/>
|
||||
<color name="macchiato_text" value="#cad3f5"/>
|
||||
<color name="macchiato_subtext1" value="#b8c0e0"/>
|
||||
<color name="macchiato_subtext0" value="#a5adcb"/>
|
||||
<color name="macchiato_overlay2" value="#939ab7"/>
|
||||
<color name="macchiato_overlay1" value="#8087a2"/>
|
||||
<color name="macchiato_overlay0" value="#6e738d"/>
|
||||
<color name="macchiato_surface2" value="#5b6078"/>
|
||||
<color name="macchiato_surface1" value="#494d64"/>
|
||||
<color name="macchiato_surface0" value="#363a4f"/>
|
||||
<color name="macchiato_base" value="#24273a"/>
|
||||
<color name="macchiato_mantle" value="#1e2030"/>
|
||||
<color name="macchiato_crust" value="#181926"/>
|
||||
|
||||
<!-- Global Settings -->
|
||||
<style name="text" foreground="macchiato_text" background = "macchiato_base"/>
|
||||
<style name="selection" foreground="macchiato_text" background="macchiato_surface2"/>
|
||||
<style name="cursor" foreground="macchiato_rosewater"/>
|
||||
<style name="secondary-cursor" foreground="macchiato_rosewater"/>
|
||||
<style name="current-line" background="macchiato_surface0"/>
|
||||
<style name="line-numbers" foreground="macchiato_text" background="macchiato_crust"/>
|
||||
<style name="draw-spaces" foreground="macchiato_text"/>
|
||||
<style name="background-pattern" background="macchiato_mantle"/>
|
||||
|
||||
<!-- Bracket Matching -->
|
||||
<style name="bracket-match" foreground="macchiato_mauve"/>
|
||||
<style name="bracket-mismatch" foreground="macchiato_text" background="macchiato_peach"/>
|
||||
|
||||
<!-- Right Margin -->
|
||||
<style name="right-margin" foreground="macchiato_text" background="crust"/>
|
||||
|
||||
<!-- Search Matching -->
|
||||
<style name="search-match" foreground="macchiato_text" background="macchiato_blue"/>
|
||||
|
||||
<!-- Comments -->
|
||||
<style name="def:comment" foreground="macchiato_overlay0"/>
|
||||
<style name="def:shebang" foreground="macchiato_overlay0" bold="true"/>
|
||||
<style name="def:doc-comment-element" italic="true"/>
|
||||
|
||||
<!-- Constants -->
|
||||
<style name="def:constant" foreground="macchiato_green"/>
|
||||
<style name="def:string" foreground="macchiato_green"/>
|
||||
<style name="def:special-char" foreground="macchiato_lavender"/>
|
||||
<style name="def:special-constant" foreground="macchiato_lavender"/>
|
||||
<style name="def:floating-point" foreground="macchiato_lavender"/>
|
||||
|
||||
<!-- Identifiers -->
|
||||
<style name="def:identifier" foreground="macchiato_blue"/>
|
||||
|
||||
<!-- Statements -->
|
||||
<style name="def:statement" foreground="macchiato_sapphire" bold="true"/>
|
||||
|
||||
<!-- Types -->
|
||||
<style name="def:type" foreground="macchiato_maroon" bold="true"/>
|
||||
|
||||
<!-- Markup -->
|
||||
<style name="def:emphasis" italic="true"/>
|
||||
<style name="def:strong-emphasis" foreground="macchiato_yellow" bold="true"/>
|
||||
<style name="def:inline-code" foreground="macchiato_green"/>
|
||||
<style name="def:insertion" underline="single"/>
|
||||
<style name="def:deletion" strikethrough="true"/>
|
||||
<style name="def:link-text" foreground="macchiato_rosewater"/>
|
||||
<style name="def:link-symbol" foreground="macchiato_blue" bold="true"/>
|
||||
<style name="def:link-destination" foreground="macchiato_blue" italic="true" underline="single"/>
|
||||
<style name="def:heading" foreground="macchiato_teal" bold="true"/>
|
||||
<style name="def:thematic-break" foreground="macchiato_green" bold="true"/>
|
||||
<style name="def:preformatted-section" foreground="macchiato_green"/>
|
||||
<style name="def:list-marker" foreground="macchiato_teal" bold="true"/>
|
||||
|
||||
<!-- Others -->
|
||||
<style name="def:preprocessor" foreground="macchiato_teal"/>
|
||||
<style name="def:error" foreground="macchiato_maroon" bold="true"/>
|
||||
<style name="def:warning" foreground="macchiato_peach"/>
|
||||
<style name="def:note" foreground="macchiato_blue" bold="true"/>
|
||||
<style name="def:net-address" italic="true" underline="single"/>
|
||||
</style-scheme>
|
||||
100
user_config/usr/share/app_name/code_styles/catppuccin-mocha.xml
Normal file
100
user_config/usr/share/app_name/code_styles/catppuccin-mocha.xml
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Catppuccin Gedit theme based on Oblivion theme and Cappuccin for Visual Studio Code.
|
||||
-->
|
||||
|
||||
<style-scheme id="catppuccin_mocha" _name="Catppuccin Mocha" version="1.0">
|
||||
|
||||
<author>sacerdos</author>
|
||||
<_description>Soothing pastel theme for Gedit</_description>
|
||||
|
||||
<!-- Tango Palette -->
|
||||
<color name="mocha_rosewater" value="#f5e0dc"/>
|
||||
<color name="mocha_flamingo" value="#f2cdcd"/>
|
||||
<color name="mocha_pink" value="#f5c2e7"/>
|
||||
<color name="mocha_mauve" value="#cba6f7"/>
|
||||
<color name="mocha_red" value="#f38ba8"/>
|
||||
<color name="mocha_maroon" value="#eba0ac"/>
|
||||
<color name="mocha_peach" value="#fab387"/>
|
||||
<color name="mocha_yellow" value="#f9e2af"/>
|
||||
<color name="mocha_green" value="#a6e3a1"/>
|
||||
<color name="mocha_teal" value="#94e2d5"/>
|
||||
<color name="mocha_sky" value="#89dceb"/>
|
||||
<color name="mocha_sapphire" value="#74c7ec"/>
|
||||
<color name="mocha_blue" value="#89b4fa"/>
|
||||
<color name="mocha_lavender" value="#b4befe"/>
|
||||
<color name="mocha_text" value="#cdd6f4"/>
|
||||
<color name="mocha_subtext1" value="#bac2de"/>
|
||||
<color name="mocha_subtext0" value="#a6adc8"/>
|
||||
<color name="mocha_overlay2" value="#9399b2"/>
|
||||
<color name="mocha_overlay1" value="#7f849c"/>
|
||||
<color name="mocha_overlay0" value="#6c7086"/>
|
||||
<color name="mocha_surface2" value="#585b70"/>
|
||||
<color name="mocha_surface1" value="#45475a"/>
|
||||
<color name="mocha_surface0" value="#313244"/>
|
||||
<color name="mocha_base" value="#1e1e2e"/>
|
||||
<color name="mocha_mantle" value="#181825"/>
|
||||
<color name="mocha_crust" value="#11111b"/>
|
||||
|
||||
<!-- Global Settings -->
|
||||
<style name="text" foreground="mocha_text" background = "mocha_base"/>
|
||||
<style name="selection" foreground="mocha_text" background="mocha_surface2"/>
|
||||
<style name="cursor" foreground="mocha_rosewater"/>
|
||||
<style name="secondary-cursor" foreground="mocha_rosewater"/>
|
||||
<style name="current-line" background="mocha_surface0"/>
|
||||
<style name="line-numbers" foreground="mocha_text" background="mocha_crust"/>
|
||||
<style name="draw-spaces" foreground="mocha_text"/>
|
||||
<style name="background-pattern" background="mocha_mantle"/>
|
||||
|
||||
<!-- Bracket Matching -->
|
||||
<style name="bracket-match" foreground="mocha_mauve"/>
|
||||
<style name="bracket-mismatch" foreground="mocha_text" background="mocha_peach"/>
|
||||
|
||||
<!-- Right Margin -->
|
||||
<style name="right-margin" foreground="mocha_text" background="mocha_crust"/>
|
||||
|
||||
<!-- Search Matching -->
|
||||
<style name="search-match" foreground="mocha_text" background="mocha_blue"/>
|
||||
|
||||
<!-- Comments -->
|
||||
<style name="def:comment" foreground="mocha_overlay0"/>
|
||||
<style name="def:shebang" foreground="mocha_overlay0" bold="true"/>
|
||||
<style name="def:doc-comment-element" italic="true"/>
|
||||
|
||||
<!-- Constants -->
|
||||
<style name="def:constant" foreground="mocha_green"/>
|
||||
<style name="def:string" foreground="mocha_green"/>
|
||||
<style name="def:special-char" foreground="mocha_lavender"/>
|
||||
<style name="def:special-constant" foreground="mocha_lavender"/>
|
||||
<style name="def:floating-point" foreground="mocha_lavender"/>
|
||||
|
||||
<!-- Identifiers -->
|
||||
<style name="def:identifier" foreground="mocha_blue"/>
|
||||
|
||||
<!-- Statements -->
|
||||
<style name="def:statement" foreground="mocha_sapphire" bold="true"/>
|
||||
|
||||
<!-- Types -->
|
||||
<style name="def:type" foreground="mocha_maroon" bold="true"/>
|
||||
|
||||
<!-- Markup -->
|
||||
<style name="def:emphasis" italic="true"/>
|
||||
<style name="def:strong-emphasis" foreground="mocha_yellow" bold="true"/>
|
||||
<style name="def:inline-code" foreground="mocha_green"/>
|
||||
<style name="def:insertion" underline="single"/>
|
||||
<style name="def:deletion" strikethrough="true"/>
|
||||
<style name="def:link-text" foreground="mocha_rosewater"/>
|
||||
<style name="def:link-symbol" foreground="mocha_blue" bold="true"/>
|
||||
<style name="def:link-destination" foreground="mocha_blue" italic="true" underline="single"/>
|
||||
<style name="def:heading" foreground="mocha_teal" bold="true"/>
|
||||
<style name="def:thematic-break" foreground="mocha_green" bold="true"/>
|
||||
<style name="def:preformatted-section" foreground="mocha_green"/>
|
||||
<style name="def:list-marker" foreground="mocha_teal" bold="true"/>
|
||||
|
||||
<!-- Others -->
|
||||
<style name="def:preprocessor" foreground="mocha_teal"/>
|
||||
<style name="def:error" foreground="mocha_maroon" bold="true"/>
|
||||
<style name="def:warning" foreground="mocha_peach"/>
|
||||
<style name="def:note" foreground="mocha_blue" bold="true"/>
|
||||
<style name="def:net-address" italic="true" underline="single"/>
|
||||
</style-scheme>
|
||||
123
user_config/usr/share/app_name/code_styles/peacocks-in-space.xml
Normal file
123
user_config/usr/share/app_name/code_styles/peacocks-in-space.xml
Normal file
@@ -0,0 +1,123 @@
|
||||
<style-scheme name="Peacocks In Space" id="peacocks-in-space" version="1.0">
|
||||
<author> ITDominator</author>
|
||||
<description>An attempted clone of Dayle Rees' Peacocks In Space theme.</description>
|
||||
|
||||
<style name="current-line" background="#2b303b" />
|
||||
<style name="current-line-number" background="#f7b83d" />
|
||||
<style name="draw-spaces" foreground="#babdb6" />
|
||||
<style name="background-pattern" background="#6e7a94" />
|
||||
<style name="bracket-match" foreground="#white" background="#gray" />
|
||||
<style name="bracket-mismatch" foreground="#white" background="#FF5D38" />
|
||||
<style name="right-margin" foreground="#dee3ec" background="#454a54" />
|
||||
<style name="search-match" background="#E6DB74" />
|
||||
<style name="def:comment" foreground="#8998b9" />
|
||||
<style name="def:shebang" foreground="#00a8c6" bold="true" />
|
||||
<style name="def:doc-comment-element" italic="true" />
|
||||
<style name="def:constant" foreground="#E6DB74" />
|
||||
<style name="def:special-char" foreground="#26A6A6" />
|
||||
<style name="def:identifier" foreground="#FF5D38" />
|
||||
<style name="def:statement" foreground="#26A6A6" bold="true" />
|
||||
<style name="def:type" foreground="#E6DB74" bold="true" />
|
||||
<style name="def:preprocessor" foreground="#8998b9" />
|
||||
<style name="def:error" background="#FF5D38" bold="true" />
|
||||
<style name="def:warning" background="#f7b83d" />
|
||||
<style name="def:note" foreground="#00a8c6" background="#yellow" bold="true" />
|
||||
<style name="def:underlined" italic="true" underline="true" />
|
||||
<style name="diff:added-line" foreground="#008B8B" />
|
||||
<style name="diff:removed-line" foreground="#6A5ACD" />
|
||||
<style name="diff:changed-line" foreground="#8998b9" />
|
||||
<style name="diff:special-case" foreground="#E6DB74" />
|
||||
<style name="diff:location" foreground="#26A6A6" bold="true" />
|
||||
<style name="diff:diff-file" foreground="#E6DB74" bold="true" />
|
||||
<style name="xml:tags" foreground="#00a8c6" />
|
||||
<style name="xml:attribute-name" foreground="#ff5d38" />
|
||||
<style name="xml:namespace" foreground="#E6DB74" bold="true" />
|
||||
<style name="js:object" foreground="#2E8B57" bold="true" />
|
||||
<style name="js:constructors" foreground="#008B8B" />
|
||||
<style name="latex:display-math" foreground="#6A5ACD" />
|
||||
<style name="latex:command" foreground="#2E8B57" bold="true" />
|
||||
<style name="latex:include" foreground="#8998b9" />
|
||||
<style name="sh:variable" foreground="#6A5ACD" />
|
||||
<style name="Others" foreground="#2E8B57" bold="true" />
|
||||
<style name="Others 2" foreground="#008B8B" />
|
||||
<style name="Others 3" foreground="#6A5ACD" />
|
||||
<style name="python:builtin-object" foreground="#00a8c6" />
|
||||
<style name="python:class-name" foreground="#ff5d38" />
|
||||
<style name="python:function-name" foreground="#e6db74" />
|
||||
<style name="python:keyword" foreground="#00a8c6" />
|
||||
<style name="python:special-variable" />
|
||||
<style name="python:boolean" foreground="#ff5d38" />
|
||||
<style name="python:complex" foreground="#ff5d38" />
|
||||
<style name="python:format" foreground="#bf3f3f" />
|
||||
<style name="python:builtin-constant" foreground="#ff5d38" />
|
||||
<style name="python:builtin-function" foreground="#e6db74" />
|
||||
<style name="python:module-handler" foreground="#00a8c6" />
|
||||
<style name="python:escaped-char" foreground="#ff5d38" />
|
||||
<style name="reserved" foreground="#ff5d38" />
|
||||
<style name="operator" foreground="#00a8c6" />
|
||||
<style name="keyword" foreground="#00a8c6" />
|
||||
<style name="line-numbers" foreground="#ffffff" />
|
||||
<style name="python3:function-name" foreground="#e6db74" />
|
||||
<style name="text" />
|
||||
<style name="emphasis" />
|
||||
<style name="function" foreground="#e6db74" />
|
||||
<style name="selection-unfocused" background="#ff7800" />
|
||||
<style name="html:attrib-name" foreground="#ff5d38" />
|
||||
<style name="html:dtd" />
|
||||
<style name="html:attrib-value" foreground="#e6db74" />
|
||||
<style name="xml:element-name" foreground="#00a8c6" />
|
||||
<style name="xml:attribute-value" foreground="#e6db74" />
|
||||
<style name="html:comment" foreground="#8998b9" />
|
||||
<style name="xml:comment" foreground="#8998b9" />
|
||||
<style name="python3:builtin-function" foreground="#ff5d38" />
|
||||
<style name="python3:builtin-object" foreground="#ff5d38" />
|
||||
<style name="python3:class-name" foreground="#ff5d38" />
|
||||
<style name="python3:builtin-constant" foreground="#ff5d38" />
|
||||
<style name="python3:complex" foreground="#e6db74" />
|
||||
<style name="python3:escaped-char" foreground="#ff5d38" />
|
||||
<style name="python3:decimal" />
|
||||
<style name="python3:format" />
|
||||
<style name="python3:base-n-integer" />
|
||||
<style name="php:comment" foreground="#8998b9" />
|
||||
<style name="php:string" foreground="#e6db74" />
|
||||
<style name="json:keyname" foreground="#ff5d38" />
|
||||
<style name="json:string" foreground="#e6db74" />
|
||||
<style name="json:null-value" foreground="#ff5d38" />
|
||||
<style name="json:float" foreground="#e6db74" />
|
||||
<style name="json:boolean" foreground="#ff5d38" />
|
||||
<style name="java:reserved" foreground="#ff5d38" />
|
||||
<style name="js:function-expression" />
|
||||
<style name="js:identifier" />
|
||||
<style name="js:object-literal" />
|
||||
<style name="js:expression-statement" foreground="#e6db74" />
|
||||
<style name="js:expression" />
|
||||
<style name="js:label-statement" />
|
||||
<style name="js:variable-declaration" />
|
||||
<style name="js:rest-syntax" />
|
||||
<style name="js:regex-group" />
|
||||
<style name="js:keyword" foreground="#00a8c6" />
|
||||
<style name="js:grouping-operator" foreground="#ed333b" />
|
||||
<style name="js:grouping" foreground="#2ec27e" />
|
||||
<style name="js:escape" foreground="#ff5d38" />
|
||||
<style name="js:directive" />
|
||||
<style name="js:class-expression" />
|
||||
<style name="js:built-in-property" />
|
||||
<style name="js:built-in-object" />
|
||||
<style name="js:built-in-method" />
|
||||
<style name="js:built-in-function" />
|
||||
<style name="js:built-in-constructor" />
|
||||
<style name="js:block-statement" />
|
||||
<style name="js:ternary-operator" foreground="#00a8c6" />
|
||||
<style name="js:throw-statement" foreground="#00a8c6" />
|
||||
<style name="js:try-catch-statement" foreground="#00a8c6" />
|
||||
<style name="js:spread-syntax" />
|
||||
<style name="js:switch-statement" foreground="#00a8c6" />
|
||||
<style name="python3:keyword" foreground="#00a8c6" />
|
||||
<style name="python3:module-handler" foreground="#00a8c6" />
|
||||
<style name="python3:method-calls" foreground="#e6db74" />
|
||||
<style name="java:keyword" foreground="#8998b9" />
|
||||
<style name="method-calls" foreground="#e6db74" />
|
||||
<style name="xml:processing-instruction" />
|
||||
<style name="xml:cdata-delim" foreground="#8998b9" />
|
||||
<style name="gdscript:method-calls" foreground="#e6db74" />
|
||||
</style-scheme>
|
||||
119
user_config/usr/share/app_name/code_styles/penguins-in-space.xml
Normal file
119
user_config/usr/share/app_name/code_styles/penguins-in-space.xml
Normal file
@@ -0,0 +1,119 @@
|
||||
<style-scheme name="Penguins In Space" id="penguins-in-space" version="1.0">
|
||||
<author> ITDominator</author>
|
||||
<description>An homage to Dayle Rees' Peacocks In Space theme.</description>
|
||||
|
||||
<style name="current-line" background="#2b303b" />
|
||||
<style name="current-line-number" background="#f7b83d" />
|
||||
<style name="draw-spaces" foreground="#babdb6" />
|
||||
<style name="background-pattern" background="#6e7a94" />
|
||||
<style name="bracket-match" foreground="#white" background="#gray" />
|
||||
<style name="bracket-mismatch" foreground="#white" background="#FF5D38" />
|
||||
<style name="right-margin" foreground="#dee3ec" background="#454a54" />
|
||||
<style name="search-match" background="#E6DB74" />
|
||||
<style name="def:comment" foreground="#454a54" />
|
||||
<style name="def:shebang" foreground="#00a8c6" bold="true" />
|
||||
<style name="def:doc-comment-element" italic="true" />
|
||||
<style name="def:constant" foreground="#E6DB74" />
|
||||
<style name="def:special-char" foreground="#26A6A6" />
|
||||
<style name="def:identifier" foreground="#FF5D38" />
|
||||
<style name="def:statement" foreground="#26A6A6" bold="true" />
|
||||
<style name="def:type" foreground="#E6DB74" bold="true" />
|
||||
<style name="def:preprocessor" foreground="#8998b9" />
|
||||
<style name="def:error" background="#FF5D38" bold="true" />
|
||||
<style name="def:warning" background="#f7b83d" />
|
||||
<style name="def:note" foreground="#00a8c6" background="#yellow" bold="true" />
|
||||
<style name="def:underlined" italic="true" underline="true" />
|
||||
<style name="diff:added-line" foreground="#008B8B" />
|
||||
<style name="diff:removed-line" foreground="#6A5ACD" />
|
||||
<style name="diff:changed-line" foreground="#8998b9" />
|
||||
<style name="diff:special-case" foreground="#E6DB74" />
|
||||
<style name="diff:location" foreground="#26A6A6" bold="true" />
|
||||
<style name="diff:diff-file" foreground="#E6DB74" bold="true" />
|
||||
<style name="xml:tags" foreground="#00a8c6" />
|
||||
<style name="xml:attribute-name" foreground="#ff5d38" />
|
||||
<style name="xml:namespace" foreground="#E6DB74" bold="true" />
|
||||
<style name="js:object" foreground="#2E8B57" bold="true" />
|
||||
<style name="js:constructors" foreground="#008B8B" />
|
||||
<style name="latex:display-math" foreground="#6A5ACD" />
|
||||
<style name="latex:command" foreground="#2E8B57" bold="true" />
|
||||
<style name="latex:include" foreground="#8998b9" />
|
||||
<style name="sh:variable" foreground="#6A5ACD" />
|
||||
<style name="Others" foreground="#2E8B57" bold="true" />
|
||||
<style name="Others 2" foreground="#008B8B" />
|
||||
<style name="Others 3" foreground="#6A5ACD" />
|
||||
<style name="python:builtin-object" foreground="#00a8c6" />
|
||||
<style name="python:class-name" foreground="#ff5d38" />
|
||||
<style name="python:function-name" foreground="#e6db74" />
|
||||
<style name="python:keyword" foreground="#00a8c6" />
|
||||
<style name="python:special-variable" foreground="#26a269" />
|
||||
<style name="python:boolean" foreground="#ff5d38" />
|
||||
<style name="python:complex" foreground="#ff5d38" />
|
||||
<style name="python:format" foreground="#bf3f3f" />
|
||||
<style name="python:builtin-constant" foreground="#ff5d38" />
|
||||
<style name="python:builtin-function" foreground="#e6db74" />
|
||||
<style name="python:module-handler" foreground="#00a8c6" />
|
||||
<style name="python:escaped-char" foreground="#ff5d38" />
|
||||
<style name="reserved" foreground="#ff5d38" />
|
||||
<style name="operator" foreground="#00a8c6" />
|
||||
<style name="keyword" foreground="#00a8c6" />
|
||||
<style name="line-numbers" foreground="#ffffff" />
|
||||
<style name="python3:function-name" foreground="#e6db74" />
|
||||
<style name="text" />
|
||||
<style name="emphasis" />
|
||||
<style name="function" foreground="#e6db74" />
|
||||
<style name="selection-unfocused" background="#ff7800" />
|
||||
<style name="html:attrib-name" foreground="#ff5d38" />
|
||||
<style name="html:dtd" />
|
||||
<style name="html:attrib-value" foreground="#e6db74" />
|
||||
<style name="xml:element-name" foreground="#00a8c6" />
|
||||
<style name="xml:attribute-value" foreground="#e6db74" />
|
||||
<style name="html:comment" foreground="#8998b9" />
|
||||
<style name="xml:comment" foreground="#8998b9" />
|
||||
<style name="python3:builtin-function" foreground="#ff5d38" />
|
||||
<style name="python3:builtin-object" foreground="#ff5d38" />
|
||||
<style name="python3:class-name" foreground="#ff5d38" />
|
||||
<style name="python3:builtin-constant" foreground="#ff5d38" />
|
||||
<style name="python3:complex" foreground="#e6db74" />
|
||||
<style name="python3:escaped-char" foreground="#ff5d38" />
|
||||
<style name="python3:decimal" />
|
||||
<style name="python3:format" />
|
||||
<style name="python3:base-n-integer" />
|
||||
<style name="php:comment" foreground="#8998b9" />
|
||||
<style name="php:string" foreground="#e6db74" />
|
||||
<style name="json:keyname" foreground="#ff5d38" />
|
||||
<style name="json:string" foreground="#e6db74" />
|
||||
<style name="json:null-value" foreground="#e01b24" />
|
||||
<style name="json:float" foreground="#00a8c6" />
|
||||
<style name="json:boolean" foreground="#33d17a" />
|
||||
<style name="java:reserved" foreground="#ff5d38" />
|
||||
<style name="js:function-expression" />
|
||||
<style name="js:identifier" />
|
||||
<style name="js:object-literal" />
|
||||
<style name="js:expression-statement" foreground="#e6db74" />
|
||||
<style name="js:expression" />
|
||||
<style name="js:label-statement" />
|
||||
<style name="js:variable-declaration" />
|
||||
<style name="js:rest-syntax" />
|
||||
<style name="js:regex-group" />
|
||||
<style name="js:keyword" foreground="#00a8c6" />
|
||||
<style name="js:grouping-operator" foreground="#ed333b" />
|
||||
<style name="js:grouping" foreground="#2ec27e" />
|
||||
<style name="js:escape" foreground="#ff5d38" />
|
||||
<style name="js:directive" />
|
||||
<style name="js:class-expression" />
|
||||
<style name="js:built-in-property" />
|
||||
<style name="js:built-in-object" />
|
||||
<style name="js:built-in-method" />
|
||||
<style name="js:built-in-function" />
|
||||
<style name="js:built-in-constructor" />
|
||||
<style name="js:block-statement" />
|
||||
<style name="js:ternary-operator" foreground="#00a8c6" />
|
||||
<style name="js:throw-statement" foreground="#00a8c6" />
|
||||
<style name="js:try-catch-statement" foreground="#00a8c6" />
|
||||
<style name="js:spread-syntax" />
|
||||
<style name="js:switch-statement" foreground="#00a8c6" />
|
||||
<style name="python:multiline-string" foreground="#454a54" />
|
||||
<style name="python3:method-calls" foreground="#e6db74" />
|
||||
<style name="xml:cdata-delim" foreground="#8998b9" />
|
||||
<style name="gdscript:method-calls" foreground="#e6db74" />
|
||||
</style-scheme>
|
||||
@@ -43,6 +43,6 @@
|
||||
|
||||
|
||||
/* Other message text colors */
|
||||
.errorTxt { color: rgb(170, 18, 18); }
|
||||
.warningTxt { color: rgb(255, 168, 0); }
|
||||
.successTxt { color: rgb(136, 204, 39); }
|
||||
.error-txt { color: rgb(170, 18, 18); }
|
||||
.warning-txt { color: rgb(255, 168, 0); }
|
||||
.success=txt { color: rgb(136, 204, 39); }
|
||||
@@ -1,6 +1,7 @@
|
||||
html, body {
|
||||
display: block;
|
||||
background-color: #32383e00;
|
||||
// background-color: #32383e00;
|
||||
background-color: rgba(39, 43, 52, 0.64);
|
||||
color: #ffffff;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -1,23 +1,12 @@
|
||||
{
|
||||
"keybindings": {
|
||||
"help" : "F1",
|
||||
"rename_files" : ["F2", "<Control>e"],
|
||||
"open_terminal" : "F4",
|
||||
"refresh_tab" : ["F5", "<Control>r"],
|
||||
"delete_files" : "Delete",
|
||||
"tggl_top_main_menubar" : "Alt_L",
|
||||
"trash_files" : "<Shift><Control>t",
|
||||
"tear_down" : "<Control>q",
|
||||
"go_up" : "<Control>Up",
|
||||
"go_home" : "<Control>slash",
|
||||
"grab_focus_path_entry" : "<Control>l",
|
||||
"open_files" : "<Control>o",
|
||||
"show_hide_hidden_files" : "<Control>h",
|
||||
"keyboard_create_tab" : "<Control>t",
|
||||
"keyboard_close_tab" : "<Control>w",
|
||||
"keyboard_copy_files" : "<Control>c",
|
||||
"keyboard_cut_files" : "<Control>x",
|
||||
"paste_files" : "<Control>v",
|
||||
"show_new_file_menu" : "<Control>n"
|
||||
"guake_key" : "",
|
||||
"rename-files" : ["F2", "<Control>e"],
|
||||
"open-terminal" : "F4",
|
||||
"refresh-tab" : ["F5", "<Control>r"],
|
||||
"load-interactive-debug" : "<Control>d",
|
||||
"tggl-top-main-menubar" : "Alt_L",
|
||||
"tear-down" : "<Control>q"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,37 @@
|
||||
/* ---- Make most desired things base transparent ---- */
|
||||
popover,
|
||||
popover > box,
|
||||
notebook,
|
||||
header,
|
||||
stack,
|
||||
scrolledwindow,
|
||||
viewport {
|
||||
background: rgba(0, 0, 0, 0.0);
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
tab {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
tab:checked {
|
||||
border-bottom-color: rgba(125, 125, 125, 1);
|
||||
}
|
||||
|
||||
|
||||
.main-window,
|
||||
.base-container,
|
||||
.body-container,
|
||||
.center-container,
|
||||
.header-container,
|
||||
.footer-container,
|
||||
.left-containerm,
|
||||
.right-container {
|
||||
background: rgba(0, 0, 0, 0.0);
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
|
||||
.base-container {
|
||||
margin: 10px;
|
||||
}
|
||||
@@ -128,3 +162,4 @@ XfdesktopIconView.view:active {
|
||||
.mw_transparency_97 { background: rgba(39, 43, 52, 0.97); }
|
||||
.mw_transparency_98 { background: rgba(39, 43, 52, 0.98); }
|
||||
.mw_transparency_99 { background: rgba(39, 43, 52, 0.99); }
|
||||
.mw_transparency_100 { background: rgba(39, 43, 52, 1.00); }
|
||||
Reference in New Issue
Block a user