Rewrote a whole new dialog system cause I was bored
This commit is contained in:
@@ -86,6 +86,8 @@ class chat(Gtk.ScrolledWindow):
|
||||
self.stop_message()
|
||||
for widget in list(self.container):
|
||||
self.container.remove(widget)
|
||||
self.show_welcome_screen(len(window.model_manager.get_model_list()) > 0)
|
||||
print('clear chat for some reason')
|
||||
|
||||
def add_message(self, message_id:str, model:str=None):
|
||||
msg = message(message_id, model)
|
||||
@@ -102,7 +104,9 @@ class chat(Gtk.ScrolledWindow):
|
||||
if self.welcome_screen:
|
||||
self.container.remove(self.welcome_screen)
|
||||
self.welcome_screen = None
|
||||
self.clear_chat()
|
||||
if len(list(self.container)) > 0:
|
||||
self.clear_chat()
|
||||
return
|
||||
button_container = Gtk.Box(
|
||||
orientation=1,
|
||||
spacing=10,
|
||||
@@ -333,6 +337,8 @@ class chat_list(Gtk.ListBox):
|
||||
window.save_history()
|
||||
|
||||
def rename_chat(self, old_chat_name:str, new_chat_name:str):
|
||||
if new_chat_name == old_chat_name:
|
||||
return
|
||||
tab = self.get_tab_by_name(old_chat_name)
|
||||
if tab:
|
||||
new_chat_name = window.generate_numbered_name(new_chat_name, [tab.chat_window.get_name() for tab in self.tab_list])
|
||||
|
||||
173
src/custom_widgets/dialog_widget.py
Normal file
173
src/custom_widgets/dialog_widget.py
Normal file
@@ -0,0 +1,173 @@
|
||||
#dialog_widget.py
|
||||
"""
|
||||
Handles all dialogs
|
||||
"""
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '4.0')
|
||||
gi.require_version('GtkSource', '5')
|
||||
from gi.repository import Gtk, Gio, Adw, Gdk, GLib
|
||||
|
||||
window=None
|
||||
|
||||
button_appearance={
|
||||
'suggested': Adw.ResponseAppearance.SUGGESTED,
|
||||
'destructive': Adw.ResponseAppearance.DESTRUCTIVE
|
||||
}
|
||||
|
||||
# Don't call this directly outside this script
|
||||
class baseDialog(Adw.AlertDialog):
|
||||
__gtype_name__ = 'AlpacaDialogBase'
|
||||
|
||||
def __init__(self, heading:str, body:str, close_response:str, options:dict):
|
||||
self.options = options
|
||||
super().__init__(
|
||||
heading=heading,
|
||||
body=body,
|
||||
close_response=close_response
|
||||
)
|
||||
for option, data in self.options.items():
|
||||
self.add_response(option, option)
|
||||
if 'appearance' in data:
|
||||
self.set_response_appearance(option, button_appearance[data['appearance']])
|
||||
if 'default' in data and data['default']:
|
||||
self.set_default_response(option)
|
||||
|
||||
|
||||
class Options(baseDialog):
|
||||
__gtype_name__ = 'AlpacaDialogOptions'
|
||||
|
||||
def __init__(self, heading:str, body:str, close_response:str, options:dict):
|
||||
super().__init__(
|
||||
heading,
|
||||
body,
|
||||
close_response,
|
||||
options
|
||||
)
|
||||
self.choose(
|
||||
parent = window,
|
||||
cancellable = None,
|
||||
callback = self.response
|
||||
)
|
||||
|
||||
def response(self, dialog, task):
|
||||
result = dialog.choose_finish(task)
|
||||
if result in self.options and 'callback' in self.options[result]:
|
||||
self.options[result]['callback']()
|
||||
|
||||
class Entry(baseDialog):
|
||||
__gtype_name__ = 'AlpacaDialogEntry'
|
||||
|
||||
def __init__(self, heading:str, body:str, close_response:str, options:dict, entries:list or dict):
|
||||
super().__init__(
|
||||
heading,
|
||||
body,
|
||||
close_response,
|
||||
options
|
||||
)
|
||||
|
||||
self.container = Gtk.Box(
|
||||
orientation=1,
|
||||
spacing=10
|
||||
)
|
||||
|
||||
if isinstance(entries, dict):
|
||||
entries = [entries]
|
||||
|
||||
for data in entries:
|
||||
entry = Gtk.Entry()
|
||||
if 'placeholder' in data and data['placeholder']:
|
||||
entry.set_placeholder_text(data['placeholder'])
|
||||
if 'css' in data and data['css']:
|
||||
entry.set_css_classes(data['css'])
|
||||
if 'text' in data and data['text']:
|
||||
entry.set_text(data['text'])
|
||||
self.container.append(entry)
|
||||
|
||||
self.set_extra_child(self.container)
|
||||
|
||||
self.connect('realize', lambda *_: list(self.container)[0].grab_focus())
|
||||
self.choose(
|
||||
parent = window,
|
||||
cancellable = None,
|
||||
callback = self.response
|
||||
)
|
||||
|
||||
def response(self, dialog, task):
|
||||
result = dialog.choose_finish(task)
|
||||
if result in self.options and 'callback' in self.options[result]:
|
||||
entry_results = []
|
||||
for entry in list(self.container):
|
||||
entry_results.append(entry.get_text())
|
||||
self.options[result]['callback'](*entry_results)
|
||||
|
||||
class DropDown(baseDialog):
|
||||
__gtype_name__ = 'AlpacaDialogDropDown'
|
||||
|
||||
def __init__(self, heading:str, body:str, close_response:str, options:dict, items:list):
|
||||
super().__init__(
|
||||
heading,
|
||||
body,
|
||||
close_response,
|
||||
options
|
||||
)
|
||||
string_list = Gtk.StringList()
|
||||
for item in items:
|
||||
string_list.append(item)
|
||||
self.set_extra_child(Gtk.DropDown(
|
||||
enable_search=len(items) > 10,
|
||||
model=string_list
|
||||
))
|
||||
|
||||
self.connect('realize', lambda *_: self.get_extra_child().grab_focus())
|
||||
self.choose(
|
||||
parent = window,
|
||||
cancellable = None,
|
||||
callback = lambda dialog, task, dropdown=self.get_extra_child(): self.response(dialog, task, dropdown.get_selected_item().get_string())
|
||||
)
|
||||
|
||||
def response(self, dialog, task, item:str):
|
||||
result = dialog.choose_finish(task)
|
||||
if result in self.options and 'callback' in self.options[result]:
|
||||
self.options[result]['callback'](item)
|
||||
|
||||
def simple(heading:str, body:str, callback:callable, button_name:str=_('Accept'), button_appearance:str='suggested'):
|
||||
options = {
|
||||
_('Cancel'): {},
|
||||
button_name: {
|
||||
'appearance': button_appearance,
|
||||
'callback': callback,
|
||||
'default': True
|
||||
}
|
||||
}
|
||||
|
||||
return Options(heading, body, 'cancel', options)
|
||||
|
||||
def simple_entry(heading:str, body:str, callback:callable, entries:list or dict, button_name:str=_('Accept'), button_appearance:str='suggested'):
|
||||
options = {
|
||||
_('Cancel'): {},
|
||||
button_name: {
|
||||
'appearance': button_appearance,
|
||||
'callback': callback,
|
||||
'default': True
|
||||
}
|
||||
}
|
||||
|
||||
return Entry(heading, body, 'cancel', options, entries)
|
||||
|
||||
def simple_dropdown(heading:str, body:str, callback:callable, items:list, button_name:str=_('Accept'), button_appearance:str='suggested'):
|
||||
options = {
|
||||
_('Cancel'): {},
|
||||
button_name: {
|
||||
'appearance': button_appearance,
|
||||
'callback': callback,
|
||||
'default': True
|
||||
}
|
||||
}
|
||||
|
||||
return DropDown(heading, body, 'cancel', options, items)
|
||||
|
||||
def simple_file(file_filter:Gtk.FileFilter, callback:callable):
|
||||
file_dialog = Gtk.FileDialog(default_filter=file_filter)
|
||||
file_dialog.open(window, None, lambda file_dialog, result: callback(file_dialog.open_finish(result)) if result else None)
|
||||
|
||||
@@ -10,7 +10,7 @@ from gi.repository import Gtk, GObject, Gio, Adw, GtkSource, GLib, Gdk
|
||||
import logging, os, datetime, re, shutil, threading, sys
|
||||
from ..internal import config_dir, data_dir, cache_dir, source_dir
|
||||
from .table_widget import TableWidget
|
||||
from .. import dialogs
|
||||
from . import dialog_widget, terminal_widget
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -180,7 +180,13 @@ class code_block(Gtk.Box):
|
||||
logger.debug("Running script")
|
||||
start = self.buffer.get_start_iter()
|
||||
end = self.buffer.get_end_iter()
|
||||
dialogs.run_script(window, self.buffer.get_text(start, end, False), language_name)
|
||||
dialog_widget.simple(
|
||||
_('Run Script'),
|
||||
_('Make sure you understand what this script does before running it, Alpaca is not responsible for any damages to your device or data'),
|
||||
lambda script=self.buffer.get_text(start, end, False), language_name=language_name: terminal_widget.run_terminal(script, language_name),
|
||||
_('Execute'),
|
||||
'destructive'
|
||||
)
|
||||
|
||||
class attachment(Gtk.Button):
|
||||
__gtype_name__ = 'AlpacaAttachment'
|
||||
|
||||
@@ -10,6 +10,7 @@ from gi.repository import Gtk, GObject, Gio, Adw, GtkSource, GLib, Gdk
|
||||
import logging, os, datetime, re, shutil, threading, json, sys, glob
|
||||
from ..internal import config_dir, data_dir, cache_dir, source_dir
|
||||
from .. import available_models_descriptions, dialogs
|
||||
from . import dialog_widget
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -178,7 +179,7 @@ class pulling_model(Gtk.ListBoxRow):
|
||||
css_classes = ["error", "circular"],
|
||||
tooltip_text = _("Stop Pulling '{}'").format(window.convert_model_name(model_name, 0))
|
||||
)
|
||||
stop_button.connect('clicked', lambda *_: dialogs.stop_pull_model(window, self))
|
||||
stop_button.connect('clicked', lambda *i: dialog_widget.simple(_('Stop Download?'), _("Are you sure you want to stop pulling '{}'?").format(window.convert_model_name(self.get_name(), 0)), self.stop, _('Stop'), 'destructive'))
|
||||
|
||||
container_box = Gtk.Box(
|
||||
hexpand=True,
|
||||
@@ -201,6 +202,11 @@ class pulling_model(Gtk.ListBoxRow):
|
||||
self.error = None
|
||||
self.digests = []
|
||||
|
||||
def stop(self):
|
||||
if len(list(self.get_parent())) == 1:
|
||||
self.get_parent().set_visible(False)
|
||||
self.get_parent().remove(self)
|
||||
|
||||
def update(self, data):
|
||||
if 'digest' in data and data['digest'] not in self.digests:
|
||||
self.digests.append(data['digest'].replace(':', '-'))
|
||||
@@ -270,7 +276,8 @@ class local_model(Gtk.ListBoxRow):
|
||||
css_classes = ["error", "circular"],
|
||||
tooltip_text = _("Remove '{}'").format(window.convert_model_name(model_name, 0))
|
||||
)
|
||||
delete_button.connect('clicked', lambda *_, model_name=model_name: dialogs.delete_model(window, model_name))
|
||||
|
||||
delete_button.connect('clicked', lambda *i: dialog_widget.simple(_('Delete Model?'), _("Are you sure you want to delete '{}'?").format(model_title), lambda model_name=model_name: window.model_manager.remove_local_model(model_name), _('Delete'), 'destructive'))
|
||||
|
||||
container_box = Gtk.Box(
|
||||
hexpand=True,
|
||||
|
||||
@@ -7,6 +7,12 @@ import gi
|
||||
gi.require_version('Gtk', '4.0')
|
||||
gi.require_version('Vte', '3.91')
|
||||
from gi.repository import Gtk, Vte, GLib, Pango, GLib, Gdk
|
||||
import logging, os, shutil, subprocess
|
||||
from ..internal import data_dir
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
window = None
|
||||
|
||||
class terminal(Vte.Terminal):
|
||||
__gtype_name__ = 'AlpacaTerminal'
|
||||
@@ -42,3 +48,44 @@ class terminal(Vte.Terminal):
|
||||
self.copy_clipboard()
|
||||
return True
|
||||
return False
|
||||
|
||||
def show_terminal(script):
|
||||
window.terminal_scroller.set_child(terminal(script))
|
||||
window.terminal_dialog.present(window)
|
||||
|
||||
def run_terminal(script:str, language_name:str):
|
||||
logger.info('Running: \n{}'.format(language_name))
|
||||
if language_name == 'python3':
|
||||
if not os.path.isdir(os.path.join(data_dir, 'pyenv')):
|
||||
os.mkdir(os.path.join(data_dir, 'pyenv'))
|
||||
with open(os.path.join(data_dir, 'pyenv', 'main.py'), 'w') as f:
|
||||
f.write(script)
|
||||
script = [
|
||||
'echo "🐍 {}\n"'.format(_('Setting up Python environment...')),
|
||||
'python3 -m venv "{}"'.format(os.path.join(data_dir, 'pyenv')),
|
||||
'{} {}'.format(os.path.join(data_dir, 'pyenv', 'bin', 'python3').replace(' ', '\\ '), os.path.join(data_dir, 'pyenv', 'main.py').replace(' ', '\\ '))
|
||||
]
|
||||
if os.path.isfile(os.path.join(data_dir, 'pyenv', 'requirements.txt')):
|
||||
script.insert(1, '{} install -r {} | grep -v "already satisfied"; clear'.format(os.path.join(data_dir, 'pyenv', 'bin', 'pip3'), os.path.join(data_dir, 'pyenv', 'requirements.txt')))
|
||||
else:
|
||||
with open(os.path.join(data_dir, 'pyenv', 'requirements.txt'), 'w') as f:
|
||||
f.write('')
|
||||
script = ';\n'.join(script)
|
||||
|
||||
script += '; echo "\n🦙 {}"'.format(_('Script exited'))
|
||||
if language_name == 'bash':
|
||||
script = re.sub(r'(?m)^\s*sudo', 'pkexec', script)
|
||||
if shutil.which('flatpak-spawn') and language_name == 'bash':
|
||||
sandbox = True
|
||||
try:
|
||||
process = subprocess.run(['flatpak-spawn', '--host', 'bash', '-c', 'echo "test"'], check=True)
|
||||
sandbox = False
|
||||
except Exception as e:
|
||||
pass
|
||||
if sandbox:
|
||||
script = 'echo "🦙 {}\n";'.format(_('The script is contained inside Flatpak')) + script
|
||||
show_terminal(['bash', '-c', script])
|
||||
else:
|
||||
show_terminal(['flatpak-spawn', '--host', 'bash', '-c', script])
|
||||
else:
|
||||
show_terminal(['bash', '-c', script])
|
||||
|
||||
Reference in New Issue
Block a user