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 0000000..c9cd245 Binary files /dev/null and b/packaging/application-x-nlve-project.png differ diff --git a/packaging/application-x-nlve-project.xml b/packaging/application-x-nlve-project.xml new file mode 100644 index 0000000..567c6e8 --- /dev/null +++ b/packaging/application-x-nlve-project.xml @@ -0,0 +1,22 @@ + + + + + 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 0000000..4736678 Binary files /dev/null and b/packaging/nlve.png differ diff --git a/tools/install-desktop.sh b/tools/install-desktop.sh new file mode 100755 index 0000000..447b82d --- /dev/null +++ b/tools/install-desktop.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# Встраивание в рабочий стол: пункт меню, значки и тип файла проекта. +# +# Что делает: +# - кладёт значок программы и значок файла проекта в ~/.local/share/icons +# - описывает тип application/x-nlve-project, чтобы *.nlve перестали +# считаться просто текстом +# - кладёт пункт меню, который открывает такие файлы нашей программой +# +# Всё в домашнем каталоге: прав администратора не нужно, другим +# пользователям системы ничего не меняется. +# +# Запуск: tools/install-desktop.sh [путь к программе] +# По умолчанию берётся nlve рядом с этим репозиторием. +set -u + +HERE=$(cd "$(dirname "$0")/.." && pwd) +BIN=${1:-$HERE/nlve} +PKG=$HERE/packaging + +DATA=${XDG_DATA_HOME:-$HOME/.local/share} +APPS=$DATA/applications +MIME=$DATA/mime/packages +ICONS=$DATA/icons/hicolor + +note() { echo "== $*"; } +fail() { echo "$*" >&2; 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()