From fb6b60bc3f251fd50955244ffc8082b28f1b5ef2 Mon Sep 17 00:00:00 2001 From: 4aiman Date: Mon, 31 Aug 2026 00:13:50 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B2=D0=BE=D0=B9=20=D1=82=D0=B8=D0=BF?= =?UTF-8?q?=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=BE=D0=B2:=20*.nlve=20=D0=B1?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D1=88=D0=B5=20=D0=BD=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Внутри проект — обычный JSON, и система считала его просто текстом: открывала редактором и рисовала значок текстового файла. Теперь у него свой тип application/x-nlve-project, свой значок (лист с загнутым углом и знаком программы) и открытие двойным щелчком. Тип объявлен наследником application/json, но не простого текста — иначе редактор снова оказался бы программой по умолчанию. Всё, что нужно для встраивания в рабочий стол, лежит в packaging и ставится скриптом tools/install-desktop.sh в домашний каталог, без прав администратора. Раньше пункт меню и значки существовали только на одной машине и нигде не были записаны. --- README.md | 24 ++++++++ packaging/application-x-nlve-project.png | Bin 0 -> 3534 bytes packaging/application-x-nlve-project.xml | 22 +++++++ packaging/nlve.desktop.in | 17 +++++ packaging/nlve.png | Bin 0 -> 3640 bytes tools/install-desktop.sh | 75 +++++++++++++++++++++++ tools/make_file_icon.py | 62 +++++++++++++++++++ 7 files changed, 200 insertions(+) create mode 100644 packaging/application-x-nlve-project.png create mode 100644 packaging/application-x-nlve-project.xml create mode 100644 packaging/nlve.desktop.in create mode 100644 packaging/nlve.png create mode 100755 tools/install-desktop.sh create mode 100644 tools/make_file_icon.py diff --git a/README.md b/README.md index 1774416..012a2af 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,30 @@ Lazarus другой версии, и собранные им модули LCL `./nlve remux <файл>...` — в коде этого нет и не было: слово `remux` не является именем файла и молча пропускалось. +### Встраивание в рабочий стол + +``` +tools/install-desktop.sh # берёт ./nlve рядом с репозиторием +tools/install-desktop.sh /путь/к/nlve +``` + +Скрипт кладёт пункт меню, значки и описание типа файла — всё в домашний +каталог, без прав администратора. После этого `*.nlve` перестают быть +просто текстом: у них своё имя типа (`application/x-nlve-project`), свой +значок и открытие двойным щелчком. Проверяется так: + +``` +xdg-mime query filetype проект.nlve # application/x-nlve-project +xdg-mime query default application/x-nlve-project +``` + +Внутри проект — обычный JSON, и тип объявлен наследником +`application/json`. Наследником простого текста делать не стали: тогда +файл снова открывался бы редактором по умолчанию. + +Файловый менеджер может показать новый значок не сразу — ему нужно +перечитать базу. + ## Управление | Действие | Клавиши | diff --git a/packaging/application-x-nlve-project.png b/packaging/application-x-nlve-project.png new file mode 100644 index 0000000000000000000000000000000000000000..c9cd24500786080213df4cd6a17d9830f094349a GIT binary patch literal 3534 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 + + + + nlve project + Проект nlve + + + + + + diff --git a/packaging/nlve.desktop.in b/packaging/nlve.desktop.in new file mode 100644 index 0000000..c9550bc --- /dev/null +++ b/packaging/nlve.desktop.in @@ -0,0 +1,17 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=nlve +GenericName=Video editor +GenericName[ru]=Видеоредактор +Comment=Non-linear video editing without re-encoding +Comment[ru]=Монтаж видео без перекодирования +Exec=@BIN@ %f +Path=@DIR@ +Icon=nlve +Terminal=false +StartupNotify=true +Categories=AudioVideo;Video;AudioVideoEditing; +MimeType=application/x-nlve-project;video/mp4;video/x-matroska; +Keywords=video;editor;montage; +Keywords[ru]=видео;монтаж;редактор; diff --git a/packaging/nlve.png b/packaging/nlve.png new file mode 100644 index 0000000000000000000000000000000000000000..4736678e86ce90771c756f88303f670d3c75da98 GIT binary patch literal 3640 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 exit 1; } + +[ -x "$BIN" ] || fail "программы нет или она не запускается: $BIN" +[ -d "$PKG" ] || fail "нет каталога $PKG" + +note "Значки" +for SIZE in 32 48 64 128; do + mkdir -p "$ICONS/${SIZE}x${SIZE}/apps" "$ICONS/${SIZE}x${SIZE}/mimetypes" + # convert есть не у всех; без него кладём один размер как есть. + if command -v convert >/dev/null 2>&1; then + convert "$PKG/nlve.png" -resize ${SIZE}x${SIZE} \ + "$ICONS/${SIZE}x${SIZE}/apps/nlve.png" + convert "$PKG/application-x-nlve-project.png" -resize ${SIZE}x${SIZE} \ + "$ICONS/${SIZE}x${SIZE}/mimetypes/application-x-nlve-project.png" + elif [ "$SIZE" = 128 ]; then + cp -f "$PKG/nlve.png" "$ICONS/128x128/apps/nlve.png" + cp -f "$PKG/application-x-nlve-project.png" \ + "$ICONS/128x128/mimetypes/application-x-nlve-project.png" + fi +done + +note "Тип файла проекта" +mkdir -p "$MIME" +cp -f "$PKG/application-x-nlve-project.xml" "$MIME/nlve.xml" +if command -v update-mime-database >/dev/null 2>&1; then + update-mime-database "$DATA/mime" +else + echo "update-mime-database не найдена: тип не зарегистрируется" >&2 +fi + +note "Пункт меню" +mkdir -p "$APPS" +sed -e "s|@BIN@|$BIN|g" -e "s|@DIR@|$(dirname "$BIN")|g" \ + "$PKG/nlve.desktop.in" > "$APPS/nlve.desktop" +chmod 644 "$APPS/nlve.desktop" +command -v update-desktop-database >/dev/null 2>&1 && + update-desktop-database "$APPS" + +note "Программа по умолчанию для *.nlve" +command -v xdg-mime >/dev/null 2>&1 && + xdg-mime default nlve.desktop application/x-nlve-project + +command -v gtk-update-icon-cache >/dev/null 2>&1 && + gtk-update-icon-cache -f -t "$ICONS" >/dev/null 2>&1 + +echo +echo "готово. Проверить: xdg-mime query filetype <файл>.nlve" +echo "Файловый менеджер может показать новый значок не сразу:" +echo "ему нужно перечитать базу (обычно достаточно перезапуска)." diff --git a/tools/make_file_icon.py b/tools/make_file_icon.py new file mode 100644 index 0000000..49a0c8e --- /dev/null +++ b/tools/make_file_icon.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +""" +Делает значок файла проекта из значка программы. + +Зачем отдельный. Значок программы и значок её файлов — разные вещи: в +списке файлов должно быть видно, что это документ, а не сама программа. +Поэтому берётся лист с загнутым углом, а знак программы кладётся на него. + +Запуск: python3 tools/make_file_icon.py +Итог: packaging/application-x-nlve-project.png +""" + +from pathlib import Path +from PIL import Image, ImageDraw + +ROOT = Path(__file__).resolve().parent.parent +SRC = ROOT / 'packaging' / 'nlve.png' +DST = ROOT / 'packaging' / 'application-x-nlve-project.png' + +SIZE = 128 +# Лист занимает не всю клетку: значкам документов принято оставлять поля. +MARGIN_X = 16 +MARGIN_Y = 6 +FOLD = 30 + +PAPER = (245, 245, 245, 255) +FOLD_COLOR = (205, 205, 205, 255) +EDGE = (120, 120, 120, 255) + + +def main(): + if not SRC.exists(): + raise SystemExit(f'нет файла {SRC}') + + img = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0)) + d = ImageDraw.Draw(img) + + left, right = MARGIN_X, SIZE - MARGIN_X + top, bottom = MARGIN_Y, SIZE - MARGIN_Y + + # Лист с срезанным правым верхним углом. + body = [ + (left, top), (right - FOLD, top), (right, top + FOLD), + (right, bottom), (left, bottom), + ] + d.polygon(body, fill=PAPER, outline=EDGE) + # Сам загнутый угол. + d.polygon([(right - FOLD, top), (right, top + FOLD), + (right - FOLD, top + FOLD)], fill=FOLD_COLOR, outline=EDGE) + + # Знак программы поверх листа, в нижней его части: сверху угол. + mark = Image.open(SRC).convert('RGBA') + side = 66 + mark = mark.resize((side, side), Image.LANCZOS) + img.alpha_composite(mark, ((SIZE - side) // 2, bottom - side - 8)) + + img.save(DST) + print('готов:', DST) + + +if __name__ == '__main__': + main()