Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
tuneit
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
Ximper Linux
tuneit
Commits
e16823cd
Commit
e16823cd
authored
Jan 13, 2025
by
Anton Palgunov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: Shop initial work
parent
e9694e8c
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
589 additions
and
1 deletion
+589
-1
ru.ximperlinux.TuteIt.json
ru.ximperlinux.TuteIt.json
+34
-0
__init__.py
src/shop/__init__.py
+431
-0
repository.py
src/shop/models/repository.py
+23
-0
github_service.py
src/shop/services/github_service.py
+21
-0
gitlab_service.py
src/shop/services/gitlab_service.py
+21
-0
other_platform_service.py
src/shop/services/other_platform_service.py
+20
-0
window.blp
src/window.blp
+32
-1
window.py
src/window.py
+7
-0
No files found.
ru.ximperlinux.TuteIt.json
View file @
e16823cd
...
...
@@ -36,6 +36,40 @@
]
},
{
"name"
:
"python3-requests"
,
"buildsystem"
:
"simple"
,
"build-commands"
:
[
"pip3 install --verbose --exists-action=i --no-index --find-links=
\"
file://${PWD}
\"
--prefix=${FLATPAK_DEST}
\"
requests==2.32.2
\"
--no-build-isolation"
],
"sources"
:
[
{
"type"
:
"file"
,
"url"
:
"https://files.pythonhosted.org/packages/1c/d5/c84e1a17bf61d4df64ca866a1c9a913874b4e9bdc131ec689a0ad013fb36/certifi-2024.7.4-py3-none-any.whl"
,
"sha256"
:
"c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"
},
{
"type"
:
"file"
,
"url"
:
"https://files.pythonhosted.org/packages/63/09/c1bc53dab74b1816a00d8d030de5bf98f724c52c1635e07681d312f20be8/charset-normalizer-3.3.2.tar.gz"
,
"sha256"
:
"f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"
},
{
"type"
:
"file"
,
"url"
:
"https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl"
,
"sha256"
:
"82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"
},
{
"type"
:
"file"
,
"url"
:
"https://files.pythonhosted.org/packages/c3/20/748e38b466e0819491f0ce6e90ebe4184966ee304fe483e2c414b0f4ef07/requests-2.32.2-py3-none-any.whl"
,
"sha256"
:
"fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"
},
{
"type"
:
"file"
,
"url"
:
"https://files.pythonhosted.org/packages/ca/1c/89ffc63a9605b583d5df2be791a27bc1a42b7c32bab68d3c8f2f73a98cd4/urllib3-2.2.2-py3-none-any.whl"
,
"sha256"
:
"a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"
}
]
},
{
"name"
:
"python3-docutils"
,
"buildsystem"
:
"simple"
,
"build-commands"
:
[
...
...
src/shop/__init__.py
0 → 100644
View file @
e16823cd
import
os
import
shutil
import
tempfile
import
threading
import
requests
import
time
import
yaml
import
gi
gi
.
require_version
(
"Gtk"
,
"4.0"
)
gi
.
require_version
(
"Adw"
,
"1"
)
from
gi.repository
import
Gtk
,
Adw
,
Gdk
,
GObject
,
GLib
## ToDo: Унести это в адаптеры для работы с API
GITHUB_API_URL
=
"https://api.github.com/search/repositories"
GITLAB_API_URL
=
"https://gitlab.com/api/v4/projects"
CACHE_DIR
=
os
.
path
.
join
(
os
.
path
.
expanduser
(
"~"
),
".cache"
,
"tuneit_shop"
)
if
not
os
.
path
.
exists
(
CACHE_DIR
):
os
.
makedirs
(
CACHE_DIR
,
exist_ok
=
True
)
MODULES_DIR
=
os
.
path
.
join
(
os
.
path
.
expanduser
(
"~"
),
".local"
,
"share"
,
"tuneit"
,
"modules"
)
if
not
os
.
path
.
exists
(
MODULES_DIR
):
os
.
makedirs
(
MODULES_DIR
,
exist_ok
=
True
)
###############################################################################
# Работа с репами и кеш
###############################################################################
def
load_from_cache
():
cache_file
=
os
.
path
.
join
(
CACHE_DIR
,
"modules_cache.json"
)
if
not
os
.
path
.
exists
(
cache_file
):
return
None
,
0
with
open
(
cache_file
,
"r"
,
encoding
=
"utf-8"
)
as
f
:
import
json
data
=
json
.
load
(
f
)
return
data
[
"repos"
],
data
[
"last_update"
]
def
save_to_cache
(
repos
):
cache_file
=
os
.
path
.
join
(
CACHE_DIR
,
"modules_cache.json"
)
with
open
(
cache_file
,
"w"
,
encoding
=
"utf-8"
)
as
f
:
import
json
json
.
dump
({
"last_update"
:
int
(
time
.
time
()),
"repos"
:
repos
},
f
,
ensure_ascii
=
False
,
indent
=
2
)
def
fetch_repos_from_github
(
search_query
,
page
=
1
,
per_page
=
30
):
# Пример https://api.github.com/search/repositories?q=tuneit-mod+in:name
params
=
{
"q"
:
search_query
+
" in:name"
,
"sort"
:
"stars"
,
"order"
:
"desc"
,
"page"
:
page
,
"per_page"
:
per_page
}
r
=
requests
.
get
(
GITHUB_API_URL
,
params
=
params
,
timeout
=
10
)
r
.
raise_for_status
()
data
=
r
.
json
()
return
data
.
get
(
"items"
,
[])
def
fetch_repos_from_gitlab
(
search_query
,
page
=
1
,
per_page
=
30
):
# Пример https://gitlab.com/api/v4/projects?search=tuneit-mod
params
=
{
"search"
:
search_query
,
"order_by"
:
"star_count"
,
"sort"
:
"desc"
,
"page"
:
page
,
"per_page"
:
per_page
}
r
=
requests
.
get
(
GITLAB_API_URL
,
params
=
params
,
timeout
=
10
)
r
.
raise_for_status
()
data
=
r
.
json
()
return
data
def
parse_module_yaml
(
raw_url
):
try
:
r
=
requests
.
get
(
raw_url
,
timeout
=
10
)
r
.
raise_for_status
()
return
yaml
.
safe_load
(
r
.
text
)
except
:
return
None
def
retrieve_modules_full_list
(
force_refresh
=
False
,
initial_page
=
1
,
per_page
=
30
):
"""
Реализует загрузку и логику суточного кеша
"""
# 1. Проверяем кеш
cached_repos
,
last_update
=
load_from_cache
()
day_in_seconds
=
24
*
60
*
60
now
=
int
(
time
.
time
())
# 2. Если кеш валиден и нет force_refresh
if
(
cached_repos
is
not
None
)
and
(
not
force_refresh
)
and
(
now
-
last_update
<
day_in_seconds
):
return
cached_repos
# 3. Иначе загружаем данные
aggregated_repos
=
[]
# GitHub
github_items
=
fetch_repos_from_github
(
"tuneit-mod"
,
page
=
initial_page
,
per_page
=
per_page
)
for
item
in
github_items
:
# Проверяем, что репозиторий (item["name"]) действительно начинается с tuneit-mod
if
not
item
[
"name"
]
.
startswith
(
"tuneit-mod"
):
continue
# Пробуем скачать module.yaml
print
(
item
)
raw_url
=
f
"https://raw.githubusercontent.com/{item['owner']['login']}/{item['name']}/{item['default_branch']}/module.yaml"
module_info
=
parse_module_yaml
(
raw_url
)
aggregated_repos
.
append
({
"source"
:
"github"
,
"repo_name"
:
item
[
"name"
],
"repo_full_name"
:
item
[
"full_name"
],
"stars"
:
item
[
"stargazers_count"
],
"branch"
:
item
[
"default_branch"
],
"description"
:
item
[
"description"
]
or
""
,
"html_url"
:
item
[
"html_url"
],
"star_url"
:
item
[
"html_url"
]
+
"/stargazers"
,
"module_yaml"
:
module_info
})
# GitLab
gitlab_items
=
fetch_repos_from_gitlab
(
"tuneit-mod"
,
page
=
initial_page
,
per_page
=
per_page
)
for
item
in
gitlab_items
:
if
not
item
[
"name"
]
.
startswith
(
"tuneit-mod"
):
continue
# Пробуем скачать module.yaml
namespace_and_repo
=
item
[
"path_with_namespace"
]
# "username/reponame"
raw_url
=
f
"https://gitlab.com/{namespace_and_repo}/-/raw/{item['default_branch']}/module.yaml"
module_info
=
parse_module_yaml
(
raw_url
)
aggregated_repos
.
append
({
"source"
:
"gitlab"
,
"repo_name"
:
item
[
"name"
],
"repo_full_name"
:
namespace_and_repo
,
"branch"
:
item
[
"default_branch"
],
"stars"
:
item
[
"star_count"
],
"description"
:
item
[
"description"
]
or
""
,
"html_url"
:
item
[
"web_url"
],
"star_url"
:
item
[
"web_url"
]
+
"/-/starrers"
,
"module_yaml"
:
module_info
})
# Сохраняем в кеш
save_to_cache
(
aggregated_repos
)
return
aggregated_repos
###############################################################################
# Логика UI
###############################################################################
def
download_and_install_repo
(
source
,
repo_full_name
,
repo_name
,
branch
):
"""
Скачивает ZIP-архив репозитория и распаковывает его
в папку ~/.local/share/tuneit/modules/<repo_name>.
"""
if
source
==
"github"
:
url
=
f
"https://github.com/{repo_full_name}/archive/refs/heads/{branch}.zip"
else
:
# GitLab:
url
=
f
"https://gitlab.com/{repo_full_name}/-/archive/{branch}/{repo_name}.zip"
# Временная папка
tmp_dir
=
tempfile
.
mkdtemp
()
zip_path
=
os
.
path
.
join
(
tmp_dir
,
f
"{repo_name}.zip"
)
try
:
r
=
requests
.
get
(
url
,
stream
=
True
)
r
.
raise_for_status
()
with
open
(
zip_path
,
"wb"
)
as
f
:
for
chunk
in
r
.
iter_content
(
chunk_size
=
8192
):
f
.
write
(
chunk
)
# Распакуем zip
import
zipfile
with
zipfile
.
ZipFile
(
zip_path
,
"r"
)
as
zip_ref
:
zip_ref
.
extractall
(
tmp_dir
)
# Найдём распакованную папку вида <repo_name>-main или что-то вроде
extracted_dirs
=
[
d
for
d
in
os
.
listdir
(
tmp_dir
)
if
os
.
path
.
isdir
(
os
.
path
.
join
(
tmp_dir
,
d
))
and
d
.
startswith
(
repo_name
)]
if
extracted_dirs
:
extracted_path
=
os
.
path
.
join
(
tmp_dir
,
extracted_dirs
[
0
])
# Создаём папку назначения
dest_path
=
os
.
path
.
join
(
MODULES_DIR
,
repo_name
)
# Если уже была папка, удалим её
if
os
.
path
.
exists
(
dest_path
):
shutil
.
rmtree
(
dest_path
)
shutil
.
move
(
extracted_path
,
dest_path
)
finally
:
shutil
.
rmtree
(
tmp_dir
,
ignore_errors
=
True
)
###############################################################################
# Виджет “карточка” модуля
###############################################################################
class
ModuleCard
(
Gtk
.
Box
):
"""
Отображает карточку модуля.
"""
__gtype_name__
=
"ModuleCard"
def
__init__
(
self
,
module_data
):
super
()
.
__init__
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
,
spacing
=
6
)
self
.
module_data
=
module_data
# Настраиваем стили и отступы
self
.
set_margin_top
(
12
)
self
.
set_margin_bottom
(
12
)
self
.
set_margin_start
(
12
)
self
.
set_margin_end
(
12
)
# Фрейм или карточка
frame
=
Gtk
.
Frame
()
frame
.
set_margin_top
(
6
)
frame
.
set_margin_bottom
(
6
)
frame
.
set_margin_start
(
6
)
frame
.
set_margin_end
(
6
)
self
.
append
(
frame
)
card_box
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
,
spacing
=
6
)
card_box
.
set_margin_top
(
6
)
card_box
.
set_margin_bottom
(
6
)
card_box
.
set_margin_start
(
6
)
card_box
.
set_margin_end
(
6
)
frame
.
set_child
(
card_box
)
# Обложка (cover)
cover_url
=
""
if
module_data
[
"module_yaml"
]:
cover_url
=
module_data
[
"module_yaml"
]
.
get
(
"cover"
,
""
)
if
cover_url
:
# TODO: Загрузка обложки
try
:
texture
=
Gdk
.
Texture
.
new_for_uri
(
cover_url
)
cover_image
=
Gtk
.
Image
.
new_from_paintable
(
texture
)
cover_image
.
set_size_request
(
200
,
150
)
# 800x600 – размер обложки
card_box
.
append
(
cover_image
)
except
:
pass
title_label
=
Gtk
.
Label
()
if
module_data
[
"module_yaml"
]
and
module_data
[
"module_yaml"
]
.
get
(
"name"
):
title_label
.
set_label
(
module_data
[
"module_yaml"
][
"name"
])
else
:
title_label
.
set_label
(
module_data
[
"repo_name"
])
title_label
.
set_xalign
(
0.0
)
title_label
.
set_markup
(
f
"<b>{title_label.get_label()}</b>"
)
card_box
.
append
(
title_label
)
# Описание
desc_label
=
Gtk
.
Label
()
desc_label
.
set_xalign
(
0.0
)
desc_label
.
set_wrap
(
True
)
if
module_data
[
"module_yaml"
]
and
module_data
[
"module_yaml"
]
.
get
(
"description"
):
desc_label
.
set_text
(
module_data
[
"module_yaml"
][
"description"
])
else
:
desc_label
.
set_text
(
module_data
.
get
(
"description"
,
""
))
card_box
.
append
(
desc_label
)
# Кол-во звёзд
stars_label
=
Gtk
.
Label
()
stars_label
.
set_xalign
(
0.0
)
stars_label
.
set_text
(
f
"Stars: {module_data['stars']}"
)
card_box
.
append
(
stars_label
)
# Кнопка “Установить”
install_button
=
Gtk
.
Button
(
label
=
"Установить"
)
install_button
.
connect
(
"clicked"
,
self
.
on_install_clicked
)
card_box
.
append
(
install_button
)
# Ссылка на репозиторий
link_repo_button
=
Gtk
.
LinkButton
.
new_with_label
(
module_data
[
"html_url"
],
"Открыть репозиторий"
)
card_box
.
append
(
link_repo_button
)
def
on_install_clicked
(
self
,
button
):
"""Обработчик нажатия “Установить”. Запускает скачивание и установку в другом потоке."""
def
worker
():
download_and_install_repo
(
self
.
module_data
[
"source"
],
self
.
module_data
[
"repo_full_name"
],
self
.
module_data
[
"repo_name"
],
self
.
module_data
[
"branch"
]
)
# TODO: Показать уведомление в UI, что установка завершена
threading
.
Thread
(
target
=
worker
,
daemon
=
True
)
.
start
()
###############################################################################
# Инициализация Shop Stack
###############################################################################
def
init_shop_stack
(
shop_pagestack
,
shop_listbox
,
shop_split_view
):
"""
Инициализация стека страницы “Магазин”.
"""
refresh_button
=
Gtk
.
Button
(
label
=
"Принудительно обновить список"
)
refresh_button
.
connect
(
"clicked"
,
on_refresh_button_clicked
)
# Индикатор загрузки
spinner
=
Gtk
.
Spinner
()
spinner
.
set_size_request
(
24
,
24
)
# В боксе горизонтально разместим кнопку и спиннер
hbox_top
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
HORIZONTAL
,
spacing
=
6
)
hbox_top
.
append
(
refresh_button
)
hbox_top
.
append
(
spinner
)
# Создадим FlowBox для карточек, по 3 в ряд
flowbox
=
Gtk
.
FlowBox
()
flowbox
.
set_vexpand
(
True
)
# Растянем по вертикали
flowbox
.
set_min_children_per_line
(
3
)
flowbox
.
set_max_children_per_line
(
3
)
flowbox
.
set_selection_mode
(
Gtk
.
SelectionMode
.
NONE
)
# Включим только вертикальный scroller
scroller
=
Gtk
.
ScrolledWindow
()
scroller
.
set_child
(
flowbox
)
# Содержимое страницы
vbox_main
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
,
spacing
=
6
)
vbox_main
.
append
(
hbox_top
)
vbox_main
.
append
(
scroller
)
# Показываем в стеке
shop_pagestack
.
add_child
(
vbox_main
)
# TODO: Вынести это отсюда
shop_pagestack
.
_flowbox
=
flowbox
shop_pagestack
.
_spinner
=
spinner
shop_pagestack
.
_current_page
=
1
shop_pagestack
.
_per_page
=
6
shop_pagestack
.
_all_data
=
[]
shop_pagestack
.
_loading
=
False
shop_pagestack
.
_all_loaded
=
False
# Подключим сигнал прокрутки для ленивой подгрузки (пагинации)
scroller
.
connect
(
"edge-reached"
,
on_edge_reached
)
# Начальная загрузка данных
def
load_data_initial
():
load_data
(
shop_pagestack
,
force_refresh
=
False
,
page
=
1
)
GLib
.
idle_add
(
load_data_initial
)
def
on_refresh_button_clicked
(
button
):
"""Обработчик нажатия кнопки “Принудительно обновить список”."""
split_view
=
button
.
get_ancestor
(
Gtk
.
Widget
)
while
split_view
and
not
hasattr
(
split_view
,
"_flowbox"
):
split_view
=
split_view
.
get_parent
()
if
not
split_view
:
return
load_data
(
split_view
,
force_refresh
=
True
,
page
=
1
)
def
on_edge_reached
(
scrolled_window
,
pos
):
"""
edge-reached срабатывает, когда прокрутка достигает края
"""
if
pos
==
Gtk
.
PositionType
.
BOTTOM
:
load_next_page
(
scrolled_window
)
def
load_next_page
(
split_view
):
"""Загружает следующую страницу"""
if
split_view
.
_all_loaded
:
return
if
split_view
.
_loading
:
return
next_page
=
split_view
.
_current_page
+
1
load_data
(
split_view
,
force_refresh
=
False
,
page
=
next_page
)
def
load_data
(
split_view
,
force_refresh
=
False
,
page
=
1
):
"""
Загружает данные.
Если force_refresh=True, то сбрасывает всё и грузит заново.
"""
if
split_view
.
_loading
:
return
split_view
.
_loading
=
True
split_view
.
_spinner
.
start
()
# TODO: Не работает на мета информации, передалать
# Если это новая загрузка (page=1 или force_refresh), чистим flowbox и список
# if page == 1 or force_refresh:
# split_view._flowbox.foreach(lambda child: split_view._flowbox.remove(child))
# split_view._all_data = []
# split_view._all_loaded = False
def
worker
():
try
:
repos
=
retrieve_modules_full_list
(
force_refresh
=
force_refresh
,
initial_page
=
page
,
per_page
=
split_view
.
_per_page
)
except
Exception
as
e
:
repos
=
[]
# Имитируем, что мы действительно получили только часть данных:
start_idx
=
(
page
-
1
)
*
split_view
.
_per_page
end_idx
=
start_idx
+
split_view
.
_per_page
page_data
=
repos
[
start_idx
:
end_idx
]
# Если page_data меньше per_page, значит всё
if
len
(
page_data
)
<
split_view
.
_per_page
:
split_view
.
_all_loaded
=
True
# Дополняем общий список
split_view
.
_all_data
.
extend
(
page_data
)
# Обновляем UI в основном потоке
def
update_ui
():
for
repo
in
page_data
:
card
=
ModuleCard
(
repo
)
split_view
.
_flowbox
.
insert
(
card
,
-
1
)
split_view
.
_current_page
=
page
split_view
.
_spinner
.
stop
()
split_view
.
_loading
=
False
return
False
# чтобы GLib.idle_add один раз выполнилось
GLib
.
idle_add
(
update_ui
)
threading
.
Thread
(
target
=
worker
,
daemon
=
True
)
.
start
()
src/shop/models/repository.py
0 → 100644
View file @
e16823cd
class
Repository
:
def
__init__
(
self
,
name
,
description
,
url
):
self
.
name
=
name
self
.
description
=
description
self
.
url
=
url
def
display_info
(
self
):
return
{
"Name"
:
self
.
name
,
"Description"
:
self
.
description
,
"URL"
:
self
.
url
# "source": "github",
# "repo_name": item["name"],
# "repo_full_name": item["full_name"],
# "stars": item["stargazers_count"],
# "branch": item["default_branch"],
# "description": item["description"] or "",
# "html_url": item["html_url"],
# "star_url": item["html_url"] + "/stargazers",
# "module_yaml": module_info
}
\ No newline at end of file
src/shop/services/github_service.py
0 → 100644
View file @
e16823cd
class
GitHubService
:
def
__init__
(
self
,
base_url
=
"https://api.github.com"
):
self
.
base_url
=
base_url
def
search_repositories
(
self
,
query
):
# Logic to search repositories
pass
def
fetch_repository_data
(
self
,
repo_id
):
# Logic to fetch detailed repository data
pass
def
parse_results
(
self
,
results
):
# Logic to parse the results from the API response
pass
def
download_module
(
self
,
repo
):
# Download zip file from the repository
pass
\ No newline at end of file
src/shop/services/gitlab_service.py
0 → 100644
View file @
e16823cd
class
GitLabService
:
def
__init__
(
self
,
base_url
=
"https://gitlab.com/api/v4"
):
self
.
base_url
=
base_url
def
search_repositories
(
self
,
query
):
# Logic to search repositories
pass
def
fetch_repository_data
(
self
,
repo_id
):
# Logic to fetch detailed repository data
pass
def
parse_results
(
self
,
results
):
# Logic to parse the results from the API response
pass
def
download_module
(
self
,
repo
):
# Download zip file from the repository
pass
\ No newline at end of file
src/shop/services/other_platform_service.py
0 → 100644
View file @
e16823cd
class
PlatformService
:
def
__init__
(
self
,
base_url
):
self
.
base_url
=
base_url
def
search_repositories
(
self
,
query
):
# Logic to search repositories
pass
def
fetch_repository_data
(
self
,
repo_id
):
# Logic to fetch detailed repository data
pass
def
parse_results
(
self
,
results
):
# Logic to parse the results from the API response
pass
def
download_module
(
self
,
repo
):
# Download zip file from the repository
pass
\ No newline at end of file
src/window.blp
View file @
e16823cd
...
...
@@ -73,7 +73,38 @@ template $TuneitWindow: Adw.ApplicationWindow {
}
Adw.ViewStackPage {
child: Box {};
child: Box {
Adw.NavigationSplitView shop_split_view {
hexpand: true;
content: Adw.NavigationPage {
Adw.ToolbarView {
[top]
Adw.HeaderBar shop_content_bar {
decoration-layout: "";
visible: false;
}
Stack shop_pagestack {}
}
};
sidebar: Adw.NavigationPage {
Adw.ClampScrollable {
margin-bottom: 8;
margin-end: 8;
margin-start: 8;
margin-top: 8;
ListBox shop_listbox {
styles [
"navigation-sidebar",
]
}
}
};
}
};
icon-name: "system-software-install-symbolic";
name: "shop";
title: _("Shop");
...
...
src/window.py
View file @
e16823cd
...
...
@@ -20,6 +20,7 @@
from
gi.repository
import
Adw
,
Gtk
from
.settings
import
init_settings_stack
from
.shop
import
init_shop_stack
@Gtk.Template
(
resource_path
=
'/ru/ximperlinux/TuteIt/window.ui'
)
class
TuneitWindow
(
Adw
.
ApplicationWindow
):
...
...
@@ -28,8 +29,14 @@ class TuneitWindow(Adw.ApplicationWindow):
settings_pagestack
=
Gtk
.
Template
.
Child
()
settings_listbox
=
Gtk
.
Template
.
Child
()
settings_split_view
=
Gtk
.
Template
.
Child
()
shop_pagestack
=
Gtk
.
Template
.
Child
()
shop_listbox
=
Gtk
.
Template
.
Child
()
shop_split_view
=
Gtk
.
Template
.
Child
()
def
__init__
(
self
,
**
kwargs
):
super
()
.
__init__
(
**
kwargs
)
init_settings_stack
(
self
.
settings_pagestack
,
self
.
settings_listbox
,
self
.
settings_split_view
)
init_shop_stack
(
self
.
shop_pagestack
,
self
.
shop_listbox
,
self
.
shop_split_view
)
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