diff --git a/README.md b/README.md index 4896ce9..9bbc620 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Python-With-Gtk-Template -A template project for Python with Gtk applications. +# Newton Editor +A Python and Gtk+ quasi-IDE. ### Requirements * PyGObject @@ -7,14 +7,4 @@ A template project for Python with Gtk applications. * pyxdg ### Note -There are a "\" strings and files that need to be set according to your app's name located at: -* \_\_builtins\_\_.py -* user_config/bin/app_name -* user_config/usr/share/app_name -* user_config/usr/share/app_name/icons/app_name.png -* user_config/usr/share/app_name/icons/app_name-64x64.png -* user_config/usr/share/applications/app_name.desktop - - -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. +WIP diff --git a/src/__builtins__.py b/src/__builtins__.py index c7b3d32..c3d7782 100644 --- a/src/__builtins__.py +++ b/src/__builtins__.py @@ -29,7 +29,7 @@ def daemon_threaded_wrapper(fn): # NOTE: Just reminding myself we can add to builtins two different ways... # __builtins__.update({"event_system": Builtins()}) -builtins.app_name = "" +builtins.app_name = "Newton_Editor" builtins.keybindings = Keybindings() builtins.event_system = EventSystem() builtins.endpoint_registry = EndpointRegistry() diff --git a/src/core/core_widget.py b/src/core/core_widget.py index 2775c0e..4fa6712 100644 --- a/src/core/core_widget.py +++ b/src/core/core_widget.py @@ -6,7 +6,8 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports - +from .widgets.base.banner_controls import BannerControls +from .widgets.base.editer_notebook import EditorNotebook @@ -14,8 +15,6 @@ class CoreWidget(Gtk.Box): def __init__(self): super(CoreWidget, self).__init__() - self._builder = settings.get_builder() - self._setup_styling() self._setup_signals() self._load_widgets() @@ -30,15 +29,5 @@ class CoreWidget(Gtk.Box): ... def _load_widgets(self): - glade_box = self._builder.get_object("glade_box") - button = Gtk.Button(label="Click Me!") - - button.connect("clicked", self._hello_world) - - self.add(button) - self.add(glade_box) - - - - def _hello_world(self, widget=None, eve=None): - print("Hello, World!") + self.add(BannerControls()) + self.add(EditorNotebook()) diff --git a/src/core/widgets/__init__.py b/src/core/widgets/__init__.py new file mode 100644 index 0000000..72b072b --- /dev/null +++ b/src/core/widgets/__init__.py @@ -0,0 +1,3 @@ +""" + Widgets Module +""" diff --git a/src/core/widgets/base/__init__.py b/src/core/widgets/base/__init__.py new file mode 100644 index 0000000..729cb64 --- /dev/null +++ b/src/core/widgets/base/__init__.py @@ -0,0 +1,3 @@ +""" + Widgets.Base Module +""" diff --git a/src/core/widgets/base/banner_controls.py b/src/core/widgets/base/banner_controls.py new file mode 100644 index 0000000..3682ef4 --- /dev/null +++ b/src/core/widgets/base/banner_controls.py @@ -0,0 +1,39 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports +from ..controls.toggle_line_highlight import ToggleLineHighlight +from ..controls.scale_up_button import ScaleUpButton +from ..controls.scale_down_button import ScaleDownButton + + + +class BannerControls(Gtk.Box): + def __init__(self): + super(BannerControls, self).__init__() + + + self._setup_styling() + self._setup_signals() + self._load_widgets() + + self.show_all() + + + def _setup_styling(self): + self.set_orientation(0) + + def _setup_signals(self): + ... + + def _load_widgets(self): + # styles_chooser_button = GtkSource.StyleSchemeChooserButton() + + self.add(ToggleLineHighlight()) + # self.add(styles_chooser_button) + self.add(ScaleUpButton()) + self.add(ScaleDownButton()) diff --git a/src/core/widgets/base/editer_notebook.py b/src/core/widgets/base/editer_notebook.py new file mode 100644 index 0000000..0af3c31 --- /dev/null +++ b/src/core/widgets/base/editer_notebook.py @@ -0,0 +1,57 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports +from ..tab_header_widget import TabHeaderWidget +from .source_view import SourceView + + + +class EditorNotebook(Gtk.Notebook): + def __init__(self): + super(EditorNotebook, self).__init__() + + self._setup_styling() + self._setup_signals() + self._load_widgets() + + self.show_all() + + + def _setup_styling(self): + ... + + def _setup_signals(self): + ... + + def _load_widgets(self): + self.create_view() + + def create_view(self): + scroll_view = Gtk.ScrolledWindow() + source_view = SourceView() + tab_widget = TabHeaderWidget(scroll_view, source_view, self.close_tab) + scroll_view.add(source_view) + + index = self.append_page(scroll_view, tab_widget) + self.set_tab_detachable(scroll_view, True) + self.set_current_page(index) + + ctx = self.get_style_context() + ctx.add_class("notebook-unselected-focus") + self.set_tab_reorderable(scroll_view, True) + + def close_tab(self, button, scroll_view, source_view, eve=None): + if self.get_n_pages() == 1: + return + + page_num = self.page_num(scroll_view) + watcher = source_view.get_file_watcher() + if watcher: + watcher.cancel() + + self.remove_page(page_num) diff --git a/src/core/widgets/base/source_view.py b/src/core/widgets/base/source_view.py new file mode 100644 index 0000000..f91966d --- /dev/null +++ b/src/core/widgets/base/source_view.py @@ -0,0 +1,94 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('GtkSource', '4') +from gi.repository import GtkSource + +# Application imports + + + +class SourceView(GtkSource.View): + def __init__(self): + super(SourceView, self).__init__() + + self._language_manager = GtkSource.LanguageManager() + self._style_scheme_manager = GtkSource.StyleSchemeManager() + self._general_style_tag = None + + self._buffer = self.get_buffer() + + self._setup_styling() + self._setup_signals() + self._subscribe_to_events() + self._load_widgets() + + + def _setup_styling(self): + 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_buffer_language() + self._set_buffer_style() + self._create_default_tag() + + self.set_vexpand(True) + + def _setup_signals(self): + ... + + def _subscribe_to_events(self): + event_system.subscribe("set_buffer_language", self._set_buffer_language) + event_system.subscribe("set_buffer_style", self._set_buffer_style) + event_system.subscribe("toggle_highlight_line", self.toggle_highlight_line) + event_system.subscribe("scale_up_text", self.scale_up_text) + event_system.subscribe("scale_down_text", self.scale_down_text) + + + def _load_widgets(self): + ... + + def _create_default_tag(self): + self._general_style_tag = self._buffer.create_tag('general_style') + self._general_style_tag.set_property('size', 100) + self._general_style_tag.set_property('scale', 100) + + def _set_buffer_language(self, language = "python3"): + self._buffer.set_language( self._language_manager.get_language(language) ) + + def _set_buffer_style(self, style = "tango"): + self._buffer.set_style_scheme( self._style_scheme_manager.get_scheme(style) ) + + def get_file_watcher(self): + return None + + + def toggle_highlight_line(self, widget=None, eve=None): + self.set_highlight_current_line( not self.get_highlight_current_line() ) + + def scale_up_text(self, scale_step = 10): + current_scale = self._general_style_tag.get_property('scale') + start_itr = self._buffer.get_start_iter() + end_itr = self._buffer.get_end_iter() + + self._general_style_tag.set_property('scale', current_scale + scale_step) + self._buffer.apply_tag(self._general_style_tag, start_itr, end_itr) + + def scale_down_text(self, scale_step = 10): + tag_table = self._buffer.get_tag_table() + start_itr = self._buffer.get_start_iter() + end_itr = self._buffer.get_end_iter() + tag = tag_table.lookup('general_style') + + tag.set_property('scale', tag.get_property('scale') - scale_step) + self._buffer.apply_tag(tag, start_itr, end_itr) diff --git a/src/core/widgets/controls/__init__.py b/src/core/widgets/controls/__init__.py new file mode 100644 index 0000000..f53f627 --- /dev/null +++ b/src/core/widgets/controls/__init__.py @@ -0,0 +1,3 @@ +""" + Widgets.Controls Module +""" diff --git a/src/core/widgets/controls/scale_down_button.py b/src/core/widgets/controls/scale_down_button.py new file mode 100644 index 0000000..5319300 --- /dev/null +++ b/src/core/widgets/controls/scale_down_button.py @@ -0,0 +1,35 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports + + + +class ScaleDownButton(Gtk.Button): + def __init__(self): + super(ScaleDownButton, self).__init__() + + self._setup_styling() + self._setup_signals() + self._subscribe_to_events() + self._load_widgets() + + + def _setup_styling(self): + self.set_label("Zoom Out (-)") + + def _setup_signals(self): + self.connect("released", self._emit_scale_eve) + + def _subscribe_to_events(self): + ... + + def _load_widgets(self): + ... + + def _emit_scale_eve(self, widget, eve = None): + event_system.emit('scale_down_text') diff --git a/src/core/widgets/controls/scale_up_button.py b/src/core/widgets/controls/scale_up_button.py new file mode 100644 index 0000000..f73409b --- /dev/null +++ b/src/core/widgets/controls/scale_up_button.py @@ -0,0 +1,35 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports + + + +class ScaleUpButton(Gtk.Button): + def __init__(self): + super(ScaleUpButton, self).__init__() + + self._setup_styling() + self._setup_signals() + self._subscribe_to_events() + self._load_widgets() + + + def _setup_styling(self): + self.set_label("Zoom In (+)") + + def _setup_signals(self): + self.connect("released", self._emit_scale_eve) + + def _subscribe_to_events(self): + ... + + def _load_widgets(self): + ... + + def _emit_scale_eve(self, widget, eve = None): + event_system.emit('scale_up_text') diff --git a/src/core/widgets/controls/toggle_line_highlight.py b/src/core/widgets/controls/toggle_line_highlight.py new file mode 100644 index 0000000..44df66e --- /dev/null +++ b/src/core/widgets/controls/toggle_line_highlight.py @@ -0,0 +1,34 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports + + +class ToggleLineHighlight(Gtk.ToggleButton): + def __init__(self): + super(ToggleLineHighlight, self).__init__() + + self._setup_styling() + self._setup_signals() + self._subscribe_to_events() + self._load_widgets() + + + def _setup_styling(self): + self.set_label("Toggle Line Highlight") + + def _setup_signals(self): + self.connect("released", self._emit_toggle_eve) + + def _subscribe_to_events(self): + ... + + def _load_widgets(self): + ... + + def _emit_toggle_eve(self, widget, eve = None): + event_system.emit('toggle_highlight_line') diff --git a/src/core/widgets/tab_header_widget.py b/src/core/widgets/tab_header_widget.py new file mode 100644 index 0000000..ad58854 --- /dev/null +++ b/src/core/widgets/tab_header_widget.py @@ -0,0 +1,60 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports + + + +class TabHeaderWidget(Gtk.ButtonBox): + """docstring for TabHeaderWidget""" + + ccount = 0 + + def __new__(cls, *args, **kwargs): + obj = super(TabHeaderWidget, cls).__new__(cls) + cls.ccount += 1 + + return obj + + + # def __init__(self, tab, close_tab): + def __init__(self, scroll_view, source_view, close_tab): + super(TabHeaderWidget, self).__init__() + + self.INDEX = self.ccount + self.NAME = f"tab_{self.INDEX}" + self._scroll_view = scroll_view + self._source_view = source_view + self._close_tab = close_tab # NOTE: Close method in tab_mixin + + self._setup_styling() + self._setup_signals() + self._load_widgets() + + + def _setup_styling(self): + self.set_orientation(0) + + def _setup_signals(self): + ... + + def _load_widgets(self): + label = Gtk.Label() + close = Gtk.Button() + icon = Gtk.Image(stock=Gtk.STOCK_CLOSE) + + label.set_label(f"{self.NAME}") + label.set_width_chars(len(self.NAME)) + label.set_xalign(0.0) + + close.connect("released", self._close_tab, *(self._scroll_view, self._source_view,)) + + close.add(icon) + self.add(label) + self.add(close) + + self.show_all() diff --git a/src/core/window.py b/src/core/window.py index 1b702a8..45c79b5 100644 --- a/src/core/window.py +++ b/src/core/window.py @@ -83,7 +83,7 @@ class Window(Gtk.ApplicationWindow): styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER) def _area_draw(self, widget: Gtk.ApplicationWindow, cr: cairo.Context) -> None: - cr.set_source_rgba(0, 0, 0, 0.54) + cr.set_source_rgba( *settings.get_paint_bg_color() ) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() cr.set_operator(cairo.OPERATOR_OVER) diff --git a/src/utils/settings/settings.py b/src/utils/settings/settings.py index f6ce27d..c3ee5f3 100644 --- a/src/utils/settings/settings.py +++ b/src/utils/settings/settings.py @@ -29,7 +29,7 @@ class Settings(StartCheckMixin): 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._WINDOW_ICON = f"{self._DEFAULT_ICONS}/icons/{app_name.lower()}.png" + self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png" if not os.path.exists(self._HOME_CONFIG_PATH): os.mkdir(self._HOME_CONFIG_PATH) @@ -73,6 +73,7 @@ class Settings(StartCheckMixin): self._main_window_w = 800 self._main_window_h = 600 self._builder = None + self.PAINT_BG_COLOR = (0, 0, 0, 0.54) self._trace_debug = False self._debug = False @@ -107,10 +108,11 @@ class Settings(StartCheckMixin): return monitors - def get_main_window(self) -> any: return self._main_window - def get_main_window_width(self) -> Gtk.ApplicationWindow: return self._main_window_w - def get_main_window_height(self) -> Gtk.ApplicationWindow: return self._main_window_h + def get_main_window(self) -> any: return self._main_window + def get_main_window_width(self) -> any: return self._main_window_w + def get_main_window_height(self) -> any: return self._main_window_h def get_builder(self) -> any: return self._builder + def get_paint_bg_color(self) -> any: return self.PAINT_BG_COLOR def get_glade_file(self) -> str: return self._GLADE_FILE def get_plugins_path(self) -> str: return self._PLUGINS_PATH diff --git a/user_config/bin/ b/user_config/bin/newton_editor similarity index 83% rename from user_config/bin/ rename to user_config/bin/newton_editor index 7a3e523..3e34fe8 100755 --- a/user_config/bin/ +++ b/user_config/bin/newton_editor @@ -19,11 +19,11 @@ function main() { # NOTE: Remove if you want to pass file(s) besides directories... if [ ! -d "${path}" ]; then - echo ": Path given not a directory..." + echo "Newton Editor: Path given not a directory..." exit 1 fi cd "/opt/" - python /opt/.zip "$@" + python /opt/newton_editor.zip "$@" } main "$@"; diff --git a/user_config/usr/applications/.desktop b/user_config/usr/applications/.desktop deleted file mode 100755 index d459bfb..0000000 --- a/user_config/usr/applications/.desktop +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Name= -GenericName= -Comment= -Exec=/bin/ %F -Icon=/usr/share//icons/.png -Type=Application -StartupNotify=true -Categories=System;FileTools;Utility;Core;GTK;FileManager; -MimeType= -Terminal=false diff --git a/user_config/usr/applications/newton_editor.desktop b/user_config/usr/applications/newton_editor.desktop new file mode 100755 index 0000000..1d6ed4a --- /dev/null +++ b/user_config/usr/applications/newton_editor.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Newton Editor +GenericName=Code IDE +Comment=General purpose IDE +Exec=/bin/newton_editor %F +Icon=/usr/share/newton_editor/icons/newton_editor.png +Type=Application +StartupNotify=true +Categories=System;FileTools;Utility; +MimeType= +Terminal=false diff --git a/user_config/usr/share/app_name/icons/app_name-64x64.png b/user_config/usr/share/app_name/icons/app_name-64x64.png deleted file mode 100644 index 6105709..0000000 Binary files a/user_config/usr/share/app_name/icons/app_name-64x64.png and /dev/null differ diff --git a/user_config/usr/share/app_name/icons/app_name.png b/user_config/usr/share/app_name/icons/app_name.png deleted file mode 100644 index c40fb0f..0000000 Binary files a/user_config/usr/share/app_name/icons/app_name.png and /dev/null differ diff --git a/user_config/usr/share/app_name/Main_Window.glade b/user_config/usr/share/newton_editor/Main_Window.glade similarity index 100% rename from user_config/usr/share/app_name/Main_Window.glade rename to user_config/usr/share/newton_editor/Main_Window.glade diff --git a/user_config/usr/share/app_name/icons/archive.png b/user_config/usr/share/newton_editor/icons/archive.png similarity index 100% rename from user_config/usr/share/app_name/icons/archive.png rename to user_config/usr/share/newton_editor/icons/archive.png diff --git a/user_config/usr/share/app_name/icons/audio.png b/user_config/usr/share/newton_editor/icons/audio.png similarity index 100% rename from user_config/usr/share/app_name/icons/audio.png rename to user_config/usr/share/newton_editor/icons/audio.png diff --git a/user_config/usr/share/app_name/icons/bin.png b/user_config/usr/share/newton_editor/icons/bin.png similarity index 100% rename from user_config/usr/share/app_name/icons/bin.png rename to user_config/usr/share/newton_editor/icons/bin.png diff --git a/user_config/usr/share/app_name/icons/dir.png b/user_config/usr/share/newton_editor/icons/dir.png similarity index 100% rename from user_config/usr/share/app_name/icons/dir.png rename to user_config/usr/share/newton_editor/icons/dir.png diff --git a/user_config/usr/share/app_name/icons/doc.png b/user_config/usr/share/newton_editor/icons/doc.png similarity index 100% rename from user_config/usr/share/app_name/icons/doc.png rename to user_config/usr/share/newton_editor/icons/doc.png diff --git a/user_config/usr/share/app_name/icons/image.png b/user_config/usr/share/newton_editor/icons/image.png similarity index 100% rename from user_config/usr/share/app_name/icons/image.png rename to user_config/usr/share/newton_editor/icons/image.png diff --git a/user_config/usr/share/newton_editor/icons/newton_editor-64x64.png b/user_config/usr/share/newton_editor/icons/newton_editor-64x64.png new file mode 100644 index 0000000..acde84d Binary files /dev/null and b/user_config/usr/share/newton_editor/icons/newton_editor-64x64.png differ diff --git a/user_config/usr/share/newton_editor/icons/newton_editor.png b/user_config/usr/share/newton_editor/icons/newton_editor.png new file mode 100644 index 0000000..30ad12a Binary files /dev/null and b/user_config/usr/share/newton_editor/icons/newton_editor.png differ diff --git a/user_config/usr/share/app_name/icons/pdf.png b/user_config/usr/share/newton_editor/icons/pdf.png similarity index 100% rename from user_config/usr/share/app_name/icons/pdf.png rename to user_config/usr/share/newton_editor/icons/pdf.png diff --git a/user_config/usr/share/app_name/icons/presentation.png b/user_config/usr/share/newton_editor/icons/presentation.png similarity index 100% rename from user_config/usr/share/app_name/icons/presentation.png rename to user_config/usr/share/newton_editor/icons/presentation.png diff --git a/user_config/usr/share/app_name/icons/spreadsheet.png b/user_config/usr/share/newton_editor/icons/spreadsheet.png similarity index 100% rename from user_config/usr/share/app_name/icons/spreadsheet.png rename to user_config/usr/share/newton_editor/icons/spreadsheet.png diff --git a/user_config/usr/share/app_name/icons/text.png b/user_config/usr/share/newton_editor/icons/text.png similarity index 100% rename from user_config/usr/share/app_name/icons/text.png rename to user_config/usr/share/newton_editor/icons/text.png diff --git a/user_config/usr/share/app_name/icons/trash.png b/user_config/usr/share/newton_editor/icons/trash.png similarity index 100% rename from user_config/usr/share/app_name/icons/trash.png rename to user_config/usr/share/newton_editor/icons/trash.png diff --git a/user_config/usr/share/app_name/icons/video.png b/user_config/usr/share/newton_editor/icons/video.png similarity index 100% rename from user_config/usr/share/app_name/icons/video.png rename to user_config/usr/share/newton_editor/icons/video.png diff --git a/user_config/usr/share/app_name/icons/web.png b/user_config/usr/share/newton_editor/icons/web.png similarity index 100% rename from user_config/usr/share/app_name/icons/web.png rename to user_config/usr/share/newton_editor/icons/web.png diff --git a/user_config/usr/share/app_name/key-bindings.json b/user_config/usr/share/newton_editor/key-bindings.json similarity index 100% rename from user_config/usr/share/app_name/key-bindings.json rename to user_config/usr/share/newton_editor/key-bindings.json diff --git a/user_config/usr/share/app_name/settings.json b/user_config/usr/share/newton_editor/settings.json similarity index 100% rename from user_config/usr/share/app_name/settings.json rename to user_config/usr/share/newton_editor/settings.json diff --git a/user_config/usr/share/app_name/stylesheet.css b/user_config/usr/share/newton_editor/stylesheet.css similarity index 100% rename from user_config/usr/share/app_name/stylesheet.css rename to user_config/usr/share/newton_editor/stylesheet.css