Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e76f49a3bd | ||
|
|
0ed10c72f9 | ||
|
|
34849c9490 | ||
|
|
ebabc7ebf7 | ||
|
|
726f2f4b43 | ||
|
|
8a94f519a3 | ||
|
|
468ea73aa6 | ||
|
|
a860cacf2c | ||
|
|
416c4e5336 | ||
|
|
48f694322a | ||
|
|
b58d768ca6 | ||
|
|
28062ff5bb | ||
|
|
4bd3028c4a | ||
|
|
8edceb667c | ||
|
|
45b495eff0 | ||
|
|
0469197d77 | ||
|
|
4f067d6850 | ||
|
|
d0c6bdfdb6 | ||
|
|
41bde9d985 | ||
|
|
ee9bb767a7 | ||
|
|
1e0f8255ea | ||
|
|
af8471ea40 | ||
|
|
4bfeae6e42 | ||
|
|
ccd3176d2a | ||
|
|
0d23121a14 | ||
|
|
4fbb250a34 | ||
|
|
6091bf2cf9 | ||
|
|
dbe5226d29 | ||
|
|
08cc66c533 | ||
|
|
c457dc0d31 | ||
|
|
b3e4ae719d | ||
|
|
dc75805a31 | ||
|
|
3aebe55162 | ||
|
|
9a7a2d5f50 | ||
|
|
b4ccebc65d | ||
|
|
36b009ecd4 | ||
|
|
372b4c6a6a | ||
|
|
15d5db87ad | ||
|
|
a8a35d5bd8 | ||
|
|
87ad9e12b6 | ||
|
|
45987c9941 | ||
|
|
a2f25738cf | ||
|
|
a1c823017b | ||
|
|
5e1640a9c6 | ||
|
|
abb6f84c60 | ||
|
|
985be9b36c | ||
|
|
33ffa28d60 | ||
|
|
e1bbdebfdd | ||
|
|
a1ae2c125d | ||
|
|
4b8f94a9cc | ||
|
|
db7201f279 | ||
|
|
bfe9a3dc91 | ||
|
|
af2db32352 | ||
|
|
c04b2df049 | ||
|
|
e8e068ba3b | ||
|
|
32ac86ed51 | ||
|
|
e33d4037b1 | ||
|
|
c5cfe30877 | ||
|
|
b8bd9cd08d | ||
|
|
d942cb64c9 | ||
|
|
f934d1e705 | ||
|
|
00c16261a4 | ||
|
|
9629717ada | ||
|
|
6fa71ed871 | ||
|
|
ab6629dd9a | ||
|
|
e90c365010 | ||
|
|
4e3ab5fba0 | ||
|
|
3dbfea89e3 | ||
|
|
daa13f2e4c | ||
|
|
2aca05928a | ||
|
|
8b2af7015b | ||
|
|
4315cd0e3f | ||
|
|
fa10a3cf0e | ||
|
|
9f932c4403 | ||
|
|
b725be78d1 | ||
|
|
7cbd3cffc7 | ||
|
|
190698a1b4 | ||
|
|
c96033311c | ||
|
|
0a225d4c3d | ||
|
|
18b92b66b1 | ||
|
|
230315bc57 | ||
|
|
3d981158b0 | ||
|
|
4ad1e38141 | ||
|
|
ae24b2386e | ||
|
|
8b5b199ff1 | ||
|
|
af291e9c7a | ||
|
|
c8cb60e42c | ||
|
|
4d508afb44 | ||
|
|
f36869bea5 | ||
|
|
0e311b5d07 | ||
|
|
cfbb6030b5 | ||
|
|
8661d0258d | ||
|
|
9bb7dc7db0 | ||
|
|
1f08c75cb2 | ||
|
|
17802d2bc5 | ||
|
|
86694b3721 | ||
|
|
ad37601b23 | ||
|
|
a6d894ce99 | ||
|
|
8877012ec4 | ||
|
|
5774e033d4 | ||
|
|
de8294b34d | ||
|
|
273e86958d | ||
|
|
d0f3d0f8d6 | ||
|
|
fc01de74b2 | ||
|
|
eb5d6bb613 | ||
|
|
e65cd2386c | ||
|
|
6b094f4905 | ||
|
|
7f44432388 | ||
|
|
fbfccd0417 | ||
|
|
1942d49f4d | ||
|
|
ab2933f8b0 | ||
|
|
4b985417c4 | ||
|
|
d52bec4798 | ||
|
|
f2c7ecf926 | ||
|
|
a929411daf | ||
|
|
8114b3cb54 | ||
|
|
04e974a0b7 | ||
|
|
efe8ef7267 | ||
|
|
a4c6ef89bf | ||
|
|
2bfb574ba1 |
No files matched your search
@@ -0,0 +1,48 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Virtual environments
|
||||
venv/
|
||||
ENV/
|
||||
env/
|
||||
.venv/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.project
|
||||
.pydevproject
|
||||
.settings/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.bak
|
||||
@@ -0,0 +1,238 @@
|
||||
# WineHelper - Руководство для AI агентов
|
||||
|
||||
## Обзор проекта
|
||||
|
||||
WineHelper — инструмент для упрощения установки Windows-приложений на Linux. Использует подготовленные скрипты, портативные версии Wine и изолированные префиксы, обеспечивая максимальную идентичность на различных операционных системах, основанных на ALT Linux (начиная с релиза p10 и выше).
|
||||
|
||||
**Лицензия:** GNU Lesser General Public License v2.1 (LGPL-2.1+)
|
||||
|
||||
**Автор:** Mikhail Tergoev (2025)
|
||||
|
||||
**Язык документации и комментариев:** Русский
|
||||
|
||||
**Статус проекта:** WIP (work in progress)
|
||||
|
||||
## Технологический стек
|
||||
|
||||
### Основные технологии
|
||||
- **Bash** — основной язык для CLI-интерфейса (~2692 строк в главном скрипте)
|
||||
- **Python 3** — графический интерфейс с использованием PyQt5
|
||||
- **Wine** — запуск Windows-приложений (поддерживаются различные версии: vanilla, staging, Proton, tkg, crossover)
|
||||
- **DXVK/VKD3D** — трансляция DirectX → Vulkan
|
||||
|
||||
### Зависимости Python
|
||||
- PyQt5 (основной GUI фреймворк)
|
||||
- Стандартная библиотека Python (os, subprocess, sys, re, shlex, shutil, html)
|
||||
|
||||
### Системные зависимости
|
||||
- i586-версии библиотек (для 32-битных приложений, если не используется wow64)
|
||||
- wget/curl для загрузки
|
||||
- 7z, tar для распаковки
|
||||
- wrestool, icotool для извлечения иконок из .exe
|
||||
- winetricks для управления компонентами Wine
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```
|
||||
winehelper/
|
||||
├── winehelper # Главный bash-скрипт (CLI)
|
||||
├── winehelper_gui.py # GUI на PyQt5 (точка входа)
|
||||
├── winehelperqt/ # Python-модуль GUI
|
||||
│ ├── __init__.py # Экспорты основных классов
|
||||
│ ├── dialogs/ # Диалоговые окна
|
||||
│ │ ├── base_version_dialog.py
|
||||
│ │ ├── component_version.py
|
||||
│ │ ├── create_prefix.py # Создание префикса
|
||||
│ │ ├── file_associations.py
|
||||
│ │ ├── settings.py # Настройки
|
||||
│ │ ├── wine_version.py # Выбор версии Wine
|
||||
│ │ └── winetricks_manager.py
|
||||
│ ├── parsers/ # Парсеры
|
||||
│ │ ├── script_parser.py # Парсинг скриптов установки
|
||||
│ │ ├── sha256_parser.py # Парсинг sha256sum.list
|
||||
│ │ └── winetricks_parser.py
|
||||
│ ├── services/ # Бизнес-логика
|
||||
│ │ ├── application_installer.py
|
||||
│ │ ├── desktop_file_manager.py
|
||||
│ │ ├── prefix_manager.py # Управление префиксами
|
||||
│ │ ├── process_handler.py
|
||||
│ │ └── winetricks_service.py
|
||||
│ ├── utils/ # Утилиты
|
||||
│ │ └── log_handler.py # Обработка логов
|
||||
│ └── widgets/ # Кастомные виджеты
|
||||
├── autoinstall/ # Скрипты автоматической установки (43 приложения)
|
||||
├── manualinstall/ # Скрипты ручной установки (9 приложений)
|
||||
├── testinstall/ # Тестовые скрипты установки
|
||||
├── database/ # Базы данных префиксов (.whdb файлы)
|
||||
├── image/ # Иконки приложений и GUI ресурсы
|
||||
│ ├── gui/ # Иконки приложения (SVG)
|
||||
│ └── handbook/ # Скриншоты для документации
|
||||
├── hiden_scripts/ # Скрытые/вспомогательные скрипты
|
||||
├── auto_completion/ # Автодополнение для bash
|
||||
├── dependencies.sh # Установка системных зависимостей
|
||||
├── sha256sum.list # SHA256 хеши загружаемых файлов
|
||||
└── winehelper.desktop # Desktop-файл для запуска GUI
|
||||
```
|
||||
|
||||
## Архитектура кода
|
||||
|
||||
### CLI (winehelper)
|
||||
|
||||
Главный скрипт `winehelper` — монолитный bash-скрипт с функциональными блоками:
|
||||
|
||||
1. **Переменные и окружение** — определение путей, версий, флагов
|
||||
2. **Функции сообщений** — цветной вывод в терминал
|
||||
3. **Утилиты** — работа с файлами, архивами, скачивание
|
||||
4. **Управление префиксами** — создание, удаление, бэкап/восстановление
|
||||
5. **Wine management** — установка версий Wine, DXVK, VKD3D
|
||||
6. **Desktop integration** — создание .desktop файлов, меню
|
||||
7. **Основной цикл** — обработка аргументов командной строки
|
||||
|
||||
### GUI (winehelperqt)
|
||||
|
||||
Модульная архитектура PyQt5:
|
||||
|
||||
- **WineHelperGUI** — главное окно, управление вкладками
|
||||
- **PrefixManager** — CRUD операции с префиксами
|
||||
- **ApplicationInstaller** — установка приложений
|
||||
- **ScriptParser** — парсинг информации из скриптов установки
|
||||
- **Диалоги** — модальные окна для настроек и выбора
|
||||
|
||||
### Скрипты установки
|
||||
|
||||
Каждый скрипт установки — это bash-скрипт с переменными:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Описание программы
|
||||
export PROG_URL="https://example.com"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64" # Версия Wine
|
||||
export WINEPREFIX="prefix_name" # Имя префикса
|
||||
export PROG_NAME="Название программы"
|
||||
export BASE_PFX="base_prefix_v01" # Базовый шаблон (опционально)
|
||||
export WINEARCH="win64" # Архитектура (win32/win64)
|
||||
export INSTALL_DLL="corefonts msxml3..." # DLL через winetricks
|
||||
|
||||
# Логика установки
|
||||
prepair_wine
|
||||
try_download "URL" "${FILE_PATH}"
|
||||
unpack "${FILE_PATH}" "${DEST_DIR}"
|
||||
wine_run_install "${SETUP_EXE}" /S
|
||||
create_desktop "Имя ярлыка" "${EXE_PATH}" "icon_name"
|
||||
```
|
||||
|
||||
## Режимы работы
|
||||
|
||||
### Системный режим
|
||||
Когда скрипт установлен в `/usr/bin/winehelper`:
|
||||
- Данные в `/usr/share/winehelper/`
|
||||
- Рабочая директория пользователя: `~/.local/share/winehelper/`
|
||||
- Иконки в `/usr/share/icons/...`
|
||||
|
||||
### Режим разработки
|
||||
При запуске из репозитория:
|
||||
- Рабочая директория: `~/test-winehelper/`
|
||||
- Данные берутся из текущей директории
|
||||
- Включается проверка синтаксиса скриптов
|
||||
|
||||
## Команды CLI
|
||||
|
||||
```bash
|
||||
# Установка
|
||||
winehelper install list # Список доступных программ
|
||||
winehelper -i <script_name> # Установить программу
|
||||
winehelper -i <script_name> /path # Установить из дистрибутива
|
||||
winehelper -i "/path/to/script" # Установить из стороннего скрипта
|
||||
|
||||
# Управление префиксами
|
||||
winehelper create-prefix # Создать префикс
|
||||
winehelper remove-prefix [name] # Удалить префикс
|
||||
winehelper backup-prefix [name] # Создать бэкап (.whpack)
|
||||
winehelper restore-prefix <path> # Восстановить из бэкапа
|
||||
|
||||
# Wine tools
|
||||
winehelper winefile # Файловый менеджер
|
||||
winehelper winecfg # Настройки Wine
|
||||
winehelper winereg # Редактор реестра
|
||||
winehelper wineconsole # Терминал Wine (cmd.exe)
|
||||
winehelper winetricks [component] # Winetricks
|
||||
winehelper <file.exe> # Запустить exe в префиксе
|
||||
winehelper debug [флаги] [программа] # Запуск программы в отладчике winedbg
|
||||
winehelper killall # Остановить все процессы Wine
|
||||
winehelper run-in-prefix <префикс> <файл> # Запустить файл в указанном префиксе
|
||||
|
||||
# Управление компонентами
|
||||
winehelper install-dxvk [version] # Установить DXVK
|
||||
winehelper install-vkd3d [version] # Установить VKD3D
|
||||
winehelper change-wine [version] # Сменить версию Wine
|
||||
winehelper clear-winetricks-cache # Очистить кэш Winetricks
|
||||
|
||||
# Другое
|
||||
winehelper --debug <command> # Режим отладки
|
||||
winehelper --changelog # История изменений
|
||||
winehelper gui # Запустить GUI
|
||||
```
|
||||
|
||||
## Разработка
|
||||
|
||||
### Запуск в режиме разработки
|
||||
|
||||
```bash
|
||||
# GUI режим
|
||||
./winehelper gui
|
||||
|
||||
# CLI режим
|
||||
./winehelper install list
|
||||
./winehelper -i alta-expert
|
||||
```
|
||||
|
||||
### Добавление нового скрипта установки
|
||||
|
||||
1. Создать файл в `autoinstall/` (для автоматической установки) или `manualinstall/` (требуется дистрибутив)
|
||||
2. Добавить обязательные переменные: `PROG_NAME`, `WINEPREFIX`, `WH_WINE_USE`, `PROG_URL`
|
||||
3. Добавить комментарий `# info_ru:` с описанием
|
||||
4. Добавить иконку в `image/` (PNG, имя совпадает с переменной в create_desktop)
|
||||
5. Обновить `sha256sum.list` если требуется загрузка архивов
|
||||
|
||||
### Требования к коду
|
||||
|
||||
**Bash:**
|
||||
- Использовать `#!/usr/bin/env bash`
|
||||
- Проверять наличие переменных перед использованием
|
||||
- Использовать функции обработки ошибок (`fatal`, `print_error`)
|
||||
- Экранировать все пути с помощью кавычек
|
||||
|
||||
**Python:**
|
||||
- Импортировать из `winehelperqt` относительно
|
||||
- Использовать type hints где возможно
|
||||
- Документация на русском языке
|
||||
- Классы должны наследоваться от соответствующих QWidget
|
||||
|
||||
## Безопасность
|
||||
|
||||
- Скрипт запрещает запуск от root
|
||||
- Проверяет noexec для /home
|
||||
- Проверяет SHA256 хеши загружаемых файлов
|
||||
- Использует временные файлы с ограниченными правами (600)
|
||||
- Поддержка лицензионного соглашения перед установкой
|
||||
|
||||
## Особенности ALT Linux
|
||||
|
||||
- Требуется репозиторий x86_64-i586 для 32-битных зависимостей
|
||||
- Интеграция с RPM (версия определяется через `rpm -q winehelper`)
|
||||
- Использование apt-get для установки зависимостей
|
||||
- Desktop-файлы размещаются в `~/.local/share/applications/`
|
||||
|
||||
## Полезные ссылки
|
||||
|
||||
- Официальная документация: https://www.altlinux.org/Winehelper
|
||||
- Совместимость ПО (P10): https://www.basealt.ru/fileadmin/user_upload/compatibility/P10-view2.html
|
||||
- Совместимость ПО (P11): https://www.basealt.ru/fileadmin/user_upload/compatibility/P11-view2.html
|
||||
|
||||
## Сторонние компоненты
|
||||
|
||||
- Wine / Wine-Staging / Proton / wine-tkg
|
||||
- Wine-Mono, Wine-Gecko
|
||||
- DXVK, VKD3D
|
||||
- Winetricks
|
||||
- wine-cpcsp_proxy (для КриптоПро)
|
||||
@@ -1,5 +1,60 @@
|
||||
История изменений:
|
||||
|
||||
0.13.0
|
||||
* обновлен графический режим Qt5:
|
||||
- исправлены/улучшены основные функции
|
||||
- запуск утилит Wine выполняется через winehelper (CLI) вместо прямого вызова wine
|
||||
- добавлены индикаторы-иконки на кнопках версий Wine и DXVK/VKD3D
|
||||
- добавлена сортировка версий Wine по убыванию
|
||||
- удалена вкладка "Загрузка" в окне выбора версии Wine
|
||||
- исправлена автопрокрутка списка в менеджере компонентов при поиске
|
||||
- исправлено определение .exe файлов без учета регистра
|
||||
- скрытие ярлыка установленного приложения, если .exe файл отсутствует
|
||||
- добавлена корректная активация CPCSP_PROXY в дополнительных настройках префикса
|
||||
- добавлена принудительная переустановка cpcsp_proxy при включении
|
||||
* добавлены версии wine:
|
||||
- wine-11.0-alt-tkg
|
||||
- wine-9.0-alt-tkg (i586, amd64, wow64)
|
||||
- wine-10.0-alt-tkg (i586, amd64, wow64)
|
||||
- wine-10.0-alt-scadoffice-wow64
|
||||
* удалены неиспользуемые версии wine
|
||||
* обновлены скрипты установок:
|
||||
- t-flex: единый префикс для всех версий, используется wine с исправлением всплывающих окон и 3D на Wayland
|
||||
- emias: используется wine с исправлением сворачивания окон
|
||||
- scadoffice: используется специальная сборка wine (демо версия программы)
|
||||
- olimp: добавлен itss в префикс, исправлен фокус окна и окна справки
|
||||
- ctm-service: исправлено имя exe для desktop файла
|
||||
- daobit-cservice: исправлено имя установщика и замена CService32.exe
|
||||
* добавлена поддержка запуска сторонних скриптов установки
|
||||
* добавлена минимальная генерация .whdb файла при ручном создании ярлыка
|
||||
* возвращено уведомление о монтировании home с флагом noexec
|
||||
* добавлена возможность выбрать рабочий каталог для WineHelper:
|
||||
winehelper data-path "/путь/к/каталогу"
|
||||
|
||||
0.12.0
|
||||
* исправлена работа cpcsp_proxy при монтировании home с флагом noexec
|
||||
* обновлены все скрипты установки ВЭД и СТМ
|
||||
|
||||
0.11.0
|
||||
* исправлена работа WineHelper при монтировании home с флагом noexec
|
||||
* исправлена иконка графического режима Qt5
|
||||
* добавлена автоматическая архивация лога, если он больше 10 Мб
|
||||
* исправлена работа сертификатов для emias (спасибо lav@)
|
||||
|
||||
0.10.0
|
||||
* добавлены скрипты установок:
|
||||
- apropos-z
|
||||
- olimp
|
||||
* обновлены скрипты установок:
|
||||
- ctm-service
|
||||
- emias
|
||||
* добавлены версии wine:
|
||||
- wine-11.3.1-alt1-wow64
|
||||
- wine-10.18.1-alt2-i586
|
||||
- wine-9.0-cx-amd64
|
||||
* добавлена поддержка wine-cx (форк wine от crossover)
|
||||
* небольшие улучшения графического режим Qt5
|
||||
|
||||
0.9.0
|
||||
* добавлена поддержка wine-wow64 (не требует установку 32-битных зависимостей в систему)
|
||||
* добавлена поддержка wine-cpcsp_proxy для wine-wow64 (не требует установку 32-битного КриптоПро в систему)
|
||||
|
||||
@@ -48,19 +48,19 @@
|
||||
$ winehelper -i
|
||||
```
|
||||
|
||||
### Запуск установки приложений
|
||||
### Запуск установки приложений из списка скриптов
|
||||
|
||||
Скрипты установки разделены на два типа:
|
||||
|
||||
1. **Список программ с возможностью автоматической установки** — содержит полностью автоматизированные скрипты установок программ у которыx есть дистрибутивы (установщики) в свободном доступе.
|
||||
1. **Список программ с возможностью автоматической установки** — содержит полностью автоматизированные скрипты установок программ у которых есть дистрибутивы (установщики) в свободном доступе.
|
||||
Процесс полностью автоматизирован.
|
||||
Пример:
|
||||
```
|
||||
$ winehelper install spravki-bk
|
||||
$ winehelper install ksamu
|
||||
```
|
||||
или сокращенная команда:
|
||||
```
|
||||
$ winehelper -i spravki-bk
|
||||
$ winehelper -i ksamu
|
||||
```
|
||||
2. **Список программ с возможностью установки из существующего дистрибутива** — содержит скрипты установок для программ, которых нет в свободном доступе.
|
||||
Пример:
|
||||
@@ -72,7 +72,13 @@
|
||||
$ winehelper -i is-record-station "/путь/до/установочного_файла"
|
||||
```
|
||||
|
||||
### Процесс установки приложений
|
||||
3. **Установка из стороннего скрипта** — можно передать путь к собственному скрипту установки, подготовленному по шаблону WineHelper.
|
||||
Пример:
|
||||
```
|
||||
$ winehelper -i "/путь/до/скрипта_установки"
|
||||
```
|
||||
|
||||
### Процесс установки приложений из списка скриптов
|
||||
|
||||
При первом запуске **WineHelper** проверяются и при необходимости устанавливаются дополнительные зависимости (запрашиваются права root).
|
||||
|
||||
@@ -88,6 +94,27 @@
|
||||
|
||||
Если устанавливаемое приложение требует дополнительных действий от пользователя (ввод лицензии, настройка), это будет явно указано в терминале.
|
||||
|
||||
### Установка своего приложения
|
||||
|
||||
Для установки своего приложения (не из списка готовых скриптов) выполните следующие шаги:
|
||||
|
||||
**Этап 1: Создание префикса**
|
||||
Создайте новый префикс с использованием wine-wow64 (рекомендуется для новых приложений):
|
||||
```
|
||||
$ winehelper create-prefix
|
||||
```
|
||||
Выберите wine-wow64 версию и разрядность 64-bit.
|
||||
|
||||
> [!NOTE]
|
||||
> **Всегда сначала пробуйте wine-wow64**, это упрощает настройку и избавляет от 32-битных зависимостей.
|
||||
|
||||
**Этап 2: Запуск установщика**
|
||||
Запустите установочный файл в созданном префиксе:
|
||||
```
|
||||
$ winehelper "/путь/до/установочного_файла.exe"
|
||||
```
|
||||
Выберите префикс из списка (введите номер и нажмите Enter).
|
||||
|
||||
### Удаление префикса с приложением
|
||||
|
||||
Для удаления префикса выполните команду:
|
||||
@@ -101,14 +128,14 @@
|
||||
2 - Префикс2
|
||||
Выберите префикс (0-2):
|
||||
```
|
||||
Необходимо указать номер удаляемого префикса и нажать клавишу **Enter**.Далее потребуется подтвердить удаление префикса вводом **y**.
|
||||
Необходимо указать номер удаляемого префикса и нажать клавишу **Enter**. Далее потребуется подтвердить удаление префикса вводом **y**.
|
||||
|
||||
В результате будут удалены:
|
||||
- сам префикс;
|
||||
- установленное ПО;
|
||||
- desktop-файлы (ярлыки для установленного ПО в префиксе).
|
||||
|
||||
###
|
||||
### Cоздание резервной копии префикса
|
||||
|
||||
Команда создания резервной копии префикса:
|
||||
```
|
||||
@@ -138,7 +165,7 @@
|
||||
Восстановление префикса не требует подключение к интернету и происходит в автоматическом режиме:
|
||||
- Распаковка префикса.
|
||||
- Восстановление версии WINE.
|
||||
- Восстановление ярлыков (.desktop-файdлов).
|
||||
- Восстановление ярлыков (.desktop-файлов).
|
||||
|
||||
После завершения восстановления приложение будет доступно для запуска через меню или рабочий стол.
|
||||
|
||||
@@ -150,7 +177,6 @@ WineHelper предоставляет доступ к основным инст
|
||||
winehelper winecfg # запуск wine конфигуратора для префикса
|
||||
winehelper winereg # запуск редактора реестра для префикса
|
||||
winehelper wineconsole # запуск терминала wine (cmd.exe)
|
||||
winehelper winetricks # запуск графического интерфейса winetricks
|
||||
winehelper winetricks [компонент] # автоматическая установка дополнительного компонента в префикс
|
||||
```
|
||||
После выполнения любой из вышеперечисленных команд отображается список существующих префиксов:
|
||||
@@ -175,7 +201,7 @@ WineHelper предоставляет доступ к основным инст
|
||||
```
|
||||
Файл будет запущен в выбранном префиксе.
|
||||
|
||||
2. С помощью файлового менеджера WINE:'''
|
||||
2. С помощью файлового менеджера WINE:
|
||||
```
|
||||
$ winehelper winefile
|
||||
0 - Отмена
|
||||
@@ -198,18 +224,35 @@ WineHelper предоставляет доступ к основным инст
|
||||
install list список возможных установочных скриптов
|
||||
install [скрипт] запустить скрипт установки программы
|
||||
install [скрипт] --clear-pfx не использовать готовый префикс для установки ПО
|
||||
install "путь/до/скрипта" запустить сторонний скрипт установки
|
||||
|
||||
install-dxvk [версия|none|list] установить, удалить или показать версии DXVK
|
||||
install-vkd3d [версия|none|list] установить, удалить или показать версии VKD3D
|
||||
change-wine [версия] изменить версию Wine для текущего префикса
|
||||
|
||||
installed список установленных программ
|
||||
run [программа] запуск программы (отладка)
|
||||
run [программа] запуск программы
|
||||
debug [флаги] [программа] запуск программы в отладчике winedbg
|
||||
Флаги:
|
||||
--auto, -a автоматический backtrace
|
||||
--gdb, -g режим gdb
|
||||
--interactive, -i интерактивный режим
|
||||
remove-all удалить WineHelper и все связанные данные
|
||||
create-prefix создать префикс
|
||||
remove-prefix [имя_префикса] удалить префикс и все связанные данные
|
||||
backup-prefix [имя_префикса] создать резервную копию префикса
|
||||
restore-prefix \"путь/до/whpack\" восстановить префикс из резервной копии
|
||||
clear-winetricks-cache очистить кэш Winetricks
|
||||
|
||||
winecfg запуск wine конфигуратора для префикса
|
||||
winereg запуск редактора реестра для префикса
|
||||
winefile запуск файлового менеджера wine
|
||||
wineconsole запуск терминала wine (cmd.exe)
|
||||
control запуск панели управления wine
|
||||
uninstaller запуск удаления программ wine
|
||||
winetricks [компонент] автоматическая установка дополнительного компонента в префикс
|
||||
killall остановить все процессы Wine
|
||||
run-in-prefix <префикс> <файл> запустить файл в указанном префиксе
|
||||
|
||||
Параметры:
|
||||
--help показать эту справку и выйти
|
||||
@@ -239,7 +282,7 @@ WineHelper предоставляет доступ к основным инст
|
||||
<p><em>Вкладка "Ручная установка"</em></p>
|
||||
</div>
|
||||
|
||||
Так же на вкладке **Автоматическая установка** есть чекбокс с тестовыми версиями скриптов установки которые еще не прошли полную проверку на зависимости и совместимость, но уже можно попробовать в работе.
|
||||
Также на вкладке **Автоматическая установка** есть чекбокс с тестовыми версиями скриптов установки которые еще не прошли полную проверку на зависимости и совместимость, но уже можно попробовать в работе.
|
||||
|
||||
<div align="center">
|
||||
<img src="image/handbook/auto_install_test.png">
|
||||
@@ -324,9 +367,9 @@ WineHelper предоставляет доступ к основным инст
|
||||
#### Создание нового префикса
|
||||
|
||||
Нажав кнопку **«Создать новый префикс»**, вы откроете диалог, где можно задать:
|
||||
* **Имя префикса**.
|
||||
* **Имя нового префикса**.
|
||||
* **Разрядность** (32-bit или 64-bit).
|
||||
* **Наполнение** (чистый префикс или с рекомендуемыми библиотеками).
|
||||
* **Шаблон префикса** (чистый префикс или с рекомендуемыми библиотеками).
|
||||
* **Версию Wine** из доступного списка.
|
||||
|
||||
<div align="center">
|
||||
@@ -334,22 +377,45 @@ WineHelper предоставляет доступ к основным инст
|
||||
<p><em>Диалог создания нового префикса</em></p>
|
||||
</div>
|
||||
|
||||
#### Установка своего приложения
|
||||
|
||||
Для установки своего приложения (не из списка готовых скриптов) выполните следующие шаги:
|
||||
|
||||
**Этап 1: Создание префикса**
|
||||
1. Вкладка **«Менеджер префиксов»**
|
||||
2. Нажмите **«Создать новый префикс»**
|
||||
3. Задайте имя префикса
|
||||
4. Выберите **wine-wow64** версию (рекомендуется)
|
||||
5. Выберите разрядность **64-bit**
|
||||
|
||||
> [!NOTE]
|
||||
> **Всегда сначала пробуйте wine-wow64**, это упрощает настройку и избавляет от 32-битных зависимостей.
|
||||
|
||||
**Этап 2: Установка приложения**
|
||||
1. Выберите созданный префикс из выпадающего списка
|
||||
2. Нажмите кнопку **«Запустить файл в префиксе»**, выберите файл для установки
|
||||
3. Нажмите кнопку **«Создать ярлык для приложения в префиксе»**, выберите установленный файл в префиксе
|
||||
|
||||
#### Управление существующим префиксом
|
||||
|
||||
Выбрав префикс из выпадающего списка, вы получаете доступ к панели управления, которая позволяет:
|
||||
|
||||
* **Управлять компонентами**:
|
||||
* **Менеджер компонентов (Winetricks)**: Удобный интерфейс для установки и переустановки библиотек, шрифтов и настроек.
|
||||
* **Запускать стандартные утилиты Wine**:
|
||||
* `Редактор настроек (winecfg)`
|
||||
* `Редактор реестра (regedit)`
|
||||
* `Удаление программ (uninstaller)`
|
||||
* `Командная строка (cmd)`
|
||||
* `Файловый менеджер (winefile)`
|
||||
* **Управлять компонентами**:
|
||||
* **Менеджер компонентов (Winetricks)**: Удобный интерфейс для установки и переустановки библиотек, шрифтов и настроек.
|
||||
* **Управление Wine**: Смена версии Wine для выбранного префикса. Диалог выбора позволяет как выбрать уже установленную версию, так и скачать новую из списков, сгруппированных по архитектуре.
|
||||
* `Панель управления (control)`
|
||||
* **Управлять версиями Wine**:
|
||||
* **Управление версией Wine**: Смена версии Wine для выбранного префикса. Диалог выбора позволяет как выбрать уже установленную версию, так и скачать новую из списков, сгруппированных по архитектуре.
|
||||
* **Управлять дополнительными настройками**:
|
||||
* **Управление DXVK/VKD3D**: Установка или удаление конкретных версий DXVK и vkd3d-proton.
|
||||
* **Ассоциации файлов**: Настройка открытия определенных типов файлов (например, `.pdf`, `.docx`) нативными приложениями Linux, чтобы избежать их открытия внутри Wine.
|
||||
* **Включать/выключать ESync и FSync**.
|
||||
* **Включать/выключать ESync и FSync**: Включение/выключение методов оптимизации синхронизации потоков в Windows-приложениях при запуске через Wine.
|
||||
* **Включать/выключать CPCSP_PROXY**: Поддержка КриптоПро CSP (электронная подпись). Включайте только для приложений, требующих ЭП.
|
||||
* **Устанавливать приложения**: Установить любой `.exe` или `.msi` файл напрямую в выбранный префикс.
|
||||
* **Создавать ярлыки**: Создать ярлык для любого исполняемого файла внутри префикса.
|
||||
* **Удалять префикс** или **создавать из него шаблон**.
|
||||
|
||||
@@ -4,8 +4,8 @@ _winehelper_completions() {
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="--help --version --debug install installed install-dxvk install-vkd3d -r -i remove-all --clear-pfx killall remove-prefix backup-prefix restore-prefix create-prefix --changelog changelog change-wine clear-winetricks-cache"
|
||||
wine_cmd="winecfg winereg winefile wineconsole winetricks desktop regedit explorer cmd run"
|
||||
opts="--help --version --debug install installed install-dxvk install-vkd3d -r -i remove-all killall remove-prefix backup-prefix restore-prefix create-prefix change-wine clear-winetricks-cache gui data-path version help --changelog changelog create-base-pfx init-prefix run-in-prefix debug"
|
||||
wine_cmd="winecfg winereg winefile wineconsole winetricks desktop regedit explorer cmd run uninstaller control"
|
||||
|
||||
case "${prev}" in
|
||||
winehelper)
|
||||
@@ -17,12 +17,12 @@ _winehelper_completions() {
|
||||
return 0
|
||||
;;
|
||||
install|-i)
|
||||
local scripts="$(ls -1 /usr/share/winehelper/autoinstall) $(ls -1 /usr/share/winehelper/manualinstall)"
|
||||
COMPREPLY=( $(compgen -W "list ${scripts}" -- "${cur}") )
|
||||
local scripts="$(ls -1 /usr/share/winehelper/autoinstall 2>/dev/null) $(ls -1 /usr/share/winehelper/manualinstall 2>/dev/null) $(ls -1 /usr/share/winehelper/testinstall 2>/dev/null)"
|
||||
COMPREPLY=( $(compgen -W "list --clear-pfx ${scripts}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
run|installed)
|
||||
local installed=$(ls -1 ~/.local/share/winehelper/ | grep ".desktop" | sed 's/.desktop//')
|
||||
run|installed|debug)
|
||||
local installed=$(ls -1 ~/.local/share/winehelper/ 2>/dev/null | grep ".desktop" | sed 's/.desktop//')
|
||||
COMPREPLY=( $(compgen -W "${installed}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
@@ -31,7 +31,17 @@ _winehelper_completions() {
|
||||
COMPREPLY=( $(compgen -W "${prefixes}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
run-in-prefix)
|
||||
local prefixes=$(ls -1 ~/.local/share/winehelper/prefixes 2>/dev/null)
|
||||
COMPREPLY=( $(compgen -W "${prefixes}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
restore-prefix)
|
||||
COMPREPLY=( $(compgen -f -X '!*.whpack' -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
data-path)
|
||||
COMPREPLY=( $(compgen -d -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
install-dxvk|install-vkd3d)
|
||||
@@ -49,6 +59,10 @@ _winehelper_completions() {
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
if [[ "${COMP_WORDS[COMP_CWORD-2]}" == "run-in-prefix" ]] ; then
|
||||
COMPREPLY=( $(compgen -f -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ _winehelper() {
|
||||
|
||||
opts=(
|
||||
'--help[Вывести справку]'
|
||||
'help[Вывести справку]'
|
||||
'--version[Показать информацию о пакете и его версии]'
|
||||
'version[Показать информацию о пакете и его версии]'
|
||||
'--debug[Режим отладки]'
|
||||
'install[Запустить скрипт установки программы]'
|
||||
'install-dxvk[Установить/удалить DXVK]'
|
||||
@@ -14,14 +16,21 @@ _winehelper() {
|
||||
'-r[Запуск программы (отладка)]'
|
||||
'-i[Запустить скрипт установки программы]'
|
||||
'remove-all[Удалить WineHelper и все связанные данные]'
|
||||
'--clear-pfx[Очистить префикс \[имя_префикса\]]'
|
||||
'killall[Убить все процессы]'
|
||||
'create-prefix[Создать новый префикс]'
|
||||
'remove-prefix[Удалить префикс и все связанные данные]'
|
||||
'backup-prefix[Создать резерную копию префикса]'
|
||||
'restore-prefix[восстановить префикс из резервной копии "путь/до/whpack"]'
|
||||
'backup-prefix[Создать резервную копию префикса]'
|
||||
'restore-prefix[Восстановить префикс из резервной копии "путь/до/whpack"]'
|
||||
'change-wine[Изменить версию Wine для префикса]'
|
||||
'clear-winetricks-cache[Очистить кэш Winetricks]'
|
||||
'gui[Запустить графический интерфейс]'
|
||||
'data-path[Изменить рабочий каталог WineHelper]'
|
||||
'create-base-pfx[Создать базовый шаблонный префикс]'
|
||||
'init-prefix[Инициализировать префикс]'
|
||||
'run-in-prefix[Запустить файл в указанном префиксе]'
|
||||
'debug[Запуск программы в отладчике]'
|
||||
'--changelog[Показать историю изменений]'
|
||||
'changelog[Показать историю изменений]'
|
||||
)
|
||||
|
||||
wine_cmd=(
|
||||
@@ -34,6 +43,8 @@ _winehelper() {
|
||||
regedit
|
||||
explorer
|
||||
cmd
|
||||
uninstaller
|
||||
control
|
||||
'run[Запуск программы (отладка)]'
|
||||
)
|
||||
|
||||
@@ -47,6 +58,11 @@ _winehelper() {
|
||||
_values 'winehelper options' "${opts[@]}" "${wine_cmd[@]}"
|
||||
;;
|
||||
args)
|
||||
if [[ "$words[2]" == "run-in-prefix" ]] && [[ ${#words[@]} -gt 3 ]] ; then
|
||||
_files
|
||||
return
|
||||
fi
|
||||
|
||||
case $words[2] in
|
||||
--debug)
|
||||
_values 'wine commands' "${wine_cmd[@]}"
|
||||
@@ -54,16 +70,19 @@ _winehelper() {
|
||||
install|-i)
|
||||
_get_list_for_install
|
||||
;;
|
||||
run|installed)
|
||||
run|installed|debug)
|
||||
_get_installed_list
|
||||
;;
|
||||
remove-prefix|backup-prefix)
|
||||
remove-prefix|backup-prefix|run-in-prefix)
|
||||
_get_prefixes
|
||||
;;
|
||||
create-prefix)
|
||||
create-prefix|init-prefix|create-base-pfx|gui|killall|clear-winetricks-cache|remove-all|version|--version|help|--help|changelog|--changelog)
|
||||
;;
|
||||
restore-prefix)
|
||||
_files
|
||||
_files -g '*.whpack'
|
||||
;;
|
||||
data-path)
|
||||
_path_files -/
|
||||
;;
|
||||
install-dxvk)
|
||||
_get_component_versions 'install-dxvk'
|
||||
@@ -74,6 +93,8 @@ _winehelper() {
|
||||
change-wine)
|
||||
_get_wine_versions
|
||||
;;
|
||||
winecfg|winereg|winefile|wineconsole|winetricks|desktop|regedit|explorer|cmd|uninstaller|control)
|
||||
;;
|
||||
*)
|
||||
_values 'winehelper options' "${opts[@]}" "${wine_cmd[@]}"
|
||||
;;
|
||||
@@ -117,8 +138,11 @@ _get_prefixes () {
|
||||
}
|
||||
|
||||
_get_list_for_install () {
|
||||
|
||||
packages=(${(f)"$(winehelper install list 2>/dev/null |
|
||||
local -a packages
|
||||
|
||||
packages=(--clear-pfx)
|
||||
|
||||
packages+=(${(f)"$(winehelper install list 2>/dev/null |
|
||||
awk -F ' - ' '
|
||||
/^[^ ]+ - \("/ {next}
|
||||
/^[[:space:]]*$/ {next}
|
||||
@@ -131,14 +155,8 @@ _get_list_for_install () {
|
||||
if (name && desc) print name ":" desc
|
||||
}
|
||||
')"})
|
||||
|
||||
packages+=(
|
||||
scadoffice:"SCAD Office"
|
||||
t-flex-cad17-applications:"Приложения для T-FLEX CAD 17"
|
||||
t-flex-cad17-resources:"Обучающие материалы T-FLEX CAD 17"
|
||||
)
|
||||
|
||||
_describe 'packages' packages
|
||||
_describe 'packages' packages
|
||||
}
|
||||
|
||||
_get_installed_list () {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Пакет программ для таможенного оформления. Включает программы Такса и ТамДок в комплектациях Эксперт, а также программу Заполнитель.
|
||||
########################################################################
|
||||
export PROG_URL="https://www.alta.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="alta"
|
||||
export PROG_NAME="Альта-Эксперт"
|
||||
export BASE_PFX="alta_pfx_x86_v01"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Таможенное оформление товаров
|
||||
########################################################################
|
||||
export PROG_URL="https://www.alta.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="alta"
|
||||
export PROG_NAME="Альта-ГТД"
|
||||
export PROG_ICON="altagtd"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Пакет программ для таможенного оформления. Включает программы Альта-ГТД, Такса и ТамДок в комплектациях Максимум, а также программу Заполнитель.
|
||||
########################################################################
|
||||
export PROG_URL="https://www.alta.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="alta"
|
||||
export PROG_NAME="Альта-Максимум"
|
||||
export BASE_PFX="alta_pfx_x86_v01"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Таможенное законодательство
|
||||
########################################################################
|
||||
export PROG_URL="https://www.alta.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="alta"
|
||||
export PROG_NAME="Таможенные документы"
|
||||
export PROG_ICON="altatamdoc"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Расчет контракта
|
||||
########################################################################
|
||||
export PROG_URL="https://www.alta.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="alta"
|
||||
export PROG_NAME="Такса"
|
||||
export PROG_ICON="altatax"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Автоматизация импорта данных
|
||||
########################################################################
|
||||
export PROG_URL="https://www.alta.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="alta"
|
||||
export PROG_NAME="Заполнитель"
|
||||
export PROG_ICON="altazap"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Система “A'PROPOS-Z - Графит ТМ” для проектирования этапов механообработки, синтеза, расчета и верефикация операционных размерных текстур. Графическое моделирование технологии иформирование карт эскизов.
|
||||
########################################################################
|
||||
export PROG_URL="https://www.tezis.pro"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="apropos-z"
|
||||
export PROG_NAME="A'PROPOS-Z - Графит ТМ"
|
||||
export PROG_ICON="apropos-z"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа “АРМ КТ ПРОФ АТТЕСТАТ” для документов об основном общем, среднем общем образовании.
|
||||
########################################################################
|
||||
export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-4"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="arm-kt"
|
||||
export PROG_NAME="АРМ КТ ПРОФ АТТЕСТАТ"
|
||||
export PROG_ICON="armkt"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа “АРМ КТ ПРОФ ДПП” для заполнения бланков документов о повышении квалификации и профессиональной переподготовке.
|
||||
########################################################################
|
||||
export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="arm-kt"
|
||||
export PROG_NAME="АРМ КТ ПРОФ ДПП"
|
||||
export PROG_ICON="armkt"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа “АРМ КТ ПРОФ НШ” для заполнения бланков документов об окончании начальной школы.
|
||||
########################################################################
|
||||
export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-1"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="arm-kt"
|
||||
export PROG_NAME="АРМ КТ ПРОФ НШ"
|
||||
export PROG_ICON="armkt"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа “АРМ КТ ПРОФ МЕД” для заполнения бланков документов о послевузовском профессиональном образовании и сертификатов специалиста.
|
||||
######################################################
|
||||
export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-3"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="arm-kt"
|
||||
export PROG_NAME="АРМ КТ ПРОФ МЕД"
|
||||
export PROG_ICON="armkt"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа “АРМ КТ ПРОФ ПРОФЕССИЯ” для заполнения бланков документов профессионального обучения.
|
||||
########################################################################
|
||||
export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-5"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="arm-kt"
|
||||
export PROG_NAME="АРМ КТ ПРОФ ПРОФЕССИЯ"
|
||||
export PROG_ICON="armkt"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа “АРМ КТ ПРОФ СПО” для заполнения бланков документов о среднем профессиональном образовании.
|
||||
########################################################################
|
||||
export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-2"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="arm-kt"
|
||||
export PROG_NAME="АРМ КТ ПРОФ СПО"
|
||||
export PROG_ICON="armkt"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа “АРМ КТ ПРОФ ВУЗ” для заполнения бланков документов о высшем образовании.
|
||||
########################################################################
|
||||
export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-6"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="arm-kt"
|
||||
export PROG_NAME="АРМ КТ ПРОФ ВУЗ"
|
||||
export PROG_ICON="armkt"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://www.ctm.ru"
|
||||
export PROG_NAME="СТМ-Финансы"
|
||||
export PROG_ICON="ctmfinance"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://www.ctm.ru"
|
||||
export PROG_NAME="СТМ-Журналы"
|
||||
export PROG_ICON="ctmjournals"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://www.ctm.ru"
|
||||
export PROG_NAME="Монитор ЭД"
|
||||
export PROG_ICON="ctmmonitor"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://www.ctm.ru"
|
||||
export PROG_NAME="СТМ-Отчет"
|
||||
export PROG_ICON="ctmreport"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://www.ctm.ru"
|
||||
export PROG_NAME="СТМ-Сервис"
|
||||
export PROG_ICON="ctmservice"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
@@ -18,7 +18,7 @@ get_and_set_reg_file --add 'Software\CTM\CTMSETUP' 'SkipKBCheck' 'REG_DWORD' "1"
|
||||
|
||||
AUTOINSTALL_EXE="${WH_TMP_DIR}/setup_cs.exe"
|
||||
AUTOINSTALL_UNPACK="${WH_TMP_DIR}/setup_cs"
|
||||
AUTOINSTALL_SETUP="${WH_TMP_DIR}/setup_cs/setup.exe"
|
||||
AUTOINSTALL_SETUP="${WH_TMP_DIR}/setup_cs/Setup.exe"
|
||||
|
||||
if try_download "https://files.ctm.ru/CSERVICE/SFX/setup_cs.exe" "${AUTOINSTALL_EXE}" ; then
|
||||
unpack "${AUTOINSTALL_EXE}" "${AUTOINSTALL_UNPACK}"
|
||||
@@ -27,8 +27,10 @@ if try_download "https://files.ctm.ru/CSERVICE/SFX/setup_cs.exe" "${AUTOINSTALL_
|
||||
wine_run_install "${AUTOINSTALL_SETUP}" /cd /targetdir="C:\\\\Program Files\\\\CTM\\\\CSERVICE" /auto /hide
|
||||
try_remove_dir "$AUTOINSTALL_UNPACK"
|
||||
|
||||
WIN_FILE_EXEC="$DRIVE_C/Program Files/CTM/CSERVICE/ctmservc.exe"
|
||||
create_desktop "$PROG_NAME" "$WIN_FILE_EXEC" "$PROG_ICON"
|
||||
WIN_FILE_EXEC="$DRIVE_C/Program Files/CTM/CSERVICE/CService32.exe"
|
||||
WIN_FAKE_EXEC="$DRIVE_C/Program Files/CTM/CSERVICE/ctm-service.exe"
|
||||
try_force_link_file "$WIN_FILE_EXEC" "$WIN_FAKE_EXEC"
|
||||
create_desktop "$PROG_NAME" "$WIN_FAKE_EXEC" "$PROG_ICON"
|
||||
|
||||
if [[ "$USE_CTMBAR" == "1" ]] ; then
|
||||
if [[ -f "$DRIVE_C/Program Files/CTM/COMMON/CTMBAR.EXE" ]]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Сервис обновления ПО: "R-Атлас", "R-Инфо" и "R-Тариф".
|
||||
########################################################################
|
||||
export PROG_URL="https://daobit.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586" # wine-9.0.9-alt1-i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="daobit"
|
||||
export PROG_NAME="Сервис обновления ПО"
|
||||
export PROG_ICON="daobitcservice"
|
||||
@@ -13,7 +13,7 @@ export INSTALL_DLL="dotnet7 dotnetdesktop7 arial renderer=gdi"
|
||||
|
||||
AUTOINSTALL_EXE="${WH_TMP_DIR}/setup_cs.exe"
|
||||
AUTOINSTALL_UNPACK="${WH_TMP_DIR}/setup_cs"
|
||||
AUTOINSTALL_SETUP="${WH_TMP_DIR}/setup_cs/SETUP.EXE"
|
||||
AUTOINSTALL_SETUP="${WH_TMP_DIR}/setup_cs/Setup.exe"
|
||||
|
||||
prepair_wine
|
||||
if try_download "https://files.daobit.ru/CSERVICE/SFX/setup_cs.exe" "${AUTOINSTALL_EXE}" ; then
|
||||
@@ -25,7 +25,9 @@ if try_download "https://files.daobit.ru/CSERVICE/SFX/setup_cs.exe" "${AUTOINSTA
|
||||
wine_run_install "${AUTOINSTALL_SETUP}" /cd /targetdir="C:\\\\Program Files\\\\DAO\\\\CSERVICE" /auto /hide
|
||||
|
||||
WIN_FILE_EXEC="$DRIVE_C/Program Files/DAO/CSERVICE/CService32.exe"
|
||||
create_desktop "$PROG_NAME" "$WIN_FILE_EXEC" "$PROG_ICON"
|
||||
WIN_FAKE_EXEC="$DRIVE_C/Program Files/DAO/CSERVICE/daobit-service.exe"
|
||||
try_force_link_file "$WIN_FILE_EXEC" "$WIN_FAKE_EXEC"
|
||||
create_desktop "$PROG_NAME" "$WIN_FAKE_EXEC" "$PROG_ICON"
|
||||
try_remove_dir "$AUTOINSTALL_UNPACK"
|
||||
try_remove_file "$AUTOINSTALL_EXE"
|
||||
fi
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Построение маршрутов железнодорожных грузоперевозок
|
||||
########################################################################
|
||||
export PROG_URL="https://daobit.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586" # wine-9.0.9-alt1-i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="daobit"
|
||||
export PROG_NAME="R-Атлас"
|
||||
export PROG_ICON="daobitratlas"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Специализированная информация для организации железнодорожных перевозок
|
||||
########################################################################
|
||||
export PROG_URL="https://daobit.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586" # wine-9.0.9-alt1-i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="daobit"
|
||||
export PROG_NAME="R-Инфо"
|
||||
export PROG_ICON="daobitrinfo"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Расчёт размера провозной платы и дополнительных сборов за грузовые перевозки по железной дороге
|
||||
########################################################################
|
||||
export PROG_URL="https://daobit.ru"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586" # wine-9.0.9-alt1-i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="daobit"
|
||||
export PROG_NAME="R-Тариф"
|
||||
export PROG_ICON="daobitrtariff"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://www.keepsoft.ru"
|
||||
export PROG_NAME="Конструктор тестов"
|
||||
export AUTOINSTALL_EXE="${WH_TMP_DIR}/simulator4.exe"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="keepsoft_similator4"
|
||||
export BASE_PFX="defpfx_x86_v01"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: “КСАМУ” - Комплексная система автоматизации медицинского учреждения.
|
||||
########################################################################
|
||||
export PROG_URL="https://docs.medicine-it.ru/"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="ksamu"
|
||||
export PROG_NAME="КСАМУ"
|
||||
export PROG_ICON="ksamu"
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="T-FLEX CAD Учебная Версия 17"
|
||||
export PROG_ICON="tflexcad17"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
# используем общий whdb файл для подготовки префикса и сервисов
|
||||
# prepair_wine используется из файла настроек
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="T-FLEX CAD 17"
|
||||
export PROG_ICON="tflexcad17"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
# используем общий whdb файл для подготовки префикса и сервисов
|
||||
# prepair_wine используется из файла настроек
|
||||
|
||||
@@ -5,13 +5,12 @@ export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="Приложения для T-FLEX CAD 17"
|
||||
export PROG_ICON="tflexcad17"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
check_prefix_var
|
||||
if [[ ! -f "$WINEPREFIX/drive_c/Program Files/T-FLEX CAD 17/Program/TFlexCad.exe" ]]
|
||||
|
||||
@@ -5,13 +5,12 @@ export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="Ресурсы для T-FLEX CAD 17"
|
||||
export PROG_ICON="tflexcad17"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
check_prefix_var
|
||||
if [[ ! -f "$WINEPREFIX/drive_c/Program Files/T-FLEX CAD 17/Program/TFlexCad.exe" ]]
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="T-FLEX CAD 18"
|
||||
export PROG_ICON="tflexcad18"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex18"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
# используем общий whdb файл для подготовки префикса и сервисов
|
||||
# prepair_wine используется из файла настроек
|
||||
|
||||
@@ -5,13 +5,12 @@ export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="Приложения для T-FLEX CAD 18"
|
||||
export PROG_ICON="tflexcad18"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WINEPREFIX="tflex18"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
check_prefix_var
|
||||
if [[ ! -f "$WINEPREFIX/drive_c/Program Files/T-FLEX CAD 18/Program/TFlexCad.exe" ]]
|
||||
|
||||
@@ -5,13 +5,12 @@ export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="Ресурсы для T-FLEX CAD 18"
|
||||
export PROG_ICON="tflexcad18"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WINEPREFIX="tflex18"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
check_prefix_var
|
||||
if [[ ! -f "$WINEPREFIX/drive_c/Program Files/T-FLEX CAD 18/Program/TFlexCad.exe" ]]
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="T-FLEX CAD 2D+ 17"
|
||||
export PROG_ICON="tflexcad17"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
# используем общий whdb файл для подготовки префикса и сервисов
|
||||
# prepair_wine используется из файла настроек
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="T-FLEX CAD 2D+ 18"
|
||||
export PROG_ICON="tflexcad18"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex18"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
# используем общий whdb файл для подготовки префикса и сервисов
|
||||
# prepair_wine используется из файла настроек
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="T-FLEX DOCs 17"
|
||||
export PROG_ICON="tflexdoc17"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=gdi"
|
||||
|
||||
# используем общий whdb файл для подготовки префикса и сервисов
|
||||
# prepair_wine используется из файла настроек
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="T-FLEX Viewer 17"
|
||||
export PROG_ICON="tflexcad17"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
# используем общий whdb файл для подготовки префикса и сервисов
|
||||
# prepair_wine используется из файла настроек
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
export PROG_URL="https://www.tflexcad.ru"
|
||||
export PROG_NAME="T-FLEX Viewer 18"
|
||||
export PROG_ICON="tflexcad18"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex18"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
# используем общий whdb файл для подготовки префикса и сервисов
|
||||
# prepair_wine используется из файла настроек
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://ctm.ru"
|
||||
export PROG_NAME="ВЭД-Алфавит"
|
||||
export PROG_ICON="vedalf"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://ctm.ru"
|
||||
export PROG_NAME="ВЭД-Контроль"
|
||||
export PROG_ICON="vedcontrol"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://ctm.ru"
|
||||
export PROG_NAME="ВЭД-Декларант"
|
||||
export PROG_ICON="veddcl"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://ctm.ru"
|
||||
export PROG_NAME="ВЭД-Инфо"
|
||||
export PROG_ICON="vedinfo"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://ctm.ru"
|
||||
export PROG_NAME="ВЭД-Платежи"
|
||||
export PROG_ICON="vedpayments"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export PROG_URL="https://ctm.ru"
|
||||
export PROG_NAME="ВЭД-Склад"
|
||||
export PROG_ICON="vedsts"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ved_ctm"
|
||||
export BASE_PFX="ved_ctm_pfx_x86_v05"
|
||||
export WINEARCH="win32"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Компоненты сервисов поддержки T-FLEX 17 и 18
|
||||
########################################################################
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tflex-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export PROG_VERSION=""
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Автоматизация установки МИС Витакарта (AIS LPU Client).
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="ais-lpu-client"
|
||||
export PROG_NAME="AIS LPU Client"
|
||||
export PROG_ICON="ais_lpu_client"
|
||||
|
||||
|
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 204 KiB After Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 199 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 223 KiB |
|
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 232 KiB |
|
Before Width: | Height: | Size: 336 KiB After Width: | Height: | Size: 365 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 221 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 208 KiB |
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Специализированное программное обеспечение «Автономная станция прослушивания» предназначено для загрузки и прослушивания электронных материалов итогового собеседования.
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="desktopaudiostation"
|
||||
export PROG_NAME="АС Прослушивания"
|
||||
export PROG_ICON="desktopaudiostation"
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
# info_ru: Установщик "ЕМИАС" - Единая медицинская информационно-аналитическая система
|
||||
########################################################################
|
||||
export PROG_URL="https://emias.info/"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-11.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="emias"
|
||||
export PROG_NAME="КИС ЕМИАС"
|
||||
export BASE_PFX="emias_pfx_x64_v01"
|
||||
export BASE_PFX="none"
|
||||
export WINEARCH="win64"
|
||||
export INSTALL_DLL="crypt32"
|
||||
export WH_WINDOWS_VER="7"
|
||||
export WH_MAIN_DECORATED="0"
|
||||
export WH_USE_CPCSP_PROXY="1"
|
||||
export STAGING_SHARED_MEMORY="1"
|
||||
export WINE_LARGE_ADDRESS_AWARE="1"
|
||||
export CPCSP_PROXY_WOW64_VER="0.7.7-alt1.1-em-wow64"
|
||||
|
||||
if [[ -f "$2" ]] \
|
||||
&& [[ $(basename "$2") =~ (kis\.exe|kis_z\.exe) ]]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Специализированное программное обеспечение «Автономная станция записи» предназначено для записи ответов участников итогового собеседования.
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="isrecordingstation"
|
||||
export PROG_NAME="АС Записи"
|
||||
export PROG_ICON="isrecordingstation"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Установщик программного комплекса NetTest (демо-версия)
|
||||
########################################################################
|
||||
export PROG_URL="https://www.kpolyakov.spb.ru/prog/nettest/nettget.htm"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-amd64"
|
||||
export WINEPREFIX="nettest"
|
||||
export PROG_NAME="NetTest"
|
||||
export BASE_PFX="none"
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
# info_ru: "КИС Олимп" - программно-аналитический комплекс, состоящий из самостоятельных подключаемых модулей.
|
||||
########################################################################
|
||||
export PROG_URL="https://olimp.best/"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="olimp"
|
||||
export PROG_NAME="КИС Олимп"
|
||||
export BASE_PFX="olimp_pfx_x86_v01"
|
||||
export BASE_PFX="olimp_pfx_x86_v04"
|
||||
export WINEARCH="win32"
|
||||
export WH_WINDOWS_VER="7"
|
||||
export INSTALL_DLL="jet40 dotnet45 corefonts lucida opensymbol tahoma cjkfonts mdac28 msxml4 native_oleaut32 vcrun2005"
|
||||
export INSTALL_DLL="jet40 dotnet45 corefonts lucida opensymbol tahoma cjkfonts mdac28 msxml4 native_oleaut32 vcrun2005 ie8 itss"
|
||||
export WINEDLLOVERRIDES="d2d1=n"
|
||||
export WH_MAIN_DECORATED="0"
|
||||
export FREETYPE_PROPERTIES="truetype:interpreter-version=35"
|
||||
|
||||
if [[ -f "$2" ]] \
|
||||
&& [[ $(basename "$2") =~ (Loader\.exe) ]]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Это мощный, современный инструмент быстрой и качественной разработки АСУТП
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586" # wine-9.0.9-alt1-i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="scada-krug-2000"
|
||||
export PROG_NAME="SCADA КРУГ 2000"
|
||||
export PROG_ICON="krugtaskmanager"
|
||||
|
||||
@@ -7,7 +7,7 @@ export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=vulkan"
|
||||
|
||||
@@ -7,7 +7,7 @@ export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex18"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ export WH_WINE_USE="wine-10.18.1-tflex-alt2-wow64"
|
||||
export BASE_PFX="tflex_pfx_x64_v03"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WINEPREFIX="tflex17"
|
||||
export WINEPREFIX="tflex"
|
||||
export WH_XDG_OPEN="log"
|
||||
export WH_USE_MESA_GL_OVERRIDE="1"
|
||||
export WINE_D3D_CONFIG="renderer=gdi"
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
##### WINE WOW64 #####
|
||||
e9a8b79dfe12cad1304dca573d73aefe109e3d69b6fff739c8dbb8b2d3c271c6 wine-10.12.1-alt1-wow64.tar.xz
|
||||
a862761c432f8619caf8100589678a1cbb523787259120ccd4388089d81e3b17 wine-10.18.1-tflex-alt2-wow64.tar.xz
|
||||
349c707148a23e667970309248bbbf97b4e2a0db59c548e73d9fe9c3f585872c wine-10.18.1-alt1-wow64.tar.xz
|
||||
90676579fc97b0bdd0cc265b5c728683f8ce8d8998b020ac39d7c26ebf8783d9 wine-11.0-alt-tkg-wow64.tar.xz
|
||||
f8763bc54a4e1f1407cec8401e9ccb166b7d1aad064dd8875143717f19796bb8 wine-11.0-alt-tflex-wow64.tar.xz
|
||||
d86724bd1b3a7a798f221a6a84430d37a3f531014756b7de49c0d8444d748bd7 wine-10.9-alt-tflex-wow64.tar.xz
|
||||
df5509e1f04424d41d734a255acd3695ac1167b73e52189b97b8acc9084f7fa6 wine-10.0-alt-scadoffice-wow64.tar.xz
|
||||
714687110724f4772d4028fb340ac1c8f9a32f0454c76822c967af9ef06844eb wine-10.0-alt-tkg-wow64.tar.xz
|
||||
4826028ddd49cc6ec2760be8dbb8ff2353a58323a87c846a8667e41e90851ea1 wine-9.0-alt-tkg-wow64.tar.xz
|
||||
|
||||
##### WINE AMD64 #####
|
||||
009c95bfe2df3f9264c9c5092f3e30ea7a168dd7869046058a718a70739602d4 wine_wh_tflex_10-9_amd64.tar.xz
|
||||
71d6fdfd23d7988471d345c68e81699b8af931352b03dd216424b398f63c7b12 wine_x_tkg_10-0_amd64.tar.xz
|
||||
e0a84bb4908c3927954d7eef6b8ac7212e442b8c107d000c6890fec340f96183 wine-9.0.14-alt1-amd64.tar.xz
|
||||
f1bf1261550ca2928cefacdb724926d3d6d103433d0ff6882ee9783a50d8f4e4 wine-8.8-staging-amd64.tar.xz
|
||||
61bec1230b37b8fcc69fd45f848b44fd88cc41fcdd5dc3080336d7da63660f40 wine-7.16.1-alt1-amd64.tar.xz
|
||||
fd209c95a3aa507002374417365b3d1119dbe3a0a6d223034171221a2b187b66 wine-9.0-cx-amd64.tar.xz
|
||||
7a735f1e00173d8d3e3727aab927c4eb86aca018f39a4e8dfc1936909b8b9654 wine-11.0-alt-tkg-amd64.tar.xz
|
||||
2f3aa24fcb52a12bac35a77bf088aa8308e2e0ac3bf89f9b3f9e8e3c7090bbe8 wine-10.0-alt-tkg-amd64.tar.xz
|
||||
4251e75b410268fca9dabc168f838a56f5f02b970c6d4250763da8e791e8880d wine-9.0-alt-tkg-amd64.tar.xz
|
||||
|
||||
##### WINE I586 #####
|
||||
3571c40a787f0386e0160b5d471b1bf11fa2a235b497156cd38198b90bcb4a9f wine_x_tkg_10-0_i586.tar.xz
|
||||
fb7fdfde96de10a1b3b051bdf2727b6a7c1768b878483726454dd6726e9e0193 wine-9.0.14-alt1-i586-spravkibk.tar.xz
|
||||
6f86d2220b65b709bf88c6f829a4998de3b929cc2091cd1333a51c32e1491b79 wine-9.0.9-alt1-i586.tar.xz
|
||||
6fea17fd131f57c2ebf7ca4c60d3c5a9e819afe16e5d0b77ecb750da99ae0e38 wine-7.16.1-alt1-i586.tar.xz
|
||||
b082dc92c0ed96366353b8a9f62b126276d2476be85d2b37d47a886771a808b6 wine-11.0-alt-tkg-i586.tar.xz
|
||||
d63ae109e2495d3817172146107d9ddfd0b63a0f76b4d575279ae6b642522795 wine-10.0-alt-tkg-i586.tar.xz
|
||||
9a3160ae815b2dd008f67bf230b4e440c6b341d770b7c2a4b1a2c50283c7a895 wine-9.0-alt-tkg-i586.tar.xz
|
||||
|
||||
##### DXVK #####
|
||||
d1a86ca53ab7e156e1252d3cf7eed3c66fe0651699cfc9c4ba152024261d8258 dxvk-1.10.1-967.tar.xz
|
||||
98411effbc1b3611b11c4ca3af2ad29400b08e1c8c380791d6351600a06fb3c7 dxvk-1.10.3-28.tar.xz
|
||||
061568b51ce99d285ef2d0f1f31aab65b3e6fd34747073859c5a719bec2a7afd dxvk-1.6.1.tar.xz
|
||||
37ed4a8cd4c2bff3abbf830e6d602c2e0a971eda7c69b3f45834539bc84b1431 dxvk-2.0-116.tar.xz
|
||||
@@ -114,9 +112,9 @@ b3f56f58b5b764aba564c8b8c69eb12425467d57bf2a6457edff08842af03573 vkd3d-proton-1
|
||||
edf16d2b37bc77d121d5d81b06b60d3f694e0060c6606e729ceab30de3d27466 vkd3d-proton-sarek-2.6.0.tar.xz
|
||||
|
||||
##### CPCSP_PROXY #####
|
||||
3153088ff28d6af415c3504a421e5382554dbb305f38d5a87dd84df90d680421 wine-cpcsp_proxy-0.6.1-alt1.tar.xz
|
||||
fbe72bfe3c2c307363782ce2d37589e142b44111f269657b0e516a6b2d6ab8a9 wine-cpcsp_proxy-0.7.3-alt5-wow64.tar.xz
|
||||
5a0c582f662ac501865f569124c153b43cded72eb98a001eaa7ebd5b2168f1a2 wine-cpcsp_proxy-0.7.7-alt1.1-em-wow64.tar.xz
|
||||
6f43427148c6f424cd49a406328669e4ec4f21df7bc86f1a6aad2b5c16b50e39 wine-cpcsp_proxy-0.7.7-alt1-wow64.tar.xz
|
||||
3153088ff28d6af415c3504a421e5382554dbb305f38d5a87dd84df90d680421 wine-cpcsp_proxy-0.6.1-alt1.tar.xz
|
||||
|
||||
##### FONTS #####
|
||||
405bfe3b7c7f80034837c05656535053305727ee4bf1d993521b67b71d08ebc6 extra_fonts_v01.tar.xz
|
||||
@@ -183,10 +181,6 @@ dfb44ce5e5af7dba1686932c63d6b05e5dd6919a21c78130a7d1d0271b93958e audiorecstatio
|
||||
# create with wine_x_tkg_10-0_i586 (universal user: xuser)
|
||||
# winetricks arial dotnet7 dotnetdesktop7 renderer=gdi
|
||||
|
||||
8c6312f2e4e846a98ca4a87fc90ee1917eb28d4caaddde040fb4d2dd05f8c0fe scadaoffice_pfx_x64_v05.tar.xz
|
||||
# create with wine_x_tkg_10-0_amd64 (universal user: xuser)
|
||||
# winetricks dotnet48 gdiplus vcrun6sp6 vcrun2005 vcrun2019 d3dx11_42 d3dx11_43 d3dx9 d3dcompiler_42 d3dcompiler_43 d3dcompiler_46 d3dcompiler_47 richtx32 riched30 riched20 msxml6 dotnet20
|
||||
|
||||
ef7e8f1ba785d48e4ea287feed5b79bd630d423e59efadb43da9653adefef218 ais-lpu-client_pfx_x86_v01.tar.xz
|
||||
# create with wine_x_tkg_10-0_i586 (universal user: xuser)
|
||||
# winetricks vcrun2005 vcrun2008 dotnet20sp2 dotnet40 mfc42 7zip
|
||||
@@ -216,11 +210,15 @@ d16c300b5451e4fad6eeebeca0949367a7bdf1cb1878fc51f0f9dee33744d3a7 emias_pfx_x64_
|
||||
# create with wine-10.18.1-alt1-wow64 (universal user: xuser)
|
||||
# winetricks crypt32
|
||||
|
||||
66a31bf72aac7354956c0ce8ddb9a2858b291bb9c8b94229b0820b0119ced97f olimp_pfx_x86_v01.tar.xz
|
||||
# create with wine_x_tkg_10-0_i586 (universal user: xuser)
|
||||
# winetricks jet40 dotnet45 corefonts lucida opensymbol tahoma cjkfonts mdac28 msxml4 native_oleaut32 vcrun2005
|
||||
49cfb047297c958c7005afa0c4ced371e867b33aca33ad7572ecf7dc7b64552a olimp_pfx_x86_v04.tar.xz
|
||||
# create with wine-10.18.1-alt2-i586
|
||||
# winetricks jet40 dotnet45 corefonts lucida opensymbol tahoma cjkfonts mdac28 msxml4 native_oleaut32 vcrun2005 ie8 itss
|
||||
# + psqlodbc_x86.msi installed from script
|
||||
|
||||
4fc8ba95190d7d2cd05f60f29fe6af801f99bf046ab75bccd82bf48a600d5fc4 scadoffice_pfx_x64_v06.tar.xz
|
||||
# create with wine-10.18.1-alt1-wow64 (universal user: xuser)
|
||||
# winetricks msxml6 gdiplus vcrun6sp6 vcrun2005 ucrtbase2019 vcrun2019 d3dx9 d3dx11_43 d3dx11_42 d3dcompiler_42 d3dcompiler_43 d3dcompiler_46 d3dcompiler_47 dotnet40 dotnet48 riched20 riched30 msls31 richtx32
|
||||
|
||||
##### ADDONS #####
|
||||
# addons with ODBC, SSH, *.reg
|
||||
0f4ef434df07bc338ae308af44330590eaa1d9c94b64850514e55b960642d0eb scadoffice_addons_v02.tar.xz
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа «Декларация» позволяет автоматически формировать налоговые декларации по форме 3-НДФЛ. В процессе заполнения Вами данных программа автоматически проверяет их корректность, что уменьшает вероятность появления ошибки.
|
||||
########################################################################
|
||||
export PROG_URL="https://www.nalog.gov.ru"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="declaration"
|
||||
export PROG_NAME="Декларация"
|
||||
export PROG_ICON="declarac-2"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Программное обеспечение для 3D-графики, предназначенное для проектирования освещения. (Версия 4.4.0.2)
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="dialux"
|
||||
export PROG_NAME="DIALux"
|
||||
export PROG_ICON="dialux"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Удобная программа для создания двухмерных схем и чертежей. Основной акцент сделан на проектировании систем тепло-, водо- и газоснабжения, водоочистки, автоматизированных систем управления технологическими процессами (АСУТП), а также планов эвакуации при пожаре и авариях.
|
||||
########################################################################
|
||||
export PROG_URL="https://easymnemo.com"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="easymnemo"
|
||||
export PROG_NAME="Easymnemo"
|
||||
export PROG_ICON="easymnemo"
|
||||
|
||||
@@ -2,46 +2,118 @@
|
||||
# info_ru: Программа автоматизации процесса подготовки юридическими и физическими лицами документов для представления в налоговые органы в электронной форме и на бумажном носителе.
|
||||
########################################################################
|
||||
export PROG_URL="https://www.nalog.gov.ru"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="nalog"
|
||||
export PROG_NAME="Налогоплательщик ЮЛ"
|
||||
export PROG_ICON="npul"
|
||||
export BASE_PFX="nalog_pfx_x64_v01"
|
||||
export BASE_PFX="none"
|
||||
export WINEARCH="win64"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export WH_XDG_OPEN="doc"
|
||||
export INSTALL_DLL="msxml4 msxml6 corefonts wsh57 gdiplus"
|
||||
export INSTALL_DLL="msxml4 msxml6 corefonts wsh57 gdiplus vb6run"
|
||||
|
||||
try_get_page "https://data.nalog.ru/rn77/program/5961229/"
|
||||
VER_MSI=$(read_page | grep -oP 'NalogUL\d+\.msi' | tail -n 1 | grep -oP '\d+')
|
||||
VER_MSI_URL="${VER_MSI:0:1}.${VER_MSI:1}" # 492 → 4.92
|
||||
VER_EXE=$(read_page | grep -oP 'NalogUL\d+\.exe' | tail -n 1 | grep -oP '\d+')
|
||||
VER_EXE_URL="${VER_EXE:0:1}.${VER_EXE:1:2}.${VER_EXE:3}" # 4924 → 4.92.4
|
||||
HTML_CONTENT=$(read_page)
|
||||
|
||||
AUTOINSTALL_MSI="${WH_TMP_DIR}/NalogUL${VER_MSI}.msi"
|
||||
AUTOINSTALL_EXE="${WH_TMP_DIR}/NalogUL${VER_EXE}.exe"
|
||||
# Извлекаем все версии одним проходом (и 3, и 4 цифры, и MSI, и EXE)
|
||||
declare -A VERSIONS
|
||||
while IFS= read -r match; do
|
||||
if [[ -n "$match" ]]; then
|
||||
ver=$(echo "$match" | grep -oP '\d+')
|
||||
ext="${match##*.}"
|
||||
digits="${#ver}"
|
||||
VERSIONS["${digits}_${ext}"]="$ver"
|
||||
fi
|
||||
done < <(echo "$HTML_CONTENT" | grep -oP 'NalogUL\d{3,4}\.(msi|exe)')
|
||||
|
||||
prepair_wine
|
||||
if try_download "https://data.nalog.ru/files/nalul/${VER_MSI_URL}/NalogUL${VER_MSI}.msi" "${AUTOINSTALL_MSI}" ; then
|
||||
wine_run_install "${AUTOINSTALL_MSI}" /quiet INSTALLDIR="c:\npul"
|
||||
try_remove_file "${AUTOINSTALL_MSI}"
|
||||
|
||||
PRINT_INSTALLER="$(find "$DRIVE_C/npul/INPUTDOC" -name "Печать НД с PDF417*.msi")"
|
||||
wine_run_install "${PRINT_INSTALLER}" "/q"
|
||||
|
||||
# Процедуры конвертации, индексация данных. По завершении процедур программа сама закроется. Признаком успешного завершения будет отсутствие в папке с программой файла setupmarker.ini. Если не принять процедуру, .exe файл обновления не установиться.
|
||||
wine_run_install "$DRIVE_C/npul/INPUTDOC/inputdoc.exe" go.ini
|
||||
#TODO: Сделать запуск процедуры в тихом режиме.
|
||||
# Версия программы (3 цифры, приоритет MSI)
|
||||
if [[ -n "${VERSIONS[3_msi]}" ]]; then
|
||||
PROG_VER="${VERSIONS[3_msi]}"
|
||||
PROG_EXT="msi"
|
||||
elif [[ -n "${VERSIONS[3_exe]}" ]]; then
|
||||
PROG_VER="${VERSIONS[3_exe]}"
|
||||
PROG_EXT="exe"
|
||||
else
|
||||
print_error "Не найдена установочная версия программы"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$VER_EXE" ]] \
|
||||
&& try_download "https://data.nalog.ru/files/nalul/${VER_EXE_URL}/NalogUL${VER_EXE}.exe" "${AUTOINSTALL_EXE}"
|
||||
then
|
||||
wine_run_install "${AUTOINSTALL_EXE}" "/SILENT"
|
||||
try_remove_file "${AUTOINSTALL_EXE}"
|
||||
# Версия обновления (4 цифры, приоритет EXE)
|
||||
if [[ -n "${VERSIONS[4_exe]}" ]]; then
|
||||
UPDATE_VER="${VERSIONS[4_exe]}"
|
||||
UPDATE_EXT="exe"
|
||||
elif [[ -n "${VERSIONS[4_msi]}" ]]; then
|
||||
UPDATE_VER="${VERSIONS[4_msi]}"
|
||||
UPDATE_EXT="msi"
|
||||
else
|
||||
UPDATE_VER=""
|
||||
UPDATE_EXT=""
|
||||
fi
|
||||
|
||||
PRINT_INSTALLER="$(find "$DRIVE_C/npul/INPUTDOC" -name "Печать НД с PDF417*.msi" | tail -n 1)"
|
||||
# Формируем URL пути
|
||||
PROG_URL_PATH="${PROG_VER:0:1}.${PROG_VER:1}"
|
||||
AUTOINSTALL_PROG="${WH_TMP_DIR}/NalogUL${PROG_VER}.${PROG_EXT}"
|
||||
|
||||
if [[ -n "$UPDATE_VER" ]]; then
|
||||
UPDATE_URL_PATH="${UPDATE_VER:0:1}.${UPDATE_VER:1:2}.${UPDATE_VER:3}"
|
||||
AUTOINSTALL_UPDATE="${WH_TMP_DIR}/NalogUL${UPDATE_VER}.${UPDATE_EXT}"
|
||||
fi
|
||||
|
||||
prepair_wine
|
||||
|
||||
# Устанавливаем основную программу
|
||||
if [[ "$PROG_EXT" == "msi" ]]; then
|
||||
if try_download "https://data.nalog.ru/files/nalul/${PROG_URL_PATH}/NalogUL${PROG_VER}.msi" "${AUTOINSTALL_PROG}"; then
|
||||
wine_run_install "${AUTOINSTALL_PROG}" /quiet /norestart INSTALLDIR="c:\npul"
|
||||
try_remove_file "${AUTOINSTALL_PROG}"
|
||||
else
|
||||
print_error "Не удалось скачать установочный файл MSI"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if try_download "https://data.nalog.ru/files/nalul/${PROG_URL_PATH}/NalogUL${PROG_VER}.exe" "${AUTOINSTALL_PROG}"; then
|
||||
wine_run_install "${AUTOINSTALL_PROG}" /VERYSILENT /NORESTART /DIR="c:\npul"
|
||||
try_remove_file "${AUTOINSTALL_PROG}"
|
||||
else
|
||||
print_error "Не удалось скачать установочный файл EXE"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Устанавливаем печать PDF417
|
||||
PRINT_INSTALLER="$(find "$DRIVE_C/npul/INPUTDOC" -name "Печать НД с PDF417*.msi" | tail -n 1)"
|
||||
if [[ -n "$PRINT_INSTALLER" ]]; then
|
||||
wine_run_install "${PRINT_INSTALLER}" "/q"
|
||||
fi
|
||||
|
||||
# Процедуры конвертации, индексация данных
|
||||
wine_run_install "$DRIVE_C/npul/INPUTDOC/inputdoc.exe" go.ini
|
||||
|
||||
# Устанавливаем обновление (если есть)
|
||||
if [[ -n "$UPDATE_VER" ]]; then
|
||||
if [[ "$UPDATE_EXT" == "msi" ]]; then
|
||||
if try_download "https://data.nalog.ru/files/nalul/${UPDATE_URL_PATH}/NalogUL${UPDATE_VER}.msi" "${AUTOINSTALL_UPDATE}"; then
|
||||
wine_run_install "${AUTOINSTALL_UPDATE}" /quiet /norestart
|
||||
try_remove_file "${AUTOINSTALL_UPDATE}"
|
||||
|
||||
# После обновления может появиться новая версия печати
|
||||
PRINT_INSTALLER="$(find "$DRIVE_C/npul/INPUTDOC" -name "Печать НД с PDF417*.msi" | tail -n 1)"
|
||||
if [[ -n "$PRINT_INSTALLER" ]]; then
|
||||
wine_run_install "${PRINT_INSTALLER}" /quiet /norestart
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if try_download "https://data.nalog.ru/files/nalul/${UPDATE_URL_PATH}/NalogUL${UPDATE_VER}.exe" "${AUTOINSTALL_UPDATE}"; then
|
||||
wine_run_install "${AUTOINSTALL_UPDATE}" /VERYSILENT /NORESTART
|
||||
try_remove_file "${AUTOINSTALL_UPDATE}"
|
||||
|
||||
# После обновления может появиться новая версия печати
|
||||
PRINT_INSTALLER="$(find "$DRIVE_C/npul/INPUTDOC" -name "Печать НД с PDF417*.msi" | tail -n 1)"
|
||||
if [[ -n "$PRINT_INSTALLER" ]]; then
|
||||
wine_run_install "${PRINT_INSTALLER}" /quiet /norestart
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
print_info "Дополнительных обновлений не требуется."
|
||||
fi
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Подготовка документов для государственной регистрации (ППДГР)
|
||||
########################################################################
|
||||
export PROG_URL="https://www.nalog.gov.ru"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="ppdgr2"
|
||||
export PROG_NAME="ППДГР-2"
|
||||
export PROG_ICON="ppdgr"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Цифровая платформа для обучения и оценки специалистов нефтегазовой отрасли.
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_i586"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export PROG_NAME="РТСИМ.Карьера"
|
||||
export WINEPREFIX="rtsim"
|
||||
export PROG_ICON="rtsim"
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
# info_ru: SCAD Office — это программный комплекс для расчёта строительных конструкций.
|
||||
########################################################################
|
||||
export PROG_URL="https://scadoffice.ru"
|
||||
export WH_WINE_USE="wine-8.8-staging-amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-scadoffice-wow64"
|
||||
export WINEPREFIX="scadoffice"
|
||||
export PROG_NAME="SCAD Office"
|
||||
export PROG_ICON="scadoffice"
|
||||
export BASE_PFX="none"
|
||||
export WH_WINDOWS_VER="10"
|
||||
export BASE_PFX="scadoffice_pfx_x64_v06"
|
||||
export WH_WINDOWS_VER="7"
|
||||
export WINEARCH="win64"
|
||||
export INSTALL_DLL="dotnet48 gdiplus vcrun6sp6 vcrun2005 vcrun2019 d3dx11_42 d3dx11_43 d3dx9 d3dcompiler_42 d3dcompiler_43 d3dcompiler_46 d3dcompiler_47 richtx32 riched30 riched20 msxml6" #dotnet20
|
||||
export WH_XDG_OPEN="rtf"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Справочник кодов обозначения налоговых органов для целей учета налогоплательщиков
|
||||
########################################################################
|
||||
export PROG_URL="https://www.nalog.gov.ru"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="soun"
|
||||
export PROG_NAME="СОУН"
|
||||
export PROG_ICON="soun"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Программный комплекс для энергетики.
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine-9.0.14-alt1-amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-amd64"
|
||||
export WINEPREFIX="swmanmodus"
|
||||
export BASE_PFX="none"
|
||||
export WH_WINDOWS_VER="10"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Программный комплекс СуперОкна для фабрик по изготовлению окон и дверей.
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="swnd"
|
||||
export PROG_NAME="СуперОкна 8"
|
||||
export PROG_ICON="swnd"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: Бесплатная версия программы СуперОкна для небольших предприятий.
|
||||
########################################################################
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-i586"
|
||||
export WINEPREFIX="swnd"
|
||||
export PROG_NAME="СуперОкна 8 бесплатная"
|
||||
export PROG_ICON="swnd"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: Программа проверки файлов на соответствие форматам представления в электронном виде налоговых деклараций, бухгалтерской отчетности.
|
||||
########################################################################
|
||||
export PROG_URL="https://www.nalog.gov.ru"
|
||||
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-wow64"
|
||||
export WINEPREFIX="nalog"
|
||||
export PROG_NAME="Тестер"
|
||||
export PROG_ICON="tester"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# info_ru: ZuluGIS 2021 Инженерные расчёты (Полный) 64-бит. Включает ZuluGIS, пакеты расчетов ZuluThermo, ZuluHydro, ZuluDrain, ZuluGaz, ZuluSteam, библиотеки ZuluXTools и ZuluNetTools. Дополнительно в состав пакета входит Microsoft SQL Server Express LocalDB 2012.
|
||||
########################################################################
|
||||
export PROG_URL="https://www.politerm.com"
|
||||
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
|
||||
export WH_WINE_USE="wine-10.0-alt-tkg-amd64"
|
||||
export PROG_NAME="ZuluGIS 2021"
|
||||
export WINEPREFIX="zulugis"
|
||||
export PROG_ICON="zulugis"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
|
||||
##### CHECK ROOT #####
|
||||
if [[ $(id -u) -eq 0 ]] ; then
|
||||
@@ -6,49 +7,6 @@ if [[ $(id -u) -eq 0 ]] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
##### DEFAULT PATH #####
|
||||
export SCRIPT_NAME USER_WORK_PATH RUN_SCRIPT DATA_PATH CHANGELOG_FILE WH_ICON_PATH \
|
||||
LICENSE_FILE AGREEMENT THIRD_PARTY_FILE WH_ICON_TRAY GENERAL WH_WINETRICKS
|
||||
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
if [[ "$(realpath "$0")" == "/usr/bin/$SCRIPT_NAME" ]] ; then
|
||||
# переменные для установленного WineHelper в систему
|
||||
WH_VERSION="$(rpm -q winehelper | awk -F'-' '{print $2}')"
|
||||
USER_WORK_PATH="$HOME/.local/share/$SCRIPT_NAME"
|
||||
RUN_SCRIPT="/usr/bin/$SCRIPT_NAME"
|
||||
DATA_PATH="/usr/share/$SCRIPT_NAME"
|
||||
WH_ICON_PATH="/usr/share/icons/hicolor/scalable/apps/winehelper.svg"
|
||||
WH_ICON_TRAY="/usr/share/icons/hicolor/symbolic/apps/winehelper-symbolic.svg"
|
||||
CHANGELOG_FILE="/usr/share/doc/winehelper-$WH_VERSION/CHANGELOG"
|
||||
LICENSE_FILE="/usr/share/doc/winehelper-$WH_VERSION/LICENSE"
|
||||
AGREEMENT="/usr/share/doc/winehelper-$WH_VERSION/LICENSE_AGREEMENT"
|
||||
THIRD_PARTY_FILE="/usr/share/doc/winehelper-$WH_VERSION/THIRD-PARTY"
|
||||
GENERAL="/usr/share/doc/winehelper-$WH_VERSION/GENERAL"
|
||||
WH_WINETRICKS="/usr/bin/winetricks"
|
||||
else
|
||||
# переменные для тестового запуска WineHelper из репозитория
|
||||
USER_WORK_PATH="$HOME/test-$SCRIPT_NAME"
|
||||
RUN_SCRIPT="$(realpath "$0")"
|
||||
DATA_PATH="$(dirname "$RUN_SCRIPT")"
|
||||
CHANGELOG_FILE="$DATA_PATH/CHANGELOG"
|
||||
WH_ICON_PATH="$DATA_PATH/image/gui/winehelper-devel.svg"
|
||||
WH_ICON_TRAY="$DATA_PATH/image/gui/winehelper-symbolic.svg"
|
||||
LICENSE_FILE="$DATA_PATH/LICENSE"
|
||||
AGREEMENT="$DATA_PATH/LICENSE_AGREEMENT"
|
||||
THIRD_PARTY_FILE="$DATA_PATH/THIRD-PARTY"
|
||||
GENERAL="$DATA_PATH/GENERAL"
|
||||
WH_WINETRICKS="/usr/bin/winetricks"
|
||||
WH_DEVEL="1"
|
||||
|
||||
# минимальная проверка синтаксиса скриптов
|
||||
for self_check_script in "$RUN_SCRIPT" \
|
||||
"$DATA_PATH/dependencies.sh" "$DATA_PATH/autoinstall"/* \
|
||||
"$DATA_PATH/manualinstall"/* "$DATA_PATH/testinstall"/* \
|
||||
"$DATA_PATH/database"/*
|
||||
do /usr/bin/env bash -n "$self_check_script" || exit 1
|
||||
done
|
||||
fi
|
||||
|
||||
##### MESSAGES FUNCTIONS #####
|
||||
if [[ $WH_USE_GUI != "1" ]] ; then
|
||||
print_error () { printf "\E[31m%s Ошибка: $* %s\e[0m\n" ;}
|
||||
@@ -65,7 +23,7 @@ fi
|
||||
print_var () { for vp in $@ ; do echo "${vp}=${!vp}" ; done ;}
|
||||
|
||||
fatal () {
|
||||
print_error "$@ Аварийное завершение работы WineHelper!"
|
||||
[[ -n "$@" ]] && print_error "$@"
|
||||
[[ -n "$WINESERVER" ]] && "$WINESERVER" -w
|
||||
exit 1
|
||||
}
|
||||
@@ -80,15 +38,129 @@ print_confirmation () {
|
||||
return 0
|
||||
}
|
||||
|
||||
##### CHECK NOEXEC FOR /HOME #####
|
||||
if mount -l | grep -E "[[:space:]]/home[[:space:]]" | grep -q "noexec" ; then
|
||||
# export WH_DIST_DIR="/opt/winehelper/dist"
|
||||
# print_warning "/home примонтирован в /etc/fstab с аргументом noexec.\nИспользуем каталог $WH_DIST_DIR"
|
||||
fatal "/home примонтирован в /etc/fstab с аргументом noexec.\nЗапуск портативной версии wine невозможен из домашнего каталога."
|
||||
##### DEFAULT PATH #####
|
||||
if [[ "$(realpath "$0")" == "/usr/bin/$SCRIPT_NAME" ]] ; then
|
||||
# переменные для установленного WineHelper в систему
|
||||
USER_WORK_PATH="$HOME/.local/share/$SCRIPT_NAME"
|
||||
WH_VERSION="$(rpm -q winehelper | awk -F'-' '{print $2}')"
|
||||
RUN_SCRIPT="/usr/bin/$SCRIPT_NAME"
|
||||
DATA_PATH="/usr/share/$SCRIPT_NAME"
|
||||
WH_ICON_PATH="/usr/share/icons/hicolor/scalable/apps/winehelper.svg"
|
||||
WH_ICON_TRAY="/usr/share/icons/hicolor/symbolic/apps/winehelper-symbolic.svg"
|
||||
CHANGELOG_FILE="/usr/share/doc/winehelper-$WH_VERSION/CHANGELOG"
|
||||
LICENSE_FILE="/usr/share/doc/winehelper-$WH_VERSION/LICENSE"
|
||||
AGREEMENT="/usr/share/doc/winehelper-$WH_VERSION/LICENSE_AGREEMENT"
|
||||
THIRD_PARTY_FILE="/usr/share/doc/winehelper-$WH_VERSION/THIRD-PARTY"
|
||||
GENERAL="/usr/share/doc/winehelper-$WH_VERSION/GENERAL"
|
||||
WH_CONFIG="$HOME/.config/winehelper.conf"
|
||||
|
||||
unset CHANGE_WORK_PATH
|
||||
if [[ "$1" == "data-path" ]] ; then
|
||||
USER_WORK_PATH="$2"
|
||||
CHANGE_WORK_PATH="1"
|
||||
echo "export USER_WORK_PATH=\"$USER_WORK_PATH\"" > "$WH_CONFIG"
|
||||
fi
|
||||
|
||||
if [[ -f "$WH_CONFIG" ]] ; then
|
||||
source "$WH_CONFIG"
|
||||
fi
|
||||
|
||||
check_path_rw () {
|
||||
local check_path="$1"
|
||||
[[ -z "$check_path" ]] && return 1
|
||||
if [[ ! -d "$check_path" ]] ; then
|
||||
mkdir -p "$check_path" || return 1
|
||||
fi
|
||||
if [[ -r "$check_path" ]] \
|
||||
&& [[ -w "$check_path" ]]
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# проверка noexec для home и путей до рабочего каталога
|
||||
if mount -l | grep -E "[[:space:]]/home[[:space:]]" | grep -q "noexec" ; then
|
||||
WH_NOEXEC_HOME="1"
|
||||
|
||||
if [[ "$USER_WORK_PATH" =~ "$HOME" ]] ; then
|
||||
if [[ $1 == "gui" ]] ; then
|
||||
/usr/bin/env python3 -m winehelperqt.dialogs.noexec_warning &
|
||||
fi
|
||||
fatal \
|
||||
"/home примонтирован в /etc/fstab с аргументом noexec.
|
||||
Запуск портативной версии wine невозможен из домашнего каталога!
|
||||
|
||||
1 - вы можете либо снять флаг noexec в /etc/fstab:
|
||||
|
||||
su -
|
||||
apt-get install nano
|
||||
nano /etc/fstab
|
||||
# тут удаляем флаг noexec напротив /home
|
||||
# ctrl+o = сохранить изменения, ctrl+x = выход
|
||||
# можно использовать любой редактор, nano - как пример
|
||||
|
||||
# обновляем загрузчик
|
||||
update-grub
|
||||
exit
|
||||
|
||||
# после перезагрузки, можно приступать к работе с WineHelper
|
||||
|
||||
2 - либо изменить рабочий каталог WineHelper
|
||||
(вне /home и с доступом на чтение-запись для пользователя $USER)
|
||||
с помощью команды: $SCRIPT_NAME data-path /путь/к/каталогу
|
||||
"
|
||||
fi
|
||||
else
|
||||
WH_NOEXEC_HOME="0"
|
||||
fi
|
||||
|
||||
if check_path_rw "$USER_WORK_PATH" ; then
|
||||
print_info "Используется рабочий каталог: $USER_WORK_PATH"
|
||||
else
|
||||
fatal \
|
||||
"Нет доступа на чтение-запись в каталог: $USER_WORK_PATH
|
||||
Вы можете изменить рабочий каталог для WineHelper с помощью команды:
|
||||
$SCRIPT_NAME data-path /путь/к/каталогу"
|
||||
fi
|
||||
|
||||
if [[ "$CHANGE_WORK_PATH" == "1" ]] ; then
|
||||
print_info "Рабочий каталог изменен на: $USER_WORK_PATH"
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
export WH_DIST_DIR="$USER_WORK_PATH/dist"
|
||||
# переменные для тестового запуска WineHelper из репозитория
|
||||
USER_WORK_PATH="$HOME/test-$SCRIPT_NAME"
|
||||
RUN_SCRIPT="$(realpath "$0")"
|
||||
DATA_PATH="$(dirname "$RUN_SCRIPT")"
|
||||
CHANGELOG_FILE="$DATA_PATH/CHANGELOG"
|
||||
WH_ICON_PATH="$DATA_PATH/image/gui/winehelper-devel.svg"
|
||||
WH_ICON_TRAY="$DATA_PATH/image/gui/winehelper-symbolic.svg"
|
||||
LICENSE_FILE="$DATA_PATH/LICENSE"
|
||||
AGREEMENT="$DATA_PATH/LICENSE_AGREEMENT"
|
||||
THIRD_PARTY_FILE="$DATA_PATH/THIRD-PARTY"
|
||||
GENERAL="$DATA_PATH/GENERAL"
|
||||
WH_DEVEL="1"
|
||||
|
||||
# минимальная проверка синтаксиса скриптов
|
||||
for self_check_script in "$RUN_SCRIPT" \
|
||||
"$DATA_PATH/dependencies.sh" "$DATA_PATH/autoinstall"/* \
|
||||
"$DATA_PATH/manualinstall"/* "$DATA_PATH/testinstall"/* \
|
||||
"$DATA_PATH/database"/*
|
||||
do /usr/bin/env bash -n "$self_check_script" || exit 1
|
||||
done
|
||||
fi
|
||||
|
||||
WH_WINETRICKS="/usr/bin/winetricks"
|
||||
WH_DIST_DIR="$USER_WORK_PATH/dist"
|
||||
WH_TMP_DIR="$USER_WORK_PATH/tmp"
|
||||
|
||||
export SCRIPT_NAME USER_WORK_PATH RUN_SCRIPT DATA_PATH CHANGELOG_FILE WH_ICON_PATH \
|
||||
LICENSE_FILE AGREEMENT THIRD_PARTY_FILE WH_ICON_TRAY GENERAL WH_WINETRICKS \
|
||||
WH_TMP_DIR WH_DIST_DIR WH_NOEXEC_HOME WH_CONFIG
|
||||
|
||||
[[ ! -d "$WH_TMP_DIR" ]] && mkdir -p "$WH_TMP_DIR"
|
||||
|
||||
if [[ $1 == "gui" ]] ; then
|
||||
export WH_USE_GUI="1"
|
||||
/usr/bin/env python3 "$DATA_PATH/winehelper_gui.py" &
|
||||
@@ -121,7 +193,6 @@ fi
|
||||
##### DEFAULT VARIABLES #####
|
||||
WH_VULKAN_LIBDIR="$USER_WORK_PATH/vulkan"
|
||||
WH_PREFIXES_DIR="$USER_WORK_PATH/prefixes"
|
||||
WH_TMP_DIR="$USER_WORK_PATH/tmp"
|
||||
|
||||
WH_IMAGE_PATH="$DATA_PATH/image"
|
||||
WH_DB_DIR="$DATA_PATH/database"
|
||||
@@ -146,7 +217,7 @@ check_variables WINEFSYNC "0"
|
||||
|
||||
check_variables WINEUSERNAME "xuser"
|
||||
check_variables WINEARCH "win64" # or "win32"
|
||||
check_variables WH_WINE_USE "wine-10.18.1-alt1-wow64" # or system
|
||||
check_variables WH_WINE_USE "wine-11.0-alt-tkg-wow64" # or system
|
||||
|
||||
check_variables WH_USE_CPCSP_PROXY "0"
|
||||
check_variables CPCSP_PROXY_X86_64_VER "0.6.1-alt1"
|
||||
@@ -646,6 +717,8 @@ create_desktop () {
|
||||
|
||||
# Создаем .desktop файл
|
||||
create_new_dir "$WH_MENU_DIR"
|
||||
local startup_wm_class
|
||||
startup_wm_class="$(basename "$exe_file" | sed 's/ //g')"
|
||||
{
|
||||
echo "[Desktop Entry]"
|
||||
echo "Name=$name_desktop"
|
||||
@@ -653,9 +726,10 @@ create_desktop () {
|
||||
echo "Type=Application"
|
||||
echo "Categories=WineHelper;"
|
||||
echo "StartupNotify=true"
|
||||
echo "Terminal=false"
|
||||
echo "Path=$DATA_PATH"
|
||||
echo "Icon=$icon_file"
|
||||
echo "StartupWMClass=$(basename "$exe_file")"
|
||||
echo "StartupWMClass=${startup_wm_class}"
|
||||
} > "$USER_WORK_PATH/$desktop_filename.desktop"
|
||||
chmod +x "$USER_WORK_PATH/$desktop_filename.desktop"
|
||||
|
||||
@@ -717,7 +791,9 @@ EOF
|
||||
# Обновляем кэш desktop-файлов
|
||||
update-desktop-database "$HOME/.local/share/applications"
|
||||
|
||||
if [[ "$desktop_filename_arg" != "nocopy" ]] ; then
|
||||
if [[ "$desktop_filename_arg" != "nocopy" ]] \
|
||||
&& [[ "$WH_NOEXEC_HOME" != "1" ]]
|
||||
then
|
||||
desktop_path="$(xdg-user-dir DESKTOP)"
|
||||
print_info "В меню и на рабочем столе создан ярлык: $desktop_filename.desktop"
|
||||
cp -f "$USER_WORK_PATH/$desktop_filename.desktop" "$desktop_path"
|
||||
@@ -725,22 +801,36 @@ EOF
|
||||
print_info "В меню создан ярлык: $desktop_filename.desktop"
|
||||
fi
|
||||
|
||||
if [[ -n "$INSTALL_SCRIPT_NAME" ]] \
|
||||
&& [[ -f "$exe_file" ]]
|
||||
then
|
||||
{
|
||||
echo '#!/usr/bin/env bash'
|
||||
echo "# cmd_name: $INSTALL_SCRIPT_NAME"
|
||||
} > "$exe_file".whdb
|
||||
if [[ -f "$exe_file" ]] ; then
|
||||
if [[ -n "$INSTALL_SCRIPT_NAME" ]] && [[ -f "$INSTALL_SCRIPT" ]] ; then
|
||||
{
|
||||
echo '#!/usr/bin/env bash'
|
||||
echo "# cmd_name: $INSTALL_SCRIPT_NAME"
|
||||
} > "$exe_file".whdb
|
||||
|
||||
grep -e "info_" -e "#####" -e "PROG_URL=" -e "WINEPREFIX=" -e "INSTALL_DLL=" \
|
||||
-e "PROG_NAME=" -e "PROG_ICON=" -e "var_" -e "WH_MAIN_DECORATED" \
|
||||
-e "WH_VIRTUAL_DESKTOP" -e "WINE_TOP_WINDOW" -e "WH_FONT_SMOOTHING "\
|
||||
-e "WH_FONT_MSS_REPLACE" -e "FREETYPE_PROPERTIES" -e "WINE_D3D_CONFIG" \
|
||||
-e "WH_USE_MESA_GL_OVERRIDE" \
|
||||
"$INSTALL_SCRIPT" | awk '{$1=$1;print}' >> "$exe_file".whdb
|
||||
grep -e "info_" -e "#####" -e "PROG_URL=" \
|
||||
-e "WINEPREFIX=" -e "INSTALL_DLL=" \
|
||||
-e "PROG_NAME=" -e "PROG_ICON=" -e "var_" \
|
||||
-e "WINEDLLOVERRIDES" -e "WH_MAIN_DECORATED" \
|
||||
-e "WH_VIRTUAL_DESKTOP" -e "WH_FONT_SMOOTHING" \
|
||||
-e "WH_FONT_MSS_REPLACE" -e "FREETYPE_PROPERTIES" \
|
||||
-e "WINE_D3D_CONFIG" -e "WH_USE_MESA_GL_OVERRIDE" \
|
||||
"$INSTALL_SCRIPT" | awk '{$1=$1;print}' >> "$exe_file".whdb
|
||||
|
||||
print_info "Создан файл настроек для $exe_file"
|
||||
print_info "Создан файл настроек для $exe_file"
|
||||
elif [[ ! -f "$exe_file".whdb ]] ; then
|
||||
# Создаем минимальный .whdb файл при ручном создании ярлыка
|
||||
local prefix_name
|
||||
prefix_name="$(basename "$WINEPREFIX")"
|
||||
cat > "$exe_file".whdb <<EOF
|
||||
#!/usr/bin/env bash
|
||||
# info_ru: $name_desktop
|
||||
########################################################################
|
||||
export PROG_NAME="$name_desktop"
|
||||
export WINEPREFIX="$prefix_name"
|
||||
EOF
|
||||
print_info "Создан минимальный файл настроек для $exe_file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -781,6 +871,8 @@ check_installed_programs () {
|
||||
elif [[ "$desktop_file" =~ ${2}.desktop ]] ; then
|
||||
export EXE_PATH
|
||||
return 0
|
||||
elif [[ -f "$2" ]] ; then
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
@@ -902,6 +994,13 @@ init_wine_ver () {
|
||||
try_remove_dir "$WINEDIR/files"
|
||||
fi
|
||||
|
||||
if [[ ! -d "$WINEDIR/lib64/wine" ]] \
|
||||
&& [[ -d "$WINEDIR/lib/wine/x86_64-unix" ]]
|
||||
then
|
||||
create_new_dir "$WINEDIR/lib64/"
|
||||
try_force_link_dir "$WINEDIR/lib/wine/" "$WINEDIR/lib64/"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$WINEDIR/version" ]] ; then
|
||||
echo "$WH_WINE_USE" > "$WINEDIR/version"
|
||||
fi
|
||||
@@ -913,9 +1012,49 @@ init_wine_ver () {
|
||||
check_deps_i586
|
||||
fi
|
||||
|
||||
if [[ $WH_USE_CPCSP_PROXY == "1" ]] ; then
|
||||
check_variables "UPDATE_CPCSP_PROXY" "0"
|
||||
local cpcsp_proxy_ver
|
||||
if [[ $WH_WINE_WOW64 == "1" ]]
|
||||
then cpcsp_proxy_ver="$CPCSP_PROXY_WOW64_VER"
|
||||
else cpcsp_proxy_ver="$CPCSP_PROXY_X86_64_VER"
|
||||
fi
|
||||
if [[ ! -f "$WINEDIR/cpcsp_proxy.ver" ]] \
|
||||
|| ! grep -q "$cpcsp_proxy_ver" "$WINEDIR/cpcsp_proxy.ver"
|
||||
then
|
||||
export UPDATE_CPCSP_PROXY="1"
|
||||
local cpcsp_proxy_name="wine-cpcsp_proxy-$cpcsp_proxy_ver"
|
||||
local cpcsp_proxy_url="$CLOUD_URL/$cpcsp_proxy_name.tar.xz"
|
||||
|
||||
try_download cloud "$cpcsp_proxy_url" "$WH_TMP_DIR/$cpcsp_proxy_name.tar.xz" check256sum
|
||||
unpack "$WH_TMP_DIR/$cpcsp_proxy_name.tar.xz" "$WH_TMP_DIR"
|
||||
|
||||
if [[ $WH_WINE_WOW64 == "1" ]] ; then
|
||||
for dir_name in x86_64-unix i386-windows x86_64-windows ; do
|
||||
if [[ -f "$WINEDIR/lib64/wine/$dir_name/cpcsp_proxy.dll" ]] ; then
|
||||
try_remove_file "$WINEDIR/lib64/wine/$dir_name/cpcsp_proxy.dll"
|
||||
fi
|
||||
cp -f "$WH_TMP_DIR/$cpcsp_proxy_name/$dir_name"/* "$WINEDIR/lib64/wine/$dir_name/"
|
||||
done
|
||||
else
|
||||
for dir_name in i386-unix i386-windows ; do
|
||||
cp -f "$WH_TMP_DIR/$cpcsp_proxy_name/$dir_name"/* "$WINEDIR/lib/wine/$dir_name/"
|
||||
done
|
||||
if [[ -d "$WINEDIR/lib64" ]] ; then
|
||||
for dir_name in x86_64-unix x86_64-windows ; do
|
||||
cp -f "$WH_TMP_DIR/$cpcsp_proxy_name/$dir_name"/* "$WINEDIR/lib64/wine/$dir_name/"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
try_remove_dir "$WH_TMP_DIR/$cpcsp_proxy_name"
|
||||
echo "$cpcsp_proxy_ver" > "$WINEDIR/cpcsp_proxy.ver"
|
||||
fi
|
||||
fi
|
||||
|
||||
export WINE="$WINEDIR/bin/wine"
|
||||
export WINELOADER="$WINEDIR/bin/wine"
|
||||
export WINESERVER="$WINEDIR/bin/wineserver"
|
||||
export WINEDATADIR="$WINEDIR/share/wine"
|
||||
|
||||
if [[ -n "${PATH}" ]]
|
||||
then export PATH="$WINEDIR/bin:${PATH}"
|
||||
@@ -925,13 +1064,6 @@ init_wine_ver () {
|
||||
var_ld_library_path_update "$WINEDIR/lib"
|
||||
export WINEDLLPATH="$WINEDIR/lib/wine"
|
||||
|
||||
if [[ ! -d "$WINEDIR/lib64/wine" ]] \
|
||||
&& [[ -d "$WINEDIR/lib/wine/x86_64-unix" ]]
|
||||
then
|
||||
create_new_dir "$WINEDIR/lib64/"
|
||||
try_force_link_dir "$WINEDIR/lib/wine/" "$WINEDIR/lib64/"
|
||||
fi
|
||||
|
||||
if [[ -d "$WINEDIR/lib64" ]] \
|
||||
&& [[ ! -L "$WINEDIR/lib64/wine" ]]
|
||||
then
|
||||
@@ -945,34 +1077,6 @@ init_wine_ver () {
|
||||
export GST_PLUGIN_SYSTEM_PATH_1_0+=":$WINEDIR/lib64/gstreamer-1.0"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $WH_USE_CPCSP_PROXY == "1" ]] ; then
|
||||
local cpcsp_proxy_ver
|
||||
if [[ $WH_WINE_WOW64 == "1" ]]
|
||||
then cpcsp_proxy_ver="$CPCSP_PROXY_WOW64_VER"
|
||||
else cpcsp_proxy_ver="$CPCSP_PROXY_X86_64_VER"
|
||||
fi
|
||||
if [[ ! -f "$WINEDIR/cpcsp_proxy.ver" ]] \
|
||||
|| ! grep -q "$cpcsp_proxy_ver" "$WINEDIR/cpcsp_proxy.ver"
|
||||
then
|
||||
CPCSP_PROXY_NAME="wine-cpcsp_proxy-$cpcsp_proxy_ver"
|
||||
CPCSP_PROXY_URL="$CLOUD_URL/$CPCSP_PROXY_NAME.tar.xz"
|
||||
|
||||
try_download cloud "$CPCSP_PROXY_URL" "$WH_TMP_DIR/$CPCSP_PROXY_NAME.tar.xz" check256sum
|
||||
unpack "$WH_TMP_DIR/$CPCSP_PROXY_NAME.tar.xz" "$WH_TMP_DIR"
|
||||
|
||||
if [[ $WH_WINE_WOW64 == "1" ]] ; then
|
||||
cp -fr "$WH_TMP_DIR/$CPCSP_PROXY_NAME/"* "$WINEDIR/lib64/wine/"
|
||||
else
|
||||
cp -fr "$WH_TMP_DIR/$CPCSP_PROXY_NAME/"i386-* "$WINEDIR/lib/wine/"
|
||||
if [[ -d "$WINEDIR/lib64" ]] ; then
|
||||
cp -fr "$WH_TMP_DIR/$CPCSP_PROXY_NAME/"x86_64-* "$WINEDIR/lib64/wine/"
|
||||
fi
|
||||
fi
|
||||
try_remove_dir "$WH_TMP_DIR/$CPCSP_PROXY_NAME"
|
||||
echo "$cpcsp_proxy_ver" > "$WINEDIR/cpcsp_proxy.ver"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# use system WINE
|
||||
if [[ ! -f "/usr/bin/wine" ]] ; then
|
||||
@@ -1150,7 +1254,12 @@ check_prefix_var () {
|
||||
fi
|
||||
|
||||
export PREFIX_NAME="$(basename "$WINEPREFIX")"
|
||||
print_info "Выбран префикс: $PREFIX_NAME"
|
||||
|
||||
# Выводим сообщение только при смене префикса, чтобы избежать дублирования
|
||||
if [[ "$PREFIX_NAME" != "${WH_LAST_PREFIX_NAME:-}" ]] ; then
|
||||
print_info "Выбран префикс: $PREFIX_NAME"
|
||||
export WH_LAST_PREFIX_NAME="$PREFIX_NAME"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -1220,16 +1329,18 @@ init_wineprefix () {
|
||||
wait_wineserver
|
||||
fi
|
||||
|
||||
local winver
|
||||
if [[ "${WH_WINDOWS_VER,,}" == "xp64" ]]
|
||||
then winver="xp 64"
|
||||
else winver="$WH_WINDOWS_VER"
|
||||
fi
|
||||
if [[ -f "$WINEPREFIX/system.reg" ]] \
|
||||
&& ! grep -iq "Microsoft Windows $WH_WINDOWS_VER" "$WINEPREFIX/system.reg"
|
||||
&& ! grep -iq "Microsoft Windows ${winver}\"" "$WINEPREFIX/system.reg"
|
||||
then
|
||||
if [[ $(echo "$WH_WINDOWS_VER" | sed 's/.*/\L&/') == "xp" ]] \
|
||||
&& [[ "$WINEARCH" != "win32" ]]
|
||||
then export WH_WINDOWS_VER="xp64"
|
||||
fi
|
||||
"$WINELOADER" winecfg -v $(echo "win${WH_WINDOWS_VER}" | sed 's/.*/\L&/')
|
||||
[[ "$winver" == "xp 64" ]] && winver="xp64"
|
||||
"$WINELOADER" winecfg -v $(echo "win${winver}" | sed 's/.*/\L&/')
|
||||
wait_wineserver
|
||||
print_info "Windows версия изменена на win${WH_WINDOWS_VER}"
|
||||
print_info "Windows версия изменена на win${winver}"
|
||||
fi
|
||||
|
||||
if [[ $WH_USE_MESA_GL_OVERRIDE == "1" ]] \
|
||||
@@ -1307,11 +1418,13 @@ init_wineprefix () {
|
||||
|
||||
# добавление ассоциаций файлов для запуска нативного приложения из wine
|
||||
# пример переменной: WH_XDG_OPEN="txt doc pdf"
|
||||
check_variables WH_XDG_OPEN "0"
|
||||
check_variables WH_XDG_OPEN "default"
|
||||
|
||||
local WRAPPER="${WH_TMP_DIR}/wh-xdg-open.sh"
|
||||
local XDG_OPEN_REG="Software\Classes\xdg-open\shell\open\command"
|
||||
if [[ $WH_XDG_OPEN != "0" ]] ; then
|
||||
if [[ $WH_XDG_OPEN == "default" ]] ; then
|
||||
: # пропускаем изменения в реестре
|
||||
elif [[ $WH_XDG_OPEN != "0" ]] ; then
|
||||
# проверяем на наличие запрещённых расширений
|
||||
local forbidden_extensions="cpl dll exe lnk msi"
|
||||
for ext in $WH_XDG_OPEN; do
|
||||
@@ -1351,16 +1464,19 @@ init_wineprefix () {
|
||||
|
||||
# настраиваем префикс для работы с cpcsp_proxy
|
||||
if [[ $WH_USE_CPCSP_PROXY == "1" ]] ; then
|
||||
if ! grep -q "cpcsp_proxy.dll" "$WINEPREFIX/system.reg" \
|
||||
|| [[ $REBOOT_PFX == "1" ]]
|
||||
if [[ $WH_FORCE_UPDATE_CERT == "1" ]] \
|
||||
|| [[ $UPDATE_CPCSP_PROXY == "1" ]] \
|
||||
|| [[ $REBOOT_PFX == "1" ]] \
|
||||
|| ! grep -q "cpcsp_proxy.dll" "$WINEPREFIX/system.reg"
|
||||
then
|
||||
print_info "Запускаем настройку cpcsp_proxy..."
|
||||
CPCSP_PROXY_OK="0"
|
||||
|
||||
try_copy_wine_dll_to_pfx_64 "cpcsp_proxy.dll"
|
||||
try_copy_wine_dll_to_pfx_32 "cpcsp_proxy.dll"
|
||||
|
||||
if [[ $WH_WINE_WOW64 == "1" ]] ; then
|
||||
print_info "Запускаем настройку cpcsp_proxy версии $CPCSP_PROXY_WOW64_VER"
|
||||
|
||||
print_info "Запускаем регистрацию 64-битного cpcsp_proxy.dll..."
|
||||
env WINEDEBUG="fixme-all" "$WINE" "C:\\windows\\system32\\regsvr32.exe" \
|
||||
/s /n /i cpcsp_proxy.dll 2>&1 | tee "$WINEPREFIX/cpcsp_setup.log"
|
||||
@@ -1371,6 +1487,8 @@ init_wineprefix () {
|
||||
/s /n /i cpcsp_proxy.dll 2>&1 | tee -a "$WINEPREFIX/cpcsp_setup.log"
|
||||
wait_wineserver
|
||||
else
|
||||
print_info "Запускаем настройку cpcsp_proxy версии $CPCSP_PROXY_X86_64_VER"
|
||||
|
||||
try_copy_wine_dll_to_pfx_64 "cpcsp_proxy_setup.exe"
|
||||
try_copy_wine_dll_to_pfx_32 "cpcsp_proxy_setup.exe"
|
||||
|
||||
@@ -1388,8 +1506,14 @@ init_wineprefix () {
|
||||
done
|
||||
fi
|
||||
|
||||
if grep -q "failed to load /opt/cprocsp/" "$WINEPREFIX/cpcsp_setup.log" ; then
|
||||
print_error "Проверьте правильность установки КриптоПро в системе.\n Инструкция: https://www.altlinux.org/CryptoPro"
|
||||
if [[ ! -d "/opt/cprocsp/" ]] \
|
||||
|| grep -q "failed to load /opt/cprocsp/" "$WINEPREFIX/cpcsp_setup.log"
|
||||
then
|
||||
print_error "Проверьте правильность установки КриптоПро в системе!
|
||||
|
||||
Официальный сайт КриптоПро: https://cryptopro.ru/products/csp
|
||||
Инструкция установки КриптоПро в систему: https://www.altlinux.org/CryptoPro
|
||||
"
|
||||
else
|
||||
CPCSP_PROXY_OK="1"
|
||||
fi
|
||||
@@ -1397,7 +1521,7 @@ init_wineprefix () {
|
||||
|
||||
if [[ $CPCSP_PROXY_OK == "1" ]]
|
||||
then print_info "Настройка cpcsp_proxy успешно завершена."
|
||||
else fatal "Ошибка во время настройки cpcsp_proxy."
|
||||
else fatal
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -1423,8 +1547,8 @@ init_wineprefix () {
|
||||
fi
|
||||
for var in WH_WINE_USE BASE_PFX WINEARCH WH_WINDOWS_VER WINEESYNC WINEFSYNC \
|
||||
STAGING_SHARED_MEMORY WINE_LARGE_ADDRESS_AWARE WH_USE_SHADER_CACHE WH_USE_WINE_DXGI \
|
||||
WINE_CPU_TOPOLOGY DXVK_VER VKD3D_VER WH_XDG_OPEN WH_USE_CPCSP_PROXY WH_USE_EXTRA_FONTS \
|
||||
WINEUSERNAME
|
||||
WINE_CPU_TOPOLOGY DXVK_VER VKD3D_VER WH_XDG_OPEN WH_USE_EXTRA_FONTS \
|
||||
WINEUSERNAME WH_USE_CPCSP_PROXY CPCSP_PROXY_X86_64_VER CPCSP_PROXY_WOW64_VER
|
||||
do
|
||||
update_last_conf_var "$var" "${!var}"
|
||||
done
|
||||
@@ -1533,7 +1657,13 @@ prepair_wine () {
|
||||
init_dxvk "$DXVK_VER"
|
||||
init_vkd3d "$VKD3D_VER"
|
||||
|
||||
[[ "$MANGOHUD" == 1 ]] && MANGOHUD_RUN="mangohud"
|
||||
if [[ "$MANGOHUD" == 1 ]] ; then
|
||||
if command -v mangohud &>/dev/null ; then
|
||||
MANGOHUD_RUN="mangohud"
|
||||
else
|
||||
print_error "mangohud не найден в системе"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
wine_regfile () {
|
||||
@@ -1553,12 +1683,12 @@ wine_regfile () {
|
||||
wine_run () {
|
||||
local wh_add_args win_file_exec win_file_path win_file_name
|
||||
|
||||
if [[ $1 =~ (winecfg|regedit|winefile|wineconsole|control) ]] ; then
|
||||
if [[ $1 =~ (winecfg|regedit|winefile|wineconsole|control|uninstaller) ]] ; then
|
||||
win_file_exec="$1"
|
||||
win_file_name="$win_file_exec"
|
||||
win_file_path="$DRIVE_C"
|
||||
wh_add_args=""
|
||||
elif [[ $1 =~ \.dll$ ]] ; then
|
||||
elif [[ "${1,,}" =~ \.(dll|ocx)$ ]] ; then
|
||||
wine_regfile regsvr32 /s "$@"
|
||||
return 0
|
||||
elif [[ -f "$1" ]] ; then
|
||||
@@ -1604,6 +1734,32 @@ wine_run () {
|
||||
|
||||
echo -e "\n##### Лог WINE #####" | tee -a "$log_file"
|
||||
$MANGOHUD_RUN "$WINELOADER" $wh_add_args "$win_file_exec" "$@" 2>&1 | tee -a "$log_file"
|
||||
|
||||
# Проверка размера лога и создание архива при превышении порога
|
||||
local MAX_LOG_SIZE_MB=10
|
||||
local MAX_LOG_SIZE_BYTES=$((MAX_LOG_SIZE_MB * 1048576))
|
||||
local log_size_bytes log_size_mb
|
||||
log_size_bytes=$(stat -c%s "$log_file" 2>/dev/null || echo 0)
|
||||
log_size_mb=$((log_size_bytes / 1048576))
|
||||
|
||||
if (( log_size_bytes > MAX_LOG_SIZE_BYTES )); then
|
||||
local timestamp archive_name archive_path
|
||||
timestamp=$(date +"%d.%m.%Y-%H.%M")
|
||||
archive_name="log_${PREFIX_NAME}_${win_file_name%.*}_${timestamp}.tar.xz"
|
||||
archive_path="$log_dir/$archive_name"
|
||||
|
||||
print_warning "Файл лога больше ${MAX_LOG_SIZE_MB}Мб (размер: ${log_size_mb}Мб)."
|
||||
print_warning "Создаем сжатый архив: $archive_name"
|
||||
|
||||
tar -cJf "$archive_path" -C "$log_dir" "$(basename "$log_file")"
|
||||
|
||||
if [[ -f "$archive_path" ]]; then
|
||||
print_ok "Архив успешно создан: $archive_path"
|
||||
rm -f "$log_file"
|
||||
else
|
||||
print_error "Не удалось создать архив: $archive_path"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
$MANGOHUD_RUN "$WINELOADER" $wh_add_args "$win_file_exec" "$@"
|
||||
fi
|
||||
@@ -1612,9 +1768,47 @@ wine_run () {
|
||||
cd "$DRIVE_C"
|
||||
}
|
||||
|
||||
wine_debug_run () {
|
||||
local winedbg_args win_file_exec win_file_path win_file_name wh_add_args
|
||||
|
||||
winedbg_args="$1"
|
||||
[[ "$winedbg_args" == "--interactive" ]] && winedbg_args=""
|
||||
shift
|
||||
|
||||
if [[ -f "$1" ]]; then
|
||||
win_file_exec="$(readlink -f "$1")"
|
||||
win_file_path="$(dirname "$win_file_exec")"
|
||||
win_file_name="$(basename "$win_file_exec")"
|
||||
else
|
||||
fatal "Файл не найден: $1"
|
||||
fi
|
||||
|
||||
shift
|
||||
cd "$win_file_path"
|
||||
|
||||
local log_dir log_file
|
||||
log_dir="$HOME/winehelper_backup_log"
|
||||
log_file="$log_dir/winedbg_${PREFIX_NAME}_${win_file_name%.*}.log"
|
||||
create_new_dir "$log_dir"
|
||||
date > "$log_file"
|
||||
echo -e "\n##### Основные переменные #####" | tee -a "$log_file"
|
||||
env | grep -e "WH_" -e "WINE" -e "DXVK" -e "VKD3D" -e "LD_" \
|
||||
| grep -v "ICON" | sort | tee -a "$log_file"
|
||||
echo -e "\n##### WineHelper Debug Mode: winedbg $winedbg_args #####" | tee -a "$log_file"
|
||||
|
||||
print_info "Запуск отладчика (режим: $winedbg_args)"
|
||||
print_warning "Лог отладки будет сохранен по пути: $log_file"
|
||||
|
||||
"$WINELOADER" winedbg $winedbg_args "$win_file_exec" "$@" 2>&1 | tee -a "$log_file"
|
||||
|
||||
wait_wineserver
|
||||
cd "$DRIVE_C"
|
||||
}
|
||||
|
||||
wine_run_install () {
|
||||
print_info "Запускаем установку: $1."
|
||||
case "$WH_INSTALL_MODE" in
|
||||
"another") print_warning "Используется скрипт сторонний установки!" ;;
|
||||
"manual") print_warning "Рекомендуется не менять пути для установки приложения!" ;;
|
||||
"test") print_warning "Установка приложения из списка экспериментальных скриптов." ;;
|
||||
esac
|
||||
@@ -1643,6 +1837,9 @@ run_autoinstall () {
|
||||
elif [[ -f "$WH_TESTINSTALL_DIR/$INSTALL_SCRIPT_NAME" ]] ; then
|
||||
INSTALL_SCRIPT="$WH_TESTINSTALL_DIR/$INSTALL_SCRIPT_NAME"
|
||||
WH_INSTALL_MODE="test"
|
||||
elif [[ -f "$1" ]] ; then
|
||||
INSTALL_SCRIPT="$1"
|
||||
WH_INSTALL_MODE="another"
|
||||
else
|
||||
INSTALL_SCRIPT="0"
|
||||
fi
|
||||
@@ -1994,8 +2191,8 @@ create_prefix() {
|
||||
|
||||
prefix_name=${prefix_name:-default}
|
||||
|
||||
if [[ ! "$prefix_name" =~ ^[a-zA-Z0-9_.-]+$ ]] ; then
|
||||
fatal "Имя префикса может содержать только латинские буквы, цифры, точки, дефисы и подчеркивания"
|
||||
if [[ ! "$prefix_name" =~ ^[a-zA-Z0-9_-]+$ ]] ; then
|
||||
fatal "Имя префикса может содержать только латинские буквы, цифры, дефисы и подчеркивания"
|
||||
fi
|
||||
|
||||
if [[ -d "$WH_PREFIXES_DIR/$prefix_name" ]] ; then
|
||||
@@ -2082,7 +2279,7 @@ remove_winehelper () {
|
||||
|
||||
# Удаление desktop-файлов
|
||||
for desktop_file in "$(xdg-user-dir DESKTOP)"/*.desktop; do
|
||||
if grep -q "Exec=env \"$RUN_SCRIPT\"" "$desktop_file"; then
|
||||
if [[ -f "$desktop_file" ]] && grep -q "Exec=env \"$RUN_SCRIPT\"" "$desktop_file"; then
|
||||
try_remove_file "$desktop_file"
|
||||
fi
|
||||
done
|
||||
@@ -2170,9 +2367,9 @@ backup_prefix() {
|
||||
local backup_base_dir backup_archive_name backup_dest_path temp_backup_dir temp_prefix_dir temp_users_dir
|
||||
backup_base_dir="$HOME/winehelper_backup_log"
|
||||
create_new_dir "$backup_base_dir"
|
||||
backup_archive_name="backup_${PREFIX_NAME}_$(date +%d.%m.%Y-%H.%M.%S).whpack"
|
||||
backup_archive_name="backup_${PREFIX_NAME}_$(date +%d.%m.%Y-%H.%M).whpack"
|
||||
backup_dest_path="$backup_base_dir/$backup_archive_name"
|
||||
temp_backup_dir="$WH_TMP_DIR/backup_${PREFIX_NAME}_$(date +%d.%m.%Y-%H.%M.%S)"
|
||||
temp_backup_dir="$WH_TMP_DIR/backup_${PREFIX_NAME}_$(date +%d.%m.%Y-%H.%M)"
|
||||
temp_prefix_dir="$temp_backup_dir/prefixes/$PREFIX_NAME"
|
||||
temp_users_dir="$temp_prefix_dir/drive_c/users"
|
||||
|
||||
@@ -2205,13 +2402,11 @@ backup_prefix() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -n "$WH_WINE_USE" ]] \
|
||||
&& [[ $WH_WINE_USE != system* ]] \
|
||||
&& [[ -d "$WH_DIST_DIR/$WH_WINE_USE" ]]
|
||||
then
|
||||
if [[ $WH_WINE_USE != system* ]] ; then
|
||||
init_wine_ver
|
||||
print_info "Копирование используемой версии WINE: $WH_WINE_USE"
|
||||
|
||||
if cp -a "$WH_DIST_DIR/$WH_WINE_USE" "$temp_backup_dir/dist/"
|
||||
if cp -aL "$WH_DIST_DIR/$WH_WINE_USE" "$temp_backup_dir/dist/"
|
||||
then print_ok "WINE скопирован."
|
||||
else fatal "Не удалось скопировать WINE."
|
||||
fi
|
||||
@@ -2221,7 +2416,7 @@ backup_prefix() {
|
||||
echo "$PREFIX_NAME" > "$temp_backup_dir/prefix_name.whmeta"
|
||||
|
||||
print_info "Создание squashfs архива..."
|
||||
if mksquashfs "$temp_backup_dir" "$backup_dest_path" -comp zstd ; then
|
||||
if mksquashfs "$temp_backup_dir" "$backup_dest_path" -comp xz ; then
|
||||
print_ok "Архив префикса $PREFIX_NAME успешно создан по пути:\n$backup_dest_path"
|
||||
else
|
||||
print_error "Не удалось создать архив префикса $PREFIX_NAME."
|
||||
@@ -2285,7 +2480,7 @@ restore_prefix() {
|
||||
|
||||
if [[ -d "$WH_PREFIXES_DIR/$prefix_name" ]] ; then
|
||||
try_remove_dir "$temp_extract_dir"
|
||||
fatal "Префикс $prefix_name уже существует!\n Удалите его, если действительно желаете восстановить префикс заново.\n Команда для удаления: $SCRIPT_NAME remove-prefix $prefix_name"
|
||||
fatal "Префикс $prefix_name уже существует!\n Удалите его перед восстановлением префикса заново.\n Команда для удаления: $SCRIPT_NAME remove-prefix $prefix_name"
|
||||
fi
|
||||
|
||||
if [[ -d "$temp_extract_dir/prefixes/$prefix_name" ]] ; then
|
||||
@@ -2306,16 +2501,17 @@ restore_prefix() {
|
||||
try_remove_dir "$temp_extract_dir"
|
||||
fatal "Не удалось восстановить префикс $prefix_name."
|
||||
else
|
||||
print_ok "Префикс $prefix_name восстановлен."
|
||||
|
||||
export WINEPREFIX="$WH_PREFIXES_DIR/$prefix_name"
|
||||
if [[ -f "$WINEPREFIX/last.conf" ]] ; then
|
||||
source "$WINEPREFIX/last.conf"
|
||||
export REBOOT_PFX="1"
|
||||
prepair_wine
|
||||
if [[ -f "$WINEPREFIX/restore_pfx.sh" ]] ; then
|
||||
source "$WINEPREFIX/restore_pfx.sh"
|
||||
try_copy_file "$WINEPREFIX/restore_pfx.sh" "$WH_TMP_DIR/restore_${prefix_name}_pfx.sh"
|
||||
source "$WH_TMP_DIR/restore_${prefix_name}_pfx.sh"
|
||||
fi
|
||||
fi
|
||||
print_ok "Префикс $prefix_name восстановлен."
|
||||
|
||||
if [[ -f "$WH_PREFIXES_DIR/$prefix_name/desktop.list" ]] ; then
|
||||
print_info "Восстановление ярлыков для префикса $prefix_name..."
|
||||
@@ -2342,6 +2538,7 @@ restore_prefix() {
|
||||
fi
|
||||
|
||||
try_remove_dir "$temp_extract_dir"
|
||||
try_remove_file "$WH_TMP_DIR/restore_${prefix_name}_pfx.sh"
|
||||
print_ok "Полное восстановление префикса $prefix_name завершено."
|
||||
return 0
|
||||
}
|
||||
@@ -2528,7 +2725,6 @@ run_install_vkd3d() {
|
||||
run_change_wine_version() {
|
||||
local new_version="$1"
|
||||
|
||||
check_prefix_var
|
||||
init_database
|
||||
|
||||
if [[ -z "$new_version" ]]; then
|
||||
@@ -2575,13 +2771,19 @@ wh_info () {
|
||||
install list список возможных установочных скриптов
|
||||
install [скрипт] запустить скрипт установки программы
|
||||
install [скрипт] --clear-pfx не использовать готовый префикс для установки ПО
|
||||
install \"путь/до/скрипта\" запустить сторонний скрипт установки
|
||||
|
||||
install-dxvk [версия|none|list] установить, удалить или показать версии DXVK
|
||||
install-vkd3d [версия|none|list] установить, удалить или показать версии VKD3D
|
||||
change-wine [версия] изменить версию Wine для текущего префикса
|
||||
|
||||
installed список установленных программ
|
||||
run [программа] запуск программы (отладка)
|
||||
run [программа] запуск программы
|
||||
debug [флаги] [программа] запуск программы в отладчике winedbg
|
||||
Флаги:
|
||||
--auto, -a автоматический backtrace
|
||||
--gdb, -g режим gdb
|
||||
--interactive, -i интерактивный режим
|
||||
remove-all удалить WineHelper и все связанные данные
|
||||
create-prefix создать префикс
|
||||
remove-prefix [имя_префикса] удалить префикс и все связанные данные
|
||||
@@ -2589,6 +2791,16 @@ wh_info () {
|
||||
restore-prefix \"путь/до/whpack\" восстановить префикс из резервной копии
|
||||
clear-winetricks-cache очистить кэш Winetricks
|
||||
|
||||
winecfg запуск wine конфигуратора для префикса
|
||||
winereg запуск редактора реестра для префикса
|
||||
winefile запуск файлового менеджера wine
|
||||
wineconsole запуск терминала wine (cmd.exe)
|
||||
control запуск панели управления wine
|
||||
uninstaller запуск удаления программ wine
|
||||
winetricks [компонент] автоматическая установка дополнительного компонента в префикс
|
||||
killall остановить все процессы Wine
|
||||
run-in-prefix <префикс> <файл> запустить файл в указанном префиксе
|
||||
|
||||
Параметры:
|
||||
--help показать эту справку и выйти
|
||||
--version показать информацию о пакете и его версии
|
||||
@@ -2605,9 +2817,8 @@ create_new_dir "$WH_PREFIXES_DIR"
|
||||
create_new_dir "$WH_VULKAN_LIBDIR"
|
||||
|
||||
if [[ $WH_DEVEL != "1" ]] \
|
||||
&& [[ -d "$HOME/.local/share/$SCRIPT_NAME" ]] \
|
||||
&& [[ ! -L "$HOME/.winehelper" ]]
|
||||
then try_force_link_dir "$HOME/.local/share/$SCRIPT_NAME" "$HOME/.winehelper"
|
||||
then try_force_link_dir "$USER_WORK_PATH" "$HOME/.winehelper"
|
||||
fi
|
||||
|
||||
if [[ -n "$1" ]] ; then
|
||||
@@ -2627,6 +2838,7 @@ case "$arg1" in
|
||||
winefile|explorer) prepair_wine ; wine_run "winefile" ;;
|
||||
wineconsole|cmd) prepair_wine ; wine_run "wineconsole" ;;
|
||||
control) prepair_wine ; wine_run "control" ;;
|
||||
uninstaller) prepair_wine ; wine_run "uninstaller" ;;
|
||||
winetricks) prepair_wine ; "$WH_WINETRICKS" -q "$@" ;;
|
||||
desktop) create_desktop "$@" ; exit 0 ;;
|
||||
install|-i) run_autoinstall "$@" ;;
|
||||
@@ -2651,6 +2863,22 @@ case "$arg1" in
|
||||
wine_run "$WIN_FILE_EXEC" "$@"
|
||||
fi
|
||||
;;
|
||||
debug)
|
||||
case "$1" in
|
||||
--gdb|-g) debug_flag="--gdb" ;;
|
||||
--interactive|-i) debug_flag="--interactive" ;;
|
||||
--auto|-a) debug_flag="--auto" ;;
|
||||
*) fatal "Неизвестный флаг отладки!" ;;
|
||||
esac
|
||||
shift
|
||||
|
||||
if check_installed_programs check_only "$1" ; then
|
||||
WIN_FILE_EXEC="$(readlink -f "$EXE_PATH")"
|
||||
shift
|
||||
prepair_wine
|
||||
wine_debug_run $debug_flag "$WIN_FILE_EXEC" "$@"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if [[ -f "$arg1" ]] ; then
|
||||
WIN_FILE_EXEC="$(readlink -f "$arg1")"
|
||||
@@ -2665,6 +2893,9 @@ case "$arg1" in
|
||||
else
|
||||
wine_run "$WIN_FILE_EXEC" "$@"
|
||||
fi
|
||||
elif [[ "${arg1,,}" =~ \.dll ]] ; then
|
||||
prepair_wine
|
||||
wine_run "$arg1"
|
||||
else
|
||||
print_error "Команды $arg1 не существует."
|
||||
wh_info
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
GUI пакет для winehelper.
|
||||
|
||||
Модульная структура:
|
||||
- dialogs: Диалоги (выбор версий, настройки и т.д.)
|
||||
- widgets: Кастомные виджеты
|
||||
- services: Бизнес-логика (кэширование, установка и т.д.)
|
||||
- parsers: Парсеры (sha256sum.list, winetricks output)
|
||||
- utils: Утилиты (обработчики логов и т.д.)
|
||||
"""
|
||||
|
||||
# Parsers
|
||||
from winehelperqt.parsers.sha256_parser import Sha256Parser
|
||||
from winehelperqt.parsers.winetricks_parser import WinetricksOutputParser
|
||||
from winehelperqt.parsers.script_parser import ScriptParser
|
||||
|
||||
# Utils
|
||||
from winehelperqt.utils.log_handler import LogProgressHandler, MultiLogHandler
|
||||
from winehelperqt.utils.cache_service import CacheService, FileCacheService
|
||||
|
||||
# Services
|
||||
from winehelperqt.services.winetricks_service import WinetricksCacheService
|
||||
from winehelperqt.services.winetricks_service import WinetricksLogReader
|
||||
from winehelperqt.services.prefix_manager import PrefixManager
|
||||
from winehelperqt.services.process_handler import ProcessHandler
|
||||
from winehelperqt.services.process_handler import CommandRunner
|
||||
from winehelperqt.services.desktop_file_manager import DesktopFileManager
|
||||
from winehelperqt.services.script_manager import ScriptManager
|
||||
from winehelperqt.services.script_manager import ScriptInfo
|
||||
from winehelperqt.services.installation_manager import InstallationManager
|
||||
from winehelperqt.services.app_launcher import AppLauncher
|
||||
from winehelperqt.services.settings_manager import SettingsManager
|
||||
|
||||
# Widgets
|
||||
from winehelperqt.widgets.icon_manager import IconManager
|
||||
|
||||
# Dialogs
|
||||
from winehelperqt.dialogs.winetricks_manager import WinetricksManagerDialog
|
||||
from winehelperqt.dialogs.noexec_warning import NoExecWarningDialog
|
||||
|
||||
__all__ = [
|
||||
# Parsers
|
||||
'Sha256Parser',
|
||||
'WinetricksOutputParser',
|
||||
'ScriptParser',
|
||||
|
||||
# Utils
|
||||
'LogProgressHandler',
|
||||
'MultiLogHandler',
|
||||
'CacheService',
|
||||
'FileCacheService',
|
||||
|
||||
# Services
|
||||
'WinetricksCacheService',
|
||||
'WinetricksLogReader',
|
||||
'PrefixManager',
|
||||
'ProcessHandler',
|
||||
'CommandRunner',
|
||||
'DesktopFileManager',
|
||||
'ScriptManager',
|
||||
'ScriptInfo',
|
||||
'InstallationManager',
|
||||
'AppLauncher',
|
||||
'SettingsManager',
|
||||
|
||||
# Widgets
|
||||
'IconManager',
|
||||
|
||||
# Dialogs
|
||||
'WinetricksManagerDialog',
|
||||
'NoExecWarningDialog',
|
||||
]
|
||||
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
Диалоги для winehelper GUI.
|
||||
"""
|
||||
from winehelperqt.dialogs.base_version_dialog import (
|
||||
BaseVersionSelectionDialog,
|
||||
WineVersionSelectionDialogBase,
|
||||
ComponentVersionSelectionDialogBase,
|
||||
)
|
||||
from winehelperqt.dialogs.winetricks_manager import WinetricksManagerDialog
|
||||
from winehelperqt.dialogs.wine_version import WineVersionSelectionDialog
|
||||
from winehelperqt.dialogs.component_version import ComponentVersionSelectionDialog
|
||||
from winehelperqt.dialogs.create_prefix import CreatePrefixDialog
|
||||
from winehelperqt.dialogs.file_associations import FileAssociationsDialog
|
||||
from winehelperqt.dialogs.settings import AdditionalSettingsDialog, AppAdditionalSettingsDialog
|
||||
from winehelperqt.dialogs.noexec_warning import NoExecWarningDialog
|
||||
|
||||
__all__ = [
|
||||
# Base classes
|
||||
'BaseVersionSelectionDialog',
|
||||
'WineVersionSelectionDialogBase',
|
||||
'ComponentVersionSelectionDialogBase',
|
||||
|
||||
# Dialogs
|
||||
'WinetricksManagerDialog',
|
||||
'WineVersionSelectionDialog',
|
||||
'ComponentVersionSelectionDialog',
|
||||
'CreatePrefixDialog',
|
||||
'FileAssociationsDialog',
|
||||
'AdditionalSettingsDialog',
|
||||
'AppAdditionalSettingsDialog',
|
||||
'NoExecWarningDialog',
|
||||
]
|
||||
@@ -0,0 +1,313 @@
|
||||
"""
|
||||
Базовые классы для диалогов выбора версий.
|
||||
Устраняет дублирование кода между WineVersionSelectionDialog и ComponentVersionSelectionDialog.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QGridLayout, QScrollArea,
|
||||
QTabWidget, QLineEdit, QPushButton, QLabel, QWidget, QMessageBox
|
||||
)
|
||||
from PyQt5.QtCore import Qt, pyqtSignal
|
||||
|
||||
from winehelperqt.parsers.sha256_parser import Sha256Parser
|
||||
from winehelperqt.utils.environment import EnvironmentConfig
|
||||
from winehelperqt.utils.grid_utils import GridUtils
|
||||
|
||||
|
||||
class BaseVersionSelectionDialog(QDialog):
|
||||
"""
|
||||
Базовый класс для диалогов выбора версий.
|
||||
|
||||
Предоставляет общую функциональность:
|
||||
- Поле поиска с фильтрацией
|
||||
- Сетка кнопок с версиями
|
||||
- Базовая логика выбора версии
|
||||
"""
|
||||
|
||||
NUM_COLUMNS = 3
|
||||
|
||||
version_selected = pyqtSignal(str)
|
||||
|
||||
def __init__(self, title, parent=None, min_width=600, min_height=400):
|
||||
"""
|
||||
Инициализирует базовый диалог выбора версий.
|
||||
"""
|
||||
super().__init__(parent)
|
||||
|
||||
self.setWindowTitle(title)
|
||||
self.setMinimumSize(min_width, min_height)
|
||||
self.setModal(True)
|
||||
|
||||
self.selected_version = None
|
||||
self.buttons = []
|
||||
self.search_edit = None
|
||||
self.main_layout = None
|
||||
|
||||
self._setup_ui()
|
||||
|
||||
def _get_sha256_path(self):
|
||||
"""Возвращает путь к файлу sha256sum.list."""
|
||||
data_path = EnvironmentConfig.DATA_PATH
|
||||
if data_path:
|
||||
return os.path.join(data_path, "sha256sum.list")
|
||||
# Фолбэк: явно разрешаем путь из расположения пакета
|
||||
return os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), '..', '..', 'sha256sum.list')
|
||||
)
|
||||
|
||||
def _setup_ui(self):
|
||||
"""Создает базовый UI диалога."""
|
||||
self.main_layout = QVBoxLayout(self)
|
||||
|
||||
self.search_edit = QLineEdit()
|
||||
self.search_edit.setPlaceholderText("Поиск версии...")
|
||||
self.search_edit.textChanged.connect(self.filter_versions)
|
||||
self.main_layout.addWidget(self.search_edit)
|
||||
|
||||
self._create_version_container()
|
||||
|
||||
def _create_version_container(self):
|
||||
"""Создает контейнер для отображения версий."""
|
||||
raise NotImplementedError("Подкласс должен реализовать _create_version_container")
|
||||
|
||||
def load_versions(self):
|
||||
"""Загружает список версий."""
|
||||
raise NotImplementedError("Подкласс должен реализовать load_versions")
|
||||
|
||||
def filter_versions(self):
|
||||
"""Фильтрует версии по тексту поиска."""
|
||||
grid_layout = getattr(self, 'grid_layout', None)
|
||||
GridUtils.filter_buttons(
|
||||
self.buttons, self.search_edit.text(), grid_layout, self.NUM_COLUMNS
|
||||
)
|
||||
|
||||
def on_version_selected(self, version_name):
|
||||
"""Обрабатывает выбор версии."""
|
||||
self.selected_version = version_name
|
||||
self.version_selected.emit(version_name)
|
||||
self.accept()
|
||||
|
||||
def get_selected_version(self):
|
||||
"""Возвращает выбранную версию."""
|
||||
return self.selected_version
|
||||
|
||||
@staticmethod
|
||||
def create_grid_buttons(
|
||||
grid_layout,
|
||||
versions_list,
|
||||
on_click_callback,
|
||||
start_row=0,
|
||||
num_columns=3,
|
||||
is_download_tab=False,
|
||||
version_filter=None
|
||||
):
|
||||
"""Создает сетку кнопок для версий."""
|
||||
buttons = []
|
||||
row, col = start_row, 0
|
||||
|
||||
for version_data in versions_list:
|
||||
if isinstance(version_data, tuple):
|
||||
display_name, value_name = version_data
|
||||
else:
|
||||
display_name = value_name = version_data
|
||||
|
||||
btn = QPushButton(display_name)
|
||||
btn.clicked.connect(lambda checked, vn=value_name: on_click_callback(vn))
|
||||
|
||||
if version_filter and not is_download_tab:
|
||||
should_disable = version_filter(value_name)
|
||||
if should_disable:
|
||||
btn.setEnabled(False)
|
||||
btn.setToolTip("Эта версия несовместима с выбранной архитектурой.")
|
||||
|
||||
grid_layout.addWidget(btn, row, col)
|
||||
buttons.append(btn)
|
||||
|
||||
col += 1
|
||||
if col >= num_columns:
|
||||
col = 0
|
||||
row += 1
|
||||
|
||||
return buttons
|
||||
|
||||
|
||||
class WineVersionSelectionDialogBase(BaseVersionSelectionDialog):
|
||||
"""
|
||||
Базовый класс для диалога выбора версии Wine.
|
||||
"""
|
||||
|
||||
def __init__(self, architecture, parent=None):
|
||||
"""
|
||||
Инициализирует диалог выбора версии Wine.
|
||||
"""
|
||||
self.architecture = architecture
|
||||
self.wine_versions_data = {}
|
||||
self.system_wine_display_name = "Системная версия"
|
||||
self.selected_display_text = None
|
||||
|
||||
super().__init__(
|
||||
title=f"Выбор версии Wine для {architecture} префикса",
|
||||
parent=parent,
|
||||
min_width=900,
|
||||
min_height=500
|
||||
)
|
||||
|
||||
def _create_version_container(self):
|
||||
"""Создает контейнер с вкладками для версий Wine."""
|
||||
self.main_tabs = QTabWidget()
|
||||
self.main_layout.addWidget(self.main_tabs)
|
||||
self.load_versions()
|
||||
|
||||
def load_versions(self):
|
||||
"""Загружает и отображает версии Wine."""
|
||||
self.main_tabs.clear()
|
||||
|
||||
loading_widget = QWidget()
|
||||
loading_layout = QVBoxLayout(loading_widget)
|
||||
status_label = QLabel("Загрузка, пожалуйста, подождите...")
|
||||
status_label.setAlignment(Qt.AlignCenter)
|
||||
loading_layout.addWidget(status_label)
|
||||
self.main_tabs.addTab(loading_widget, "Загрузка...")
|
||||
self.main_tabs.setEnabled(False)
|
||||
|
||||
self._parse_sha256_list()
|
||||
self.populate_ui()
|
||||
|
||||
self.main_tabs.setEnabled(True)
|
||||
|
||||
def _parse_sha256_list(self):
|
||||
"""Парсит sha256sum.list для получения списка версий Wine."""
|
||||
sha256_path = self._get_sha256_path()
|
||||
self.wine_versions_data = Sha256Parser.parse_wine_versions(sha256_path)
|
||||
|
||||
if not self.wine_versions_data:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"Ошибка",
|
||||
f"Файл с версиями не найден или пуст:\n{sha256_path}"
|
||||
)
|
||||
|
||||
def _get_installed_versions(self):
|
||||
"""Возвращает список локально установленных версий Wine."""
|
||||
dist_path = EnvironmentConfig.WH_DIST_DIR
|
||||
if not dist_path:
|
||||
return []
|
||||
return Sha256Parser.get_installed_versions(dist_path)
|
||||
|
||||
def _get_system_wine_version(self):
|
||||
"""Получает версию системного Wine."""
|
||||
if shutil.which('wine'):
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['wine', '--version'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
encoding='utf-8'
|
||||
)
|
||||
return result.stdout.strip()
|
||||
except (FileNotFoundError, subprocess.CalledProcessError) as e:
|
||||
print(f"Не удалось получить версию системного wine: {e}")
|
||||
return "Системная версия"
|
||||
|
||||
def _is_version_compatible(self, version_name):
|
||||
"""Проверяет совместимость версии с выбранной архитектурой."""
|
||||
is_win64_prefix = self.architecture == "win64"
|
||||
is_win32_prefix = self.architecture == "win32"
|
||||
re_32bit_version = re.compile(r'i[3-6]86|i586')
|
||||
|
||||
if is_win64_prefix and re_32bit_version.search(version_name):
|
||||
return False
|
||||
|
||||
if is_win32_prefix:
|
||||
if version_name == "system" or 'wow64' in version_name:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def populate_ui(self):
|
||||
"""Заполняет UI версиями Wine."""
|
||||
raise NotImplementedError("Подкласс должен реализовать populate_ui")
|
||||
|
||||
|
||||
class ComponentVersionSelectionDialogBase(BaseVersionSelectionDialog):
|
||||
"""
|
||||
Базовый класс для диалога выбора версии компонента (DXVK, VKD3D).
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
component_group,
|
||||
title,
|
||||
parent=None,
|
||||
add_extra_options=True
|
||||
):
|
||||
"""
|
||||
Инициализирует диалог выбора версии компонента.
|
||||
"""
|
||||
self.component_group = component_group
|
||||
self.versions_data = []
|
||||
self.add_extra_options = add_extra_options
|
||||
|
||||
super().__init__(
|
||||
title=title,
|
||||
parent=parent,
|
||||
min_width=700,
|
||||
min_height=400
|
||||
)
|
||||
|
||||
def _create_version_container(self):
|
||||
"""Создает контейнер для версий компонента."""
|
||||
self.scroll_area = QScrollArea()
|
||||
self.scroll_area.setWidgetResizable(True)
|
||||
self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
self.main_layout.addWidget(self.scroll_area)
|
||||
|
||||
scroll_content = QWidget()
|
||||
self.scroll_area.setWidget(scroll_content)
|
||||
|
||||
self.grid_layout = QGridLayout(scroll_content)
|
||||
self.grid_layout.setAlignment(Qt.AlignTop)
|
||||
|
||||
self.load_versions(start_row=0)
|
||||
|
||||
if self.add_extra_options:
|
||||
self._create_action_buttons()
|
||||
|
||||
def _create_action_buttons(self):
|
||||
"""Создает кнопки действий (Удалить, Отмена)."""
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
uninstall_btn = QPushButton("Удалить из префикса")
|
||||
uninstall_btn.setToolTip("Удаляет текущую установленную версию компонента из префикса.")
|
||||
uninstall_btn.clicked.connect(lambda: self.on_version_selected("none"))
|
||||
button_layout.addWidget(uninstall_btn)
|
||||
|
||||
button_layout.addStretch(1)
|
||||
|
||||
cancel_button = QPushButton("Отмена")
|
||||
cancel_button.clicked.connect(self.reject)
|
||||
button_layout.addWidget(cancel_button)
|
||||
|
||||
self.main_layout.addLayout(button_layout)
|
||||
|
||||
def load_versions(self, start_row=0):
|
||||
"""Загружает и отображает версии компонента."""
|
||||
self._parse_sha256_list()
|
||||
self.populate_ui(start_row)
|
||||
|
||||
def _parse_sha256_list(self):
|
||||
"""Парсит sha256sum.list для получения списка версий компонента."""
|
||||
sha256_path = self._get_sha256_path()
|
||||
self.versions_data = Sha256Parser.parse_component_versions(
|
||||
sha256_path,
|
||||
self.component_group
|
||||
)
|
||||
|
||||
def populate_ui(self, start_row):
|
||||
"""Заполняет UI версиями компонента."""
|
||||
raise NotImplementedError("Подкласс должен реализовать populate_ui")
|
||||
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
Диалог для выбора версии компонента (DXVK, VKD3D).
|
||||
|
||||
"""
|
||||
from functools import partial
|
||||
|
||||
from winehelperqt.dialogs.base_version_dialog import ComponentVersionSelectionDialogBase
|
||||
from winehelperqt.dialogs.wine_version import VersionButtonWidget
|
||||
from winehelperqt.utils.version_utils import sort_versions
|
||||
|
||||
|
||||
class ComponentVersionSelectionDialog(ComponentVersionSelectionDialogBase):
|
||||
"""Диалог для выбора версии компонента (DXVK, VKD3D)."""
|
||||
|
||||
def __init__(self, component_group, title, parent=None, add_extra_options=True, installed_version=None):
|
||||
"""
|
||||
Инициализирует диалог выбора версии компонента.
|
||||
|
||||
Args:
|
||||
component_group: Группа компонента (dxvk, vkd3d)
|
||||
title: Заголовок диалога
|
||||
parent: Родительский виджет
|
||||
add_extra_options: Добавлять ли кнопки действий
|
||||
installed_version: Текущая установленная версия компонента в префиксе
|
||||
"""
|
||||
self.installed_version = installed_version
|
||||
super().__init__(
|
||||
component_group=component_group,
|
||||
title=title,
|
||||
parent=parent,
|
||||
add_extra_options=add_extra_options
|
||||
)
|
||||
|
||||
def populate_ui(self, start_row):
|
||||
"""Заполняет UI кнопками версий."""
|
||||
versions = sort_versions(self.versions_data, reverse=True)
|
||||
row, col = start_row, 0
|
||||
for version_name in versions:
|
||||
is_installed = version_name == self.installed_version
|
||||
btn = VersionButtonWidget(
|
||||
version_name, version_name,
|
||||
is_installed=is_installed, show_icon=True
|
||||
)
|
||||
btn.clicked.connect(partial(self.on_version_selected, version_name))
|
||||
self.grid_layout.addWidget(btn, row, col)
|
||||
self.buttons.append(btn)
|
||||
col += 1
|
||||
if col >= self.NUM_COLUMNS:
|
||||
col = 0
|
||||
row += 1
|
||||
|
||||
def on_version_selected(self, version_name):
|
||||
"""Обрабатывает выбор версии."""
|
||||
self.selected_version = version_name
|
||||
self.accept()
|
||||
@@ -0,0 +1,204 @@
|
||||
"""
|
||||
Диалог для создания нового префикса.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QFormLayout, QPushButton,
|
||||
QLabel, QLineEdit, QRadioButton, QComboBox, QMessageBox, QWidget
|
||||
)
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
from winehelperqt.parsers.sha256_parser import Sha256Parser
|
||||
from winehelperqt.dialogs.wine_version import WineVersionSelectionDialog
|
||||
from winehelperqt.utils.environment import EnvironmentConfig
|
||||
|
||||
|
||||
class CreatePrefixDialog(QDialog):
|
||||
"""Диалог для создания нового префикса."""
|
||||
|
||||
PREFIX_NAME_PATTERN = r'^[a-zA-Z0-9_-]+$'
|
||||
PREFIX_NAME_CHARS = r'[^a-zA-Z0-9_-]'
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.parent_gui = parent
|
||||
self.setWindowTitle("Создание нового префикса")
|
||||
self.setMinimumSize(680, 250)
|
||||
self.setModal(True)
|
||||
|
||||
self.prefix_name = None
|
||||
self.wine_arch = None
|
||||
self.base_pfx = None
|
||||
self.prepared_prefixes = {}
|
||||
self.selected_wine_version_value = None
|
||||
self.selected_wine_version_display = None
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
form_layout = QFormLayout()
|
||||
form_layout.setSpacing(10)
|
||||
|
||||
name_input_widget = QWidget()
|
||||
name_input_layout = QVBoxLayout(name_input_widget)
|
||||
name_input_layout.setContentsMargins(0, 0, 0, 0)
|
||||
name_input_layout.setSpacing(2)
|
||||
|
||||
self.prefix_name_edit = QLineEdit()
|
||||
self.prefix_name_edit.setPlaceholderText("Например: my_prefix")
|
||||
name_input_layout.addWidget(self.prefix_name_edit)
|
||||
|
||||
self.name_warning_label = QLabel(
|
||||
"Имя может содержать только латинские буквы, цифры, тире и знаки подчеркивания."
|
||||
)
|
||||
self.name_warning_label.setStyleSheet("color: red;")
|
||||
self.name_warning_label.setVisible(False)
|
||||
name_input_layout.addWidget(self.name_warning_label)
|
||||
|
||||
form_layout.addRow("<b>Имя нового префикса:</b>", name_input_widget)
|
||||
|
||||
arch_widget = QWidget()
|
||||
arch_layout = QHBoxLayout(arch_widget)
|
||||
arch_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.arch_win32_radio = QRadioButton("32-bit")
|
||||
self.arch_win64_radio = QRadioButton("64-bit")
|
||||
self.arch_win64_radio.setChecked(True)
|
||||
arch_layout.addWidget(self.arch_win32_radio)
|
||||
arch_layout.addWidget(self.arch_win64_radio)
|
||||
form_layout.addRow("<b>Разрядность:</b>", arch_widget)
|
||||
|
||||
self.prefix_template_selector = QComboBox()
|
||||
self.prefix_template_selector.setToolTip("Выберите шаблон для создания префикса.")
|
||||
form_layout.addRow("<b>Шаблон префикса:</b>", self.prefix_template_selector)
|
||||
|
||||
self.wine_version_edit = QLineEdit()
|
||||
self.wine_version_edit.setReadOnly(True)
|
||||
self.wine_version_edit.setPlaceholderText("Версия не выбрана")
|
||||
|
||||
select_version_button = QPushButton("Выбрать версию...")
|
||||
select_version_button.clicked.connect(self.open_wine_version_dialog)
|
||||
|
||||
version_layout = QHBoxLayout()
|
||||
version_layout.addWidget(self.wine_version_edit)
|
||||
version_layout.addWidget(select_version_button)
|
||||
form_layout.addRow("<b>Версия Wine:</b>", version_layout)
|
||||
|
||||
layout.addLayout(form_layout)
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
self.create_button = QPushButton("Создать")
|
||||
self.create_button.setFont(QFont('Arial', 11, QFont.Bold))
|
||||
self.create_button.setStyleSheet("background-color: #0078d7; color: white;")
|
||||
self.create_button.setEnabled(False)
|
||||
self.create_button.clicked.connect(self.accept_creation)
|
||||
|
||||
cancel_button = QPushButton("Отмена")
|
||||
cancel_button.clicked.connect(self.reject)
|
||||
|
||||
button_layout.addStretch()
|
||||
button_layout.addWidget(self.create_button)
|
||||
button_layout.addWidget(cancel_button)
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
self.arch_win32_radio.toggled.connect(self.on_architecture_changed)
|
||||
self.prefix_name_edit.textChanged.connect(self.validate_prefix_name)
|
||||
self.wine_version_edit.textChanged.connect(self.update_create_button_state)
|
||||
|
||||
self._load_prepared_prefixes()
|
||||
self.on_architecture_changed()
|
||||
|
||||
def _load_prepared_prefixes(self):
|
||||
"""Загружает и парсит шаблоны префиксов из sha256sum.list."""
|
||||
self.prepared_prefixes = {'win32': [], 'win64': []}
|
||||
data_path = EnvironmentConfig.DATA_PATH
|
||||
if not data_path:
|
||||
QMessageBox.warning(self, "Ошибка", "Переменная окружения DATA_PATH не установлена.")
|
||||
return
|
||||
sha256_file = os.path.join(data_path, "sha256sum.list")
|
||||
if not os.path.exists(sha256_file):
|
||||
QMessageBox.warning(self, "Ошибка", f"Файл с описаниями префиксов не найден: {sha256_file}")
|
||||
return
|
||||
|
||||
prepared = Sha256Parser.parse_prepared_prefixes(sha256_file)
|
||||
self.prepared_prefixes = prepared
|
||||
|
||||
def open_wine_version_dialog(self):
|
||||
"""Открывает диалог выбора версии Wine."""
|
||||
architecture = "win32" if self.arch_win32_radio.isChecked() else "win64"
|
||||
dialog = WineVersionSelectionDialog(architecture, self)
|
||||
if dialog.exec_() == QDialog.Accepted and dialog.selected_version:
|
||||
self.wine_version_edit.setText(dialog.selected_display_text)
|
||||
self.selected_wine_version_value = dialog.selected_version
|
||||
|
||||
def on_architecture_changed(self):
|
||||
"""Обновляет список шаблонов и сбрасывает выбор версии Wine."""
|
||||
self.wine_version_edit.clear()
|
||||
self.selected_wine_version_value = None
|
||||
|
||||
self.prefix_template_selector.blockSignals(True)
|
||||
self.prefix_template_selector.clear()
|
||||
|
||||
architecture = "win32" if self.arch_win32_radio.isChecked() else "win64"
|
||||
templates = self.prepared_prefixes.get(architecture, [])
|
||||
|
||||
for value, description in templates:
|
||||
display_name = "Чистый префикс" if value == "none" else value
|
||||
self.prefix_template_selector.addItem(display_name, userData={'value': value, 'tooltip': description})
|
||||
|
||||
self.prefix_template_selector.blockSignals(False)
|
||||
self.prefix_template_selector.currentIndexChanged.connect(
|
||||
lambda i: self.prefix_template_selector.setToolTip(
|
||||
self.prefix_template_selector.itemData(i)['tooltip']
|
||||
)
|
||||
)
|
||||
self.prefix_template_selector.setToolTip(self.prefix_template_selector.itemData(0)['tooltip'])
|
||||
|
||||
def validate_prefix_name(self, text):
|
||||
"""Проверяет имя префикса в реальном времени."""
|
||||
if re.match(self.PREFIX_NAME_PATTERN, text):
|
||||
self.name_warning_label.setVisible(False)
|
||||
else:
|
||||
cleaned_text = re.sub(self.PREFIX_NAME_CHARS, '', text)
|
||||
self.prefix_name_edit.blockSignals(True)
|
||||
self.prefix_name_edit.setText(cleaned_text)
|
||||
self.prefix_name_edit.blockSignals(False)
|
||||
self.name_warning_label.setVisible(True)
|
||||
|
||||
self.update_create_button_state()
|
||||
|
||||
def update_create_button_state(self):
|
||||
"""Включает или выключает кнопку 'Создать'."""
|
||||
name_ok = bool(self.prefix_name_edit.text().strip())
|
||||
version_ok = bool(self.wine_version_edit.text().strip())
|
||||
self.create_button.setEnabled(
|
||||
name_ok and version_ok and not self.name_warning_label.isVisible()
|
||||
)
|
||||
|
||||
def accept_creation(self):
|
||||
"""Валидирует данные, сохраняет их и закрывает диалог с успехом."""
|
||||
prefix_name = self.prefix_name_edit.text().strip()
|
||||
|
||||
if not prefix_name:
|
||||
QMessageBox.warning(self, "Ошибка", "Имя префикса не может быть пустым.")
|
||||
return
|
||||
|
||||
if not re.match(self.PREFIX_NAME_PATTERN, prefix_name):
|
||||
QMessageBox.warning(
|
||||
self, "Ошибка",
|
||||
"Имя префикса может содержать только латинские буквы, цифры, дефисы и знаки подчеркивания."
|
||||
)
|
||||
return
|
||||
|
||||
prefix_path = os.path.join(EnvironmentConfig.USER_WORK_PATH, "prefixes", prefix_name)
|
||||
if os.path.exists(prefix_path):
|
||||
QMessageBox.warning(self, "Ошибка", f"Префикс с именем '{prefix_name}' уже существует.")
|
||||
return
|
||||
|
||||
self.prefix_name = prefix_name
|
||||
self.wine_arch = "win32" if self.arch_win32_radio.isChecked() else "win64"
|
||||
|
||||
current_index = self.prefix_template_selector.currentIndex()
|
||||
self.base_pfx = self.prefix_template_selector.itemData(current_index)['value']
|
||||
self.selected_wine_version_display = self.wine_version_edit.text()
|
||||
|
||||
self.accept()
|
||||
@@ -0,0 +1,75 @@
|
||||
"""
|
||||
Диалог для управления ассоциациями файлов (WH_XDG_OPEN).
|
||||
"""
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QLineEdit, QLabel, QDialogButtonBox, QMessageBox
|
||||
)
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
|
||||
class FileAssociationsDialog(QDialog):
|
||||
"""Диалог для управления ассоциациями файлов."""
|
||||
|
||||
def __init__(self, current_associations, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Настройка ассоциаций файлов")
|
||||
self.setMinimumWidth(450)
|
||||
self.setModal(True)
|
||||
|
||||
self.new_associations = current_associations
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setSpacing(10)
|
||||
|
||||
info_label = QLabel(
|
||||
"Укажите расширения файлов, которые должны открываться нативными<br>"
|
||||
"приложениями Linux. Чтобы удалить все ассоциации, очистите поле.<br><br>"
|
||||
"<b>Пример:</b> <code>pdf docx txt</code>"
|
||||
)
|
||||
info_label.setWordWrap(True)
|
||||
info_label.setTextFormat(Qt.RichText)
|
||||
layout.addWidget(info_label)
|
||||
|
||||
self.associations_edit = QLineEdit()
|
||||
if current_associations != "0":
|
||||
self.associations_edit.setText(current_associations)
|
||||
|
||||
self.associations_edit.setPlaceholderText("Введите расширения через пробел...")
|
||||
layout.addWidget(self.associations_edit)
|
||||
|
||||
forbidden_label = QLabel(
|
||||
"<small><b>Запрещено использовать:</b> cpl, dll, exe, lnk, msi</small>"
|
||||
)
|
||||
forbidden_label.setTextFormat(Qt.RichText)
|
||||
layout.addWidget(forbidden_label)
|
||||
|
||||
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
button_box.accepted.connect(self.validate_and_accept)
|
||||
button_box.rejected.connect(self.reject)
|
||||
layout.addWidget(button_box)
|
||||
|
||||
def validate_and_accept(self):
|
||||
"""Проверяет введенные данные перед закрытием."""
|
||||
forbidden_extensions = {"cpl", "dll", "exe", "lnk", "msi"}
|
||||
|
||||
input_text = self.associations_edit.text().lower().strip()
|
||||
entered_extensions = {
|
||||
ext.strip() for ext in input_text.split() if ext.strip()
|
||||
}
|
||||
|
||||
found_forbidden = entered_extensions.intersection(forbidden_extensions)
|
||||
|
||||
if found_forbidden:
|
||||
msg_box = QMessageBox(self)
|
||||
msg_box.setIcon(QMessageBox.Warning)
|
||||
msg_box.setWindowTitle("Недопустимые расширения")
|
||||
msg_box.setTextFormat(Qt.RichText)
|
||||
msg_box.setText(
|
||||
"Следующие расширения запрещены и не могут быть использованы:<br><br>"
|
||||
f"<b>{', '.join(sorted(list(found_forbidden)))}</b>"
|
||||
)
|
||||
msg_box.exec_()
|
||||
return
|
||||
|
||||
self.new_associations = " ".join(sorted(list(entered_extensions)))
|
||||
self.accept()
|
||||
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Модуль вывода предупреждения о noexec для /home.
|
||||
|
||||
Выводит информационное окно с инструкциями по устранению проблемы,
|
||||
когда /home примонтирован с флагом noexec и запуск Wine невозможен.
|
||||
"""
|
||||
import getpass
|
||||
import sys
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication,
|
||||
QDialog,
|
||||
QTextBrowser,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
|
||||
class NoExecWarningDialog(QDialog):
|
||||
"""Диалог предупреждения о флаге noexec для /home."""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("WineHelper — Предупреждение!")
|
||||
self.setMinimumSize(600, 620)
|
||||
self.setModal(True)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setSpacing(12)
|
||||
|
||||
self.info_browser = QTextBrowser()
|
||||
self.info_browser.setOpenExternalLinks(True)
|
||||
self.info_browser.setStyleSheet("""
|
||||
QTextBrowser {
|
||||
background-color: #1e1e1e;
|
||||
color: #e4e4e4;
|
||||
border: none;
|
||||
}
|
||||
""")
|
||||
self.info_browser.setHtml(self._build_html_content())
|
||||
layout.addWidget(self.info_browser)
|
||||
|
||||
def _build_html_content(self) -> str:
|
||||
"""Формирует HTML-содержимое окна с подстановкой имени пользователя."""
|
||||
username = getpass.getuser()
|
||||
|
||||
body_style = (
|
||||
"font-family: 'Segoe UI', 'Noto Sans', sans-serif; "
|
||||
"font-size: 14px; color: #e4e4e4; line-height: 1.55;"
|
||||
)
|
||||
warning_style = (
|
||||
"background-color: #3d351f; border-left: 4px solid #ffcc00; "
|
||||
"padding: 12px 14px; margin: 0;"
|
||||
)
|
||||
warning_text_style = "color: #ffd700; font-weight: bold; text-align: center; margin: 0 0 6px 0;"
|
||||
card_style = "padding: 14px; margin: 0;"
|
||||
title_style = "font-size: 15px; font-weight: bold; color: #ffffff; margin: 0 0 10px 0;"
|
||||
paragraph_style = "margin: 0 0 10px 0;"
|
||||
pre_style = (
|
||||
"color: #7ee787; font-family: 'JetBrains Mono', 'Consolas', 'Courier New', monospace; "
|
||||
"font-size: 13px; padding: 4px 0; margin: 0 0 12px 0;"
|
||||
)
|
||||
|
||||
return f"""
|
||||
<html>
|
||||
<body style="{body_style}">
|
||||
<p style="text-align: center; font-size: 20px; font-weight: bold; color: #ffd700; margin: 0 0 8px 0;">
|
||||
Предупреждение!
|
||||
</p>
|
||||
<div style="{warning_style}">
|
||||
<p style="{warning_text_style} margin-bottom: 0;">
|
||||
⚠️ /home примонтирован в /etc/fstab с аргументом noexec.<br>
|
||||
Запуск портативной версии wine невозможен из домашнего каталога!
|
||||
Используйте один из двух вариантов решения проблемы.
|
||||
</p>
|
||||
</div>
|
||||
<div style="line-height: 18px; font-size: 1px;"> </div>
|
||||
|
||||
<div style="{card_style}">
|
||||
<p style="{title_style}">1. Снять флаг noexec в /etc/fstab</p>
|
||||
<pre style="{pre_style}">$ su -
|
||||
# apt-get install nano
|
||||
# nano /etc/fstab</pre>
|
||||
<p style="{paragraph_style}">
|
||||
Удаляем флаг <b>noexec</b> напротив <b>/home</b>.<br>
|
||||
<b>Ctrl+O</b> — сохранить изменения,<br>
|
||||
<b>Ctrl+X</b> — выход.<br>
|
||||
Можно использовать любой редактор; nano приведён как пример.
|
||||
</p>
|
||||
|
||||
<p style="{title_style} margin-top: 14px;">Обновляем загрузчик:</p>
|
||||
<pre style="{pre_style}"># update-grub
|
||||
# exit</pre>
|
||||
<p style="{paragraph_style} margin-bottom: 0;">После перезагрузки можно приступать к работе с WineHelper.</p>
|
||||
</div>
|
||||
<div style="line-height: 18px; font-size: 1px;"> </div>
|
||||
|
||||
<div style="{card_style}">
|
||||
<p style="{title_style}">2. Или изменить рабочий каталог для WineHelper</p>
|
||||
<p style="{paragraph_style}">
|
||||
Каталог должен находиться <b>вне /home</b> и иметь права на чтение-запись
|
||||
для пользователя <b>{username}</b>.
|
||||
</p>
|
||||
<p style="{paragraph_style}">Используйте команду:</p>
|
||||
<pre style="{pre_style} margin-bottom: 0;">$ winehelper data-path /путь/к/каталогу</pre>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Точка входа для автономного запуска модуля."""
|
||||
app = QApplication(sys.argv)
|
||||
dialog = NoExecWarningDialog()
|
||||
dialog.show()
|
||||
return app.exec_()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,369 @@
|
||||
"""
|
||||
Диалоги для дополнительных настроек префикса и приложений.
|
||||
"""
|
||||
import os
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QGridLayout, QPushButton,
|
||||
QLabel, QCheckBox, QComboBox, QMessageBox, QSizePolicy
|
||||
)
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
from winehelperqt.utils.export_utils import ExportUtils
|
||||
|
||||
|
||||
class AdditionalSettingsDialog(QDialog):
|
||||
"""Диалог для дополнительных настроек префикса (ESync, FSync, DXVK, VKD3D)."""
|
||||
|
||||
def __init__(self, prefix_name, parent=None):
|
||||
super().__init__(parent)
|
||||
self.parent_gui = parent
|
||||
self.prefix_name = prefix_name
|
||||
|
||||
self.setWindowTitle("Дополнительные настройки")
|
||||
self.setMinimumWidth(400)
|
||||
self.setModal(True)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
grid_layout = QGridLayout()
|
||||
grid_layout.setSpacing(10)
|
||||
|
||||
# ESync/FSync
|
||||
self.esync_button = QPushButton("ESync")
|
||||
self.esync_button.setCheckable(True)
|
||||
self.esync_button.setMinimumHeight(32)
|
||||
self.esync_button.setToolTip("Включить/выключить Eventfd-based synchronization.")
|
||||
self.esync_button.clicked.connect(
|
||||
lambda checked: self._toggle_sync_option("WINEESYNC", checked, self.esync_button)
|
||||
)
|
||||
self.esync_button.toggled.connect(
|
||||
lambda checked, btn=self.esync_button: self._update_button_text(btn, "ESync", checked)
|
||||
)
|
||||
self.esync_button.setStyleSheet(
|
||||
"QPushButton:checked { background-color: #4CAF50; color: white; font-weight: bold; }"
|
||||
)
|
||||
grid_layout.addWidget(self.esync_button, 0, 0)
|
||||
|
||||
self.fsync_button = QPushButton("FSync")
|
||||
self.fsync_button.setMinimumHeight(32)
|
||||
self.fsync_button.setCheckable(True)
|
||||
self.fsync_button.setToolTip("Включить/выключить Futex-based synchronization.")
|
||||
self.fsync_button.clicked.connect(
|
||||
lambda checked: self._toggle_sync_option("WINEFSYNC", checked, self.fsync_button)
|
||||
)
|
||||
self.fsync_button.toggled.connect(
|
||||
lambda checked, btn=self.fsync_button: self._update_button_text(btn, "FSync", checked)
|
||||
)
|
||||
self.fsync_button.setStyleSheet(
|
||||
"QPushButton:checked { background-color: #4CAF50; color: white; font-weight: bold; }"
|
||||
)
|
||||
grid_layout.addWidget(self.fsync_button, 0, 1)
|
||||
|
||||
self.esync_button.setFocusPolicy(Qt.NoFocus)
|
||||
self.fsync_button.setFocusPolicy(Qt.NoFocus)
|
||||
|
||||
# DXVK/VKD3D
|
||||
self.dxvk_manage_button = QPushButton("Управление DXVK")
|
||||
self.dxvk_manage_button.setMinimumHeight(32)
|
||||
self.dxvk_manage_button.clicked.connect(
|
||||
lambda: self._open_component_manager('dxvk')
|
||||
)
|
||||
self.dxvk_manage_button.setToolTip("Установка или удаление определенной версии DXVK в префиксе.")
|
||||
grid_layout.addWidget(self.dxvk_manage_button, 1, 0)
|
||||
|
||||
self.vkd3d_manage_button = QPushButton("Управление VKD3D")
|
||||
self.vkd3d_manage_button.setMinimumHeight(32)
|
||||
self.vkd3d_manage_button.clicked.connect(
|
||||
lambda: self._open_component_manager('vkd3d-proton')
|
||||
)
|
||||
self.vkd3d_manage_button.setToolTip("Установка или удаление определенной версии vkd3d-proton в префиксе.")
|
||||
grid_layout.addWidget(self.vkd3d_manage_button, 1, 1)
|
||||
|
||||
self.dxvk_manage_button.setFocusPolicy(Qt.NoFocus)
|
||||
self.vkd3d_manage_button.setFocusPolicy(Qt.NoFocus)
|
||||
|
||||
# Ассоциации файлов
|
||||
self.file_associations_button = QPushButton("Ассоциации файлов")
|
||||
self.file_associations_button.setMinimumHeight(32)
|
||||
self.file_associations_button.clicked.connect(self.parent_gui.open_file_associations_manager)
|
||||
self.file_associations_button.setToolTip(
|
||||
"Настройка открытия определенных типов файлов с помощью нативных приложений Linux."
|
||||
)
|
||||
grid_layout.addWidget(self.file_associations_button, 2, 0)
|
||||
self.file_associations_button.setFocusPolicy(Qt.NoFocus)
|
||||
|
||||
# CPCSP_PROXY
|
||||
self.cpcsp_proxy_button = QPushButton("CPCSP_PROXY")
|
||||
self.cpcsp_proxy_button.setMinimumHeight(32)
|
||||
self.cpcsp_proxy_button.setCheckable(True)
|
||||
self.cpcsp_proxy_button.setToolTip("Включить/выключить использование CPCSP_PROXY.")
|
||||
self.cpcsp_proxy_button.clicked.connect(
|
||||
lambda checked: self._toggle_cpcsp_proxy(checked, self.cpcsp_proxy_button)
|
||||
)
|
||||
self.cpcsp_proxy_button.toggled.connect(
|
||||
lambda checked, btn=self.cpcsp_proxy_button: self._update_button_text(btn, "CPCSP_PROXY", checked)
|
||||
)
|
||||
self.cpcsp_proxy_button.setStyleSheet(
|
||||
"QPushButton:checked { background-color: #4CAF50; color: white; font-weight: bold; }"
|
||||
)
|
||||
grid_layout.addWidget(self.cpcsp_proxy_button, 2, 1)
|
||||
self.cpcsp_proxy_button.setFocusPolicy(Qt.NoFocus)
|
||||
|
||||
layout.addLayout(grid_layout)
|
||||
|
||||
self.close_button = QPushButton("Закрыть")
|
||||
self.close_button.setMinimumHeight(32)
|
||||
self.close_button.clicked.connect(self.accept)
|
||||
self.close_button.setFocusPolicy(Qt.NoFocus)
|
||||
layout.addWidget(self.close_button, alignment=Qt.AlignRight)
|
||||
|
||||
self.update_button_states()
|
||||
|
||||
def _toggle_sync_option(self, option_name, is_checked, button):
|
||||
"""Обновляет опцию синхронизации."""
|
||||
self.parent_gui.update_sync_option(option_name, is_checked)
|
||||
|
||||
def _toggle_cpcsp_proxy(self, is_checked, button):
|
||||
"""Обновляет опцию CPCSP_PROXY и запускает установку при включении."""
|
||||
if is_checked:
|
||||
# Сначала сохраняем WH_USE_CPCSP_PROXY="1" в last.conf,
|
||||
# чтобы winehelper init-prefix прочитал его при запуске
|
||||
self.parent_gui.update_sync_option("WH_USE_CPCSP_PROXY", True)
|
||||
|
||||
def on_install_finished(success):
|
||||
if not success:
|
||||
# При ошибке откатываем значение в last.conf и сбрасываем кнопку
|
||||
self.parent_gui.update_sync_option("WH_USE_CPCSP_PROXY", False)
|
||||
button.blockSignals(True)
|
||||
button.setChecked(False)
|
||||
self._update_button_text(button, "CPCSP_PROXY", False)
|
||||
button.blockSignals(False)
|
||||
|
||||
self.parent_gui.run_cpcsp_proxy_install(self.prefix_name, on_install_finished)
|
||||
else:
|
||||
self.parent_gui.update_sync_option("WH_USE_CPCSP_PROXY", False)
|
||||
|
||||
def _update_button_text(self, button, base_text, is_checked):
|
||||
"""Обновляет текст кнопки, добавляя или убирая галочку."""
|
||||
if is_checked:
|
||||
button.setText(f"✓ {base_text}")
|
||||
else:
|
||||
button.setText(base_text)
|
||||
|
||||
def _open_component_manager(self, component_name):
|
||||
"""Открывает менеджер компонентов."""
|
||||
self.parent_gui.open_component_version_manager(component_name)
|
||||
|
||||
def update_button_states(self):
|
||||
"""Обновляет состояние кнопок на основе данных из last.conf."""
|
||||
esync_enabled = self.parent_gui._get_prefix_component_version(
|
||||
self.prefix_name, "WINEESYNC"
|
||||
) == "1"
|
||||
fsync_enabled = self.parent_gui._get_prefix_component_version(
|
||||
self.prefix_name, "WINEFSYNC"
|
||||
) == "1"
|
||||
cpcsp_proxy_enabled = self.parent_gui._get_prefix_component_version(
|
||||
self.prefix_name, "WH_USE_CPCSP_PROXY"
|
||||
) == "1"
|
||||
|
||||
self.esync_button.blockSignals(True)
|
||||
self.fsync_button.blockSignals(True)
|
||||
self.cpcsp_proxy_button.blockSignals(True)
|
||||
|
||||
self.esync_button.setChecked(esync_enabled)
|
||||
self.fsync_button.setChecked(fsync_enabled)
|
||||
self.cpcsp_proxy_button.setChecked(cpcsp_proxy_enabled)
|
||||
|
||||
self._update_button_text(self.esync_button, "ESync", esync_enabled)
|
||||
self._update_button_text(self.fsync_button, "FSync", fsync_enabled)
|
||||
self._update_button_text(self.cpcsp_proxy_button, "CPCSP_PROXY", cpcsp_proxy_enabled)
|
||||
|
||||
self.esync_button.blockSignals(False)
|
||||
self.fsync_button.blockSignals(False)
|
||||
self.cpcsp_proxy_button.blockSignals(False)
|
||||
|
||||
|
||||
class AppAdditionalSettingsDialog(QDialog):
|
||||
"""Диалог для дополнительных настроек приложения из .whdb файла."""
|
||||
|
||||
def __init__(self, exe_path, parent=None):
|
||||
super().__init__(parent)
|
||||
self.parent_gui = parent
|
||||
self.exe_path = os.path.abspath(exe_path)
|
||||
self.whdb_path = self.exe_path + '.whdb'
|
||||
|
||||
self.settings = {
|
||||
'WH_MAIN_DECORATED': 'default',
|
||||
'WH_VIRTUAL_DESKTOP': 'default',
|
||||
'WH_FONT_SMOOTHING': '0',
|
||||
'WH_FONT_MSS_REPLACE': '0',
|
||||
'WINE_D3D_CONFIG': ''
|
||||
}
|
||||
|
||||
self.setWindowTitle("Дополнительные настройки приложения")
|
||||
self.setMinimumSize(380, 200)
|
||||
self.setModal(True)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
checkboxes_layout = QHBoxLayout()
|
||||
checkboxes_layout.setSpacing(20)
|
||||
|
||||
left_column = QVBoxLayout()
|
||||
left_column.setSpacing(10)
|
||||
|
||||
self.wh_main_decorated_checkbox = QCheckBox("MAIN_DECORATED")
|
||||
self.wh_main_decorated_checkbox.setToolTip("Управляет декорациями окон главного приложения")
|
||||
left_column.addWidget(self.wh_main_decorated_checkbox)
|
||||
|
||||
self.wh_font_smoothing_checkbox = QCheckBox("FONT_SMOOTHING")
|
||||
self.wh_font_smoothing_checkbox.setToolTip("Сглаживание шрифтов")
|
||||
left_column.addWidget(self.wh_font_smoothing_checkbox)
|
||||
|
||||
right_column = QVBoxLayout()
|
||||
right_column.setSpacing(10)
|
||||
|
||||
self.wh_virtual_desktop_checkbox = QCheckBox("VIRTUAL_DESKTOP")
|
||||
self.wh_virtual_desktop_checkbox.setToolTip("Виртуальный рабочий стол для приложения")
|
||||
right_column.addWidget(self.wh_virtual_desktop_checkbox)
|
||||
|
||||
self.wh_font_mss_replace_checkbox = QCheckBox("FONT_MSS_REPLACE")
|
||||
self.wh_font_mss_replace_checkbox.setToolTip("Замена шрифтов MSS")
|
||||
right_column.addWidget(self.wh_font_mss_replace_checkbox)
|
||||
|
||||
checkboxes_layout.addLayout(left_column)
|
||||
checkboxes_layout.addLayout(right_column)
|
||||
layout.addLayout(checkboxes_layout)
|
||||
|
||||
layout.addSpacing(15)
|
||||
d3d_layout = QHBoxLayout()
|
||||
d3d_label = QLabel("WINE_D3D_CONFIG:")
|
||||
d3d_layout.addWidget(d3d_label)
|
||||
|
||||
self.wine_d3d_config_combo = QComboBox()
|
||||
self.wine_d3d_config_combo.setMinimumWidth(250)
|
||||
self.wine_d3d_config_combo.setSizePolicy(
|
||||
QSizePolicy.Preferred, QSizePolicy.Preferred
|
||||
)
|
||||
self.wine_d3d_config_combo.addItem("Не задано", "")
|
||||
self.wine_d3d_config_combo.addItem("renderer=vulkan", "renderer=vulkan")
|
||||
self.wine_d3d_config_combo.addItem("renderer=gdi", "renderer=gdi")
|
||||
self.wine_d3d_config_combo.addItem("renderer=gl", "renderer=gl")
|
||||
self.wine_d3d_config_combo.setToolTip("Выберите режим рендеринга Direct3D")
|
||||
d3d_layout.addWidget(self.wine_d3d_config_combo, stretch=1)
|
||||
d3d_layout.addStretch()
|
||||
layout.addLayout(d3d_layout)
|
||||
|
||||
layout.addSpacing(20)
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.addStretch()
|
||||
|
||||
self.save_button = QPushButton("Сохранить")
|
||||
self.save_button.setMinimumHeight(32)
|
||||
self.save_button.clicked.connect(self._save_settings)
|
||||
self.save_button.setFocusPolicy(Qt.NoFocus)
|
||||
button_layout.addWidget(self.save_button)
|
||||
|
||||
self.close_button = QPushButton("Закрыть")
|
||||
self.close_button.setMinimumHeight(32)
|
||||
self.close_button.clicked.connect(self.accept)
|
||||
self.close_button.setFocusPolicy(Qt.NoFocus)
|
||||
button_layout.addWidget(self.close_button)
|
||||
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
self._load_settings()
|
||||
|
||||
def _load_settings(self):
|
||||
"""Загружает настройки из .whdb файла."""
|
||||
if not os.path.exists(self.whdb_path):
|
||||
self._update_ui_from_settings()
|
||||
return
|
||||
|
||||
try:
|
||||
with open(self.whdb_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
for line in content.split('\n'):
|
||||
var_name, var_value = self._parse_export_line(line)
|
||||
if var_name and var_name in self.settings:
|
||||
self.settings[var_name] = var_value
|
||||
|
||||
self._update_ui_from_settings()
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.warning(
|
||||
self, "Ошибка",
|
||||
f"Не удалось прочитать файл настроек:\n{self.whdb_path}\n\nОшибка: {e}"
|
||||
)
|
||||
self._update_ui_from_settings()
|
||||
|
||||
def _update_ui_from_settings(self):
|
||||
"""Обновляет элементы управления на основе загруженных настроек."""
|
||||
self.wh_main_decorated_checkbox.setChecked(
|
||||
self.settings.get('WH_MAIN_DECORATED') == '1'
|
||||
)
|
||||
wh_virtual_desktop = self.settings.get('WH_VIRTUAL_DESKTOP', '')
|
||||
self.wh_virtual_desktop_checkbox.setChecked(
|
||||
wh_virtual_desktop == '1' or wh_virtual_desktop.lower() not in ('0', 'default', '')
|
||||
)
|
||||
self.wh_font_smoothing_checkbox.setChecked(
|
||||
self.settings.get('WH_FONT_SMOOTHING') == '1'
|
||||
)
|
||||
self.wh_font_mss_replace_checkbox.setChecked(
|
||||
self.settings.get('WH_FONT_MSS_REPLACE') == '1'
|
||||
)
|
||||
|
||||
d3d_value = self.settings.get('WINE_D3D_CONFIG', '')
|
||||
index = self.wine_d3d_config_combo.findData(d3d_value)
|
||||
if index >= 0:
|
||||
self.wine_d3d_config_combo.setCurrentIndex(index)
|
||||
else:
|
||||
self.wine_d3d_config_combo.setCurrentIndex(0)
|
||||
|
||||
def _save_settings(self):
|
||||
"""Сохраняет настройки в .whdb файл."""
|
||||
try:
|
||||
existing_lines = []
|
||||
if os.path.exists(self.whdb_path):
|
||||
with open(self.whdb_path, 'r', encoding='utf-8') as f:
|
||||
existing_lines = f.readlines()
|
||||
|
||||
settings_values = {
|
||||
var_name: self._get_setting_value(var_name)
|
||||
for var_name in self.settings
|
||||
}
|
||||
new_lines = ExportUtils.update_lines(existing_lines, settings_values)
|
||||
|
||||
with open(self.whdb_path, 'w', encoding='utf-8') as f:
|
||||
f.writelines(new_lines)
|
||||
|
||||
self.accept()
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "Ошибка", f"Не удалось сохранить настройки:\n{e}")
|
||||
|
||||
def _get_setting_value(self, var_name):
|
||||
"""Возвращает текущее значение переменной из UI."""
|
||||
if var_name == 'WINE_D3D_CONFIG':
|
||||
return self.wine_d3d_config_combo.currentData()
|
||||
if var_name == 'WH_MAIN_DECORATED':
|
||||
return '1' if self.wh_main_decorated_checkbox.isChecked() else 'default'
|
||||
if var_name == 'WH_VIRTUAL_DESKTOP':
|
||||
return '1' if self.wh_virtual_desktop_checkbox.isChecked() else 'default'
|
||||
if var_name == 'WH_FONT_SMOOTHING':
|
||||
return '1' if self.wh_font_smoothing_checkbox.isChecked() else '0'
|
||||
if var_name == 'WH_FONT_MSS_REPLACE':
|
||||
return '1' if self.wh_font_mss_replace_checkbox.isChecked() else '0'
|
||||
return ''
|
||||
|
||||
@staticmethod
|
||||
def _parse_export_line(line):
|
||||
"""Парсит строку export VAR=value, игнорируя комментарии и секции."""
|
||||
return ExportUtils.parse_line(line)
|
||||
|
||||
@staticmethod
|
||||
def _format_export_line(var_name, value):
|
||||
"""Форматирует строку export VAR=value с экранированием."""
|
||||
return ExportUtils.format_line(var_name, value)
|
||||
@@ -0,0 +1,331 @@
|
||||
"""
|
||||
Диалог для выбора версии Wine с группировкой.
|
||||
"""
|
||||
import re
|
||||
from functools import partial
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QGridLayout, QScrollArea, QTabWidget, QPushButton, QLabel, QWidget, QVBoxLayout,
|
||||
QHBoxLayout
|
||||
)
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
from winehelperqt.dialogs.base_version_dialog import WineVersionSelectionDialogBase
|
||||
from winehelperqt.utils.version_utils import sort_versions
|
||||
from winehelperqt.utils.grid_utils import GridUtils
|
||||
|
||||
|
||||
class VersionButtonWidget(QPushButton):
|
||||
"""Кастомная кнопка версии с текстом слева и галочкой справа."""
|
||||
|
||||
def __init__(self, display_name, value_name, is_installed=False, show_icon=True, parent=None):
|
||||
super().__init__(parent)
|
||||
self.value_name = value_name
|
||||
self.display_name = display_name
|
||||
self.is_installed = is_installed
|
||||
self.show_icon = show_icon
|
||||
|
||||
self.setMinimumHeight(40)
|
||||
self.setCursor(Qt.PointingHandCursor)
|
||||
|
||||
# Создаем внутренний layout для размещения текста и галочки
|
||||
self._setup_layout()
|
||||
self._apply_style()
|
||||
|
||||
def _setup_layout(self):
|
||||
"""Настраивает внутренний layout кнопки с текстом слева и галочкой справа."""
|
||||
# Создаем контейнер для содержимого кнопки
|
||||
container = QWidget(self)
|
||||
layout = QHBoxLayout(container)
|
||||
layout.setContentsMargins(12, 0, 12, 0)
|
||||
layout.setSpacing(0)
|
||||
|
||||
# Если show_icon=False (вкладка "Установленные версии Wine"), текст по центру
|
||||
if not self.show_icon:
|
||||
layout.addStretch(1)
|
||||
# Метка с названием версии (по центру)
|
||||
self.name_label = QLabel(self.display_name)
|
||||
self.name_label.setStyleSheet("background: transparent;")
|
||||
self.name_label.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(self.name_label)
|
||||
layout.addStretch(1)
|
||||
else:
|
||||
# Метка с названием версии (слева)
|
||||
self.name_label = QLabel(self.display_name)
|
||||
self.name_label.setStyleSheet("background: transparent;")
|
||||
layout.addWidget(self.name_label)
|
||||
|
||||
# Растягивающийся spacer (занимает всё доступное пространство между текстом и галочкой)
|
||||
layout.addStretch(1)
|
||||
|
||||
# Метка со значком статуса (справа)
|
||||
if self.is_installed:
|
||||
self.check_label = QLabel("✓")
|
||||
self.check_label.setStyleSheet(
|
||||
"background: transparent; color: #7fff7f; font-weight: bold; font-size: 22px;"
|
||||
)
|
||||
layout.addWidget(self.check_label)
|
||||
else:
|
||||
self.check_label = QLabel("⭳")
|
||||
self.check_label.setStyleSheet("background: transparent; color: #888888; font-size: 22px;")
|
||||
layout.addWidget(self.check_label)
|
||||
|
||||
# Устанавливаем layout для контейнера
|
||||
container.setLayout(layout)
|
||||
|
||||
# Устанавливаем layout кнопки (PyQt5 поддерживает это)
|
||||
button_layout = QHBoxLayout(self)
|
||||
button_layout.setContentsMargins(0, 0, 0, 0)
|
||||
button_layout.setSpacing(0)
|
||||
button_layout.addWidget(container)
|
||||
self.setLayout(button_layout)
|
||||
|
||||
def _apply_style(self):
|
||||
"""Применяет стили в зависимости от статуса установки."""
|
||||
# Не применяем никаких стилей — используем стандартные цвета системы
|
||||
if self.is_installed:
|
||||
self.setToolTip("Эта версия уже скачана и установлена. Нажмите, чтобы выбрать её.")
|
||||
|
||||
def text(self):
|
||||
"""Возвращает текст кнопки для фильтрации."""
|
||||
return self.display_name
|
||||
|
||||
def setText(self, text):
|
||||
"""Устанавливает текст метки названия версии."""
|
||||
self.display_name = text
|
||||
if hasattr(self, 'name_label'):
|
||||
self.name_label.setText(text)
|
||||
|
||||
|
||||
class WineVersionSelectionDialog(WineVersionSelectionDialogBase):
|
||||
"""Диалог для выбора версии Wine с группировкой."""
|
||||
|
||||
def __init__(self, architecture, parent=None):
|
||||
"""
|
||||
Инициализирует диалог выбора версии Wine.
|
||||
|
||||
Args:
|
||||
architecture: Архитектура префикса (win32/win64)
|
||||
parent: Родительский виджет
|
||||
"""
|
||||
self.main_tabs = None
|
||||
self.installed_grid_layout = None
|
||||
self.installed_buttons = []
|
||||
self.download_buttons = []
|
||||
self._installed_version_names = set()
|
||||
|
||||
super().__init__(architecture=architecture, parent=parent)
|
||||
|
||||
def _create_version_container(self):
|
||||
"""Создает контейнер с вкладками для версий Wine."""
|
||||
self.main_tabs = QTabWidget()
|
||||
self.main_layout.addWidget(self.main_tabs)
|
||||
self.load_versions()
|
||||
|
||||
def populate_ui(self):
|
||||
"""Заполняет UI версиями Wine."""
|
||||
self.main_tabs.clear()
|
||||
self._installed_version_names = set()
|
||||
|
||||
# Вкладка "Установленные версии Wine"
|
||||
installed_tab = QWidget()
|
||||
self.main_tabs.addTab(installed_tab, "Установленные версии Wine")
|
||||
installed_layout = QVBoxLayout(installed_tab)
|
||||
installed_scroll_area = QScrollArea()
|
||||
installed_scroll_area.setWidgetResizable(True)
|
||||
installed_scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
installed_layout.addWidget(installed_scroll_area)
|
||||
installed_content = QWidget()
|
||||
installed_scroll_area.setWidget(installed_content)
|
||||
self.installed_grid_layout = QGridLayout(installed_content)
|
||||
self.installed_grid_layout.setAlignment(Qt.AlignTop)
|
||||
|
||||
installed_versions_for_grid = []
|
||||
|
||||
# Системная версия
|
||||
self.system_wine_display_name = self._get_system_wine_version()
|
||||
installed_versions_for_grid.append((self.system_wine_display_name, "system"))
|
||||
|
||||
# Локально установленные версии
|
||||
local_versions = self._get_installed_versions()
|
||||
installed_versions_for_grid.extend(local_versions)
|
||||
|
||||
# Запоминаем имена установленных версий для пометки на вкладках загрузки
|
||||
for version_data in installed_versions_for_grid:
|
||||
if isinstance(version_data, tuple):
|
||||
_, value_name = version_data
|
||||
else:
|
||||
value_name = version_data
|
||||
self._installed_version_names.add(value_name)
|
||||
|
||||
self._create_grid_buttons_for_wine(
|
||||
self.installed_grid_layout, installed_versions_for_grid, is_download_tab=False
|
||||
)
|
||||
|
||||
# Вкладки с версиями для скачивания
|
||||
if not self.wine_versions_data:
|
||||
error_widget = QWidget()
|
||||
error_layout = QVBoxLayout(error_widget)
|
||||
error_label = QLabel("Список версий пуст или не удалось его загрузить.")
|
||||
error_label.setAlignment(Qt.AlignCenter)
|
||||
error_layout.addWidget(error_label)
|
||||
self.main_tabs.addTab(error_widget, "Ошибка")
|
||||
self.filter_versions()
|
||||
return
|
||||
|
||||
# Фильтрация и сортировка групп в зависимости от архитектуры
|
||||
is_win64 = self.architecture == "win64"
|
||||
|
||||
if is_win64:
|
||||
allowed_groups_for_arch = {"WINE AMD64", "WINE WOW64"}
|
||||
tab_order = ["WINE WOW64", "WINE AMD64"]
|
||||
display_names = {
|
||||
"WINE WOW64": "Загрузить wine-wow64",
|
||||
"WINE AMD64": "Загрузить wine-amd64"
|
||||
}
|
||||
else:
|
||||
allowed_groups_for_arch = {"WINE I586", "WINE AMD64"}
|
||||
tab_order = ["WINE I586", "WINE AMD64"]
|
||||
display_names = {
|
||||
"WINE I586": "Загрузить wine-i586",
|
||||
"WINE AMD64": "Загрузить wine-amd64"
|
||||
}
|
||||
|
||||
available_keys = [
|
||||
key for key in self.wine_versions_data.keys()
|
||||
if key in allowed_groups_for_arch
|
||||
]
|
||||
group_keys = sorted(available_keys, key=lambda k: tab_order.index(k))
|
||||
|
||||
for key in group_keys:
|
||||
versions = self.wine_versions_data.get(key, [])
|
||||
if not versions:
|
||||
continue
|
||||
display_name = display_names.get(key, key)
|
||||
self._create_version_tab_directly(display_name, sort_versions(versions, reverse=True))
|
||||
|
||||
self.filter_versions()
|
||||
|
||||
def _create_version_tab_directly(self, title, versions_list):
|
||||
"""Создает вкладку с сеткой кнопок и добавляет её напрямую в main_tabs."""
|
||||
tab_page = QWidget()
|
||||
tab_layout = QVBoxLayout(tab_page)
|
||||
tab_layout.setContentsMargins(5, 5, 5, 5)
|
||||
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
tab_layout.addWidget(scroll_area)
|
||||
|
||||
scroll_content = QWidget()
|
||||
scroll_area.setWidget(scroll_content)
|
||||
|
||||
grid_layout = QGridLayout(scroll_content)
|
||||
grid_layout.setAlignment(Qt.AlignTop)
|
||||
|
||||
self._create_grid_buttons_for_wine(grid_layout, versions_list, is_download_tab=True)
|
||||
self.main_tabs.addTab(tab_page, title)
|
||||
|
||||
def _create_grid_buttons_for_wine(self, grid_layout, versions_list, is_download_tab=False):
|
||||
"""Создает кнопки для версий в сетке."""
|
||||
is_win64_prefix = self.architecture == "win64"
|
||||
is_win32_prefix = self.architecture == "win32"
|
||||
re_32bit_version = re.compile(r'i[3-6]86|i586')
|
||||
|
||||
row, col = 0, 0
|
||||
for version_data in versions_list:
|
||||
if isinstance(version_data, tuple):
|
||||
display_name, value_name = version_data
|
||||
else:
|
||||
display_name = value_name = version_data
|
||||
|
||||
# Определяем, установлена ли версия
|
||||
# На вкладке установленных все версии установлены по определению
|
||||
if is_download_tab:
|
||||
is_installed = value_name in self._installed_version_names
|
||||
else:
|
||||
is_installed = True
|
||||
|
||||
# Создаем кастомную кнопку
|
||||
# На вкладке "Установленные версии Wine" значки не показываем
|
||||
show_icon = is_download_tab
|
||||
btn = VersionButtonWidget(display_name, value_name, is_installed=is_installed, show_icon=show_icon)
|
||||
btn.clicked.connect(partial(self.on_version_selected, value_name, display_name))
|
||||
|
||||
# Подсказка для неустановленных версий на вкладках загрузки
|
||||
if is_download_tab and not is_installed:
|
||||
btn.setToolTip("Эта версия доступна для загрузки. Нажмите, чтобы скачать и выбрать её.")
|
||||
|
||||
if value_name == "system":
|
||||
btn.setText(f"{display_name} (Системный)")
|
||||
btn.setToolTip("Системная версия Wine, установленная в вашей ОС.")
|
||||
|
||||
# Отключение 32-битных версий для 64-битного префикса
|
||||
if not is_download_tab and is_win64_prefix:
|
||||
if re_32bit_version.search(value_name):
|
||||
btn.setEnabled(False)
|
||||
btn.setToolTip("Эта 32-битная версия Wine несовместима с 64-битным префиксом.")
|
||||
|
||||
# Отключение 64-битных версий для 32-битного префикса
|
||||
if not is_download_tab and is_win32_prefix:
|
||||
if value_name == "system" or 'wow64' in value_name:
|
||||
btn.setEnabled(False)
|
||||
btn.setToolTip("Эта 64-битная версия Wine несовместима с 32-битным префиксом.")
|
||||
|
||||
grid_layout.addWidget(btn, row, col)
|
||||
# Сохраняем для фильтрации
|
||||
if is_download_tab:
|
||||
self.download_buttons.append(btn)
|
||||
else:
|
||||
self.installed_buttons.append(btn)
|
||||
col += 1
|
||||
if col >= self.NUM_COLUMNS:
|
||||
col = 0
|
||||
row += 1
|
||||
|
||||
def filter_versions(self):
|
||||
"""Фильтрует видимость кнопок версий на основе текста поиска."""
|
||||
search_text = self.search_edit.text()
|
||||
|
||||
# Фильтр для вкладки "Установленные"
|
||||
if hasattr(self, 'installed_grid_layout'):
|
||||
GridUtils.filter_buttons(
|
||||
self.installed_buttons, search_text,
|
||||
self.installed_grid_layout, self.NUM_COLUMNS
|
||||
)
|
||||
|
||||
# Фильтр для вкладок с версиями (теперь напрямую в main_tabs)
|
||||
# Пропускаем первую вкладку "Установленные" (индекс 0)
|
||||
for i in range(1, self.main_tabs.count()):
|
||||
tab_widget = self.main_tabs.widget(i)
|
||||
grid_layout, buttons = self._get_grid_layout_and_buttons(tab_widget)
|
||||
if grid_layout:
|
||||
visible = GridUtils.filter_buttons(
|
||||
buttons, search_text, grid_layout, self.NUM_COLUMNS
|
||||
)
|
||||
self.main_tabs.setTabEnabled(i, bool(visible))
|
||||
|
||||
def _get_grid_layout_and_buttons(self, tab_widget):
|
||||
"""Возвращает QGridLayout и список кнопок из вкладки."""
|
||||
scroll_area = tab_widget.findChild(QScrollArea)
|
||||
if not scroll_area:
|
||||
return None, []
|
||||
scroll_content = scroll_area.widget()
|
||||
if not scroll_content:
|
||||
return None, []
|
||||
grid_layout = scroll_content.layout()
|
||||
if not isinstance(grid_layout, QGridLayout):
|
||||
return None, []
|
||||
|
||||
buttons = []
|
||||
for j in range(grid_layout.count()):
|
||||
item = grid_layout.itemAt(j)
|
||||
if item and item.widget():
|
||||
buttons.append(item.widget())
|
||||
return grid_layout, buttons
|
||||
|
||||
def on_version_selected(self, version_name, display_name=None):
|
||||
"""Обрабатывает выбор версии Wine."""
|
||||
self.selected_version = version_name
|
||||
self.selected_display_text = display_name or version_name
|
||||
self.accept()
|
||||
@@ -0,0 +1,579 @@
|
||||
"""
|
||||
Диалог для управления компонентами Winetricks.
|
||||
"""
|
||||
import os
|
||||
import shlex
|
||||
from functools import partial
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QTabWidget,
|
||||
QTextEdit, QListWidget, QListWidgetItem, QMessageBox, QLineEdit, QWidget
|
||||
)
|
||||
from PyQt5.QtCore import Qt, QProcess, QTimer, QProcessEnvironment, pyqtSignal
|
||||
from PyQt5.QtGui import QTextCursor, QTextCharFormat, QFont
|
||||
|
||||
from winehelperqt.parsers.winetricks_parser import WinetricksOutputParser
|
||||
from winehelperqt.services.winetricks_service import WinetricksLogReader, WinetricksCacheService
|
||||
from winehelperqt.utils.environment import EnvironmentConfig
|
||||
from winehelperqt.utils.dialog_utils import DialogUtils
|
||||
|
||||
|
||||
class NoAutoScrollListWidget(QListWidget):
|
||||
"""QListWidget с отключённой автопрокруткой к текущему элементу."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._scroll_enabled = False # Флаг для ручной прокрутки
|
||||
|
||||
def scrollTo(self, index, hint=QListWidget.EnsureVisible):
|
||||
"""Переопределяем, чтобы игнорировать автоматическую прокрутку."""
|
||||
if self._scroll_enabled:
|
||||
super().scrollTo(index, hint)
|
||||
|
||||
def enable_scroll(self):
|
||||
"""Включает прокрутку для ручного управления."""
|
||||
self._scroll_enabled = True
|
||||
|
||||
def disable_scroll(self):
|
||||
"""Отключает прокрутку."""
|
||||
self._scroll_enabled = False
|
||||
|
||||
|
||||
class WinetricksManagerDialog(QDialog):
|
||||
"""Диалог для управления компонентами Winetricks."""
|
||||
|
||||
INFO_TEXT = (
|
||||
"Компоненты можно только установить либо переустановить.\n"
|
||||
"Удаление компонентов не реализовано в Winetricks.\n"
|
||||
"Для установки нового компонента: Поставьте галочку и нажмите «Применить».\n"
|
||||
"Для переустановки компонента: Выделите его в списке и нажмите кнопку «Переустановить»."
|
||||
)
|
||||
|
||||
installation_complete = pyqtSignal()
|
||||
|
||||
def __init__(self, prefix_path, winetricks_path, parent=None, wine_executable=None, winehelper_path=None):
|
||||
super().__init__(parent)
|
||||
self.prefix_path = prefix_path
|
||||
self.winetricks_path = winetricks_path
|
||||
self.wine_executable = wine_executable or 'wine'
|
||||
self.winehelper_path = winehelper_path or 'winehelper'
|
||||
self.initial_states = {}
|
||||
self.apply_process = None
|
||||
self.installation_finished = False
|
||||
self.user_cancelled = False
|
||||
self.processes = {}
|
||||
self.category_statuses = {}
|
||||
self.previous_tab_widget = None
|
||||
self.cache_service = WinetricksCacheService()
|
||||
self.is_reloading_after_cache_clear = False
|
||||
self.cache_clear_process = None
|
||||
self._install_queue = []
|
||||
|
||||
self.setWindowTitle(f"Менеджер компонентов для префикса: {os.path.basename(prefix_path)}")
|
||||
self.setMinimumSize(800, 500)
|
||||
|
||||
main_layout = QVBoxLayout(self)
|
||||
|
||||
self.tabs = QTabWidget()
|
||||
main_layout.addWidget(self.tabs)
|
||||
|
||||
self.categories = {
|
||||
"Библиотеки": "dlls",
|
||||
"Шрифты": "fonts",
|
||||
"Настройки": "settings"
|
||||
}
|
||||
self.list_widgets = {}
|
||||
self.search_edits = {}
|
||||
for display_name, internal_name in self.categories.items():
|
||||
list_widget, search_edit = self._create_category_tab(display_name)
|
||||
self.list_widgets[internal_name] = list_widget
|
||||
self.search_edits[internal_name] = search_edit
|
||||
|
||||
self.log_output = QTextEdit()
|
||||
self.log_output.setReadOnly(True)
|
||||
self.log_output.setFont(QFont('DejaVu Sans Mono', 10))
|
||||
self.log_output.setMaximumHeight(150)
|
||||
self.log_output.setText(self.INFO_TEXT)
|
||||
main_layout.addWidget(self.log_output)
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
self.clear_cache_button = QPushButton("Очистить кеш")
|
||||
self.clear_cache_button.setStyleSheet("background-color: red; color: white;")
|
||||
self.clear_cache_button.clicked.connect(self.clear_winetricks_cache)
|
||||
button_layout.addWidget(self.clear_cache_button)
|
||||
|
||||
button_layout.addStretch(1)
|
||||
|
||||
self.apply_button = QPushButton("Применить")
|
||||
self.apply_button.setEnabled(False)
|
||||
self.apply_button.clicked.connect(self.apply_changes)
|
||||
button_layout.addWidget(self.apply_button)
|
||||
|
||||
self.reinstall_button = QPushButton("Переустановить")
|
||||
self.reinstall_button.setEnabled(False)
|
||||
self.reinstall_button.clicked.connect(self.reinstall_selected)
|
||||
button_layout.addWidget(self.reinstall_button)
|
||||
|
||||
self.close_button = QPushButton("Закрыть")
|
||||
self.close_button.clicked.connect(self.close)
|
||||
button_layout.addWidget(self.close_button)
|
||||
main_layout.addLayout(button_layout)
|
||||
|
||||
self.tabs.currentChanged.connect(self.on_tab_switched)
|
||||
|
||||
self.load_all_categories()
|
||||
self.previous_tab_widget = self.tabs.currentWidget()
|
||||
|
||||
def on_tab_switched(self, index):
|
||||
"""Обрабатывает переключение вкладок."""
|
||||
if self.previous_tab_widget:
|
||||
previous_index = self.tabs.indexOf(self.previous_tab_widget)
|
||||
if previous_index >= 0:
|
||||
category = list(self.categories.values())[previous_index]
|
||||
search_edit = self.search_edits.get(category)
|
||||
if search_edit:
|
||||
search_edit.clear()
|
||||
|
||||
if self.installation_finished:
|
||||
self.log_output.setText(self.INFO_TEXT)
|
||||
self.installation_finished = False
|
||||
self._update_ui_state()
|
||||
self.previous_tab_widget = self.tabs.widget(index)
|
||||
|
||||
def _create_category_tab(self, title):
|
||||
"""Создает вкладку с поиском и списком."""
|
||||
tab = QWidget()
|
||||
layout = QVBoxLayout(tab)
|
||||
|
||||
search_edit = QLineEdit()
|
||||
search_edit.setPlaceholderText("Поиск...")
|
||||
layout.addWidget(search_edit)
|
||||
|
||||
list_widget = NoAutoScrollListWidget()
|
||||
list_widget.setAutoScroll(False) # Отключаем автопрокрутку
|
||||
list_widget.itemChanged.connect(self._on_item_changed)
|
||||
list_widget.currentItemChanged.connect(self._update_ui_state)
|
||||
layout.addWidget(list_widget)
|
||||
|
||||
search_edit.textChanged.connect(lambda text, lw=list_widget: self.filter_list(text, lw))
|
||||
|
||||
self.tabs.addTab(tab, title)
|
||||
return list_widget, search_edit
|
||||
|
||||
def filter_list(self, text, list_widget):
|
||||
"""Фильтрует элементы в списке."""
|
||||
# Блокируем все сигналы виджета, чтобы избежать автопрокрутки
|
||||
# и лишних вызовов _update_ui_state при скрытии элементов
|
||||
list_widget.blockSignals(True)
|
||||
list_widget.disable_scroll() # Отключаем прокрутку
|
||||
|
||||
for i in range(list_widget.count()):
|
||||
item = list_widget.item(i)
|
||||
item.setHidden(text.lower() not in item.text().lower())
|
||||
|
||||
# Включаем прокрутку и прокручиваем к первому видимому элементу
|
||||
list_widget.enable_scroll()
|
||||
for i in range(list_widget.count()):
|
||||
item = list_widget.item(i)
|
||||
if not item.isHidden():
|
||||
list_widget.scrollToItem(item, QListWidget.PositionAtTop)
|
||||
break
|
||||
|
||||
list_widget.blockSignals(False)
|
||||
|
||||
# Обновляем состояние кнопок после фильтрации
|
||||
self._update_ui_state()
|
||||
|
||||
def load_all_categories(self):
|
||||
"""Запускает загрузку всех категорий."""
|
||||
self.loading_count = len(self.categories)
|
||||
for internal_name in self.categories.values():
|
||||
self._start_load_process(internal_name)
|
||||
|
||||
def _start_load_process(self, category):
|
||||
"""Запускает QProcess для получения списка компонентов, используя кэш."""
|
||||
cached_output = self.cache_service.get_cached_data(category, self.winetricks_path)
|
||||
if cached_output is not None:
|
||||
QTimer.singleShot(0, lambda: self._on_load_finished(
|
||||
category, 0, QProcess.NormalExit, from_cache=cached_output
|
||||
))
|
||||
return
|
||||
|
||||
process = QProcess(self)
|
||||
self.processes[category] = process
|
||||
process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
|
||||
env = QProcessEnvironment.systemEnvironment()
|
||||
env.insert("WINEPREFIX", self.prefix_path)
|
||||
process.setProcessEnvironment(env)
|
||||
|
||||
process.finished.connect(partial(self._on_load_finished, category))
|
||||
process.start(self.winehelper_path, ["winetricks", category, "list"])
|
||||
|
||||
def _parse_winetricks_log(self):
|
||||
"""Читает winetricks.log и возвращает множество установленных компонентов."""
|
||||
log_reader = WinetricksLogReader(self.prefix_path)
|
||||
return log_reader.get_installed_verbs()
|
||||
|
||||
def _parse_winetricks_list_output(self, output, installed_verbs, list_widget, category):
|
||||
"""Парсит вывод 'winetricks list' и заполняет QListWidget."""
|
||||
parser = WinetricksOutputParser()
|
||||
items, found_items = parser.parse_list_output(output, installed_verbs, category)
|
||||
|
||||
for item_data in items:
|
||||
item = QListWidgetItem(item_data.item_text)
|
||||
item.setData(Qt.UserRole, item_data.name)
|
||||
item.setFont(QFont("DejaVu Sans Mono", 10))
|
||||
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
||||
item.setCheckState(Qt.Checked if item_data.is_installed else Qt.Unchecked)
|
||||
list_widget.addItem(item)
|
||||
self.initial_states[item_data.name] = item_data.is_installed
|
||||
|
||||
return found_items
|
||||
|
||||
def _on_load_finished(self, category, exit_code, exit_status, from_cache=None):
|
||||
"""Обрабатывает завершение загрузки списка компонентов."""
|
||||
if from_cache is not None:
|
||||
output = from_cache
|
||||
process = None
|
||||
else:
|
||||
process = self.processes[category]
|
||||
output = process.readAllStandardOutput().data().decode('utf-8', 'ignore')
|
||||
|
||||
list_widget = self.list_widgets.get(category)
|
||||
if list_widget is None:
|
||||
return
|
||||
|
||||
category_display_name = next(
|
||||
(k for k, v in self.categories.items() if v == category),
|
||||
category
|
||||
)
|
||||
|
||||
list_widget.clear()
|
||||
|
||||
if exit_code != 0 or exit_status != QProcess.NormalExit:
|
||||
error_string = process.errorString() if process else "N/A"
|
||||
self._log(f"--- Ошибка загрузки категории '{category_display_name}' (код: {exit_code}) ---", "red")
|
||||
if exit_status == QProcess.CrashExit:
|
||||
self._log("--- Процесс winetricks завершился аварийно. ---", "red")
|
||||
if error_string != "Неизвестная ошибка":
|
||||
self._log(f"--- Системная ошибка: {error_string} ---", "red")
|
||||
self._log(output if output.strip() else "Winetricks не вернул вывод. Проверьте, что он работает корректно.")
|
||||
self._log("--------------------------------------------------", "red")
|
||||
else:
|
||||
installed_verbs = self._parse_winetricks_log()
|
||||
found_items = self._parse_winetricks_list_output(output, installed_verbs, list_widget, category)
|
||||
|
||||
if from_cache is None:
|
||||
if not self.cache_service.save_to_cache(category, output, self.winetricks_path):
|
||||
self._log(f"--- Не удалось сохранить кэш для '{category}' ---")
|
||||
if not found_items and output.strip():
|
||||
self._log(f"--- Не удалось распознать вывод для категории '{category}' ---")
|
||||
self._log(output)
|
||||
self._log("--------------------------------------------------")
|
||||
|
||||
has_errors = any(status == 'error' for status in self.category_statuses.values())
|
||||
|
||||
self.loading_count -= 1
|
||||
if self.loading_count == 0:
|
||||
self._update_ui_state()
|
||||
if self.is_reloading_after_cache_clear:
|
||||
if has_errors:
|
||||
self._log("\n=== Ошибка при обновлении списков. Проверьте лог выше. ===", "red")
|
||||
else:
|
||||
self._log("\n=== Списки успешно обновлены ===")
|
||||
self.is_reloading_after_cache_clear = False
|
||||
|
||||
def _on_item_changed(self, item):
|
||||
"""Обрабатывает изменение состояния чекбокса."""
|
||||
name = item.data(Qt.UserRole)
|
||||
if name in self.initial_states and self.initial_states.get(name) is True:
|
||||
if item.checkState() == Qt.Unchecked:
|
||||
list_widget = item.listWidget()
|
||||
if list_widget:
|
||||
list_widget.blockSignals(True)
|
||||
item.setCheckState(Qt.Checked)
|
||||
if list_widget:
|
||||
list_widget.blockSignals(False)
|
||||
self._update_ui_state()
|
||||
|
||||
def _update_ui_state(self, *args):
|
||||
"""Обновляет состояние кнопок 'Применить' и 'Переустановить'."""
|
||||
has_changes = False
|
||||
for list_widget in self.list_widgets.values():
|
||||
for i in range(list_widget.count()):
|
||||
item = list_widget.item(i)
|
||||
name = item.data(Qt.UserRole)
|
||||
if name in self.initial_states:
|
||||
initial_state = self.initial_states[name]
|
||||
current_state = item.checkState() == Qt.Checked
|
||||
if current_state != initial_state:
|
||||
has_changes = True
|
||||
break
|
||||
if has_changes:
|
||||
break
|
||||
|
||||
self.apply_button.setEnabled(has_changes)
|
||||
|
||||
is_reinstallable = False
|
||||
if not has_changes:
|
||||
current_index = self.tabs.currentIndex()
|
||||
if current_index >= 0:
|
||||
category = list(self.categories.values())[current_index]
|
||||
current_list_widget = self.list_widgets.get(category)
|
||||
if current_list_widget:
|
||||
current_item = current_list_widget.currentItem()
|
||||
if current_item:
|
||||
name = current_item.data(Qt.UserRole)
|
||||
if self.initial_states.get(name, False):
|
||||
is_reinstallable = True
|
||||
|
||||
self.reinstall_button.setEnabled(is_reinstallable)
|
||||
|
||||
def reinstall_selected(self):
|
||||
"""Переустанавливает выбранный компонент."""
|
||||
current_index = self.tabs.currentIndex()
|
||||
if current_index < 0:
|
||||
return
|
||||
category = list(self.categories.values())[current_index]
|
||||
current_list_widget = self.list_widgets.get(category)
|
||||
if not current_list_widget:
|
||||
return
|
||||
|
||||
current_item = current_list_widget.currentItem()
|
||||
if not current_item:
|
||||
return
|
||||
|
||||
name = current_item.data(Qt.UserRole)
|
||||
if not name:
|
||||
return
|
||||
|
||||
self.log_output.setText(self.INFO_TEXT)
|
||||
self.apply_button.setEnabled(False)
|
||||
self.reinstall_button.setEnabled(False)
|
||||
self.close_button.setEnabled(False)
|
||||
|
||||
verbs_to_reinstall = [name]
|
||||
self._start_install_process([], verbs_to_reinstall)
|
||||
|
||||
def apply_changes(self):
|
||||
"""Применяет выбранные изменения."""
|
||||
verbs_to_install = []
|
||||
verbs_to_reinstall = []
|
||||
|
||||
for list_widget in self.list_widgets.values():
|
||||
for i in range(list_widget.count()):
|
||||
item = list_widget.item(i)
|
||||
name = item.data(Qt.UserRole)
|
||||
if name not in self.initial_states:
|
||||
continue
|
||||
|
||||
initial_state = self.initial_states[name]
|
||||
current_state = item.checkState() == Qt.Checked
|
||||
|
||||
if current_state != initial_state:
|
||||
if initial_state:
|
||||
verbs_to_reinstall.append(name)
|
||||
else:
|
||||
verbs_to_install.append(name)
|
||||
|
||||
if not verbs_to_install and not verbs_to_reinstall:
|
||||
QMessageBox.information(self, "Нет изменений", "Не выбрано ни одного компонента для установки.")
|
||||
return
|
||||
|
||||
self.log_output.setText(self.INFO_TEXT)
|
||||
self.apply_button.setEnabled(False)
|
||||
self.reinstall_button.setEnabled(False)
|
||||
self.close_button.setEnabled(False)
|
||||
|
||||
self._start_install_process(verbs_to_install, verbs_to_reinstall)
|
||||
|
||||
def _start_install_process(self, verbs_to_install, verbs_to_reinstall=None):
|
||||
"""Запускает процесс установки/переустановки winetricks.
|
||||
|
||||
Args:
|
||||
verbs_to_install: Список компонентов для новой установки (без --force)
|
||||
verbs_to_reinstall: Список компонентов для переустановки (с --force)
|
||||
"""
|
||||
if verbs_to_reinstall is None:
|
||||
verbs_to_reinstall = []
|
||||
|
||||
# Устанавливает новые компоненты (без --force)
|
||||
if verbs_to_install:
|
||||
self._install_queue.append((verbs_to_install, False))
|
||||
|
||||
# Переустанавливает компоненты (с --force)
|
||||
if verbs_to_reinstall:
|
||||
self._install_queue.append((verbs_to_reinstall, True))
|
||||
|
||||
# Запускаем первую задачу, если сейчас ничего не выполняется
|
||||
if not self.apply_process or self.apply_process.state() != QProcess.Running:
|
||||
self._process_next_install_task()
|
||||
|
||||
def _process_next_install_task(self):
|
||||
"""Берёт следующую задачу из очереди и запускает процесс."""
|
||||
if not self._install_queue:
|
||||
return
|
||||
|
||||
verbs, use_force = self._install_queue.pop(0)
|
||||
if use_force:
|
||||
self._log(f"Выполнение переустановки: winehelper winetricks --force {' '.join(verbs)}")
|
||||
else:
|
||||
self._log(f"Выполнение установки: winehelper winetricks {' '.join(verbs)}")
|
||||
self._run_winetricks_process(verbs, use_force)
|
||||
|
||||
def _run_winetricks_process(self, verbs, use_force=False):
|
||||
"""Запускает процесс winetricks с указанными компонентами.
|
||||
|
||||
Args:
|
||||
verbs: Список компонентов для установки
|
||||
use_force: Использовать ли флаг --force
|
||||
"""
|
||||
args = []
|
||||
if use_force:
|
||||
args.append("--force")
|
||||
args.extend(verbs)
|
||||
|
||||
# Всегда создаём новый QProcess, чтобы избежать повторного вызова start()
|
||||
# и дублирования обработчиков сигналов.
|
||||
if self.apply_process:
|
||||
try:
|
||||
self.apply_process.readyReadStandardOutput.disconnect()
|
||||
self.apply_process.finished.disconnect(self.on_apply_finished)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
self.apply_process = QProcess(self)
|
||||
self.apply_process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
|
||||
env = QProcessEnvironment.systemEnvironment()
|
||||
env.insert("WINEPREFIX", self.prefix_path)
|
||||
self.apply_process.setProcessEnvironment(env)
|
||||
self.apply_process.readyReadStandardOutput.connect(
|
||||
lambda: self.log_output.append(
|
||||
self.apply_process.readAllStandardOutput().data().decode('utf-8', 'ignore').strip()
|
||||
)
|
||||
)
|
||||
self.apply_process.finished.connect(self.on_apply_finished)
|
||||
|
||||
self.apply_process.start(self.winehelper_path, ["winetricks"] + args)
|
||||
|
||||
def on_apply_finished(self, exit_code, exit_status):
|
||||
"""Обрабатывает завершение применения изменений."""
|
||||
if self.user_cancelled:
|
||||
self._install_queue.clear()
|
||||
self._log("\n=== Установка прервана пользователем. ===")
|
||||
self.close()
|
||||
return
|
||||
|
||||
if exit_code != 0 or exit_status != QProcess.NormalExit:
|
||||
self._install_queue.clear()
|
||||
self._log(f"\n=== Ошибка во время выполнения операций (код: {exit_code}). ===", "red")
|
||||
self._show_message_box(
|
||||
"Ошибка",
|
||||
"Произошла ошибка во время выполнения операций.\nПодробности смотрите в логе.",
|
||||
QMessageBox.Warning,
|
||||
{"buttons": {"OK": QMessageBox.AcceptRole}}
|
||||
)
|
||||
self.log_output.setCurrentCharFormat(QTextCharFormat())
|
||||
self.apply_button.setEnabled(True)
|
||||
self.close_button.setEnabled(True)
|
||||
return
|
||||
|
||||
if self._install_queue:
|
||||
self._process_next_install_task()
|
||||
return
|
||||
|
||||
self._log("\n=== Все операции успешно завершены ===")
|
||||
self.apply_button.setEnabled(True)
|
||||
self.reinstall_button.setEnabled(False)
|
||||
self.close_button.setEnabled(True)
|
||||
|
||||
for search_edit in self.search_edits.values():
|
||||
search_edit.clear()
|
||||
|
||||
self.initial_states.clear()
|
||||
self.load_all_categories()
|
||||
self.installation_complete.emit()
|
||||
self.installation_finished = True
|
||||
|
||||
def clear_winetricks_cache(self):
|
||||
"""Запускает очистку кэша Winetricks."""
|
||||
if not DialogUtils.confirm(
|
||||
self,
|
||||
"Очистка кэша Winetricks",
|
||||
"Вы собираетесь удалить все скачанные установщики и списки компонентов Winetricks.\n\n"
|
||||
"Это действие может потребоваться, если у вас возникают проблемы "
|
||||
"со скачиванием или установкой компонентов.\n\n"
|
||||
"Продолжить?"
|
||||
):
|
||||
return
|
||||
|
||||
self.tabs.setEnabled(False)
|
||||
self.clear_cache_button.setEnabled(False)
|
||||
self.apply_button.setEnabled(False)
|
||||
self.reinstall_button.setEnabled(False)
|
||||
self.close_button.setEnabled(False)
|
||||
|
||||
self.log_output.clear()
|
||||
|
||||
self.cache_clear_process = QProcess(self)
|
||||
self.cache_clear_process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
|
||||
def handle_output():
|
||||
output = self.cache_clear_process.readAll().data().decode('utf-8', 'ignore').strip()
|
||||
if output:
|
||||
self._log(output)
|
||||
|
||||
def handle_finish(exit_code, exit_status):
|
||||
if exit_code == 0:
|
||||
self.is_reloading_after_cache_clear = True
|
||||
self.category_statuses.clear()
|
||||
self.cache_service._ensure_cache_dir()
|
||||
self._log("Обновление списков...")
|
||||
self.initial_states.clear()
|
||||
self.load_all_categories()
|
||||
else:
|
||||
self._log(f"\n=== Ошибка (код: {exit_code}) ===", "red")
|
||||
|
||||
self.tabs.setEnabled(True)
|
||||
self.clear_cache_button.setEnabled(True)
|
||||
self.close_button.setEnabled(True)
|
||||
self._update_ui_state()
|
||||
|
||||
self.cache_clear_process.readyRead.connect(handle_output)
|
||||
self.cache_clear_process.finished.connect(handle_finish)
|
||||
|
||||
if self.parent() and hasattr(self.parent(), 'winehelper_path'):
|
||||
winehelper_path = self.parent().winehelper_path
|
||||
else:
|
||||
winehelper_path = EnvironmentConfig.RUN_SCRIPT
|
||||
args = ["clear-winetricks-cache", "--force"]
|
||||
|
||||
self._log(f"Выполнение: {shlex.quote(winehelper_path)} {' '.join(args)}\n")
|
||||
self.cache_clear_process.start(winehelper_path, args)
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Обрабатывает закрытие окна."""
|
||||
if self.apply_process and self.apply_process.state() == QProcess.Running:
|
||||
if DialogUtils.confirm(
|
||||
self,
|
||||
'Подтверждение',
|
||||
"Процесс установки еще не завершен. Вы уверены, что хотите прервать его?"
|
||||
):
|
||||
self.user_cancelled = True
|
||||
self.log_output.append("\n=== Прерывание установки... Ожидание завершения процесса... ===")
|
||||
self.apply_process.terminate()
|
||||
event.ignore()
|
||||
else:
|
||||
event.accept()
|
||||
|
||||
def _log(self, message, color=None):
|
||||
"""Добавляет сообщение в лог с возможностью указания цвета."""
|
||||
if color:
|
||||
self.log_output.append(f'<span style="color:{color};">{message}</span>')
|
||||
self.log_output.setCurrentCharFormat(QTextCharFormat())
|
||||
else:
|
||||
self.log_output.append(message)
|
||||
self.log_output.moveCursor(QTextCursor.End)
|
||||