Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
eepm-play-gui
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vladimir Vaskov
eepm-play-gui
Commits
1e760ee0
Commit
1e760ee0
authored
Sep 20, 2024
by
Roman Alifanov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
initial commit
parents
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
237 additions
and
0 deletions
+237
-0
eepm-play-gui
eepm-play-gui
+237
-0
No files found.
eepm-play-gui
0 → 100755
View file @
1e760ee0
#!/usr/bin/python3
import
sys
import
gi
import
subprocess
import
threading
gi
.
require_version
(
'Gtk'
,
'4.0'
)
gi
.
require_version
(
'Adw'
,
'1'
)
from
gi.repository
import
Gtk
,
Adw
,
GLib
class
CommandRunner
:
def
__init__
(
self
,
on_done
=
None
):
self
.
dialog
=
None
self
.
textbuffer
=
None
self
.
on_done
=
on_done
# Callback function to be called after completion
def
run_command
(
self
,
command
,
dialog
):
self
.
dialog
=
dialog
self
.
textbuffer
=
dialog
.
get_child
()
.
get_child
()
.
get_buffer
()
def
append_log
(
text
):
GLib
.
idle_add
(
self
.
textbuffer
.
insert_at_cursor
,
text
)
GLib
.
idle_add
(
dialog
.
get_child
()
.
get_child
()
.
scroll_to_mark
,
self
.
textbuffer
.
get_insert
(),
0
,
False
,
0.0
,
1.0
)
def
read_output
(
source
):
while
True
:
line
=
source
.
readline
()
if
line
:
GLib
.
idle_add
(
append_log
,
line
)
else
:
break
def
process_runner
():
try
:
process
=
subprocess
.
Popen
(
command
,
shell
=
True
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
text
=
True
)
threading
.
Thread
(
target
=
read_output
,
args
=
(
process
.
stdout
,))
.
start
()
threading
.
Thread
(
target
=
read_output
,
args
=
(
process
.
stderr
,))
.
start
()
process
.
wait
()
GLib
.
idle_add
(
dialog
.
close
)
if
self
.
on_done
:
GLib
.
idle_add
(
self
.
on_done
)
# Call the callback function after completion
except
subprocess
.
CalledProcessError
as
e
:
GLib
.
idle_add
(
append_log
,
f
"Ошибка: {str(e)}
\n
"
)
GLib
.
idle_add
(
dialog
.
close
)
if
self
.
on_done
:
GLib
.
idle_add
(
self
.
on_done
)
# Call the callback function after completion
threading
.
Thread
(
target
=
process_runner
)
.
start
()
class
ApplicationManager
:
@staticmethod
def
get_available_applications
():
output
=
subprocess
.
check_output
([
"epm"
,
"play"
,
"--list-all"
],
universal_newlines
=
True
)
return
ApplicationManager
.
parse_applications_output
(
output
)
@staticmethod
def
get_installed_applications
():
output
=
subprocess
.
check_output
([
"epm"
,
"play"
,
"--list"
],
universal_newlines
=
True
)
return
ApplicationManager
.
parse_installed_applications_output
(
output
)
@staticmethod
def
parse_applications_output
(
output
):
lines
=
output
.
splitlines
()[
1
:]
applications
=
[]
for
line
in
lines
:
parts
=
line
.
split
(
' - '
)
if
len
(
parts
)
==
2
:
# Ensure that line has exactly 2 parts
name
,
dscr
=
parts
applications
.
append
({
'name'
:
name
.
strip
()
.
replace
(
'&'
,
'&'
),
'dscr'
:
dscr
.
strip
()
.
replace
(
'&'
,
'&'
)})
return
applications
@staticmethod
def
parse_installed_applications_output
(
output
):
lines
=
output
.
splitlines
()[
1
:]
return
[
line
.
split
(
' - '
)[
0
]
.
strip
()
.
split
()[
0
]
for
line
in
lines
]
class
MainWindow
(
Gtk
.
ApplicationWindow
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_title
(
"eepm play gui"
)
self
.
set_default_size
(
400
,
600
)
# Инициализация основного контейнера
self
.
box1
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
)
self
.
set_child
(
self
.
box1
)
# Создание элементов UI
self
.
create_ui_elements
()
self
.
show_loading_message
()
self
.
load_applications
()
def
create_ui_elements
(
self
):
# Создание скролл-окна
self
.
scrolled_window
=
Gtk
.
ScrolledWindow
()
self
.
scrolled_window
.
set_vexpand
(
True
)
# Создание контейнера для содержимого и группы настроек
self
.
content_box
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
)
self
.
preferences_group
=
Adw
.
PreferencesGroup
()
self
.
content_box
.
append
(
self
.
preferences_group
)
# Добавление скролл-окна в основной контейнер
self
.
scrolled_window
.
set_child
(
self
.
content_box
)
self
.
box1
.
append
(
self
.
scrolled_window
)
# Кнопка применения
apply_button
=
Gtk
.
Button
(
label
=
"Применить"
)
apply_button
.
connect
(
"clicked"
,
self
.
on_apply_clicked
)
self
.
box1
.
append
(
apply_button
)
# Создание и добавление сообщения о загрузке
self
.
loading_label
=
Gtk
.
Label
(
label
=
"Загрузка, пожалуйста подождите..."
)
self
.
content_box
.
append
(
self
.
loading_label
)
self
.
loading_label
.
set_visible
(
False
)
# Изначально скрыта
def
show_loading_message
(
self
):
self
.
loading_label
.
set_visible
(
True
)
self
.
preferences_group
.
set_visible
(
False
)
# Скрыть группу настроек во время загрузки
def
hide_loading_message
(
self
):
self
.
loading_label
.
set_visible
(
False
)
self
.
preferences_group
.
set_visible
(
True
)
# Показать группу настроек после загрузки
def
load_applications
(
self
):
def
on_done
():
self
.
hide_loading_message
()
# Скрыть сообщение о загрузке, когда загрузка завершена
# Асинхронная загрузка приложений
GLib
.
idle_add
(
self
.
_load_applications_async
,
on_done
)
def
_load_applications_async
(
self
,
on_done
):
# Симуляция долгой операции
def
simulate_long_running_op
():
self
.
applications
=
ApplicationManager
.
get_available_applications
()
GLib
.
idle_add
(
self
.
update_ui
)
# Обновление UI с новыми данными
GLib
.
idle_add
(
on_done
)
threading
.
Thread
(
target
=
simulate_long_running_op
)
.
start
()
def
update_ui
(
self
):
# Обновление списка установленных приложений
self
.
installed_apps
=
ApplicationManager
.
get_installed_applications
()
# Удаление текущего preferences_group
if
self
.
preferences_group
:
self
.
content_box
.
remove
(
self
.
preferences_group
)
self
.
preferences_group
=
None
# Создание нового preferences_group
self
.
preferences_group
=
Adw
.
PreferencesGroup
()
self
.
content_box
.
append
(
self
.
preferences_group
)
# Добавление новых элементов
self
.
checkboxes
=
{}
for
app
in
self
.
applications
:
self
.
add_application_row
(
app
)
def
add_application_row
(
self
,
app
):
row
=
Adw
.
ActionRow
(
title
=
app
[
'name'
],
subtitle
=
app
[
'dscr'
])
checkbox
=
Gtk
.
CheckButton
()
checkbox
.
set_active
(
app
[
'name'
]
in
self
.
installed_apps
)
checkbox
.
connect
(
"toggled"
,
self
.
on_checkbox_toggled
,
app
[
'name'
])
row
.
add_suffix
(
checkbox
)
self
.
preferences_group
.
add
(
row
)
self
.
checkboxes
[
app
[
'name'
]]
=
checkbox
def
on_checkbox_toggled
(
self
,
checkbox
,
app_name
):
active
=
checkbox
.
get_active
()
print
(
f
"{app_name} {'установлен' if active else 'снят'}"
)
def
on_apply_clicked
(
self
,
button
):
self
.
show_loading_message
()
# Показать сообщение о загрузке перед выполнением команды
to_install
,
to_remove
=
self
.
get_install_remove_lists
()
commands
=
self
.
build_commands
(
to_install
,
to_remove
)
if
commands
:
full_command
=
" && "
.
join
(
commands
)
pkexec_command
=
f
'pkexec sh -c "{full_command}"'
self
.
show_log_dialog
(
pkexec_command
)
def
get_install_remove_lists
(
self
):
to_install
=
[
app_name
for
app_name
,
checkbox
in
self
.
checkboxes
.
items
()
if
checkbox
.
get_active
()
and
app_name
not
in
self
.
installed_apps
]
to_remove
=
[
app_name
for
app_name
,
checkbox
in
self
.
checkboxes
.
items
()
if
not
checkbox
.
get_active
()
and
app_name
in
self
.
installed_apps
]
return
to_install
,
to_remove
def
build_commands
(
self
,
to_install
,
to_remove
):
commands
=
[]
if
to_install
:
commands
.
append
(
f
"epm play --auto {' '.join(to_install)}"
)
if
to_remove
:
commands
.
append
(
f
"epm play --auto --remove {' '.join(to_remove)}"
)
return
commands
def
show_log_dialog
(
self
,
command
):
dialog
=
Gtk
.
Dialog
(
title
=
"Лог выполнения"
,
transient_for
=
self
,
modal
=
True
)
dialog
.
set_default_size
(
400
,
300
)
textview
=
Gtk
.
TextView
()
textview
.
set_editable
(
False
)
textbuffer
=
textview
.
get_buffer
()
scrolled_window
=
Gtk
.
ScrolledWindow
()
scrolled_window
.
set_child
(
textview
)
scrolled_window
.
set_vexpand
(
True
)
dialog
.
set_child
(
scrolled_window
)
dialog
.
present
()
# Создание и передача функции обратного вызова для обновления UI
runner
=
CommandRunner
(
on_done
=
self
.
update_ui_after_log
)
runner
.
run_command
(
command
,
dialog
)
def
update_ui_after_log
(
self
):
self
.
update_ui
()
# Обновление UI после закрытия диалога
self
.
hide_loading_message
()
# Скрыть сообщение о загрузке после закрытия диалога
class
MyApp
(
Adw
.
Application
):
def
__init__
(
self
,
**
kwargs
):
super
()
.
__init__
(
**
kwargs
)
self
.
connect
(
'activate'
,
self
.
on_activate
)
def
on_activate
(
self
,
app
):
self
.
win
=
MainWindow
(
application
=
app
)
self
.
win
.
present
()
if
__name__
==
"__main__"
:
app
=
MyApp
(
application_id
=
"com.example.GtkApplication"
)
app
.
run
(
sys
.
argv
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment