Commit 4d83504d authored by Roman Alifanov's avatar Roman Alifanov

errordialog implementation

parent f39332ca
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<file>style.css</file> <file>style.css</file>
<file preprocess="xml-stripblanks">window.ui</file> <file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">widgets/logdialog.ui</file> <file preprocess="xml-stripblanks">widgets/logdialog.ui</file>
<file preprocess="xml-stripblanks">widgets/errordialog.ui</file>
<file preprocess="xml-stripblanks">widgets/flagsdialog.ui</file> <file preprocess="xml-stripblanks">widgets/flagsdialog.ui</file>
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file> <file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
</gresource> </gresource>
......
...@@ -29,6 +29,7 @@ eepm_play_gui_widgets = [ ...@@ -29,6 +29,7 @@ eepm_play_gui_widgets = [
'__init__.py', '__init__.py',
'widgets/logdialog.py', 'widgets/logdialog.py',
'widgets/flagsdialog.py', 'widgets/flagsdialog.py',
'widgets/errordialog.py',
'widgets/applicationrow.py', 'widgets/applicationrow.py',
] ]
eepm_play_gui_tools = [ eepm_play_gui_tools = [
......
...@@ -83,6 +83,8 @@ class CommandRunner: ...@@ -83,6 +83,8 @@ class CommandRunner:
process = None process = None
sel = None sel = None
master_fd, slave_fd = pty.openpty() master_fd, slave_fd = pty.openpty()
error_message = None
try: try:
env = os.environ.copy() env = os.environ.copy()
env['TERM'] = 'xterm' env['TERM'] = 'xterm'
...@@ -107,13 +109,51 @@ class CommandRunner: ...@@ -107,13 +109,51 @@ class CommandRunner:
break break
finally: finally:
sel.unregister(master_fd) if sel:
sel.unregister(master_fd)
os.close(master_fd) os.close(master_fd)
process.wait() process.wait()
error_message = self.handle_exit_code(process)
# Close dialog and call on_done callback with full log in case of error
GLib.idle_add(self.dialog.force_close) GLib.idle_add(self.dialog.force_close)
if self.on_done: if self.on_done:
GLib.idle_add(self.on_done) # Call the callback function after completion GLib.idle_add(self.on_done, error_message)
def handle_exit_code(self, process):
error = None
match process.returncode:
case 0:
message = "Command completed successfully. Packages installed!"
print(message)
case 1:
error_message = "Command failed."
error = self.build_error_log()
print(error_message)
case 100:
error_message = "Command failed."
error = self.build_error_log()
print(error_message)
case 126:
error_message = "Action canceled by the user."
print(error_message)
case _:
error_message = f"Unknown exit code: {process.returncode}"
error = self.build_error_log()
print(error_message)
return error
def build_error_log(self):
start_iter = self.textbuffer.get_start_iter()
end_iter = self.textbuffer.get_end_iter()
error_message = self.textbuffer.get_text(start_iter, end_iter, True)
print(error_message)
return error_message
def run_command(self, command, on_done, dialog): def run_command(self, command, on_done, dialog):
self.dialog = dialog self.dialog = dialog
......
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<!DOCTYPE cambalache-project SYSTEM "cambalache-project.dtd">
<cambalache-project version="0.92.0" target_tk="gtk-4.0">
<ui>
(1,1,"logdialog.ui","errordialog.ui",None,None,None,None,None,None,None)
</ui>
<ui_library>
(1,"adwaita","1.0",None),
(1,"gtk","4.0",None),
(1,"libadwaita","1.5",None)
</ui_library>
<object>
(1,1,"AdwDialog","ErrorDialog",None,None,None,None,0,None,None),
(1,15,"AdwToolbarView",None,1,None,None,None,0,None,None),
(1,16,"AdwClamp",None,15,None,None,None,1,None,None),
(1,17,"GtkBox",None,16,None,None,None,0,None,None),
(1,18,"GtkScrolledWindow",None,17,None,None,None,0,None,None),
(1,19,"GtkTextView","textview",18,None,None,None,0,None,None),
(1,29,"AdwHeaderBar",None,15,None,"top",None,0,None,None),
(1,30,"AdwClamp",None,17,None,None,None,1,None,None),
(1,31,"GtkBox",None,30,None,None,None,0,None,None),
(1,32,"GtkLabel",None,31,None,None,None,0,None,None),
(1,33,"GtkBox",None,31,None,None,None,1,None,None),
(1,34,"GtkListBox",None,33,None,None,None,0,None,None),
(1,35,"AdwButtonRow","tg_button",34,None,None,None,0,None,None),
(1,36,"AdwButtonRow","gh_button",34,None,None,None,1,None,None)
</object>
<object_property>
(1,1,"AdwDialog","follows-content-size","true",0,None,None,None,None,None,None,None,None),
(1,1,"AdwDialog","title","Error detected",1,None,None,None,None,None,None,None,None),
(1,16,"AdwClamp","maximum-size","500",0,None,None,None,None,None,None,None,None),
(1,16,"GtkWidget","margin-bottom","12",0,None,None,None,None,None,None,None,None),
(1,16,"GtkWidget","margin-end","12",0,None,None,None,None,None,None,None,None),
(1,16,"GtkWidget","margin-start","12",0,None,None,None,None,None,None,None,None),
(1,16,"GtkWidget","margin-top","12",0,None,None,None,None,None,None,None,None),
(1,17,"GtkBox","spacing","12",0,None,None,None,None,None,None,None,None),
(1,17,"GtkOrientable","orientation","vertical",0,None,None,None,None,None,None,None,None),
(1,18,"GtkScrolledWindow","hscrollbar-policy","never",0,None,None,None,None,None,None,None,None),
(1,18,"GtkWidget","height-request","300",0,None,None,None,None,None,None,None,None),
(1,18,"GtkWidget","vexpand","true",0,None,None,None,None,None,None,None,None),
(1,18,"GtkWidget","width-request","198",0,None,None,None,None,None,None,None,None),
(1,19,"GtkTextView","wrap-mode","word-char",None,None,None,None,None,None,None,None,None),
(1,30,"GtkWidget","margin-bottom","12",0,None,None,None,None,None,None,None,None),
(1,30,"GtkWidget","margin-end","12",0,None,None,None,None,None,None,None,None),
(1,30,"GtkWidget","margin-start","12",0,None,None,None,None,None,None,None,None),
(1,30,"GtkWidget","margin-top","12",0,None,None,None,None,None,None,None,None),
(1,31,"GtkOrientable","orientation","vertical",0,None,None,None,None,None,None,None,None),
(1,32,"GtkLabel","justify","center",0,None,None,None,None,None,None,None,None),
(1,32,"GtkLabel","label","You can contact us with this problem",1,None,None,None,None,None,None,None,None),
(1,32,"GtkLabel","wrap","True",0,None,None,None,None,None,None,None,None),
(1,32,"GtkLabel","wrap-mode","word-char",0,None,None,None,None,None,None,None,None),
(1,32,"GtkWidget","halign","center",0,None,None,None,None,None,None,None,None),
(1,32,"GtkWidget","margin-bottom","12",0,None,None,None,None,None,None,None,None),
(1,32,"GtkWidget","valign","center",0,None,None,None,None,None,None,None,None),
(1,33,"GtkBox","spacing","12",0,None,None,None,None,None,None,None,None),
(1,34,"GtkWidget","hexpand","True",0,None,None,None,None,None,None,None,None),
(1,35,"AdwButtonRow","end-icon-name","help-about-symbolic",0,None,None,None,None,None,None,None,None),
(1,35,"AdwPreferencesRow","title","Copy the log and go to the telegram chat",None,None,None,None,None,None,None,None,None),
(1,36,"AdwButtonRow","end-icon-name","help-about-symbolic",0,None,None,None,None,None,None,None,None),
(1,36,"AdwPreferencesRow","title","Copy the log and сreate an issue on github",0,None,None,None,None,None,None,None,None)
</object_property>
<object_data>
(1,32,"GtkWidget",1,1,None,None,None,None,None,None),
(1,32,"GtkWidget",2,2,None,1,None,None,None,None),
(1,35,"GtkWidget",1,1,None,None,None,None,None,None),
(1,36,"GtkWidget",1,1,None,None,None,None,None,None),
(1,34,"GtkWidget",1,1,None,None,None,None,None,None),
(1,34,"GtkWidget",2,2,None,1,None,None,None,None)
</object_data>
<object_data_arg>
(1,32,"GtkWidget",2,2,"name","title-4"),
(1,34,"GtkWidget",2,2,"name","boxed-list-separate")
</object_data_arg>
</cambalache-project>
import webbrowser
from gi.repository import Gtk, GLib, Gdk, Adw
@Gtk.Template(resource_path='/ru/eepm/PlayGUI/widgets/errordialog.ui')
class ErrorDialog(Adw.Dialog):
__gtype_name__ = 'ErrorDialog'
textview = Gtk.Template.Child()
tg_button = Gtk.Template.Child()
gh_button = Gtk.Template.Child()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.textbuffer = self.textview.get_buffer()
self.error = None
self.tg_button.connect("activated", self.on_tg_clicked)
self.gh_button.connect("activated", self.on_gh_clicked)
def append_log(self, text):
GLib.idle_add(self.textbuffer.insert_at_cursor, text)
GLib.idle_add(self.textview.scroll_to_mark,
self.textbuffer.get_insert(), 0, False, 0.0, 1.0)
def present_error(self, win, error):
self.error = error
self.append_log(error)
self.present(win)
def copy_error(self):
display = Gdk.Display.get_default()
clipboard = display.get_clipboard()
clipboard.set(self.error)
def on_tg_clicked(self, button):
self.copy_error()
webbrowser.open("https://t.me/useepm")
def on_gh_clicked(self, button):
self.copy_error()
webbrowser.open("https://github.com/Etersoft/eepm/issues")
\ No newline at end of file
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.92.1 -->
<interface>
<!-- interface-name logdialog.ui -->
<requires lib="adwaita" version="1.0"/>
<requires lib="gtk" version="4.0"/>
<requires lib="libadwaita" version="1.5"/>
<template class="ErrorDialog" parent="AdwDialog">
<property name="follows-content-size">true</property>
<property name="title" translatable="yes">Error detected</property>
<child>
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<child>
<object class="AdwClamp">
<property name="margin-bottom">12</property>
<property name="margin-end">12</property>
<property name="margin-start">12</property>
<property name="margin-top">12</property>
<property name="maximum-size">500</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkScrolledWindow">
<property name="height-request">300</property>
<property name="hscrollbar-policy">never</property>
<property name="vexpand">true</property>
<property name="width-request">198</property>
<child>
<object class="GtkTextView" id="textview">
<property name="wrap-mode">word-char</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwClamp">
<property name="margin-bottom">12</property>
<property name="margin-end">12</property>
<property name="margin-start">12</property>
<property name="margin-top">12</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="halign">center</property>
<property name="justify">center</property>
<property name="label" translatable="yes">You can contact us with this problem</property>
<property name="margin-bottom">12</property>
<property name="valign">center</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<style>
<class name="title-4"/>
</style>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">12</property>
<child>
<object class="GtkListBox">
<property name="hexpand">True</property>
<child>
<object class="AdwButtonRow" id="tg_button">
<property name="end-icon-name">help-about-symbolic</property>
<property name="title">Copy the log and go to the telegram chat</property>
<style/>
</object>
</child>
<child>
<object class="AdwButtonRow" id="gh_button">
<property name="end-icon-name">help-about-symbolic</property>
<property name="title">Copy the log and сreate an issue on github</property>
<style/>
</object>
</child>
<style>
<class name="boxed-list-separate"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>
...@@ -23,6 +23,7 @@ import gettext ...@@ -23,6 +23,7 @@ import gettext
from .widgets.applicationrow import ApplicationRow from .widgets.applicationrow import ApplicationRow
from .widgets.logdialog import LogDialog from .widgets.logdialog import LogDialog
from .widgets.errordialog import ErrorDialog
from .widgets.flagsdialog import FlagsDialog from .widgets.flagsdialog import FlagsDialog
gettext.textdomain('eepm-play-gui') gettext.textdomain('eepm-play-gui')
...@@ -58,6 +59,8 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow): ...@@ -58,6 +59,8 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow):
self.apply_button.connect("activated", self.on_apply_clicked) self.apply_button.connect("activated", self.on_apply_clicked)
self.errordialog = ErrorDialog()
self.flagsdialog = FlagsDialog() self.flagsdialog = FlagsDialog()
self.flags_button.connect("clicked", lambda _: self.flagsdialog.present(self)) self.flags_button.connect("clicked", lambda _: self.flagsdialog.present(self))
...@@ -198,6 +201,12 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow): ...@@ -198,6 +201,12 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow):
else: else:
return matches_search # All return matches_search # All
def on_logdialog_closed(self, error=None):
if error:
self.errordialog.present_error(self, error)
else:
self.update_ui()
def on_apply_clicked(self, button): def on_apply_clicked(self, button):
self.props.is_loading = True # Show loading message before command execution self.props.is_loading = True # Show loading message before command execution
...@@ -206,7 +215,7 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow): ...@@ -206,7 +215,7 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow):
if full_command: if full_command:
pkexec_command = f'pkexec sh -c "{full_command}"' pkexec_command = f'pkexec sh -c "{full_command}"'
self.logdialog.run(pkexec_command, on_done=self.update_ui) self.logdialog.run(pkexec_command, on_done=self.on_logdialog_closed)
else: else:
self.logdialog.run(self.flagsdialog.apply_flags( self.logdialog.run(self.flagsdialog.apply_flags(
"epm play", "epm play",
...@@ -215,7 +224,7 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow): ...@@ -215,7 +224,7 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow):
"--force", "--force",
] ]
), ),
on_done=self.update_ui on_done=self.on_logdialog_closed
) )
def get_install_remove_lists(self): def get_install_remove_lists(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment