├── po ├── LINGUAS ├── meson.build ├── POTFILES.in └── pt.po ├── data ├── screenshots │ ├── screenshot1.png │ ├── screenshot2.png │ ├── screenshot3.png │ ├── screenshot4.png │ └── screenshot5.png ├── immagini.gresource.xml ├── dev.salaniLeo.immagini.desktop.in ├── meson.build ├── dev.salaniLeo.immagini.gschema.xml ├── dev.salaniLeo.immagini.appdata.xml.in ├── python-dependencies.json └── dev.salaniLeo.immagini.svg ├── Immagini ├── creator │ ├── builder │ │ ├── tool │ │ │ ├── .DirIcon │ │ │ ├── usr │ │ │ │ ├── bin │ │ │ │ │ ├── AppRun │ │ │ │ │ ├── zsyncmake │ │ │ │ │ ├── appimagetool │ │ │ │ │ └── desktop-file-validate │ │ │ │ ├── lib │ │ │ │ │ ├── libffi.so.6 │ │ │ │ │ ├── libpcre.so │ │ │ │ │ ├── libgio-2.0.so │ │ │ │ │ ├── libglib-2.0.so │ │ │ │ │ ├── libpcre.so.1 │ │ │ │ │ ├── libpcrecpp.so │ │ │ │ │ ├── libgio-2.0.so.0 │ │ │ │ │ ├── libglib-2.0.so.0 │ │ │ │ │ ├── libpcre.so.1.2.8 │ │ │ │ │ ├── libpcrecpp.so.0 │ │ │ │ │ ├── libpcreposix.so │ │ │ │ │ ├── libgmodule-2.0.so │ │ │ │ │ ├── libgmodule-2.0.so.0 │ │ │ │ │ ├── libgobject-2.0.so │ │ │ │ │ ├── libgobject-2.0.so.0 │ │ │ │ │ ├── libgthread-2.0.so │ │ │ │ │ ├── libgthread-2.0.so.0 │ │ │ │ │ ├── libpcrecpp.so.0.0.1 │ │ │ │ │ ├── libpcreposix.so.0 │ │ │ │ │ ├── libpcreposix.so.0.0.4 │ │ │ │ │ ├── appimagekit │ │ │ │ │ │ └── mksquashfs │ │ │ │ │ ├── libgio-2.0.so.0.5600.0 │ │ │ │ │ ├── libglib-2.0.so.0.5600.0 │ │ │ │ │ ├── libgmodule-2.0.so.0.5600.0 │ │ │ │ │ ├── libgobject-2.0.so.0.5600.0 │ │ │ │ │ └── libgthread-2.0.so.0.5600.0 │ │ │ │ └── share │ │ │ │ │ ├── icons │ │ │ │ │ └── hicolor │ │ │ │ │ │ └── 128x128 │ │ │ │ │ │ └── apps │ │ │ │ │ │ └── appimagetool.png │ │ │ │ │ ├── applications │ │ │ │ │ └── appimagetool.desktop │ │ │ │ │ └── metainfo │ │ │ │ │ └── appimagetool.appdata.xml │ │ │ ├── appimagetool.png │ │ │ ├── appimagetool.desktop │ │ │ └── AppRun │ │ └── builder.py │ ├── copyInterpreters.py │ ├── desktopFile.py │ ├── copyExeFile.py │ ├── copyLibraries.py │ ├── AppRun.py │ └── copyIconFile.py ├── main.py ├── ui │ ├── console.py │ ├── error.py │ ├── uiElements.py │ ├── template.py │ ├── strings.py │ ├── mainWindow.py │ └── newImage.py ├── convertFlatpak.py ├── imageCreator.py └── library │ ├── getContent.py │ └── imageOptions.py ├── __init__.py ├── share └── icons │ ├── meson.build │ └── hicolor │ ├── symbolic │ └── apps │ │ └── dev.salaniLeo.immagini-symbolic.svg │ └── scalable │ ├── apps │ ├── dev.salaniLeo.immagini.svg │ └── dev.salaniLeo.immagini.Devel.svg │ └── actions │ └── im-symbolic.svg ├── .gitignore ├── meson.build ├── immagini.in ├── README.md ├── messages.po └── dev.salaniLeo.immagini.json /po/LINGUAS: -------------------------------------------------------------------------------- 1 | pt -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n.gettext(meson.project_name(), preset: 'glib') -------------------------------------------------------------------------------- /data/screenshots/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/data/screenshots/screenshot1.png -------------------------------------------------------------------------------- /data/screenshots/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/data/screenshots/screenshot2.png -------------------------------------------------------------------------------- /data/screenshots/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/data/screenshots/screenshot3.png -------------------------------------------------------------------------------- /data/screenshots/screenshot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/data/screenshots/screenshot4.png -------------------------------------------------------------------------------- /data/screenshots/screenshot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/data/screenshots/screenshot5.png -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/.DirIcon: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/.DirIcon -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/bin/AppRun: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/bin/AppRun -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/appimagetool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/appimagetool.png -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/bin/zsyncmake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/bin/zsyncmake -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | if __name__ == '__main__': 4 | 5 | from gi.repository import Gio 6 | 7 | from Immagini import main 8 | -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libffi.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libffi.so.6 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcre.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcre.so -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/bin/appimagetool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/bin/appimagetool -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgio-2.0.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgio-2.0.so -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libglib-2.0.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libglib-2.0.so -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcre.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcre.so.1 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcrecpp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcrecpp.so -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgio-2.0.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgio-2.0.so.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libglib-2.0.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libglib-2.0.so.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcre.so.1.2.8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcre.so.1.2.8 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcrecpp.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcrecpp.so.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcreposix.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcreposix.so -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgmodule-2.0.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgmodule-2.0.so -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgmodule-2.0.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgmodule-2.0.so.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgobject-2.0.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgobject-2.0.so -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgobject-2.0.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgobject-2.0.so.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgthread-2.0.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgthread-2.0.so -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgthread-2.0.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgthread-2.0.so.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcrecpp.so.0.0.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcrecpp.so.0.0.1 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcreposix.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcreposix.so.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/bin/desktop-file-validate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/bin/desktop-file-validate -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libpcreposix.so.0.0.4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libpcreposix.so.0.0.4 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/appimagekit/mksquashfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/appimagekit/mksquashfs -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgio-2.0.so.0.5600.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgio-2.0.so.0.5600.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libglib-2.0.so.0.5600.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libglib-2.0.so.0.5600.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgmodule-2.0.so.0.5600.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgmodule-2.0.so.0.5600.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgobject-2.0.so.0.5600.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgobject-2.0.so.0.5600.0 -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/lib/libgthread-2.0.so.0.5600.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/lib/libgthread-2.0.so.0.5600.0 -------------------------------------------------------------------------------- /data/immagini.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /data/dev.salaniLeo.immagini.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Immagini 3 | Exec=immagini 4 | Icon=dev.salaniLeo.immagini 5 | Terminal=false 6 | Type=Application 7 | Categories=GTK; 8 | StartupNotify=true 9 | -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/share/icons/hicolor/128x128/apps/appimagetool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalaniLeo/Immagini/HEAD/Immagini/creator/builder/tool/usr/share/icons/hicolor/128x128/apps/appimagetool.png -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | # List of source files containing translatable strings. 2 | data/dev.salaniLeo.immagini.appdata.xml.in 3 | data/dev.salaniLeo.immagini.desktop.in 4 | data/dev.salaniLeo.immagini.gschema.xml 5 | Immagini/ui/strings.py -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/appimagetool.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=appimagetool 4 | Exec=appimagetool 5 | Comment=Tool to generate AppImages from AppDirs 6 | Icon=appimagetool 7 | Categories=Development; 8 | Terminal=true 9 | 10 | -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/share/applications/appimagetool.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=appimagetool 4 | Exec=appimagetool 5 | Comment=Tool to generate AppImages from AppDirs 6 | Icon=appimagetool 7 | Categories=Development; 8 | Terminal=true 9 | 10 | -------------------------------------------------------------------------------- /Immagini/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from .ui.mainWindow import Immagini 3 | import os 4 | 5 | AppId="dev.salaniLeo.immagini" 6 | flatpak = False 7 | 8 | if 'FLATPAK_SANDBOX_DIR' in os.environ: 9 | flatpak = True 10 | 11 | 12 | class main(): 13 | app = Immagini(AppId,flatpak) 14 | app.run(sys.argv) -------------------------------------------------------------------------------- /share/icons/meson.build: -------------------------------------------------------------------------------- 1 | application_id = 'dev.salaniLeo.immagini' 2 | 3 | scalable_dir = join_paths('hicolor', 'scalable', 'apps') 4 | install_data( 5 | join_paths(scalable_dir, ('@0@.svg').format(application_id)), 6 | install_dir: join_paths(get_option('datadir'), 'icons', scalable_dir) 7 | ) 8 | 9 | symbolic_dir = join_paths('hicolor', 'symbolic', 'apps') 10 | install_data( 11 | join_paths(symbolic_dir, ('@0@-symbolic.svg').format(application_id)), 12 | install_dir: join_paths(get_option('datadir'), 'icons', symbolic_dir) 13 | ) 14 | 15 | -------------------------------------------------------------------------------- /Immagini/creator/copyInterpreters.py: -------------------------------------------------------------------------------- 1 | import os 2 | from ..ui.error import throwError 3 | import shutil 4 | 5 | class copyInterpreters: 6 | def copyInterpreter(location, destination): 7 | if os.path.isdir(location): 8 | copyInterpreters.copyFolder(location, destination) 9 | elif os.path.isfile(location): 10 | copyInterpreters.copyFile(location, destination) 11 | 12 | def copyFolder(location, destination): 13 | shutil.copytree(location, destination) 14 | 15 | def copyFile(location, destination): 16 | shutil.copy(location, destination) 17 | -------------------------------------------------------------------------------- /Immagini/creator/desktopFile.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import ntpath 4 | 5 | def createDesktopFile(name,exeName,iconName,type,categories,appDirPath): 6 | 7 | tmp = ntpath.basename(iconName) 8 | icon = os.path.splitext(tmp)[0] 9 | 10 | f = open(appDirPath + name + ".desktop", "w") 11 | 12 | f.writelines("[Desktop Entry]") 13 | f.writelines("\nName=" + name) 14 | f.writelines("\nExec=" + exeName) 15 | f.writelines("\nIcon=" + icon) 16 | f.writelines("\nType=" + type) 17 | f.writelines("\nCategories=" + categories) 18 | f.close() 19 | 20 | def copyDesktopFile(file, dest): 21 | shutil.copy(file, dest) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | start.py 2 | assets/run.sh 3 | assets/test.ui 4 | build-dir/* 5 | .flatpak-builder/* 6 | local \build/* 7 | .gitignore 8 | data/creator/__pycache__/AppDir.cpython-311.pyc 9 | data/creator/__pycache__/AppRun.cpython-311.pyc 10 | data/creator/__pycache__/copyExeFile.cpython-311.pyc 11 | data/creator/__pycache__/copyIconFile.cpython-311.pyc 12 | data/creator/__pycache__/desktopFile.cpython-311.pyc 13 | data/creator/__pycache__/error.cpython-311.pyc 14 | data/creator/builder/__pycache__/builder.cpython-311.pyc 15 | data/__pycache__/imageCreator.cpython-311.pyc 16 | data/__pycache__/main.cpython-311.pyc 17 | local build/flatpak-build.sh 18 | test.py 19 | TODO 20 | flatpak-repo/build-repo.sh 21 | messages.mo 22 | -------------------------------------------------------------------------------- /Immagini/creator/copyExeFile.py: -------------------------------------------------------------------------------- 1 | import os 2 | from os import path 3 | from ..ui.error import throwError 4 | from ..ui.strings import * 5 | import shutil 6 | 7 | # default copyExe option 8 | def copyExe(exe,appDirPath,exeName, self, mainWindow): 9 | 10 | # exe file copy destination 11 | dst = appDirPath + "usr/bin/" + exeName 12 | 13 | # checks if exe file exists 14 | if path.exists(exe): 15 | shutil.copyfile(exe, dst) 16 | else: 17 | throwError(self, invalidExeSubtitle, invalidExeTitle, mainWindow) 18 | 19 | def copyExePFolder(appDirPath,pFolderName,parentFolder,exe, self, mainWindow): 20 | 21 | appDirPath = appDirPath + 'usr/' + pFolderName 22 | 23 | 24 | if path.exists(parentFolder): 25 | shutil.copytree(parentFolder, appDirPath) 26 | os.chmod(exe , 777) 27 | else: 28 | throwError(self, invalidExeSubtitle, invalidExeTitle, mainWindow) 29 | -------------------------------------------------------------------------------- /Immagini/creator/copyLibraries.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | import os 3 | from ..ui.error import throwError 4 | import shutil 5 | from ..ui.strings import * 6 | 7 | # default copyExe option 8 | def copyLibraries(libraries, appDirPath, self, mainWindow): 9 | 10 | num = len(libraries) 11 | libArray = libraries.split('\n') 12 | 13 | x = 0 14 | 15 | for x in range(len(libArray)): 16 | 17 | if x == 0: 18 | src = '/'+libArray[x][1:] 19 | else: 20 | src = libArray[x][1:] 21 | 22 | if os.path.exists(src): 23 | dst = appDirPath + "usr/lib/" + os.path.basename(libArray[x]) 24 | 25 | if x == 0: 26 | shutil.copy(src, dst) 27 | else: 28 | shutil.copy(src, dst) 29 | 30 | os.chmod(dst, 777) 31 | else: 32 | throwError(self, invalidLibraryTitle + " '" + libArray[x][1:] + "'", invalidLibrarySubtitle, mainWindow) 33 | -------------------------------------------------------------------------------- /share/icons/hicolor/symbolic/apps/dev.salaniLeo.immagini-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Immagini/creator/builder/builder.py: -------------------------------------------------------------------------------- 1 | import os 2 | from ...ui.console import console 3 | import gi 4 | 5 | gi.require_version(namespace='Gtk', version='4.0') 6 | gi.require_version(namespace='Adw', version='1') 7 | 8 | from gi.repository import Adw, Gtk 9 | 10 | # import shutil 11 | 12 | def initBuild(appDirPath, output, name, flatpak, mainWindow, thread=None): 13 | # os.system("ARCH=x86_64 ./creator/builder/appimagetool-x86_64.AppImage " + "'" + appDirPath + "'" + " " + output + "/" + name + "-x86_64.AppImage") 14 | # shutil.move(name + "-x86_64.AppImage", output + "/" + name + "-x86_64.AppImage") 15 | 16 | if flatpak: 17 | toolDir = "/app/bin/Immagini/creator/builder/tool/AppRun" 18 | else: 19 | toolDir = "Immagini/creator/builder/tool/AppRun" 20 | 21 | # os.chmod(toolDir, 777) 22 | buildoutput = os.popen("ARCH=x86_64 " + toolDir + " '" + appDirPath + "'" + " '" + output + "/" + name + "-x86_64.AppImage' ").read() 23 | 24 | terminal = Gtk.TextView() 25 | terminal.set_editable(False) 26 | 27 | bff = Gtk.TextBuffer() 28 | terminal = Gtk.TextView(buffer = bff) 29 | 30 | iter = bff.get_end_iter() 31 | bff.insert(iter, buildoutput) 32 | 33 | consolePage = console(mainWindow, terminal) 34 | consolePage.present() 35 | 36 | 37 | 38 | return buildoutput -------------------------------------------------------------------------------- /Immagini/ui/console.py: -------------------------------------------------------------------------------- 1 | import gi 2 | from ..ui.strings import * 3 | gi.require_version(namespace='Gtk', version='4.0') 4 | gi.require_version(namespace='Adw', version='1') 5 | 6 | from gi.repository import Adw, Gtk 7 | 8 | class console(Adw.MessageDialog): 9 | def __init__(self, mainWindow, console, **kwargs): 10 | super().__init__(**kwargs) 11 | 12 | self.set_default_size(500,225) 13 | self.set_title(title=terminalTitle) 14 | self.set_transient_for(mainWindow) 15 | self.set_modal(True) 16 | 17 | self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) 18 | 19 | self.scrolled = Gtk.ScrolledWindow() 20 | self.scrolled.set_margin_bottom(25) 21 | self.scrolled.set_margin_top(25) 22 | self.scrolled.set_margin_end(25) 23 | self.scrolled.set_margin_start(25) 24 | self.scrolled.set_vexpand(True) 25 | 26 | self.closeButton = Gtk.Button(label=globalClose) 27 | self.closeButton.set_hexpand(True) 28 | self.closeButton.set_size_request(-1, 50) 29 | self.closeButton.connect('clicked', self.exit) 30 | 31 | self.box.append(self.scrolled) 32 | self.box.append(self.closeButton) 33 | 34 | self.set_child(self.box) 35 | 36 | self.scrolled.set_child(console) 37 | 38 | def exit(self, button): 39 | self.close() 40 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('immagini', 2 | version: '0.1.1', 3 | meson_version: '>= 0.59.0', 4 | default_options: [ 'warning_level=2', 'werror=false', ], 5 | ) 6 | 7 | APPLICATION_ID = 'io.github.salaniLeo.immagini@0@'.format('') 8 | PKGDATA_DIR = join_paths(get_option('prefix'), get_option('datadir'), APPLICATION_ID) 9 | PKGLIB_DIR = join_paths(get_option('prefix'), get_option('libdir'), APPLICATION_ID) 10 | 11 | i18n = import('i18n') 12 | gnome = import('gnome') 13 | 14 | pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name()) 15 | moduledir = join_paths(pkgdatadir, 'immagini') 16 | 17 | subdir('data') 18 | 19 | python = import('python') 20 | 21 | conf = configuration_data() 22 | conf.set('PYTHON', python.find_installation('python3').path()) 23 | conf.set('VERSION', meson.project_version()) 24 | conf.set('localedir', join_paths(get_option('prefix'), get_option('localedir'))) 25 | conf.set('pkgdatadir', pkgdatadir) 26 | 27 | configure_file( 28 | input: 'immagini.in', 29 | output: 'immagini', 30 | configuration: conf, 31 | install: true, 32 | install_dir: get_option('bindir') 33 | ) 34 | 35 | install_subdir('Immagini', install_dir: '/app/bin') 36 | subdir('share/icons') 37 | 38 | gnome.post_install( 39 | glib_compile_schemas: true, 40 | gtk_update_icon_cache: true, 41 | update_desktop_database: true, 42 | ) 43 | -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/AppRun: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | SELF=$(readlink -f "$0") 3 | HERE=${SELF%/*} 4 | export PATH="${HERE}/usr/bin/:${HERE}/usr/sbin/:${HERE}/usr/games/:${HERE}/bin/:${HERE}/sbin/${PATH:+:$PATH}" 5 | export LD_LIBRARY_PATH="${HERE}/usr/lib/:${HERE}/usr/lib/i386-linux-gnu/:${HERE}/usr/lib/x86_64-linux-gnu/:${HERE}/usr/lib32/:${HERE}/usr/lib64/:${HERE}/lib/:${HERE}/lib/i386-linux-gnu/:${HERE}/lib/x86_64-linux-gnu/:${HERE}/lib32/:${HERE}/lib64/${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" 6 | export PYTHONPATH="${HERE}/usr/share/pyshared/${PYTHONPATH:+:$PYTHONPATH}" 7 | export XDG_DATA_DIRS="${HERE}/usr/share/${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}" 8 | export PERLLIB="${HERE}/usr/share/perl5/:${HERE}/usr/lib/perl5/${PERLLIB:+:$PERLLIB}" 9 | export GSETTINGS_SCHEMA_DIR="${HERE}/usr/share/glib-2.0/schemas/${GSETTINGS_SCHEMA_DIR:+:$GSETTINGS_SCHEMA_DIR}" 10 | export QT_PLUGIN_PATH="${HERE}/usr/lib/qt4/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt4/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt4/plugins/:${HERE}/usr/lib32/qt4/plugins/:${HERE}/usr/lib64/qt4/plugins/:${HERE}/usr/lib/qt5/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt5/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt5/plugins/:${HERE}/usr/lib32/qt5/plugins/:${HERE}/usr/lib64/qt5/plugins/${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}" 11 | EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1) 12 | exec "${EXEC}" "$@" 13 | -------------------------------------------------------------------------------- /Immagini/creator/builder/tool/usr/share/metainfo/appimagetool.appdata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | appimagetool.desktop 4 | MIT 5 | MIT 6 | appimagetool 7 | Create AppImage files 8 | 9 |

10 | appimagetool is a tool that lets you generate AppImage files. An AppImage 11 | is a self-running bundle that contains an application and everything 12 | it needs to run that cannot reasonably expected to be part of each target system. 13 |

14 |

15 | This can include libraries that are not commonly available on target systems, 16 | resources such as translations, icons, fonts, and other auxiliary files. 17 | appimagetool makes it easy to take an AppDir (e.g., generated by linuxdeployqt) 18 | and turn it into an AppImage. 19 |

20 |

21 | You can also embed update information so that your users can update the AppImage 22 | using binary delta updates with the AppImageUpdate tool. 23 | You can also sign the AppImage with GPG. 24 |

25 |
26 | https://github.com/AppImage/AppImageKit 27 | AppImage 28 | 29 | appimagetool 30 | 31 |
32 | -------------------------------------------------------------------------------- /immagini.in: -------------------------------------------------------------------------------- 1 | #!@PYTHON@ 2 | 3 | # immagini.in 4 | # 5 | # Copyright 2023 immagini 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | # 20 | # SPDX-License-Identifier: GPL-3.0-or-later 21 | 22 | import os 23 | import sys 24 | import signal 25 | import locale 26 | import gettext 27 | 28 | VERSION = '@VERSION@' 29 | pkgdatadir = '@pkgdatadir@' 30 | localedir = '@localedir@' 31 | 32 | sys.path.insert(1, pkgdatadir) 33 | signal.signal(signal.SIGINT, signal.SIG_DFL) 34 | locale.bindtextdomain('immagini', localedir) 35 | locale.textdomain('immagini') 36 | gettext.install('immagini', localedir) 37 | 38 | if __name__ == '__main__': 39 | import gi 40 | 41 | from gi.repository import Gio 42 | resource = Gio.Resource.load(os.path.join(pkgdatadir, 'immagini.gresource')) 43 | resource._register() 44 | 45 | from Immagini import main 46 | 47 | 48 | -------------------------------------------------------------------------------- /data/meson.build: -------------------------------------------------------------------------------- 1 | desktop_file = i18n.merge_file( 2 | input: 'dev.salaniLeo.immagini.desktop.in', 3 | output: 'dev.salaniLeo.immagini.desktop', 4 | type: 'desktop', 5 | po_dir: '../po', 6 | install: true, 7 | install_dir: join_paths(get_option('datadir'), 'applications') 8 | ) 9 | 10 | desktop_utils = find_program('desktop-file-validate', required: false) 11 | if desktop_utils.found() 12 | test('Validate desktop file', desktop_utils, args: [desktop_file]) 13 | endif 14 | 15 | appstream_file = i18n.merge_file( 16 | input: 'dev.salaniLeo.immagini.appdata.xml.in', 17 | output: 'dev.salaniLeo.immagini.appdata.xml', 18 | po_dir: '../po', 19 | install: true, 20 | install_dir: join_paths(get_option('datadir'), 'appdata') 21 | ) 22 | 23 | appstream_util = find_program('appstream-util', required: false) 24 | if appstream_util.found() 25 | test('Validate appstream file', appstream_util, args: ['validate', appstream_file]) 26 | endif 27 | 28 | install_data('dev.salaniLeo.immagini.gschema.xml', 29 | install_dir: join_paths(get_option('datadir'), 'glib-2.0/schemas') 30 | ) 31 | 32 | compile_schemas = find_program('glib-compile-schemas', required: false) 33 | if compile_schemas.found() 34 | test('Validate schema file', 35 | compile_schemas, 36 | args: ['--strict', '--dry-run', meson.current_source_dir()]) 37 | endif 38 | 39 | gnome.compile_resources('immagini', 40 | 'immagini.gresource.xml', 41 | gresource_bundle: true, 42 | install: true, 43 | install_dir: pkgdatadir, 44 | ) -------------------------------------------------------------------------------- /data/dev.salaniLeo.immagini.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | the app starts with this option enabled 8 | automatically enables the option to create appimages in foldermode 9 | 10 | 11 | 12 | true 13 | Does the app removes .AppDir as default? 14 | automatically removes .appdir folder generated to build the appimage 15 | 16 | 17 | 18 | false 19 | the app requests a customapprun as default 20 | automatically enables the option to create appimages with a custom apprun 21 | 22 | 23 | 24 | '~/Applications' 25 | location of output and library 26 | test 27 | 28 | 29 | 30 | true 31 | location of output 32 | test 33 | 34 | 35 | 36 | false 37 | executes appimage in a terminal 38 | If the option is on the appimage selected will be run inside a terminal 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Immagini/creator/AppRun.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import os 4 | from pathlib import Path 5 | from ..ui.error import throwError 6 | from ..ui.strings import * 7 | from os import path 8 | 9 | def createAppRunFile(exeName,appDirPath,folderMode,exePathFolderMode,pFolderName, includeInterpreters, self): 10 | 11 | try: 12 | includePython = includeInterpreters[0] 13 | includeJava = includeInterpreters[1] 14 | except: 15 | None 16 | 17 | executeMethod = "exec" 18 | 19 | f = open(appDirPath + "AppRun", "w") 20 | 21 | try: 22 | if exeName.split('.')[1] == 'py': 23 | executeMethod = 'python' 24 | if includePython: 25 | executeMethod = '${HERE}/usr/bin/python' 26 | 27 | if exeName.split('.')[1] == 'jar': 28 | executeMethod = 'java --jar' 29 | except: 30 | None 31 | 32 | f.writelines("#!/bin/sh") 33 | f.writelines("\nHERE=\"$(dirname \"$(readlink -f \"${0}\")\")\"") 34 | if not folderMode: 35 | f.writelines("\nEXEC=\"${HERE}/usr/bin/" + exeName + "\"") 36 | elif folderMode: 37 | path = Path(exePathFolderMode) 38 | if str(path.parent.absolute())[0:] == pFolderName: 39 | f.writelines("\nEXEC=\"${HERE}/usr/"+ pFolderName + exeName + "\"") 40 | else: 41 | f.writelines("\nEXEC=\"${HERE}/usr/"+ pFolderName + exePathFolderMode + "\"") 42 | f.writelines('\n' + executeMethod + " ${EXEC}") 43 | f.close() 44 | os.system("chmod +x '" + appDirPath + "AppRun'") 45 | 46 | 47 | def copyAppRunFile(AppRun,appDirPath, self, mainWindow): 48 | 49 | dst = appDirPath + "AppRun" 50 | 51 | if path.exists(AppRun): 52 | shutil.copyfile(AppRun, dst) 53 | os.chmod(dst, 777) 54 | 55 | else: 56 | throwError(self, invalidAppRunSubTitle, invalidAppRunTitle, mainWindow) 57 | 58 | 59 | -------------------------------------------------------------------------------- /Immagini/convertFlatpak.py: -------------------------------------------------------------------------------- 1 | from .creator.desktopFile import createDesktopFile 2 | from .creator.AppRun import createAppRunFile 3 | from .creator.copyIconFile import createIconSymlink 4 | from .creator.builder.builder import initBuild 5 | from .ui.error import folderExistsError 6 | from .ui.strings import * 7 | from .ui.error import throwError 8 | import os 9 | import shutil 10 | 11 | def startConvertingFlatpak(page, libraryLoc, appName, desktopFile, self): 12 | appDirPath = f'{libraryLoc}/{appName}.AppDir' 13 | iconLoc = f'{appDirPath}/{self.icon}' 14 | iconSource = f'{self.flatpakLocation}/{self.iconName}' 15 | shareFolder = f'{appDirPath}/usr/share' 16 | shareSource = f'{self.flatpakLocation}/{self.shareLoc}' 17 | libFolder = f'{appDirPath}/usr/lib' 18 | libSource = f'{self.flatpakLocation}/{self.libLoc}' 19 | binFolder = f'{appDirPath}/usr/bin' 20 | binSource = f'{self.flatpakLocation}/{self.binLoc}' 21 | 22 | if os.path.exists(appDirPath): 23 | folderExistsError(None, folderAlreadyExistsSubtitle, folderAlreadyExistsTitle, page, appDirPath) 24 | else: 25 | os.makedirs(appDirPath) 26 | os.symlink(f'{appDirPath}/usr', f'{appDirPath}/app') 27 | 28 | print(f'{self.currentLocation}{self.filesLoc}') 29 | 30 | try: 31 | shutil.copytree(f'{self.currentLocation}{self.filesLoc}', f'{appDirPath}/usr') 32 | except: 33 | throwError(self, couldNotCopyFilesSubtilte, couldNotCopyFilesTitle, self.page, None) 34 | 35 | createDesktopFile(self.appName, self.command, self.icon, 'Application', 'GTK', f'{appDirPath}/') 36 | createAppRunFile(self.command, f'{appDirPath}/', False, None, None, False, self) 37 | createIconSymlink(iconSource, iconLoc) 38 | 39 | initBuild(appDirPath, self.imageLoc, self.appName, self.flatpak, self.page, None) 40 | -------------------------------------------------------------------------------- /Immagini/ui/error.py: -------------------------------------------------------------------------------- 1 | import gi 2 | import sys 3 | import shutil 4 | from ..ui.strings import * 5 | gi.require_version('Gtk', '4.0') 6 | gi.require_version('Adw', '1') 7 | from gi.repository import Gtk, Adw 8 | 9 | def throwError(self, error, title, mainWindow, thread = None): 10 | 11 | dialog = Adw.MessageDialog.new() 12 | 13 | dialog.set_transient_for(mainWindow) 14 | dialog.set_modal(True) 15 | 16 | dialog.set_heading(heading=title) 17 | dialog.set_body(body=error) 18 | dialog.add_response(Gtk.ResponseType.OK.value_nick, okButton) 19 | dialog.set_response_appearance( 20 | response=Gtk.ResponseType.OK.value_nick, 21 | appearance=Adw.ResponseAppearance.SUGGESTED 22 | ) 23 | 24 | dialog.present() 25 | 26 | if thread != None: 27 | sys.exit() 28 | 29 | def folderExistsError(self, error, title, mainWindow, appdir, thread=None): 30 | dialog = Adw.MessageDialog.new() 31 | 32 | dialog.set_heading(heading=title) 33 | dialog.set_body(body=error) 34 | dialog.add_response(Gtk.ResponseType.CANCEL.value_nick, globalDelete) 35 | dialog.set_response_appearance( 36 | response=Gtk.ResponseType.CANCEL.value_nick, 37 | appearance=Adw.ResponseAppearance.DESTRUCTIVE 38 | ) 39 | dialog.add_response(Gtk.ResponseType.OK.value_nick, okButton) 40 | dialog.set_response_appearance( 41 | response=Gtk.ResponseType.OK.value_nick, 42 | appearance=Adw.ResponseAppearance.SUGGESTED 43 | ) 44 | dialog.connect('response', dialog_response, appdir) 45 | 46 | dialog.present() 47 | 48 | def dialog_response(self, response, appdir): 49 | if response == Gtk.ResponseType.OK.value_nick: 50 | None 51 | elif response == Gtk.ResponseType.CANCEL.value_nick: 52 | shutil.rmtree(appdir) -------------------------------------------------------------------------------- /Immagini/creator/copyIconFile.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | import os 3 | from os import path 4 | from ..ui.error import throwError 5 | from PIL import Image 6 | from ..ui.strings import * 7 | import ntpath 8 | 9 | def copyIcon(icon, sharePath, appDirPath, self, mainWindow): 10 | 11 | iconExtension = os.path.splitext(icon)[1] 12 | iconName = ntpath.basename(icon) 13 | 14 | if path.exists(icon): 15 | if iconExtension == ".png" or iconExtension == ".jpg" or iconExtension == ".jpeg": 16 | 17 | icon_file = icon 18 | with Image.open(icon_file) as img: 19 | width, height = img.size 20 | imageSize = (f"{width}x{height}") 21 | 22 | if check_icon_size(icon): 23 | 24 | symbolicPath = sharePath + "/icons/hicolor/" + imageSize + "/" 25 | dst = symbolicPath + iconName 26 | 27 | os.makedirs(symbolicPath) 28 | shutil.copy(icon, dst) 29 | createIconSymlink(dst, appDirPath + iconName) 30 | 31 | else: 32 | throwError(self, invalidIconSizeSubtitle + ' ' + imageSize, invalidIconSizeTitle, mainWindow) 33 | 34 | elif iconExtension == ".svg": 35 | 36 | symbolicPath = sharePath + "/icons/hicolor/scalable/" 37 | dst = symbolicPath + iconName 38 | 39 | os.makedirs(symbolicPath) 40 | shutil.copy(icon, dst) 41 | os.symlink(dst, appDirPath + iconName) 42 | 43 | else: 44 | throwError(self, invalidIconTitle, invalidIconSubtitle, mainWindow) 45 | 46 | def createIconSymlink(src, dst): 47 | os.symlink(src, dst) 48 | 49 | 50 | def check_icon_size(filepath): 51 | valid_sizes = [8, 16, 32, 48, 64, 128, 256, 512] 52 | 53 | with Image.open(filepath) as img: 54 | width, height = img.size 55 | 56 | if width == height and width in valid_sizes: 57 | return True 58 | else: 59 | return False -------------------------------------------------------------------------------- /Immagini/ui/uiElements.py: -------------------------------------------------------------------------------- 1 | import gi 2 | import os 3 | gi.require_version(namespace='Gtk', version='4.0') 4 | gi.require_version(namespace='Adw', version='1') 5 | from gi.repository import Adw, Gio, Gtk 6 | 7 | 8 | class pathEntry(Gtk.Entry): 9 | def __init__(self, placeholder, **kwargs): 10 | super().__init__(**kwargs) 11 | 12 | self.set_valign(align=Gtk.Align.CENTER) 13 | self.set_placeholder_text(placeholder) 14 | self.connect('changed', checkExists, pathEntry) 15 | 16 | class fileChooser(): 17 | def __init__(self, button , title, folderMode, entry, mainWindow, **kwargs): 18 | super().__init__(**kwargs) 19 | 20 | self.dialog = Gtk.FileChooserNative.new(title=title,parent=None,action=Gtk.FileChooserAction.OPEN) 21 | self.dialog.set_transient_for(mainWindow) 22 | self.dialog.set_modal(True) 23 | 24 | if folderMode: 25 | self.dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER) 26 | 27 | self.dialog.show() 28 | self.dialog.set_title(title) 29 | self.dialog.connect("response", self.fileCResponse, entry, self.dialog.get_select_multiple()) 30 | 31 | 32 | def fileCResponse(self, dialog, window, entry, multiple): 33 | if multiple: 34 | files_model = dialog.get_files() 35 | filenames = [file.get_path() for file in files_model] 36 | rawName = str(filenames) 37 | finName = rawName.replace("[", "").replace("]", "").replace("'", "").replace(",", "\n") 38 | entry.set_text(entry.get_text + finName) 39 | else: 40 | self.dialog.destroy() 41 | entry.set_text(dialog.get_file().get_path()) 42 | 43 | 44 | 45 | def checkExists(entry, key): 46 | global changedPath 47 | if os.path.exists(entry.get_text()): 48 | setRowState(entry, 'default') 49 | else: 50 | setRowState(entry, 'error') 51 | 52 | if entry.get_text() == "": 53 | setRowState(entry, 'default') 54 | 55 | def setRowState(widget, mode): 56 | if mode == 'default': 57 | widget.get_style_context().remove_class(class_name='error') 58 | 59 | widget.get_style_context().add_class(class_name=mode) 60 | 61 | def browseButton(fileChooser, name, folderMode, entry, page): 62 | button = Gtk.Button.new_from_icon_name("document-open-symbolic") 63 | button.set_valign(Gtk.Align.CENTER) 64 | button.connect('clicked', fileChooser, name, folderMode, entry, page) 65 | 66 | return button -------------------------------------------------------------------------------- /Immagini/ui/template.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version(namespace='Gtk', version='4.0') 4 | gi.require_version(namespace='Adw', version='1') 5 | 6 | from gi.repository import Adw, Gio, Gtk 7 | 8 | Adw.init() 9 | 10 | 11 | class ExampleWindow(Gtk.ApplicationWindow): 12 | 13 | def __init__(self, **kwargs): 14 | super().__init__(**kwargs) 15 | 16 | self.set_title(title='Immagini - Template') 17 | self.set_default_size(width=int(1366 / 2), height=int(768 / 2)) 18 | self.set_size_request(width=int(1366 / 2), height=int(768 / 2)) 19 | 20 | header_bar = Gtk.HeaderBar.new() 21 | header_bar.add_css_class(css_class='flat') 22 | self.set_titlebar(titlebar=header_bar) 23 | 24 | 25 | vbox = Gtk.Box.new(orientation=Gtk.Orientation.VERTICAL, spacing=12) 26 | vbox.set_homogeneous(homogeneous=True) 27 | vbox.set_margin_top(margin=12) 28 | vbox.set_margin_end(margin=12) 29 | vbox.set_margin_bottom(margin=12) 30 | vbox.set_margin_start(margin=12) 31 | self.set_child(child=vbox) 32 | 33 | status_page = Adw.StatusPage.new() 34 | status_page.set_description(description='This is a template application of Immagini') 35 | status_page.set_icon_name(icon_name='face-smile-big-symbolic') 36 | status_page.set_title(title='Hi!') 37 | vbox.append(child=status_page) 38 | 39 | 40 | class ExampleApplication(Adw.Application): 41 | 42 | def __init__(self): 43 | super().__init__(application_id='hi.from.salaniLeo', 44 | flags=Gio.ApplicationFlags.FLAGS_NONE) 45 | 46 | self.create_action('quit', self.exit_app, ['q']) 47 | self.create_action('preferences', self.on_preferences_action) 48 | 49 | def do_activate(self): 50 | win = self.props.active_window 51 | if not win: 52 | win = ExampleWindow(application=self) 53 | win.present() 54 | 55 | def do_startup(self): 56 | Gtk.Application.do_startup(self) 57 | 58 | def do_shutdown(self): 59 | Gtk.Application.do_shutdown(self) 60 | 61 | def on_preferences_action(self, action, param): 62 | print('Ação app.preferences foi ativa.') 63 | 64 | def exit_app(self, action, param): 65 | self.quit() 66 | 67 | def create_action(self, name, callback, shortcuts=None): 68 | action = Gio.SimpleAction.new(name, None) 69 | action.connect('activate', callback) 70 | self.add_action(action) 71 | if shortcuts: 72 | self.set_accels_for_action(f'app.{name}', shortcuts) 73 | 74 | 75 | if __name__ == '__main__': 76 | import sys 77 | 78 | app = ExampleApplication() 79 | app.run(sys.argv) -------------------------------------------------------------------------------- /data/dev.salaniLeo.immagini.appdata.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | dev.salaniLeo.immagini 4 | Immagini 5 | Library and creation tool for AppImage apps 6 | 7 |

8 | 9 | Immagini provides an easy solution to manage and create AppImages 10 | 11 |

12 |
13 | dev.salaniLeo.immagini.desktop 14 | https://github.com/SalaniLeo/Immagini 15 | CC-BY-SA-3.0 16 | GPL-3.0 17 | 18 | 19 | 20 | https://raw.githubusercontent.com/SalaniLeo/Immagini/master/assets/screenshots/screenshot1.png 21 | Library 22 | 23 | 24 | https://raw.githubusercontent.com/SalaniLeo/Immagini/master/assets/screenshots/screenshot2.png 25 | New image page 26 | 27 | 28 | https://raw.githubusercontent.com/SalaniLeo/Immagini/master/assets/screenshots/screenshot3.png 29 | New image page with advanced options 30 | 31 | 32 | https://raw.githubusercontent.com/SalaniLeo/Immagini/master/assets/screenshots/screenshot4.png 33 | Preferences 34 | 35 | 36 | https://raw.githubusercontent.com/SalaniLeo/Immagini/master/assets/screenshots/screenshot5.png 37 | Image options 38 | 39 | 40 | 41 | 42 | 43 |

What's changed

44 |
    45 |
  • Added 'include libraries' option
  • 46 |
  • Fixed rename app not working if renamed more than one time
  • 47 |
48 |

>Updates

49 |
    50 |
  • Fixed error with renaming the app more than one time
  • 51 |
  • Fixed error with launching appimages in some distros
  • 52 |
53 |
54 |
55 | 56 | 57 |

58 | Added library page 59 | Added credits, preferences and about window 60 |

61 |
62 |
63 | 64 | 65 |

66 | UI ported to libadwaita 67 | Added app to flathub 68 |

69 |
70 |
71 |
72 |
73 | -------------------------------------------------------------------------------- /Immagini/imageCreator.py: -------------------------------------------------------------------------------- 1 | import os 2 | import ntpath 3 | from .creator.desktopFile import * 4 | from .creator.AppRun import * 5 | from .creator.copyExeFile import * 6 | from .creator.copyIconFile import * 7 | from .creator.builder.builder import * 8 | from .creator.copyLibraries import * 9 | from .creator.copyInterpreters import * 10 | from .ui.error import * 11 | from .ui.strings import * 12 | 13 | def startCreatingImage(name, 14 | exe, 15 | icon, 16 | type, 17 | categories, 18 | output, 19 | useCustomAppRun, 20 | appRunLoc, 21 | useFolderMode, 22 | folderLoc, 23 | includeLibraries, 24 | librariesPath, 25 | includeInterpreters, 26 | flatpak, 27 | self, 28 | mainWindow): 29 | 30 | exeName = ntpath.basename(exe) 31 | appDirPath = output + "/" + name + ".AppDir/" 32 | pFolderName = os.path.basename(folderLoc) 33 | exePathFolderMode = compare(pFolderName, exe, self, mainWindow, useFolderMode) 34 | binFolder = output + "/" + name + ".AppDir/usr/bin" 35 | shareFolder = output + "/" + name + ".AppDir/usr/share" 36 | libFolder = output + "/" + name + ".AppDir/usr/lib" 37 | 38 | createBase(appDirPath, shareFolder, libFolder, binFolder) 39 | 40 | pyLocation = '/usr/bin/python' 41 | javaLocation = '/usr/bin/java' 42 | 43 | includePython = includeInterpreters[0] 44 | includeJava = includeInterpreters[1] 45 | 46 | # creates desktop file inside .AppDir folder 47 | createDesktopFile(name,exeName,type,categories,appDirPath) 48 | 49 | # copies icon file inside .AppDir 50 | copyIcon(icon, shareFolder, appDirPath, self, mainWindow) 51 | 52 | # checks if custom apprun is enabled 53 | if not(useCustomAppRun): 54 | createAppRunFile(exeName,appDirPath,useFolderMode,exePathFolderMode,pFolderName, includeInterpreters, self) 55 | elif(useCustomAppRun): 56 | # checks if AppRun is named AppRun 57 | if(ntpath.basename(appRunLoc)!="AppRun"): 58 | # throws error in case 59 | throwError(self, invalidAppRunSubTitle, invalidAppRunTitle, mainWindow) 60 | return 0 61 | # copies apprun if everything is ok 62 | copyAppRunFile(appRunLoc,appDirPath,self, mainWindow) 63 | 64 | # checks if foldermode is enabled 65 | if not(useFolderMode): 66 | # if foldermode is not enabled copies executable file normally 67 | copyExe(exe,appDirPath,exeName, self, mainWindow) 68 | elif(useFolderMode): 69 | # if foldermode is enabled moves the entire app inside .AppDir 70 | copyExePFolder(appDirPath,pFolderName,folderLoc,exe, self, mainWindow) 71 | 72 | if(includeLibraries): 73 | copyLibraries(librariesPath, appDirPath, self, mainWindow) 74 | 75 | if includeJava: 76 | copyInterpreters.copyInterpreter(javaLocation, binFolder) 77 | 78 | if includePython: 79 | copyInterpreters.copyInterpreter(pyLocation, binFolder + '/python') 80 | 81 | # sets outputtxt to the appimagetool output 82 | outputtxt = initBuild(appDirPath,output,name,flatpak, mainWindow) 83 | 84 | return outputtxt 85 | 86 | def compare(folderName, s2, self, mainWindow, folderMode): 87 | if folderMode: 88 | try: 89 | result = s2.split(folderName,1)[1] 90 | return result 91 | except IndexError: 92 | throwError(self, invalidAppFolderSubtitle, invalidAppFolderTitle, mainWindow) 93 | else: 94 | return None 95 | 96 | def createBase(appDirPath, shareFolder, libFolder, binFolder): 97 | os.makedirs(appDirPath) 98 | os.makedirs(shareFolder) 99 | os.makedirs(libFolder) 100 | os.makedirs(binFolder) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Immagini icon

2 | 3 | An application made to easily manage and create .AppImage apps
4 | 5 |

Install

6 | 7 | 8 |

Library

9 | 10 |

Ways to manage AppImages inside library:

11 | 12 |
  • Rename a file 13 |
  • Set a file executable or not 14 |
  • Extract an appimage in a selected location 15 |
  • Delete an AppImage from disk 16 | 17 |

    Create new AppImage

    18 | 19 |

    Create options

    20 |
  • Delete .AppDir after build has finished 21 |
  • Include custom AppRun 22 |
  • Folder mode 23 | 24 |

    Documentation

    25 | 26 |

    Name

    27 | The name can be whatever you like, with every character. Even spaces 28 | 29 |
    30 |

    Executable

    31 | The executable file is the file you want to execute as .AppImage.
    32 | With the app default .AppRun you can only execute shell scripts. If you want to include a python script as executable you need to specify the script runner at the top of the file. 33 | 34 | Example: 35 | 36 |
    37 | Python 38 |
    39 | 40 | #!/bin/python3 41 | 42 | import getpass 43 | user = getpass.getuser() 44 | print('My name is: ' + user) 45 | 46 |
    47 |
    48 | 49 |
    50 | Bash 51 |
    52 | 53 | #!/bin/sh 54 | 55 | echo My name is: 56 | whoami 57 | 58 |
    59 |
    60 | 61 | Also, if you want to package whole folders see FolderMode 62 |
    63 | 64 |

    Icon

    65 | The Icon must respect the AppImage icon specifications.
    66 | Selected icons get put in different locations, based on the size and extension of the image.
    67 | The location of the icon is:

    68 |
  • For png images: 69 | usr/share/icons/hicolor/{image dimensions}/icon.png 70 |
  • For svg images: 71 | usr/share/icons/hicolor/scalable/icon.svg 72 | 73 |

    Category and Type

    74 | To see what category and tpye you can add to your AppImage see freedesktop specifications website 75 | 76 |

    Advanced options

    77 |
    78 |

    Folder mode

    79 | This option is still in beta quality, so don't expect much.
    80 | The exe file needs to be inside the selected folder
    81 | Folder mode allow you to package folders inside an AppImage.
    82 | To package folders into an AppImage you have to select the main app executable as the app executable, and then in the foldermode entry select the app folder.
    83 | Also, it's recommended to use a custom AppRun if you enable this option. 84 | 85 |
    86 | 87 |
    88 |

    Custom AppRun

    89 | By enabling 'Custom AppRun' you can package in the application your own custom-made AppRun file.
    90 | it's recommended to use this option if you use folder mode. If packaging only a single file the executable is located in usr/bin/, so for example if you want to create your own apprun the path to the executable should be usr/bin/(exe). 91 | 92 |
    93 | 94 |
    95 |

    Why the name Immagini

    96 |

    First of all let's start by sying that I'm italian.
    97 | The name Immagini is the italian translation for 'images'... you see where I'm going? 98 | Given that the app is made to manage .AppImage files and I wanted to give a name that has something to do with the app I came up with the name Immagini.
    99 | Next step is making an icon 100 |

    101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /Immagini/ui/strings.py: -------------------------------------------------------------------------------- 1 | from gettext import gettext as _ 2 | 3 | # ----- most used word ---- # 4 | globalImmagini = _("Immagini") 5 | 6 | globalName = _("Name") 7 | globalExecutable = _("Executable") 8 | globalIcon = _("Icon") 9 | globalPath = _("Path") 10 | globalCategory = _("Category") 11 | globalType = _("Type") 12 | globalDelete = _("Delete") 13 | globalClose = _("Close") 14 | globalRefresh = _("Refresh") 15 | globalConfirm = _("Confirm") 16 | globalTemplate = _("Template") 17 | globalShare = _('Share folder') 18 | globalLib = _('Libraries folder') 19 | globalInfo = _('Info') 20 | globalDesktop = _('Desktop file') 21 | 22 | globalApplication = _("Application") 23 | globalUtility = _("Utility") 24 | 25 | globalLibraryTitle = _("Immagini - Library") 26 | globalNewImageTitle = _("Immagini - New") 27 | globalInstalledFlatpaks = _("Immagini - Installed Flatpaks") 28 | 29 | # ----- MAIN WINDOW ----- # 30 | menuRefresh = _("Refresh") 31 | menuShowInFolder = _("Show in folder") 32 | menuPreferences = _("Preferences") 33 | menuShortcuts = _("Shortcuts") 34 | menuAbout = _("About Immagini") 35 | 36 | aboutWindowComment = _("Management tool for AppImage applications") 37 | 38 | # ----- PREFERENCES WINDOW ----- # 39 | prefrencesTitle = _("Preferences") 40 | newImagePreferencesTitle = _("New image options") 41 | libraryPreferencesTitle = _('Library options') 42 | 43 | libraryLocationTitle = _('Library location') 44 | libraryLocationSubtitle = _("To apply changes restart the app") 45 | librarySelectionTitle = _('Select library location') 46 | 47 | autoDeleteAppDirTitle = _('Auto delete AppDir') 48 | autoDeleteAppDirSubtitle = _('Deletes the .AppDir folder after creating an AppImage file') 49 | 50 | autoFolderModeTitle = _('Enable FolderMode by default') 51 | autoFolderModeSubtitle = _('Automatically enables the "Folder Mode" option when creating a new image file') 52 | 53 | autoCustomAppRunTitle = _('Enable custom AppRun by default') 54 | autoCustomAppRunSubtitle = _('Automatically enables the "Custom AppRun" option when creating a new image file') 55 | 56 | useLibraryPathTitle = _('Use library folder as default') 57 | useLibraryPathSubtitle = _('Uses library folder as default location when creating new apps') 58 | 59 | libraryPathChanged = _("Library path changed") 60 | 61 | # ----- NEW IMAGE WINDOW ----- # 62 | 63 | includeLibrariesTitle = _("Include libraries") 64 | includeLibrariesSubtitle = _('Select a library to include inside an AppImage') 65 | selectLibrariesTitle = _("Select libraries") 66 | 67 | useFolderModeTitle = _("Folder mode") 68 | useFolderModeSubtitle = _("Parent folder location") 69 | 70 | useCustomAppRunTitle = _("Custom AppRun") 71 | useCustomAppRunSubtitle = _("Custom AppRun location") 72 | 73 | includeDependeciesTitle = _("Include dependencies") 74 | installedIntepreters = _("Installed languages: ") 75 | selectManually = _('Select manually: ') 76 | 77 | createTemplateImage = _('Create template image') 78 | 79 | outputLocationTitle = _("Location") 80 | outputLocationSubtitle = _("App location") 81 | 82 | selectFiles = _("Select files ") 83 | selectFolders = _("Select folders ") 84 | selectedItems = _("Selected items: ") 85 | 86 | pleaseFillInAllInfoSubtitle = _("Please fill in all the informations") 87 | pleaseFillInAllInfoTitle = _("All the info are required") 88 | 89 | createNewOne = _('Create new') 90 | convertFromFlatpak = _('Convert from Flatpak') 91 | 92 | installedFlatpaks = _('Intalled Flatpaks') 93 | 94 | executableNotProvidedByManifest = _("Not provided by manifest, may be wrong") 95 | executableNotFoundInsideFlatpak = _("Can't locate binary inside flatpak application") 96 | 97 | convertButtonLabel = _('Convert') 98 | 99 | couldNotCopyFilesSubtilte = _('Could not copy the application files into the appimage') 100 | couldNotCopyFilesTitle = _('Could not copy files') 101 | 102 | # advanced options 103 | advancedTitle = _("Advanced") 104 | 105 | # ----- TERMINAL ----- # 106 | terminalTitle = _('Terminal') 107 | 108 | 109 | # ----- IMAGE OPTIONS ----- # 110 | imageOptionsTitle = _('Image Options') 111 | imageOptionsExecutable = _('Executable:') 112 | imageOptionsExtract = _('Extract image:') 113 | imageOptionsStartTerminal = _('Start in terminal:') 114 | 115 | askConfirmDeleting = _('Deleting an appimage file is not reversible') 116 | extractingImage = _("Extracting image") 117 | 118 | 119 | # ----- ERRORS ----- # 120 | 121 | okButton = "Ok" 122 | 123 | noExePermissionSubtitle = _("The app has no executable permissions") 124 | noExePermissionTitle = _("Permission denied") 125 | 126 | folderAlreadyExistsSubtitle = _(' alredy exists') 127 | folderAlreadyExistsTitle = _('Folder already exists') 128 | 129 | invalidAppRunSubTitle = _("Selected file must be named 'AppRun'") 130 | invalidAppRunTitle = _("AppRun file not valid") 131 | 132 | invalidAppFolderSubtitle = _("The Application folder does not contain the selected executable file") 133 | invalidAppFolderTitle = _("Application folder does not contain executable") 134 | 135 | invalidExeTitle = _('does not exists') 136 | invalidExeSubtitle = _("could not copy the exe file") 137 | 138 | invalidIconTitle = _("does't exist") 139 | invalidIconSubtitle = _("could not copy icon") 140 | 141 | invalidIconSizeSubtitle = _("The icon size must be 32x32, 48x48 etc.. not") 142 | invalidIconSizeTitle = _("Icon size not valid") 143 | 144 | invalidLibraryTitle = _("could not copy library") 145 | invalidLibrarySubtitle = _("Library does not exist") -------------------------------------------------------------------------------- /Immagini/library/getContent.py: -------------------------------------------------------------------------------- 1 | import os 2 | import stat 3 | import pathlib 4 | import gi 5 | from .imageOptions import * 6 | from ..ui.strings import * 7 | 8 | gi.require_version(namespace='Gtk', version='4.0') 9 | gi.require_version(namespace='Adw', version='1') 10 | 11 | from gi.repository import Adw, Gtk 12 | 13 | class getImages(list): 14 | def __init__(self, list, loc): 15 | 16 | i = 0 17 | self.appimages = 0 18 | self.executable = [] 19 | self.imageNames = [] 20 | 21 | for x in list: 22 | file = pathlib.Path(list[i-1]) 23 | i += 1 24 | self.file_extension = file.suffix 25 | if(self.file_extension == ".AppImage"): 26 | self.appimages += 1 27 | imageName = str(loc) + '/' + str(file).encode('utf-8').decode() 28 | self.imageNames.append(imageName) 29 | 30 | def createImageRow(appImage, refresh, mainWindow, setState, flatpak): 31 | 32 | adw_expander_row = Adw.ExpanderRow.new() 33 | 34 | imageName = os.path.splitext(appImage)[0] 35 | 36 | fullName = os.path.basename(imageName) 37 | baseName = fullName.replace("-x86_64", "") 38 | 39 | st = os.stat(appImage) 40 | executable = bool(st.st_mode & stat.S_IEXEC) 41 | 42 | rightBox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 43 | 44 | rightBox.append(createElementButton('media-playback-start-symbolic','success', 45 | 46 | manageImages.startImage, 47 | appImage, 48 | None, 49 | mainWindow, 50 | flatpak, 51 | None, 52 | None)) 53 | 54 | rightBox.append(createElementButton('org.gnome.Settings-symbolic', None, 55 | 56 | manageImages.imageOptions, 57 | appImage, 58 | fullName, 59 | refresh, 60 | mainWindow, 61 | setState, 62 | adw_expander_row)) 63 | 64 | rightBox.append(createElementButton('user-trash-symbolic','error', 65 | 66 | manageImages.deleteImage, 67 | appImage, 68 | refresh, 69 | baseName, 70 | mainWindow, 71 | setState, 72 | adw_expander_row)) 73 | 74 | leftBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) 75 | leftBox.set_hexpand(True) 76 | leftBox.append(createElementLabel(globalName, fullName + ".AppImage")) 77 | leftBox.append(createElementLabel(globalPath, appImage)) 78 | 79 | expandableLayout = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 80 | expandableLayout.append(leftBox) 81 | expandableLayout.append(rightBox) 82 | 83 | box = Adw.PreferencesGroup.new() 84 | 85 | adw_expander_row.set_title(title=baseName) 86 | adw_expander_row.add_row(child=expandableLayout) 87 | 88 | if not executable: 89 | setState(adw_expander_row, 'error') 90 | 91 | 92 | box.add(adw_expander_row) 93 | 94 | return box 95 | 96 | def createDirRow(appImage, refresh, mainWindow, setState, flatpak): 97 | 98 | adw_expander_row = Adw.ExpanderRow.new() 99 | 100 | imageName = os.path.splitext(appImage)[0] 101 | 102 | fullName = os.path.basename(imageName) 103 | baseName = fullName.replace("-x86_64", "") 104 | 105 | st = os.stat(appImage) 106 | executable = bool(st.st_mode & stat.S_IEXEC) 107 | 108 | rightBox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 109 | 110 | rightBox.append(createElementButton('org.gnome.Settings-symbolic', None, 111 | 112 | manageImages.imageOptions, 113 | appImage, 114 | fullName, 115 | refresh, 116 | mainWindow, 117 | setState, 118 | adw_expander_row)) 119 | 120 | rightBox.append(createElementButton('user-trash-symbolic','error', 121 | 122 | manageImages.deleteImage, 123 | appImage, 124 | refresh, 125 | baseName, 126 | mainWindow, 127 | setState, 128 | adw_expander_row)) 129 | 130 | leftBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) 131 | leftBox.set_hexpand(True) 132 | leftBox.append(createElementLabel(globalName, fullName + ".AppImage")) 133 | leftBox.append(createElementLabel(globalPath, appImage)) 134 | 135 | expandableLayout = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 136 | expandableLayout.append(leftBox) 137 | expandableLayout.append(rightBox) 138 | 139 | box = Adw.PreferencesGroup.new() 140 | 141 | adw_expander_row.set_title(title=baseName) 142 | adw_expander_row.add_row(child=expandableLayout) 143 | 144 | if not executable: 145 | setState(adw_expander_row, 'error') 146 | 147 | 148 | box.add(adw_expander_row) 149 | 150 | return box 151 | 152 | def restart_count(): 153 | global desktopCount 154 | global nameNum 155 | desktopCount = 0 156 | nameNum = 0 157 | 158 | def createElementButton(iconName, style, action, actionArg1, refresh, name, mainWindow, setRowState, row): 159 | 160 | b = Gtk.Button() 161 | b.set_size_request(30,30) 162 | b.set_halign(Gtk.Align.END) 163 | b.set_valign(Gtk.Align.CENTER) 164 | b.set_icon_name(icon_name=iconName) 165 | if style is not None: 166 | b.get_style_context().add_class(class_name=style) 167 | b.set_margin_start(3) 168 | b.set_margin_top(12) 169 | b.set_margin_end(6) 170 | b.set_margin_bottom(12) 171 | b.connect('clicked', action, actionArg1, refresh, name, mainWindow, setRowState, row) 172 | 173 | return b 174 | 175 | def createElementLabel(text, name): 176 | 177 | l = Gtk.Label() 178 | l.set_margin_start(12) 179 | l.set_margin_top(6) 180 | l.set_margin_end(12) 181 | l.set_margin_bottom(12) 182 | # l.set_ellipsize_status(12) 183 | l.set_text(text + name) 184 | l.set_halign(Gtk.Align.START) 185 | l.set_wrap(True) 186 | 187 | return l 188 | 189 | desktopCount=0 190 | names = [] 191 | nameNum = 0 192 | 193 | def getFileNum(list, loc): 194 | return getImages(list, loc) -------------------------------------------------------------------------------- /messages.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2023-06-22 18:18+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: Immagini/ui/strings.py:4 21 | msgid "Immagini" 22 | msgstr "" 23 | 24 | #: Immagini/ui/strings.py:6 25 | msgid "Name" 26 | msgstr "" 27 | 28 | #: Immagini/ui/strings.py:7 29 | msgid "Executable" 30 | msgstr "" 31 | 32 | #: Immagini/ui/strings.py:8 33 | msgid "Icon" 34 | msgstr "" 35 | 36 | #: Immagini/ui/strings.py:9 37 | msgid "Path" 38 | msgstr "" 39 | 40 | #: Immagini/ui/strings.py:10 41 | msgid "Category" 42 | msgstr "" 43 | 44 | #: Immagini/ui/strings.py:11 45 | msgid "Type" 46 | msgstr "" 47 | 48 | #: Immagini/ui/strings.py:12 49 | msgid "Delete" 50 | msgstr "" 51 | 52 | #: Immagini/ui/strings.py:13 53 | msgid "Close" 54 | msgstr "" 55 | 56 | #: Immagini/ui/strings.py:14 Immagini/ui/strings.py:25 57 | msgid "Refresh" 58 | msgstr "" 59 | 60 | #: Immagini/ui/strings.py:15 61 | msgid "Confirm" 62 | msgstr "" 63 | 64 | #: Immagini/ui/strings.py:16 65 | msgid "Template" 66 | msgstr "" 67 | 68 | #: Immagini/ui/strings.py:18 69 | msgid "Application" 70 | msgstr "" 71 | 72 | #: Immagini/ui/strings.py:19 73 | msgid "Utility" 74 | msgstr "" 75 | 76 | #: Immagini/ui/strings.py:21 77 | msgid "Immagini - Library" 78 | msgstr "" 79 | 80 | #: Immagini/ui/strings.py:22 81 | msgid "Immagini - New" 82 | msgstr "" 83 | 84 | #: Immagini/ui/strings.py:26 85 | msgid "Show in folder" 86 | msgstr "" 87 | 88 | #: Immagini/ui/strings.py:27 Immagini/ui/strings.py:34 89 | msgid "Preferences" 90 | msgstr "" 91 | 92 | #: Immagini/ui/strings.py:28 93 | msgid "Shortcuts" 94 | msgstr "" 95 | 96 | #: Immagini/ui/strings.py:29 97 | msgid "About Immagini" 98 | msgstr "" 99 | 100 | #: Immagini/ui/strings.py:31 101 | msgid "Management tool for AppImage applications" 102 | msgstr "" 103 | 104 | #: Immagini/ui/strings.py:35 105 | msgid "New image options" 106 | msgstr "" 107 | 108 | #: Immagini/ui/strings.py:36 109 | msgid "Library options" 110 | msgstr "" 111 | 112 | #: Immagini/ui/strings.py:38 113 | msgid "Library location" 114 | msgstr "" 115 | 116 | #: Immagini/ui/strings.py:39 117 | msgid "To apply changes restart the app" 118 | msgstr "" 119 | 120 | #: Immagini/ui/strings.py:40 121 | msgid "Select library location" 122 | msgstr "" 123 | 124 | #: Immagini/ui/strings.py:42 125 | msgid "Auto delete AppDir" 126 | msgstr "" 127 | 128 | #: Immagini/ui/strings.py:43 129 | msgid "Deletes the .AppDir folder after creating an AppImage file" 130 | msgstr "" 131 | 132 | #: Immagini/ui/strings.py:45 133 | msgid "Enable FolderMode by default" 134 | msgstr "" 135 | 136 | #: Immagini/ui/strings.py:46 137 | msgid "" 138 | "Automatically enables the \"Folder Mode\" option when creating a new image " 139 | "file" 140 | msgstr "" 141 | 142 | #: Immagini/ui/strings.py:48 143 | msgid "Enable custom AppRun by default" 144 | msgstr "" 145 | 146 | #: Immagini/ui/strings.py:49 147 | msgid "" 148 | "Automatically enables the \"Custom AppRun\" option when creating a new image " 149 | "file" 150 | msgstr "" 151 | 152 | #: Immagini/ui/strings.py:51 153 | msgid "Use library folder as default" 154 | msgstr "" 155 | 156 | #: Immagini/ui/strings.py:52 157 | msgid "Uses library folder as default location when creating new apps" 158 | msgstr "" 159 | 160 | #: Immagini/ui/strings.py:54 161 | msgid "Library path changed" 162 | msgstr "" 163 | 164 | #: Immagini/ui/strings.py:58 165 | msgid "Include libraries" 166 | msgstr "" 167 | 168 | #: Immagini/ui/strings.py:59 169 | msgid "Select a library to include inside an AppImage" 170 | msgstr "" 171 | 172 | #: Immagini/ui/strings.py:60 173 | msgid "Select libraries" 174 | msgstr "" 175 | 176 | #: Immagini/ui/strings.py:62 177 | msgid "Folder mode" 178 | msgstr "" 179 | 180 | #: Immagini/ui/strings.py:63 181 | msgid "Parent folder location" 182 | msgstr "" 183 | 184 | #: Immagini/ui/strings.py:65 185 | msgid "Custom AppRun" 186 | msgstr "" 187 | 188 | #: Immagini/ui/strings.py:66 189 | msgid "Custom AppRun location" 190 | msgstr "" 191 | 192 | #: Immagini/ui/strings.py:68 193 | msgid "Include dependencies" 194 | msgstr "" 195 | 196 | #: Immagini/ui/strings.py:69 197 | msgid "Installed interpreters" 198 | msgstr "" 199 | 200 | #: Immagini/ui/strings.py:70 201 | msgid "Select manually" 202 | msgstr "" 203 | 204 | #: Immagini/ui/strings.py:72 205 | msgid "Create template image" 206 | msgstr "" 207 | 208 | #: Immagini/ui/strings.py:74 209 | msgid "Location" 210 | msgstr "" 211 | 212 | #: Immagini/ui/strings.py:75 213 | msgid "App location" 214 | msgstr "" 215 | 216 | #: Immagini/ui/strings.py:77 217 | msgid "Select files: " 218 | msgstr "" 219 | 220 | #: Immagini/ui/strings.py:78 221 | msgid "Select folders: " 222 | msgstr "" 223 | 224 | #: Immagini/ui/strings.py:79 225 | msgid "Selected items: " 226 | msgstr "" 227 | 228 | #: Immagini/ui/strings.py:81 229 | msgid "Please fill in all the informations" 230 | msgstr "" 231 | 232 | #: Immagini/ui/strings.py:82 233 | msgid "All the info are required" 234 | msgstr "" 235 | 236 | #: Immagini/ui/strings.py:85 237 | msgid "Advanced" 238 | msgstr "" 239 | 240 | #: Immagini/ui/strings.py:88 241 | msgid "Terminal" 242 | msgstr "" 243 | 244 | #: Immagini/ui/strings.py:92 245 | msgid "Image Options" 246 | msgstr "" 247 | 248 | #: Immagini/ui/strings.py:93 249 | msgid "Executable:" 250 | msgstr "" 251 | 252 | #: Immagini/ui/strings.py:94 253 | msgid "Extract image:" 254 | msgstr "" 255 | 256 | #: Immagini/ui/strings.py:95 257 | msgid "Start in terminal:" 258 | msgstr "" 259 | 260 | #: Immagini/ui/strings.py:97 261 | msgid "Deleting an appimage file is not reversible" 262 | msgstr "" 263 | 264 | #: Immagini/ui/strings.py:98 265 | msgid "Extracting image" 266 | msgstr "" 267 | 268 | #: Immagini/ui/strings.py:102 269 | msgid "The app has no executable permissions" 270 | msgstr "" 271 | 272 | #: Immagini/ui/strings.py:103 273 | msgid "Permission denied" 274 | msgstr "" 275 | 276 | #: Immagini/ui/strings.py:105 277 | msgid " alredy exists" 278 | msgstr "" 279 | 280 | #: Immagini/ui/strings.py:106 281 | msgid "Folder already exists" 282 | msgstr "" 283 | 284 | #: Immagini/ui/strings.py:108 285 | msgid "Selected file must be named 'AppRun'" 286 | msgstr "" 287 | 288 | #: Immagini/ui/strings.py:109 289 | msgid "AppRun file not valid" 290 | msgstr "" 291 | 292 | #: Immagini/ui/strings.py:111 293 | msgid "The Application folder does not contain the selected executable file" 294 | msgstr "" 295 | 296 | #: Immagini/ui/strings.py:112 297 | msgid "Application folder does not contain executable" 298 | msgstr "" 299 | 300 | #: Immagini/ui/strings.py:114 301 | msgid " does not exists" 302 | msgstr "" 303 | 304 | #: Immagini/ui/strings.py:115 305 | msgid "could not copy the exe file" 306 | msgstr "" 307 | 308 | #: Immagini/ui/strings.py:117 309 | msgid "icon file does't exist" 310 | msgstr "" 311 | 312 | #: Immagini/ui/strings.py:118 313 | msgid "could not copy icon" 314 | msgstr "" 315 | 316 | #: Immagini/ui/strings.py:120 317 | msgid "The icon size must be 32x32, 48x48 etc.. not " 318 | msgstr "" 319 | 320 | #: Immagini/ui/strings.py:121 321 | msgid "Icon size not valid" 322 | msgstr "" 323 | 324 | #: Immagini/ui/strings.py:123 325 | msgid "could not copy library" 326 | msgstr "" 327 | 328 | #: Immagini/ui/strings.py:124 329 | msgid "Library does not exist" 330 | msgstr "" 331 | -------------------------------------------------------------------------------- /Immagini/library/imageOptions.py: -------------------------------------------------------------------------------- 1 | import gi 2 | import os 3 | import stat 4 | import threading 5 | from ..ui.console import console 6 | from ..ui.error import throwError 7 | from ..ui.uiElements import * 8 | from ..ui.strings import * 9 | gi.require_version(namespace='Gtk', version='4.0') 10 | gi.require_version(namespace='Adw', version='1') 11 | from gi.repository import Gtk, Adw 12 | 13 | class manageImages(list): 14 | def __init__(self, list, loc): 15 | menu = Gtk.Menu() 16 | menu_item = Gtk.MenuItem() 17 | menu.append(menu_item) 18 | menu_item.show() 19 | 20 | def deleteImage(button, imagePath, refresh, name, mainWindow, setRowState, row): 21 | manageImages.askSure(name, imagePath, refresh, mainWindow) 22 | 23 | def askSure(name, imagePath, refresh, mainWindow): 24 | 25 | dialog = Adw.MessageDialog.new() 26 | 27 | dialog.set_transient_for(mainWindow) 28 | dialog.set_modal(True) 29 | dialog.set_heading(heading=f'{globalDelete} {name}?') 30 | dialog.set_body(body=askConfirmDeleting) 31 | dialog.add_response(Gtk.ResponseType.CANCEL.value_nick, 'Cancel') 32 | dialog.set_response_appearance( 33 | response=Gtk.ResponseType.CANCEL.value_nick, 34 | appearance=Adw.ResponseAppearance.DESTRUCTIVE 35 | ) 36 | dialog.add_response(Gtk.ResponseType.OK.value_nick, 'Ok') 37 | dialog.set_response_appearance( 38 | response=Gtk.ResponseType.OK.value_nick, 39 | appearance=Adw.ResponseAppearance.SUGGESTED 40 | ) 41 | dialog.connect('response', manageImages.dialog_response, imagePath, refresh) 42 | 43 | dialog.present() 44 | 45 | def dialog_response(dialog, response, imagePath, refresh): 46 | if response == Gtk.ResponseType.OK.value_nick: 47 | os.remove(imagePath) 48 | refresh(None, None, None) 49 | elif response == Gtk.ResponseType.CANCEL.value_nick: 50 | None 51 | 52 | def imageOptions(button, appImage, fullName, executable ,mainWindow, setRowState, row): 53 | options = imageOptions(mainWindow, executable, appImage, fullName, setRowState, row) 54 | options.show() 55 | 56 | def setExecutable(switch, state, appImage, setRowState, row): 57 | if switch.get_active(): 58 | st = os.stat(appImage) 59 | os.chmod(appImage, st.st_mode | stat.S_IEXEC) 60 | setRowState(row, 'default') 61 | else: 62 | current = stat.S_IMODE(os.lstat(appImage).st_mode) 63 | os.chmod(appImage, current & ~stat.S_IEXEC) 64 | setRowState(row, 'error') 65 | 66 | def extractImage(button, imagePath, entry, mainWindow, name): 67 | command = "cd " + entry.get_placeholder_text() + " && " + imagePath + " --appimage-extract" 68 | 69 | dst = entry.get_placeholder_text() + '/' + name.get_text() + '.AppDir' 70 | 71 | if os.path.exists(dst): 72 | throwError(None, dst + folderAlreadyExistsSubtitle, folderAlreadyExistsTitle, mainWindow) 73 | else: 74 | terminal = Gtk.TextView() 75 | terminal.set_editable(False) 76 | 77 | bff = Gtk.TextBuffer() 78 | terminal = Gtk.TextView(buffer = bff) 79 | bff.set_text(extractingImage) 80 | 81 | iter = bff.get_end_iter() 82 | 83 | consolePage = console(mainWindow, terminal) 84 | consolePage.present() 85 | 86 | extractOutput = os.popen(command).read() 87 | bff.insert(iter, extractOutput) 88 | 89 | os.rename(entry.get_placeholder_text() + '/squashfs-root', dst) 90 | 91 | 92 | def renameImage(button, appImage, name, loc, refresh, imageName=None, imageNum=None): 93 | dst = loc + "/" + name.get_text() + ".AppImage" 94 | 95 | os.rename(appImage, dst) 96 | 97 | refresh(None, None, None) 98 | 99 | def startImage(button, appImage, startInTerminal, mainWindow, flatpak, setState, row): 100 | 101 | command = None 102 | 103 | st = os.stat(appImage) 104 | executable = bool(st.st_mode & stat.S_IEXEC) 105 | 106 | if not executable: 107 | throwError(None, noExePermissionSubtitle, noExePermissionTitle, mainWindow) 108 | else: 109 | if flatpak: 110 | command = 'cd ~ && ' + 'flatpak-spawn --host ' + appImage.split("/home/",1)[1].split("/",1)[1] 111 | else: 112 | command = appImage 113 | 114 | launchThread = threading.Thread(target=os.popen(command)) 115 | launchThread.start() 116 | 117 | 118 | imageNum = None 119 | imageNames = None 120 | 121 | class imageOptions(Adw.PreferencesWindow): 122 | 123 | def __init__(self, parent, refresh, appImage, fullName, setRowState, row, **kwargs): 124 | super().__init__(**kwargs) 125 | 126 | self.set_transient_for(parent) 127 | self.set_modal(True) 128 | 129 | self.set_title(imageOptionsTitle) 130 | self.set_default_size(450,375) 131 | 132 | prefercePage = Adw.PreferencesPage.new() 133 | self.add(page=prefercePage) 134 | 135 | imageOptions = Adw.PreferencesGroup.new() 136 | 137 | nameEntry = Gtk.Entry() 138 | nameEntry.set_hexpand(True) 139 | nameEntry.set_text(fullName) 140 | nameEntry.set_valign(Gtk.Align.CENTER) 141 | 142 | renameButton = Gtk.Button() 143 | renameButton.connect('clicked', manageImages.renameImage, appImage, nameEntry, os.path.dirname(appImage), refresh) 144 | renameButton.set_icon_name(icon_name='emblem-ok-symbolic') 145 | renameButton.set_valign(Gtk.Align.CENTER) 146 | 147 | self.renameImage = Adw.ActionRow.new() 148 | self.renameImage.set_title(title=globalName + ':') 149 | self.renameImage.add_suffix(nameEntry) 150 | self.renameImage.add_suffix(renameButton) 151 | imageOptions.add(child=self.renameImage) 152 | 153 | st = os.stat(appImage) 154 | executable = bool(st.st_mode & stat.S_IEXEC) 155 | 156 | executableSw = Gtk.Switch.new() 157 | executableSw.set_valign(align=Gtk.Align.CENTER) 158 | if executable: 159 | executableSw.set_active(True) 160 | executableSw.connect('notify::active', manageImages.setExecutable, appImage, setRowState, row) 161 | 162 | setExecutable = Adw.ActionRow.new() 163 | setExecutable.set_title(title=imageOptionsExecutable) 164 | setExecutable.add_suffix(widget=executableSw) 165 | imageOptions.add(child=setExecutable) 166 | 167 | 168 | extractEntry = pathEntry(os.path.dirname(os.path.abspath(appImage))) 169 | extractEntry.set_hexpand(True) 170 | extractEntry.set_valign(Gtk.Align.CENTER) 171 | 172 | extractButton = Gtk.Button.new() 173 | extractButton.set_icon_name(icon_name='emblem-ok-symbolic') 174 | extractButton.set_valign(Gtk.Align.CENTER) 175 | extractButton.connect('clicked', manageImages.extractImage, appImage, extractEntry, parent, nameEntry) 176 | 177 | extractImage = Adw.ActionRow.new() 178 | extractImage.set_title(title=imageOptionsExtract) 179 | extractImage.add_suffix(extractEntry) 180 | extractImage.add_suffix(extractButton) 181 | 182 | startInTerminalSw = Gtk.Switch.new() 183 | startInTerminalSw.set_active(False) 184 | startInTerminalSw.set_valign(align=Gtk.Align.CENTER) 185 | # startInTerminalSw.connect('notify::active', manageImages.createShortcut, 'desktop', str(pathlib.Path.home())+'/Desktop', appImage) 186 | 187 | startInTerminal = Adw.ActionRow.new() 188 | startInTerminal.set_title(title=imageOptionsStartTerminal) 189 | startInTerminal.add_suffix(widget=startInTerminalSw) 190 | 191 | 192 | # integrateSw = Gtk.Switch.new() 193 | # integrateSw.set_active(False) 194 | # integrateSw.set_valign(align=Gtk.Align.CENTER) 195 | # integrateSw.connect('notify::active', manageImages.integrateImage, appImage, flatpak) 196 | 197 | # setLauncherShortcut = Adw.ActionRow.new() 198 | # setLauncherShortcut.set_title(title='System integrate:') 199 | # setLauncherShortcut.add_suffix(widget=integrateSw) 200 | 201 | imageOptions.add(child=startInTerminal) 202 | # imageOptions.add(child=setLauncherShortcut) 203 | imageOptions.add(child=extractImage) 204 | 205 | prefercePage.add(imageOptions) 206 | -------------------------------------------------------------------------------- /data/python-dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "python3", 3 | "buildsystem": "simple", 4 | "build-commands": [], 5 | "modules": [ 6 | { 7 | "name": "python3-sphinx", 8 | "buildsystem": "simple", 9 | "build-commands": [ 10 | "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"sphinx\" --no-build-isolation" 11 | ], 12 | "sources": [ 13 | { 14 | "type": "file", 15 | "url": "https://files.pythonhosted.org/packages/68/47/93d3d28e97c7577f563903907912f4b3804054e4877a5ba6651f7182c53b/urllib3-1.26.10-py2.py3-none-any.whl", 16 | "sha256": "8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec" 17 | }, 18 | { 19 | "type": "file", 20 | "url": "https://files.pythonhosted.org/packages/60/2e/dec1cc18c51b8df33c7c4d0a321b084cf38e1733b98f9d15018880fb4970/pytz-2022.1-py2.py3-none-any.whl", 21 | "sha256": "e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c" 22 | }, 23 | { 24 | "type": "file", 25 | "url": "https://files.pythonhosted.org/packages/6c/10/a7d0fa5baea8fe7b50f448ab742f26f52b80bfca85ac2be9d35cdd9a3246/pyparsing-3.0.9-py3-none-any.whl", 26 | "sha256": "5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" 27 | }, 28 | { 29 | "type": "file", 30 | "url": "https://files.pythonhosted.org/packages/1d/97/2288fe498044284f39ab8950703e88abbac2abbdf65524d576157af70556/MarkupSafe-2.1.1.tar.gz", 31 | "sha256": "7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b" 32 | }, 33 | { 34 | "type": "file", 35 | "url": "https://files.pythonhosted.org/packages/04/a2/d918dcd22354d8958fe113e1a3630137e0fc8b44859ade3063982eacd2a4/idna-3.3-py3-none-any.whl", 36 | "sha256": "84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff" 37 | }, 38 | { 39 | "type": "file", 40 | "url": "https://files.pythonhosted.org/packages/94/69/64b11e8c2fb21f08634468caef885112e682b0ebe2908e74d3616eb1c113/charset_normalizer-2.1.0-py3-none-any.whl", 41 | "sha256": "5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5" 42 | }, 43 | { 44 | "type": "file", 45 | "url": "https://files.pythonhosted.org/packages/e9/06/d3d367b7af6305b16f0d28ae2aaeb86154fa91f144f036c2d5002a5a202b/certifi-2022.6.15-py3-none-any.whl", 46 | "sha256": "fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412" 47 | }, 48 | { 49 | "type": "file", 50 | "url": "https://files.pythonhosted.org/packages/2b/14/05f9206cf4e9cfca1afb5fd224c7cd434dcc3a433d6d9e4e0264d29c6cdb/sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", 51 | "sha256": "bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" 52 | }, 53 | { 54 | "type": "file", 55 | "url": "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", 56 | "sha256": "2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178" 57 | }, 58 | { 59 | "type": "file", 60 | "url": "https://files.pythonhosted.org/packages/c5/09/5de5ed43a521387f18bdf5f5af31d099605c992fd25372b2b9b825ce48ee/sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", 61 | "sha256": "8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e" 62 | }, 63 | { 64 | "type": "file", 65 | "url": "https://files.pythonhosted.org/packages/dc/47/86022665a9433d89a66f5911b558ddff69861766807ba685de2e324bd6ed/sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", 66 | "sha256": "806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a" 67 | }, 68 | { 69 | "type": "file", 70 | "url": "https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl", 71 | "sha256": "ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" 72 | }, 73 | { 74 | "type": "file", 75 | "url": "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", 76 | "sha256": "0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b" 77 | }, 78 | { 79 | "type": "file", 80 | "url": "https://files.pythonhosted.org/packages/c6/77/5464ec50dd0f1c1037e3c93249b040c8fc8078fdda97530eeb02424b6eea/sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", 81 | "sha256": "352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd" 82 | }, 83 | { 84 | "type": "file", 85 | "url": "https://files.pythonhosted.org/packages/63/40/c854ef09500e25f6432dcbad0f37df87fd7046d376272292d8654cc71c95/sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", 86 | "sha256": "d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07" 87 | }, 88 | { 89 | "type": "file", 90 | "url": "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", 91 | "sha256": "c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" 92 | }, 93 | { 94 | "type": "file", 95 | "url": "https://files.pythonhosted.org/packages/ca/91/6d9b8ccacd0412c08820f72cebaa4f0c0441b5cda699c90f618b6f8a1b42/requests-2.28.1-py3-none-any.whl", 96 | "sha256": "8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" 97 | }, 98 | { 99 | "type": "file", 100 | "url": "https://files.pythonhosted.org/packages/bc/c3/f068337a370801f372f2f8f6bad74a5c140f6fda3d9de154052708dd3c65/Jinja2-3.1.2-py3-none-any.whl", 101 | "sha256": "6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" 102 | }, 103 | { 104 | "type": "file", 105 | "url": "https://files.pythonhosted.org/packages/4c/5e/6003a0d1f37725ec2ebd4046b657abb9372202655f96e76795dca8c0063c/docutils-0.17.1-py2.py3-none-any.whl", 106 | "sha256": "cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61" 107 | }, 108 | { 109 | "type": "file", 110 | "url": "https://files.pythonhosted.org/packages/2e/57/a4177e24f8ed700c037e1eca7620097fdfbb1c9b358601e40169adf6d364/Babel-2.10.3-py3-none-any.whl", 111 | "sha256": "ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb" 112 | }, 113 | { 114 | "type": "file", 115 | "url": "https://files.pythonhosted.org/packages/10/ad/00b090d23a222943eb0eda509720a404f531a439e803f6538f35136cae9e/alabaster-0.7.12-py2.py3-none-any.whl", 116 | "sha256": "446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359" 117 | }, 118 | { 119 | "type": "file", 120 | "url": "https://files.pythonhosted.org/packages/fd/a2/3139e82a7caa2fb6954d0e63db206cc60e0ad6c67ae61ef9cf87dc70ade1/Sphinx-5.0.2-py3-none-any.whl", 121 | "sha256": "d3e57663eed1d7c5c50895d191fdeda0b54ded6f44d5621b50709466c338d1e8" 122 | } 123 | ] 124 | }, 125 | { 126 | "name": "python3-Pillow", 127 | "buildsystem": "simple", 128 | "build-commands": [ 129 | "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"pillow\" --no-build-isolation" 130 | ], 131 | "sources": [ 132 | { 133 | "type": "file", 134 | "url": "https://files.pythonhosted.org/packages/bc/07/830784e061fb94d67649f3e438ff63cfb902dec6d48ac75aeaaac7c7c30e/Pillow-9.4.0.tar.gz", 135 | "sha256": "a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e" 136 | } 137 | ] 138 | } 139 | ] 140 | } -------------------------------------------------------------------------------- /po/pt.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: Immagini\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2023-06-22 18:18+0200\n" 11 | "PO-Revision-Date: 2023-07-16 10:10-0300\n" 12 | "Last-Translator: \n" 13 | "Language-Team: Rilson Joás 1);\n" 19 | "X-Generator: Poedit 3.3.2\n" 20 | 21 | #: Immagini/ui/strings.py:4 22 | msgid "Immagini" 23 | msgstr "Immagini" 24 | 25 | #: Immagini/ui/strings.py:6 26 | msgid "Name" 27 | msgstr "Nome" 28 | 29 | #: Immagini/ui/strings.py:7 30 | msgid "Executable" 31 | msgstr "Executável" 32 | 33 | #: Immagini/ui/strings.py:8 34 | msgid "Icon" 35 | msgstr "Ícone" 36 | 37 | #: Immagini/ui/strings.py:9 38 | msgid "Path" 39 | msgstr "Caminho" 40 | 41 | #: Immagini/ui/strings.py:10 42 | msgid "Category" 43 | msgstr "Categoria" 44 | 45 | #: Immagini/ui/strings.py:11 46 | msgid "Type" 47 | msgstr "Tipo" 48 | 49 | #: Immagini/ui/strings.py:12 50 | msgid "Delete" 51 | msgstr "Deletar" 52 | 53 | #: Immagini/ui/strings.py:13 54 | msgid "Close" 55 | msgstr "Fechar" 56 | 57 | #: Immagini/ui/strings.py:14 Immagini/ui/strings.py:25 58 | msgid "Refresh" 59 | msgstr "Recarregar" 60 | 61 | #: Immagini/ui/strings.py:15 62 | msgid "Confirm" 63 | msgstr "Confirmar" 64 | 65 | #: Immagini/ui/strings.py:16 66 | msgid "Template" 67 | msgstr "Modelo" 68 | 69 | #: Immagini/ui/strings.py:18 70 | msgid "Application" 71 | msgstr "Aplicativo" 72 | 73 | #: Immagini/ui/strings.py:19 74 | msgid "Utility" 75 | msgstr "Utilidade" 76 | 77 | #: Immagini/ui/strings.py:21 78 | msgid "Immagini - Library" 79 | msgstr "Immagini - Biblioteca" 80 | 81 | #: Immagini/ui/strings.py:22 82 | msgid "Immagini - New" 83 | msgstr "Immagini- Novo" 84 | 85 | #: Immagini/ui/strings.py:26 86 | msgid "Show in folder" 87 | msgstr "Mostrar na pasta" 88 | 89 | #: Immagini/ui/strings.py:27 Immagini/ui/strings.py:34 90 | msgid "Preferences" 91 | msgstr "Preferências" 92 | 93 | #: Immagini/ui/strings.py:28 94 | msgid "Shortcuts" 95 | msgstr "Atalhos" 96 | 97 | #: Immagini/ui/strings.py:29 98 | msgid "About Immagini" 99 | msgstr "Sobre o Immagini" 100 | 101 | #: Immagini/ui/strings.py:31 102 | msgid "Management tool for AppImage applications" 103 | msgstr "Ferramenta de gerenciamento de aplicativos AppImage" 104 | 105 | #: Immagini/ui/strings.py:35 106 | msgid "New image options" 107 | msgstr "Opções de nova imagem" 108 | 109 | #: Immagini/ui/strings.py:36 110 | msgid "Library options" 111 | msgstr "Opções de biblioteca" 112 | 113 | #: Immagini/ui/strings.py:38 114 | msgid "Library location" 115 | msgstr "Local de biblioteca" 116 | 117 | #: Immagini/ui/strings.py:39 118 | msgid "To apply changes restart the app" 119 | msgstr "Reinicie o app para aplicar as mudanças" 120 | 121 | #: Immagini/ui/strings.py:40 122 | msgid "Select library location" 123 | msgstr "Selecione o local da biblioteca" 124 | 125 | #: Immagini/ui/strings.py:42 126 | msgid "Auto delete AppDir" 127 | msgstr "Deletar AppDir automaticamente" 128 | 129 | #: Immagini/ui/strings.py:43 130 | msgid "Deletes the .AppDir folder after creating an AppImage file" 131 | msgstr "Deleta a pasta .AppDir depois de criar um arquivo AppImage" 132 | 133 | #: Immagini/ui/strings.py:45 134 | msgid "Enable FolderMode by default" 135 | msgstr "Aplicar Folder Mode por padrão" 136 | 137 | #: Immagini/ui/strings.py:46 138 | msgid "" 139 | "Automatically enables the \"Folder Mode\" option when creating a new image " 140 | "file" 141 | msgstr "" 142 | "Automaticamente aplica o \"Folder Mode\" ao criar uma nova imagem de arquivo" 143 | 144 | #: Immagini/ui/strings.py:48 145 | msgid "Enable custom AppRun by default" 146 | msgstr "Habilita AppRun customizável por padrão" 147 | 148 | #: Immagini/ui/strings.py:49 149 | msgid "" 150 | "Automatically enables the \"Custom AppRun\" option when creating a new image " 151 | "file" 152 | msgstr "" 153 | "Automaticamente habilita o AppRun customizável por padrão ao criar uma nova " 154 | "imagem de arquivo" 155 | 156 | #: Immagini/ui/strings.py:51 157 | msgid "Use library folder as default" 158 | msgstr "Usar pasta de biblioteca como padrão" 159 | 160 | #: Immagini/ui/strings.py:52 161 | msgid "Uses library folder as default location when creating new apps" 162 | msgstr "" 163 | "Automaticamente usa pasta de biblioteca como padrão ao criar novos apps" 164 | 165 | #: Immagini/ui/strings.py:54 166 | msgid "Library path changed" 167 | msgstr "Caminho da biblioteca mudado" 168 | 169 | #: Immagini/ui/strings.py:58 170 | msgid "Include libraries" 171 | msgstr "Inclui bibliotecas" 172 | 173 | #: Immagini/ui/strings.py:59 174 | msgid "Select a library to include inside an AppImage" 175 | msgstr "Selecione uma biblioteca para incluir dentro de um AppImage" 176 | 177 | #: Immagini/ui/strings.py:60 178 | msgid "Select libraries" 179 | msgstr "Selecione bibliotecas" 180 | 181 | #: Immagini/ui/strings.py:62 182 | msgid "Folder mode" 183 | msgstr "Folder Mode" 184 | 185 | #: Immagini/ui/strings.py:63 186 | msgid "Parent folder location" 187 | msgstr "Localização da pasta principal" 188 | 189 | #: Immagini/ui/strings.py:65 190 | msgid "Custom AppRun" 191 | msgstr "AppRun customizável" 192 | 193 | #: Immagini/ui/strings.py:66 194 | msgid "Custom AppRun location" 195 | msgstr "Local de AppRun customizável" 196 | 197 | #: Immagini/ui/strings.py:68 198 | msgid "Include dependencies" 199 | msgstr "Incluir dependências" 200 | 201 | #: Immagini/ui/strings.py:69 202 | msgid "Installed interpreters" 203 | msgstr "Interpretadores instalados" 204 | 205 | #: Immagini/ui/strings.py:70 206 | msgid "Select manually" 207 | msgstr "Selecionar manualmente" 208 | 209 | #: Immagini/ui/strings.py:72 210 | msgid "Create template image" 211 | msgstr "Criar imagem modelo" 212 | 213 | #: Immagini/ui/strings.py:74 214 | msgid "Location" 215 | msgstr "Local" 216 | 217 | #: Immagini/ui/strings.py:75 218 | msgid "App location" 219 | msgstr "Local de app" 220 | 221 | #: Immagini/ui/strings.py:77 222 | msgid "Select files: " 223 | msgstr "Selecionar arquivos: " 224 | 225 | #: Immagini/ui/strings.py:78 226 | msgid "Select folders: " 227 | msgstr "Selecionar pastas: " 228 | 229 | #: Immagini/ui/strings.py:79 230 | msgid "Selected items: " 231 | msgstr "Selecionar itens: " 232 | 233 | #: Immagini/ui/strings.py:81 234 | msgid "Please fill in all the informations" 235 | msgstr "Por favor, preencha as informações" 236 | 237 | #: Immagini/ui/strings.py:82 238 | msgid "All the info are required" 239 | msgstr "Todas as informações são obrigatórias" 240 | 241 | #: Immagini/ui/strings.py:85 242 | msgid "Advanced" 243 | msgstr "Avançado" 244 | 245 | #: Immagini/ui/strings.py:88 246 | msgid "Terminal" 247 | msgstr "Terminal" 248 | 249 | #: Immagini/ui/strings.py:92 250 | msgid "Image Options" 251 | msgstr "Opções de imagem" 252 | 253 | #: Immagini/ui/strings.py:93 254 | msgid "Executable:" 255 | msgstr "Executável:" 256 | 257 | #: Immagini/ui/strings.py:94 258 | msgid "Extract image:" 259 | msgstr "Extrair imagem:" 260 | 261 | #: Immagini/ui/strings.py:95 262 | msgid "Start in terminal:" 263 | msgstr "Começar no terminal:" 264 | 265 | #: Immagini/ui/strings.py:97 266 | msgid "Deleting an appimage file is not reversible" 267 | msgstr "Deletar um arquivo appimage é uma ação irreversível" 268 | 269 | #: Immagini/ui/strings.py:98 270 | msgid "Extracting image" 271 | msgstr "Extraindo imagem" 272 | 273 | #: Immagini/ui/strings.py:102 274 | msgid "The app has no executable permissions" 275 | msgstr "O app não possui permissão de execução" 276 | 277 | #: Immagini/ui/strings.py:103 278 | msgid "Permission denied" 279 | msgstr "Permissão negada" 280 | 281 | #: Immagini/ui/strings.py:105 282 | msgid " alredy exists" 283 | msgstr " já existe" 284 | 285 | #: Immagini/ui/strings.py:106 286 | msgid "Folder already exists" 287 | msgstr "Pasta já existe" 288 | 289 | #: Immagini/ui/strings.py:108 290 | msgid "Selected file must be named 'AppRun'" 291 | msgstr "Arquivo selecionado deve ser nomeado como 'AppRun'" 292 | 293 | #: Immagini/ui/strings.py:109 294 | msgid "AppRun file not valid" 295 | msgstr "Arquivo AppRun não válido" 296 | 297 | #: Immagini/ui/strings.py:111 298 | msgid "The Application folder does not contain the selected executable file" 299 | msgstr "A pasta de Aplicativo não contém o arquivo executável selecionado" 300 | 301 | #: Immagini/ui/strings.py:112 302 | msgid "Application folder does not contain executable" 303 | msgstr "Pasta de aplicativo não possui executável" 304 | 305 | #: Immagini/ui/strings.py:114 306 | msgid " does not exists" 307 | msgstr " não existe" 308 | 309 | #: Immagini/ui/strings.py:115 310 | msgid "could not copy the exe file" 311 | msgstr "não pôde copiar o arquivo executável" 312 | 313 | #: Immagini/ui/strings.py:117 314 | msgid "icon file does't exist" 315 | msgstr "arquivo de ícone não existe" 316 | 317 | #: Immagini/ui/strings.py:118 318 | msgid "could not copy icon" 319 | msgstr "não pôde copiar o ícone" 320 | 321 | #: Immagini/ui/strings.py:120 322 | msgid "The icon size must be 32x32, 48x48 etc.. not " 323 | msgstr "O tamanho do ícone deve ser 32x32, 48x48, etc... não " 324 | 325 | #: Immagini/ui/strings.py:121 326 | msgid "Icon size not valid" 327 | msgstr "Tamanho do arquivo não válido" 328 | 329 | #: Immagini/ui/strings.py:123 330 | msgid "could not copy library" 331 | msgstr "não pôde copiar biblioteca" 332 | 333 | #: Immagini/ui/strings.py:124 334 | msgid "Library does not exist" 335 | msgstr "Biblioteca não existe" 336 | -------------------------------------------------------------------------------- /data/dev.salaniLeo.immagini.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /share/icons/hicolor/scalable/apps/dev.salaniLeo.immagini.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /dev.salaniLeo.immagini.json: -------------------------------------------------------------------------------- 1 | { 2 | "app-id" : "dev.salaniLeo.immagini", 3 | "runtime" : "org.gnome.Platform", 4 | "runtime-version" : "43", 5 | "sdk" : "org.gnome.Sdk", 6 | "command" : "immagini", 7 | "finish-args" : [ 8 | "--device=dri", 9 | "--share=ipc", 10 | "--socket=fallback-x11", 11 | "--socket=wayland", 12 | "--talk-name=org.freedesktop.Flatpak", 13 | "--filesystem=home" 14 | ], 15 | "build-options" : { 16 | "env" : { 17 | "V" : "1", 18 | "BASH_COMPLETIONSDIR" : "/app/share/bash-completion/completions", 19 | "MOUNT_FUSE_PATH" : "../tmp/" 20 | } 21 | }, 22 | "cleanup" : [ 23 | "/include", 24 | "/share/doc", 25 | "/share/gtk-doc" 26 | ], 27 | "modules" : [ 28 | { 29 | "name": "python3", 30 | "buildsystem": "simple", 31 | "build-commands": [], 32 | "modules": [ 33 | { 34 | "name" : "libfuse", 35 | "config-opts" : [ 36 | "UDEV_RULES_PATH=/app/etc/udev/rules.d", 37 | "INIT_D_PATH=/app/etc/init.d" 38 | ], 39 | "cleanup" : [ 40 | "/bin/ulockmgr_server" 41 | ], 42 | "post-install" : [ 43 | "install -m a+rx fusermount-wrapper.sh /app/bin/fusermount" 44 | ], 45 | "sources" : [ 46 | { 47 | "name" : "uncrustify", 48 | "buildsystem" : "cmake-ninja", 49 | "config-opts" : [ 50 | "-DCMAKE_BUILD_TYPE=Release" 51 | ], 52 | "builddir" : true, 53 | "sources" : [ 54 | { 55 | "type" : "archive", 56 | "url" : "https://github.com/uncrustify/uncrustify/archive/uncrustify-0.71.0.tar.gz", 57 | "sha256" : "403a0f34463c0d6b0fbf230d8a03b7af9f493faa235208417793350db062003c" 58 | } 59 | ] 60 | }, 61 | { 62 | "type" : "archive", 63 | "url" : "https://github.com/libfuse/libfuse/releases/download/fuse-2.9.9/fuse-2.9.9.tar.gz", 64 | "sha256" : "d0e69d5d608cc22ff4843791ad097f554dd32540ddc9bed7638cc6fea7c1b4b5" 65 | }, 66 | { 67 | "type" : "patch", 68 | "path" : "build-aux/flatpak/fuse-2.9.2-namespace-conflict-fix.patch" 69 | }, 70 | { 71 | "type" : "patch", 72 | "path" : "build-aux/flatpak/fuse-disable-sys-mount-under-flatpak.patch" 73 | }, 74 | { 75 | "type" : "patch", 76 | "path" : "build-aux/flatpak/fuse-2.9.2-closefrom.patch" 77 | }, 78 | { 79 | "type" : "file", 80 | "path" : "build-aux/flatpak/fusermount-wrapper.sh" 81 | } 82 | ] 83 | }, 84 | { 85 | "name": "python3-sphinx", 86 | "buildsystem": "simple", 87 | "build-commands": [ 88 | "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"sphinx\" --no-build-isolation" 89 | ], 90 | "sources": [ 91 | { 92 | "type": "file", 93 | "url": "https://files.pythonhosted.org/packages/68/47/93d3d28e97c7577f563903907912f4b3804054e4877a5ba6651f7182c53b/urllib3-1.26.10-py2.py3-none-any.whl", 94 | "sha256": "8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec" 95 | }, 96 | { 97 | "type": "file", 98 | "url": "https://files.pythonhosted.org/packages/60/2e/dec1cc18c51b8df33c7c4d0a321b084cf38e1733b98f9d15018880fb4970/pytz-2022.1-py2.py3-none-any.whl", 99 | "sha256": "e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c" 100 | }, 101 | { 102 | "type": "file", 103 | "url": "https://files.pythonhosted.org/packages/6c/10/a7d0fa5baea8fe7b50f448ab742f26f52b80bfca85ac2be9d35cdd9a3246/pyparsing-3.0.9-py3-none-any.whl", 104 | "sha256": "5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" 105 | }, 106 | { 107 | "type": "file", 108 | "url": "https://files.pythonhosted.org/packages/1d/97/2288fe498044284f39ab8950703e88abbac2abbdf65524d576157af70556/MarkupSafe-2.1.1.tar.gz", 109 | "sha256": "7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b" 110 | }, 111 | { 112 | "type": "file", 113 | "url": "https://files.pythonhosted.org/packages/04/a2/d918dcd22354d8958fe113e1a3630137e0fc8b44859ade3063982eacd2a4/idna-3.3-py3-none-any.whl", 114 | "sha256": "84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff" 115 | }, 116 | { 117 | "type": "file", 118 | "url": "https://files.pythonhosted.org/packages/94/69/64b11e8c2fb21f08634468caef885112e682b0ebe2908e74d3616eb1c113/charset_normalizer-2.1.0-py3-none-any.whl", 119 | "sha256": "5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5" 120 | }, 121 | { 122 | "type": "file", 123 | "url": "https://files.pythonhosted.org/packages/e9/06/d3d367b7af6305b16f0d28ae2aaeb86154fa91f144f036c2d5002a5a202b/certifi-2022.6.15-py3-none-any.whl", 124 | "sha256": "fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412" 125 | }, 126 | { 127 | "type": "file", 128 | "url": "https://files.pythonhosted.org/packages/2b/14/05f9206cf4e9cfca1afb5fd224c7cd434dcc3a433d6d9e4e0264d29c6cdb/sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", 129 | "sha256": "bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" 130 | }, 131 | { 132 | "type": "file", 133 | "url": "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", 134 | "sha256": "2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178" 135 | }, 136 | { 137 | "type": "file", 138 | "url": "https://files.pythonhosted.org/packages/c5/09/5de5ed43a521387f18bdf5f5af31d099605c992fd25372b2b9b825ce48ee/sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", 139 | "sha256": "8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e" 140 | }, 141 | { 142 | "type": "file", 143 | "url": "https://files.pythonhosted.org/packages/dc/47/86022665a9433d89a66f5911b558ddff69861766807ba685de2e324bd6ed/sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", 144 | "sha256": "806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a" 145 | }, 146 | { 147 | "type": "file", 148 | "url": "https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl", 149 | "sha256": "ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" 150 | }, 151 | { 152 | "type": "file", 153 | "url": "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", 154 | "sha256": "0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b" 155 | }, 156 | { 157 | "type": "file", 158 | "url": "https://files.pythonhosted.org/packages/c6/77/5464ec50dd0f1c1037e3c93249b040c8fc8078fdda97530eeb02424b6eea/sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", 159 | "sha256": "352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd" 160 | }, 161 | { 162 | "type": "file", 163 | "url": "https://files.pythonhosted.org/packages/63/40/c854ef09500e25f6432dcbad0f37df87fd7046d376272292d8654cc71c95/sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", 164 | "sha256": "d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07" 165 | }, 166 | { 167 | "type": "file", 168 | "url": "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", 169 | "sha256": "c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" 170 | }, 171 | { 172 | "type": "file", 173 | "url": "https://files.pythonhosted.org/packages/ca/91/6d9b8ccacd0412c08820f72cebaa4f0c0441b5cda699c90f618b6f8a1b42/requests-2.28.1-py3-none-any.whl", 174 | "sha256": "8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" 175 | }, 176 | { 177 | "type": "file", 178 | "url": "https://files.pythonhosted.org/packages/bc/c3/f068337a370801f372f2f8f6bad74a5c140f6fda3d9de154052708dd3c65/Jinja2-3.1.2-py3-none-any.whl", 179 | "sha256": "6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" 180 | }, 181 | { 182 | "type": "file", 183 | "url": "https://files.pythonhosted.org/packages/4c/5e/6003a0d1f37725ec2ebd4046b657abb9372202655f96e76795dca8c0063c/docutils-0.17.1-py2.py3-none-any.whl", 184 | "sha256": "cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61" 185 | }, 186 | { 187 | "type": "file", 188 | "url": "https://files.pythonhosted.org/packages/2e/57/a4177e24f8ed700c037e1eca7620097fdfbb1c9b358601e40169adf6d364/Babel-2.10.3-py3-none-any.whl", 189 | "sha256": "ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb" 190 | }, 191 | { 192 | "type": "file", 193 | "url": "https://files.pythonhosted.org/packages/10/ad/00b090d23a222943eb0eda509720a404f531a439e803f6538f35136cae9e/alabaster-0.7.12-py2.py3-none-any.whl", 194 | "sha256": "446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359" 195 | }, 196 | { 197 | "type": "file", 198 | "url": "https://files.pythonhosted.org/packages/fd/a2/3139e82a7caa2fb6954d0e63db206cc60e0ad6c67ae61ef9cf87dc70ade1/Sphinx-5.0.2-py3-none-any.whl", 199 | "sha256": "d3e57663eed1d7c5c50895d191fdeda0b54ded6f44d5621b50709466c338d1e8" 200 | } 201 | ] 202 | }, 203 | { 204 | "name": "python3-Pillow", 205 | "buildsystem": "simple", 206 | "build-commands": [ 207 | "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"pillow\" --no-build-isolation" 208 | ], 209 | "sources": [ 210 | { 211 | "type": "file", 212 | "url": "https://files.pythonhosted.org/packages/bc/07/830784e061fb94d67649f3e438ff63cfb902dec6d48ac75aeaaac7c7c30e/Pillow-9.4.0.tar.gz", 213 | "sha256": "a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e" 214 | } 215 | ] 216 | } 217 | ] 218 | }, 219 | { 220 | "name" : "immagini", 221 | "buildsystem" : "meson", 222 | "sources" : [ 223 | { 224 | "type" : "git", 225 | "url" : "https://github.com/SalaniLeo/Immagini", 226 | "tag" : "0.1.0", 227 | "commit" : "1afae11d4dd3693b7086a57fd3685d944e91e86d" 228 | } 229 | ], 230 | "dependencies": [ 231 | "python3", 232 | "python3-Pillow" 233 | ] 234 | } 235 | ] 236 | } -------------------------------------------------------------------------------- /Immagini/ui/mainWindow.py: -------------------------------------------------------------------------------- 1 | import gi 2 | import time 3 | import os 4 | from ..library.getContent import * 5 | from threading import Thread 6 | from .newImage import * 7 | from .uiElements import * 8 | from ..ui.strings import * 9 | 10 | gi.require_version(namespace='Gtk', version='4.0') 11 | gi.require_version(namespace='Adw', version='1') 12 | 13 | from gi.repository import Adw, Gio, Gtk 14 | 15 | ##Global Variables 16 | Adw.init() 17 | 18 | flatpak = False 19 | contentWindow = Adw.PreferencesPage.new() 20 | images = [] 21 | dirs = [] 22 | changedPath = False 23 | toast_overlay = Adw.ToastOverlay.new() 24 | page = None 25 | settings = Gio.Settings.new("dev.salaniLeo.immagini") 26 | libraryPath = settings.get_string("librarypath") 27 | 28 | if "~" in libraryPath: 29 | libraryPath = libraryPath.replace("~", str(pathlib.Path.home())) 30 | 31 | 32 | ##main app window 33 | class mainWindow(Gtk.ApplicationWindow): 34 | def __init__(self, **kwargs): 35 | super().__init__(**kwargs) 36 | 37 | global page 38 | page = self 39 | 40 | self.createImageBox = newImageBox(self, Immagini) 41 | newImageBox.getFlatpak(flatpak) 42 | 43 | self.switch_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 44 | self.set_default_size(850, 550) 45 | self.set_title(title=globalLibraryTitle) 46 | 47 | ##stack that contains the scrolled and newImage 48 | self.stack = Gtk.Stack() 49 | #scrolled that contains the flowbox 50 | self.scrolled = Gtk.ScrolledWindow() 51 | 52 | #adds as child toast_overlay, that contains everything 53 | self.set_child(child=toast_overlay) 54 | 55 | #adds as toast_overlay child stack 56 | toast_overlay.set_child(child=self.stack) 57 | 58 | #adds as scrolled child flowbox 59 | # self.scrolled.set_child(contentWindow) 60 | 61 | #adds the 2 pages to stack 62 | self.stack.add_child(child=contentWindow) 63 | self.stack.add_child(child=self.createImageBox) 64 | 65 | #Main stack 66 | self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) 67 | 68 | t1 = Thread(target=mainWindow.images) 69 | t1.start() 70 | 71 | self.headerbar = Gtk.HeaderBar.new() 72 | self.headerbar.add_css_class(css_class='flat') 73 | self.set_titlebar(titlebar=self.headerbar) 74 | 75 | about = Gio.SimpleAction.new("about", None) 76 | about.connect("activate", Immagini.show_about) 77 | 78 | self.show_in_folder = Gtk.Button.new() 79 | 80 | show_in_folder = Gio.SimpleAction.new("show_in_folder", None) 81 | show_in_folder.connect("activate", Immagini.show_in_folder) 82 | 83 | menu_button_model = Gio.Menu() 84 | 85 | menu_button_model.append(menuRefresh, 'app.refresh') 86 | menu_button_model.append(menuShowInFolder, 'app.show_in_folder') 87 | menu_button_model.append(menuPreferences, 'app.preferences') 88 | menu_button_model.append(menuShortcuts, 'app.show_shortcuts') 89 | menu_button_model.append(menuAbout, 'app.about') 90 | 91 | menuButton = Gtk.MenuButton.new() 92 | menuButton.set_icon_name(icon_name='open-menu-symbolic') 93 | menuButton.set_menu_model(menu_model=menu_button_model) 94 | self.headerbar.pack_end(child=menuButton) 95 | 96 | self.newAppImage = Gtk.Button() 97 | self.newAppImage.connect('clicked', Immagini.createImage, self) 98 | self.newAppImage.set_icon_name(icon_name='list-add-symbolic') 99 | self.headerbar.pack_start(child=self.newAppImage) 100 | 101 | self.backButton = Gtk.Button.new_from_icon_name("pan-start-symbolic") 102 | self.backButton.connect("clicked", Immagini.goBack, self) 103 | 104 | self.advancedOptions = Gtk.Box() 105 | self.advancedSwitch = Gtk.Switch() 106 | self.advancedLabel = Gtk.Label(label=advancedTitle) 107 | self.advancedLabel.set_margin_end(12) 108 | self.advancedOptions.append(self.advancedLabel) 109 | self.advancedOptions.append(self.advancedSwitch) 110 | self.advancedSwitch.connect("state-set", newImageBox.showAdvanced) 111 | 112 | def images(): 113 | global imagesNum 114 | global page 115 | 116 | libraryPath = settings.get_string("librarypath") 117 | 118 | appslist = os.listdir(libraryPath.replace("~", str(pathlib.Path.home()))) 119 | appsInfo = getFileNum(appslist, libraryPath.replace("~", str(pathlib.Path.home()))) 120 | imagesNum = appsInfo.appimages 121 | # time.sleep(0.1) 122 | 123 | for n in range(imagesNum): 124 | imageRow = getImages.createImageRow(appsInfo.imageNames[n], Immagini.refresh, page, setRowState, flatpak) 125 | images.append(imageRow) 126 | contentWindow.add(images[n]) 127 | 128 | imagesNum = None 129 | 130 | class Immagini(Adw.Application): 131 | def __init__(self, AppId, isFlatpak): 132 | super().__init__(application_id="dev.salaniLeo.immagini", 133 | flags=Gio.ApplicationFlags.FLAGS_NONE) 134 | 135 | self.create_action('show_in_folder', self.show_in_folder, ['f']) 136 | self.create_action('preferences', self.show_preferences, ['comma']) 137 | self.create_action('about', self.show_about) 138 | self.create_action('show_shortcuts', self.show_shortcuts) 139 | self.create_action('refresh', self.refresh, ['r']) 140 | self.create_action('quit', self.exit_app, ['w', 'q']) 141 | self.create_action('createImage', self.createImageShortcut, ['n']) 142 | 143 | global flatpak 144 | flatpak = isFlatpak 145 | 146 | def do_activate(self): 147 | global page 148 | page = self.props.active_window 149 | if not page: 150 | page = mainWindow(application=self) 151 | page.present() 152 | 153 | def do_startup(self): 154 | Gtk.Application.do_startup(self) 155 | 156 | def do_shutdown(self): 157 | # shutil.rmtree(dir + "/squashfs-root") 158 | Gtk.Application.do_shutdown(self) 159 | self.quit() 160 | 161 | def show_preferences(self, action, param): 162 | adw_preferences_window = ImmaginiPreferences(page) 163 | adw_preferences_window.show() 164 | 165 | def create_action(self, name, callback, shortcuts=None): 166 | action = Gio.SimpleAction.new(name, None) 167 | action.connect('activate', callback) 168 | self.add_action(action) 169 | if shortcuts: 170 | self.set_accels_for_action(f'app.{name}', shortcuts) 171 | 172 | def show_about(self, action, param): 173 | dialog = Adw.AboutWindow() 174 | dialog.set_application_name(globalImmagini) 175 | dialog.set_version("0.1.1") 176 | # dialog.set_developer_name("Leonardo Salani") 177 | dialog.set_license_type(Gtk.License(Gtk.License.GPL_3_0)) 178 | dialog.set_comments(aboutWindowComment) 179 | dialog.set_website("https://github.com/SalaniLeo/Immagini") 180 | dialog.set_developers(["Leonardo Salani"]) 181 | dialog.set_artists(["Brage Fuglseth"]) 182 | dialog.set_application_icon("dev.salaniLeo.immagini") 183 | dialog.present() 184 | 185 | def show_in_folder(self, action, param): 186 | os.system('xdg-open "%s"' % libraryPath) 187 | 188 | def show_shortcuts(self, action, param): 189 | shortcuts_window = ShortcutsWindow(transient_for=self.get_active_window()) 190 | shortcuts_window.present() 191 | 192 | def refresh(self, action, param): 193 | for n in range(imagesNum): 194 | contentWindow.remove(images[0]) 195 | images.remove(images[0]) 196 | getImages.restart_count() 197 | t1 = Thread(target=mainWindow.images) 198 | t1.start() 199 | t1.join() 200 | 201 | def createImage(button, self): 202 | self.stack.set_visible_child(self.createImageBox) 203 | self.headerbar.remove(self.newAppImage) 204 | self.headerbar.pack_start(self.backButton) 205 | self.headerbar.pack_start(self.advancedOptions) 206 | self.set_title(title=globalNewImageTitle) 207 | 208 | def createImageShortcut(win, action, shortcut): 209 | Immagini.createImage(None, page) 210 | 211 | def goBack(button, self): 212 | self.stack.set_visible_child(contentWindow) 213 | self.headerbar.remove(self.backButton) 214 | self.headerbar.remove(self.advancedOptions) 215 | self.headerbar.pack_start(self.newAppImage) 216 | self.set_title(title=globalLibraryTitle) 217 | 218 | def newToast(self, title, action): 219 | 220 | toast = Adw.Toast.new(title=title) 221 | toast.set_timeout(True) 222 | toast.set_button_label(globalRefresh) 223 | toast.set_action_name(action) 224 | 225 | return toast 226 | 227 | def exit_app(self, action, param): 228 | self.quit() 229 | 230 | class ImmaginiPreferences(Adw.PreferencesWindow): 231 | 232 | def __init__(self, parent, **kwargs): 233 | super().__init__(**kwargs) 234 | 235 | global settings 236 | 237 | autoDeleteOption = settings.get_boolean("removeappdir") 238 | autoFolderMode = settings.get_boolean("foldermode") 239 | autoCustomAppRun = settings.get_boolean("customapprun") 240 | uselibraryPath = settings.get_boolean("uselibrarypath") 241 | 242 | self.set_title(title=prefrencesTitle) 243 | 244 | self.set_transient_for(parent) 245 | self.set_modal(True) 246 | 247 | 248 | self.connect('close-request', self.do_shutdown) 249 | 250 | prefercePage = Adw.PreferencesPage.new() 251 | self.add(page=prefercePage) 252 | 253 | newImageOptions = Adw.PreferencesGroup.new() 254 | newImageOptions.set_title(title=newImagePreferencesTitle) 255 | 256 | self.autoDelete = Gtk.Switch.new() 257 | self.autoDelete.set_valign(align=Gtk.Align.CENTER) 258 | self.autoDelete.connect('notify::active', self.saveOpt, "removeappdir") 259 | self.autoDelete.set_state(autoDeleteOption) 260 | 261 | deleteADRow = Adw.ActionRow.new() 262 | deleteADRow.set_title(title=autoDeleteAppDirTitle) 263 | deleteADRow.set_subtitle(autoDeleteAppDirSubtitle) 264 | deleteADRow.add_suffix(widget=self.autoDelete) 265 | newImageOptions.add(child=deleteADRow) 266 | 267 | self.autoFolderMSw = Gtk.Switch.new() 268 | self.autoFolderMSw.set_valign(align=Gtk.Align.CENTER) 269 | self.autoFolderMSw.connect('notify::active', self.saveOpt, "foldermode") 270 | self.autoFolderMSw.set_state(autoFolderMode) 271 | 272 | autoFolderMRow = Adw.ActionRow.new() 273 | autoFolderMRow.set_title(title=autoFolderModeTitle) 274 | autoFolderMRow.set_subtitle(autoFolderModeSubtitle) 275 | autoFolderMRow.add_suffix(widget=self.autoFolderMSw) 276 | newImageOptions.add(child=autoFolderMRow) 277 | 278 | self.autoCustomARSw = Gtk.Switch.new() 279 | self.autoCustomARSw.set_valign(align=Gtk.Align.CENTER) 280 | self.autoCustomARSw.connect('notify::active', self.saveOpt, "customapprun") 281 | self.autoCustomARSw.set_state(autoCustomAppRun) 282 | 283 | autoCustomARRow = Adw.ActionRow.new() 284 | autoCustomARRow.set_title(title=autoCustomAppRunTitle) 285 | autoCustomARRow.set_subtitle(autoCustomAppRunSubtitle) 286 | autoCustomARRow.add_suffix(widget=self.autoCustomARSw) 287 | newImageOptions.add(child=autoCustomARRow) 288 | 289 | libraryOptions = Adw.PreferencesGroup.new() 290 | libraryOptions.set_title(title=libraryPreferencesTitle) 291 | 292 | prefercePage.add(group=libraryOptions) 293 | prefercePage.add(group=newImageOptions) 294 | 295 | self.libraryPathEntry = pathEntry(libraryPath) 296 | self.libraryPathEntry.connect('changed', self.saveString, "librarypath") 297 | 298 | self.browseLibLoc = browseButton(fileChooser, librarySelectionTitle, True, self.libraryPathEntry, page) 299 | 300 | libraryPathRow = Adw.ActionRow.new() 301 | libraryPathRow.set_title(title=libraryLocationTitle) 302 | libraryPathRow.set_subtitle(libraryLocationSubtitle) 303 | libraryPathRow.add_suffix(widget=self.libraryPathEntry) 304 | libraryPathRow.add_suffix(widget=self.browseLibLoc) 305 | 306 | 307 | libraryOptions.add(child=libraryPathRow) 308 | 309 | global changedPath 310 | 311 | changedPath = False 312 | 313 | useLPath = Gtk.Switch.new() 314 | useLPath.set_valign(align=Gtk.Align.CENTER) 315 | useLPath.connect('notify::active', self.useLPath, "uselibrarypath") 316 | useLPath.set_state(uselibraryPath) 317 | 318 | useLPathRow = Adw.ActionRow.new() 319 | useLPathRow.set_title(title=useLibraryPathTitle) 320 | useLPathRow.set_subtitle(useLibraryPathSubtitle) 321 | useLPathRow.add_suffix(widget=useLPath) 322 | 323 | newImageOptions.add(child=useLPathRow) 324 | 325 | 326 | def saveOpt(self, switch, GParamBoolean, key): 327 | global settings 328 | settings.set_boolean(key, switch.get_state()) 329 | 330 | def useLPath(self, switch, GParamBoolean, key): 331 | global settings 332 | settings.set_boolean(key, switch.get_state()) 333 | newImageBox.sameOutput(switch.get_state()) 334 | 335 | def saveString(self, entry, key): 336 | global changedPath 337 | global settings 338 | if os.path.exists(entry.get_text()): 339 | changedPath = True 340 | settings.set_string(key, entry.get_text()) 341 | else: 342 | settings.set_string(key, str(pathlib.Path.home()) + "/Applications") 343 | 344 | def do_shutdown(self, quit): 345 | global changedPath 346 | 347 | if(changedPath): 348 | toast_overlay.add_toast(Immagini.newToast(self, libraryPathChanged, "app.refresh")) 349 | 350 | class ShortcutsWindow(Gtk.ShortcutsWindow): 351 | __gtype_name__ = 'ShortcutsWindow' 352 | def __init__(self, **kwargs): 353 | super().__init__(**kwargs) 354 | 355 | if __name__ == '__main__': 356 | import sys 357 | 358 | app = Immagini() 359 | app.run(sys.argv) 360 | -------------------------------------------------------------------------------- /share/icons/hicolor/scalable/apps/dev.salaniLeo.immagini.Devel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /share/icons/hicolor/scalable/actions/im-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 30 | 32 | 36 | 40 | 41 | 51 | 53 | 57 | 61 | 62 | 72 | 74 | 78 | 82 | 83 | 94 | 96 | 100 | 104 | 105 | 116 | 118 | 122 | 126 | 127 | 137 | 139 | 143 | 147 | 148 | 158 | 160 | 164 | 168 | 169 | 179 | 181 | 185 | 189 | 190 | 198 | 200 | 204 | 208 | 212 | 213 | 214 | 233 | 235 | 236 | 238 | image/svg+xml 239 | 241 | 242 | 243 | 244 | 245 | 249 | 253 | 257 | 264 | 272 | 279 | 280 | 281 | 290 | 294 | 298 | 302 | 311 | 315 | 319 | 320 | 321 | -------------------------------------------------------------------------------- /Immagini/ui/newImage.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from ..imageCreator import startCreatingImage 3 | import shutil 4 | from .error import * 5 | import gi 6 | import threading 7 | import pathlib 8 | import json 9 | from ..convertFlatpak import startConvertingFlatpak 10 | from .uiElements import * 11 | from ..ui.strings import * 12 | gi.require_version('Gtk', '4.0') 13 | gi.require_version('Adw', '1') 14 | gi.require_version('Gio', '2.0') 15 | from gi.repository import Gtk, Adw, Gio 16 | 17 | AdvancedInfo = Adw.PreferencesGroup.new() 18 | outputRow = Adw.PreferencesGroup.new() 19 | isOutputActive = False 20 | settings = Gio.Settings.new("dev.salaniLeo.immagini") 21 | page = None 22 | dependeciesSwitches = [] 23 | 24 | class newImageBox(Gtk.Box): 25 | def __init__(self, mainWindow, application, **kwargs): 26 | super().__init__(**kwargs) 27 | global page 28 | page = mainWindow 29 | 30 | mainBox = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL, spacing=12) 31 | stack = Gtk.Stack() 32 | stack.add_titled(child=self.createNew(mainWindow, application), name=createNewOne, title=createNewOne) 33 | stack.add_titled(child=convertFlatpak(mainWindow, application), name=convertFromFlatpak, title=convertFromFlatpak) 34 | 35 | stack.set_transition_type( 36 | transition=Gtk.StackTransitionType.CROSSFADE 37 | ) 38 | stack_sidebar = Gtk.StackSidebar.new() 39 | stack_sidebar.set_stack(stack=stack) 40 | # stack_sidebar.connect('clicked', self.test) 41 | 42 | mainBox.append(stack_sidebar) 43 | mainBox.append(stack) 44 | self.append(mainBox) 45 | 46 | def createNew(self, mainWindow, application): 47 | global AdvancedInfo 48 | global outputRow 49 | 50 | mainBox = Adw.PreferencesPage.new() 51 | 52 | self.entryNum = 0 53 | 54 | self.bottomBox = Gtk.Box() 55 | self.bottomBox.set_vexpand(True) 56 | 57 | mainBox.set_vexpand(True) 58 | 59 | AdvancedInfo = Adw.PreferencesGroup.new() 60 | AdvancedInfo.set_title("Advanced") 61 | 62 | self.addInfo = Adw.PreferencesGroup.new() 63 | self.addInfo.set_title("New") 64 | 65 | self.nameEntry = self.newEntryRow(globalName, False, globalName,False, False) 66 | self.exeEntry = self.newEntryRow(globalExecutable,True,globalExecutable,False, True) 67 | self.iconEntry = self.newEntryRow(globalIcon, True, globalIcon, False, True) 68 | self.categoriesEntry = self.newEntryRow(globalCategory,False,globalCategory,False, False) 69 | self.typeEntry = self.newEntryRow(globalType,False,globalType,False, False) 70 | 71 | self.includeLibraries = self.newAdvancedList(includeLibrariesTitle, includeLibrariesSubtitle) 72 | self.parentFolder = self.newAdvancedRow(useFolderModeTitle, useFolderModeSubtitle, True, True, True) 73 | self.customARLoc = self.newAdvancedRow(useCustomAppRunTitle, useCustomAppRunSubtitle,True, False, True) 74 | self.includeInterpreter = self.newInterpreterSelector(includeDependeciesTitle, installedIntepreters, selectManually) 75 | self.createTemplateImage = self.newTemplateRow(createTemplateImage) 76 | 77 | AdvancedInfo.add(self.parentFolder) 78 | AdvancedInfo.add(self.customARLoc) 79 | AdvancedInfo.add(self.includeLibraries) 80 | AdvancedInfo.add(self.includeInterpreter) 81 | AdvancedInfo.add(self.createTemplateImage) 82 | AdvancedInfo.set_visible(False) 83 | 84 | self.addInfo.add(self.nameEntry) 85 | self.addInfo.add(self.exeEntry) 86 | self.addInfo.add(self.iconEntry) 87 | self.addInfo.add(self.categoriesEntry) 88 | self.addInfo.add(self.typeEntry) 89 | self.addInfo.set_hexpand(True) 90 | 91 | self.okButton = Gtk.Button(label=globalConfirm) 92 | self.okButton.set_size_request(80, -1) 93 | self.okButton.set_hexpand(True) 94 | self.okButton.set_halign(Gtk.Align.CENTER) 95 | self.okButton.set_valign(Gtk.Align.CENTER) 96 | self.okButton.set_margin_bottom(6) 97 | self.okButton.set_margin_top(6) 98 | self.okButton.connect('clicked', newImageBox.initCreation, application.refresh, page) 99 | 100 | mainBox.add(group=self.addInfo) 101 | 102 | self.uselibraryPath = settings.get_boolean("uselibrarypath") 103 | 104 | okPage = Adw.PreferencesGroup.new() 105 | 106 | okRow = Adw.ActionRow.new() 107 | # okRow.set_visible(False) 108 | okRow.set_child(self.okButton) 109 | 110 | okPage.add(okRow) 111 | 112 | mainBox.add(outputRow) 113 | mainBox.add(okPage) 114 | mainBox.add(AdvancedInfo) 115 | 116 | self.outputEntry = self.newEntryRow(outputLocationTitle,True,outputLocationSubtitle,True, True) 117 | outputRow.add(self.outputEntry) 118 | 119 | global isOutputActive 120 | 121 | if not self.uselibraryPath: 122 | isOutputActive = True 123 | outputRow.set_visible(True) 124 | else: 125 | isOutputActive = False 126 | outputRow.set_visible(False) 127 | 128 | autoFolderMode = settings.get_boolean("foldermode") 129 | autoCustomAppRun = settings.get_boolean("customapprun") 130 | 131 | if autoFolderMode: 132 | advancedSwitch[1].set_active(True) 133 | 134 | if autoCustomAppRun: 135 | advancedSwitch[0].set_active(True) 136 | 137 | return mainBox 138 | 139 | def showAdvanced(widget, active): 140 | if active is True: 141 | AdvancedInfo.set_visible(True) 142 | else: 143 | AdvancedInfo.set_visible(False) 144 | 145 | def sameOutput(active): 146 | global outputRow 147 | global isOutputActive 148 | 149 | if not active: 150 | if not isOutputActive: 151 | isOutputActive = True 152 | outputRow.set_visible(True) 153 | else: 154 | if isOutputActive: 155 | isOutputActive = False 156 | outputRow.set_visible(False) 157 | 158 | def newEntryRow(self, name, buttonNeeded, placeholder, folderMode, path): 159 | 160 | if path: 161 | entry = pathEntry(placeholder) 162 | else: 163 | entry = Gtk.Entry() 164 | 165 | label = Gtk.Label(label=name) 166 | label.set_hexpand(False) 167 | label.set_xalign(0.0) 168 | label.set_size_request(65,-1) 169 | label.set_halign(Gtk.Align.START) 170 | 171 | entry.set_valign(Gtk.Align.CENTER) 172 | entry.set_halign(Gtk.Align.FILL) 173 | entry.set_placeholder_text(placeholder) 174 | entry.set_hexpand(True) 175 | 176 | global normalRow 177 | normalRow.append(entry) 178 | 179 | row = Adw.ActionRow.new() 180 | row.add_suffix(entry) 181 | row.add_prefix(label) 182 | if buttonNeeded: 183 | row.add_suffix(browseButton(fileChooser, name, folderMode, entry, page)) 184 | 185 | return row 186 | 187 | def newAdvancedRow(self, name, placeholder, buttonNeeded, folderMode, path): 188 | 189 | switch = Gtk.Switch() 190 | switch.set_valign(Gtk.Align.CENTER) 191 | 192 | label = Gtk.Label(label=name) 193 | 194 | if path: 195 | entry = pathEntry(placeholder) 196 | else: 197 | entry = Gtk.Entry() 198 | 199 | entry.set_valign(Gtk.Align.CENTER) 200 | entry.get_style_context().add_class(class_name='error') 201 | entry.set_editable(False) 202 | entry.set_size_request(180,-1) 203 | 204 | button = browseButton(fileChooser, name, folderMode, entry, page) 205 | button.set_sensitive(False) 206 | 207 | switch.connect('state-set', self.enableOption, entry, button) 208 | 209 | row = Adw.ActionRow.new() 210 | row.add_suffix(switch) 211 | row.add_suffix(entry) 212 | row.add_prefix(label) 213 | row.add_suffix(button) 214 | 215 | global advancedRow 216 | advancedRow.append(entry) 217 | 218 | global advancedSwitch 219 | advancedSwitch.append(switch) 220 | 221 | return row 222 | 223 | def newAdvancedList(self, name, placeholder): 224 | 225 | adw_expander_row = Adw.ExpanderRow.new() 226 | 227 | switch = Gtk.Switch() 228 | switch.set_valign(Gtk.Align.CENTER) 229 | switch.set_halign(Gtk.Align.END) 230 | 231 | nameLabel = Gtk.Label() 232 | nameLabel.set_halign(Gtk.Align.START) 233 | nameLabel.set_valign(Gtk.Align.CENTER) 234 | nameLabel.set_margin_start(12) 235 | nameLabel.set_margin_top(12) 236 | nameLabel.set_margin_bottom(12) 237 | nameLabel.set_text(placeholder) 238 | 239 | button = browseButton(fileChooser, selectLibrariesTitle, False, nameLabel, page) 240 | button.set_valign(Gtk.Align.CENTER) 241 | button.set_margin_bottom(12) 242 | button.set_margin_top(12) 243 | button.set_margin_end(12) 244 | button.set_margin_start(12) 245 | button.set_sensitive(False) 246 | 247 | switch.connect('state-set', self.enableOption, None, button) 248 | 249 | 250 | rightBox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 251 | rightBox.append(switch) 252 | rightBox.append(button) 253 | 254 | leftBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) 255 | leftBox.set_hexpand(True) 256 | 257 | leftBox.append(nameLabel) 258 | 259 | expandableLayout = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 260 | expandableLayout.append(leftBox) 261 | expandableLayout.append(rightBox) 262 | expandableLayout.set_size_request(-1, -1) 263 | 264 | box = Adw.PreferencesGroup.new() 265 | 266 | adw_expander_row.add_row(child=expandableLayout) 267 | adw_expander_row.set_title(title=includeLibrariesTitle) 268 | 269 | box.add(adw_expander_row) 270 | 271 | global advancedRow 272 | advancedRow.append(nameLabel) 273 | 274 | global advancedSwitch 275 | advancedSwitch.append(switch) 276 | 277 | return adw_expander_row 278 | 279 | def newInterpreterSelector(self, title, sysInterp, browseInterp): 280 | global advancedRow, dependeciesSwitches 281 | 282 | adw_expander_row = Adw.ExpanderRow.new() 283 | 284 | selItemsLabel = Gtk.Label() 285 | 286 | switch = Gtk.Switch() 287 | switch.set_valign(Gtk.Align.CENTER) 288 | switch.set_halign(Gtk.Align.END) 289 | 290 | javaSwitch = Gtk.Switch() 291 | pySwitch = Gtk.Switch() 292 | 293 | titleLabel = Gtk.Label() 294 | titleLabel.set_halign(Gtk.Align.START) 295 | titleLabel.set_valign(Gtk.Align.CENTER) 296 | titleLabel.set_text(sysInterp) 297 | 298 | sysInterpretersBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) 299 | sysInterpretersBox.set_halign(Gtk.Align.START) 300 | sysInterpretersBox.set_valign(Gtk.Align.CENTER) 301 | 302 | if 'python' in os.listdir('/usr/bin'): 303 | pyBox = Gtk.Box(spacing=6) 304 | pyLabel = Gtk.Label() 305 | pyVersion = os.popen('/usr/bin/python --version').read() 306 | 307 | pySwitch.set_valign(Gtk.Align.CENTER) 308 | # pyCheck.connect('state-set', self.enableOption, None, pyCheck) 309 | 310 | pyLabel.set_valign(Gtk.Align.CENTER) 311 | pyLabel.set_label(str(pyVersion).split('\n')[0]) 312 | 313 | pyBox.append(pySwitch) 314 | pyBox.append(pyLabel) 315 | 316 | sysInterpretersBox.append(pyBox) 317 | 318 | if 'java' in os.listdir('/usr/bin'): 319 | javaBox = Gtk.Box(spacing=6) 320 | javaLabel = Gtk.Label() 321 | javaVersion = os.popen('/usr/bin/java --version').read() 322 | 323 | javaSwitch.set_valign(Gtk.Align.CENTER) 324 | # javaCheck.connect('state-set', self.enableOption, None, pyCheck) 325 | 326 | javaLabel.set_valign(Gtk.Align.CENTER) 327 | javaLabel.set_label(str(javaVersion).split('\n')[0]) 328 | 329 | javaBox.append(javaSwitch) 330 | javaBox.append(javaLabel) 331 | 332 | sysInterpretersBox.append(javaBox) 333 | 334 | 335 | fileBox = Gtk.Box() 336 | fileLabel = Gtk.Label(label=selectFiles) 337 | fileLabel.set_size_request(110, -1) 338 | fileLabel.set_xalign(0) 339 | 340 | fileButton = browseButton(fileChooser, sysInterp, False, selItemsLabel, page) 341 | fileButton.set_valign(Gtk.Align.CENTER) 342 | 343 | fileBox.append(fileLabel) 344 | fileBox.append(fileButton) 345 | 346 | 347 | folderBox = Gtk.Box() 348 | folderLabel = Gtk.Label(label=selectFolders) 349 | folderLabel.set_size_request(110, -1) 350 | folderLabel.set_xalign(0) 351 | 352 | folderButton = browseButton(fileChooser, sysInterp, True, selItemsLabel, page) 353 | folderButton.set_valign(Gtk.Align.CENTER) 354 | 355 | folderBox.append(folderLabel) 356 | folderBox.append(folderButton) 357 | 358 | browseLabel = Gtk.Label() 359 | browseLabel.set_margin_top(6) 360 | browseLabel.set_markup(browseInterp) 361 | browseLabel.set_halign(Gtk.Align.START) 362 | browseLabel.set_valign(Gtk.Align.CENTER) 363 | 364 | selectedFileView = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) 365 | selectedFileView.append(Gtk.Label(label=selectedItems)) 366 | selectedFileView.set_margin_top(6) 367 | selectedFileView.append(selItemsLabel) 368 | selectedFileView.set_halign(Gtk.Align.START) 369 | 370 | leftBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) 371 | leftBox.set_hexpand(True) 372 | leftBox.set_margin_start(12) 373 | leftBox.append(titleLabel) 374 | leftBox.append(sysInterpretersBox) 375 | leftBox.append(browseLabel) 376 | leftBox.append(fileBox) 377 | leftBox.append(folderBox) 378 | leftBox.append(selectedFileView) 379 | 380 | expandableLayout = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 381 | expandableLayout.append(leftBox) 382 | 383 | box = Adw.PreferencesGroup.new() 384 | 385 | adw_expander_row.add_row(child=expandableLayout) 386 | adw_expander_row.set_title(title) 387 | 388 | box.add(adw_expander_row) 389 | 390 | advancedRow.append(titleLabel) 391 | 392 | dependeciesSwitches.append(pySwitch) 393 | dependeciesSwitches.append(javaSwitch) 394 | 395 | return adw_expander_row 396 | 397 | def newTemplateRow(self, text): 398 | 399 | button = Gtk.Button(label=text) 400 | button.set_size_request(120, -1) 401 | button.set_hexpand(True) 402 | button.set_halign(Gtk.Align.CENTER) 403 | button.set_margin_bottom(6) 404 | button.set_margin_top(6) 405 | button.connect('clicked', self.fillTemplateInfo) 406 | 407 | row = Adw.ActionRow.new() 408 | row.set_child(button) 409 | 410 | return row 411 | 412 | def fillTemplateInfo(self, button): 413 | nameEntry = normalRow[0] 414 | exeEntry = normalRow[1] 415 | iconEntry = normalRow[2] 416 | typeEntry = normalRow[3] 417 | categoryEntry = normalRow[4] 418 | 419 | if flatpak: 420 | tPath = "/app/bin/Immagini/ui/" 421 | iPath = '/app/share/icons/hicolor/scalable/apps/' 422 | else: 423 | tPath = "Immagini/ui/" 424 | iPath = 'share/icons/hicolor/scalable/apps/' 425 | 426 | nameEntry.set_text(globalTemplate) 427 | exeEntry.set_text(tPath + 'template.py') 428 | iconEntry.set_text(iPath + 'dev.salaniLeo.immagini.svg') 429 | typeEntry.set_text(globalApplication) 430 | categoryEntry.set_text(globalUtility) 431 | 432 | def enableOption(self, switch, state, row, button): 433 | if state == True: 434 | if row != None: 435 | row.get_style_context().remove_class(class_name='error') 436 | row.set_editable(True) 437 | button.set_sensitive(True) 438 | elif state == False: 439 | if row != None: 440 | row.get_style_context().add_class(class_name='error') 441 | row.set_editable(False) 442 | button.set_sensitive(False) 443 | 444 | 445 | def initCreation(self, refresh, mainWindow): 446 | createThread = threading.Thread(target=newImageBox.createImage, args=(self, refresh, mainWindow), daemon=True, name='createThread') 447 | createThread.start() 448 | createThread.join() 449 | 450 | def createImage(self, refresh, mainWindow): 451 | currentThread = threading.current_thread() 452 | nameText = normalRow[0].get_text() 453 | exeText = normalRow[1].get_text() 454 | iconText = normalRow[2].get_text() 455 | typeText = normalRow[3].get_text() 456 | categoryText = normalRow[4].get_text() 457 | 458 | libraryPath = settings.get_string("librarypath") 459 | 460 | if "~" in libraryPath: 461 | libraryPath = libraryPath.replace("~", str(pathlib.Path.home())) 462 | 463 | uselibraryPath = settings.get_boolean("uselibrarypath") 464 | removeappdir = settings.get_boolean("removeappdir") 465 | 466 | if not uselibraryPath: 467 | outputText = normalRow[5].get_text() 468 | else: 469 | outputText = libraryPath 470 | 471 | librariesText = advancedRow[0].get_text() 472 | parentFolderText = advancedRow[1].get_text() 473 | appRunText = advancedRow[2].get_text() 474 | 475 | librariesSwitch = advancedSwitch[0] 476 | parentFolderSwitch = advancedSwitch[1] 477 | appRunSwitch = advancedSwitch[2] 478 | 479 | pythonSwitch = dependeciesSwitches[0] 480 | javaSwitch = dependeciesSwitches[1] 481 | 482 | if None or "" in (nameText,exeText,iconText,typeText,categoryText,outputText): 483 | 484 | throwError(self, pleaseFillInAllInfoSubtitle, pleaseFillInAllInfoTitle, mainWindow, currentThread) 485 | 486 | else: 487 | 488 | folderName = nameText + ".AppDir" 489 | 490 | if(parentFolderSwitch.get_active()): 491 | folderMode = True 492 | else: 493 | folderMode = False 494 | 495 | if(appRunSwitch.get_active()): 496 | customAppRun = True 497 | else: 498 | customAppRun = False 499 | 500 | if(librariesSwitch.get_active()): 501 | includeLibraries = True 502 | else: 503 | includeLibraries = False 504 | 505 | if(pythonSwitch.get_active()): 506 | includePython = True 507 | else: 508 | includePython = False 509 | 510 | if(javaSwitch.get_active()): 511 | includeJava = True 512 | else: 513 | includeJava = False 514 | 515 | includeInterpreters = [] 516 | includeInterpreters.append(includePython) 517 | includeInterpreters.append(includeJava) 518 | 519 | if os.path.exists(iconText) and os.path.exists(exeText): 520 | 521 | AppDir = outputText + "/" + folderName 522 | 523 | if os.path.exists(AppDir): 524 | folderExistsError(None, folderName + folderAlreadyExistsSubtitle, folderAlreadyExistsTitle, mainWindow, AppDir) 525 | else: 526 | startCreatingImage( 527 | 528 | nameText, 529 | exeText, 530 | iconText, 531 | typeText, 532 | categoryText, 533 | outputText, 534 | customAppRun, 535 | appRunText, 536 | folderMode, 537 | parentFolderText, 538 | includeLibraries, 539 | librariesText, 540 | includeInterpreters, 541 | flatpak, 542 | self, 543 | mainWindow 544 | 545 | ) 546 | 547 | elif not os.path.exists(exeText): 548 | throwError(None, exeText + ' ' + invalidExeTitle, invalidExeSubtitle, mainWindow) 549 | 550 | elif not os.path.exists(iconText): 551 | throwError(None, iconText + ' ' + invalidIconTitle, invalidIconSubtitle, mainWindow) 552 | 553 | if removeappdir: 554 | try: 555 | shutil.rmtree(outputText + "/" + nameText + ".AppDir") 556 | except: 557 | None 558 | 559 | refresh(None, None, None) 560 | 561 | 562 | def getFlatpak(isFlatpak): 563 | global flatpak 564 | flatpak = isFlatpak 565 | 566 | class convertFlatpak(Gtk.Box): 567 | def __init__(self, mainWindow, application, **kwargs): 568 | super().__init__(**kwargs) 569 | self.mainBox = Gtk.Box() 570 | self.stack = Gtk.Stack() 571 | self.applications = [] 572 | self.flatpakLocation = f'{pathlib.Path.home()}/.var/flatpak/app' 573 | 574 | self.scrolled_window = Gtk.ScrolledWindow.new() 575 | self.scrolled_window.set_vexpand(True) 576 | self.scrolled_window.set_hexpand(True) 577 | self.stack.add_child(self.scrolled_window) 578 | self.stack.set_transition_type( 579 | transition=Gtk.StackTransitionType.SLIDE_LEFT_RIGHT 580 | ) 581 | self.mainBox.append(self.stack) 582 | 583 | self.installedFlatpaks = Gtk.Label() 584 | self.installedFlatpaks.set_markup(f'{installedFlatpaks}') 585 | self.installedFlatpaks.set_halign(Gtk.Align.START) 586 | 587 | self.flowbox = Gtk.FlowBox.new() 588 | self.flowbox.set_margin_top(margin=12) 589 | self.flowbox.set_margin_end(margin=12) 590 | self.flowbox.set_margin_bottom(margin=12) 591 | self.flowbox.set_margin_start(margin=12) 592 | self.flowbox.set_valign(align=Gtk.Align.START) 593 | self.flowbox.set_max_children_per_line(n_children=5) 594 | self.flowbox.set_selection_mode(mode=Gtk.SelectionMode.NONE) 595 | self.flowbox.insert(self.installedFlatpaks, 0) 596 | self.scrolled_window.set_child(child=self.flowbox) 597 | 598 | n = 1 599 | for app in os.listdir(self.flatpakLocation): 600 | self.applications.append(app) 601 | self.button = Gtk.Button.new_with_label(label=f'{app}') 602 | self.button.connect('clicked', self.createFromFlatpakPage, n-1) 603 | self.flowbox.insert(widget=self.button, position=n) 604 | n = n + 1 605 | 606 | self.append(self.mainBox) 607 | 608 | 609 | def createFromFlatpakPage(self, button, appNumber): 610 | self.imageLoc = settings.get_string('librarypath') 611 | self.appId = self.applications[appNumber] 612 | self.appName = self.appId.split('.')[-1] 613 | self.currentLocation = f'{self.flatpakLocation}/{self.appId}' 614 | self.filesLoc = f'/current/active/files' 615 | self.sharedLoc = f'{self.appId}/current/active/export' 616 | self.jsonLoc = f'{self.currentLocation}{self.filesLoc}/manifest.json' 617 | self.flatpak = flatpak 618 | self.page = page 619 | 620 | mainBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) 621 | topBox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6) 622 | centerBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) 623 | bottomBox = Gtk.Box() 624 | flatpakInfoBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) 625 | infoLabel = Gtk.Label() 626 | nameLabel = Gtk.Label() 627 | binaryLabel = Gtk.Label() 628 | iconLabel = Gtk.Label() 629 | desktopLabel = Gtk.Label() 630 | shareLabel = Gtk.Label() 631 | libLabel = Gtk.Label() 632 | convertButton = Gtk.Button() 633 | 634 | self.readFlatpakManifest() 635 | self.findIconLoc() 636 | self.getApplicationFolders() 637 | 638 | self.binaryName = f'{self.appId}{self.filesLoc}/bin/{self.command}' 639 | self.iconName = f'{self.iconDir}{self.icon}' 640 | 641 | page.set_title(self.appId) 642 | 643 | self.backButton = Gtk.Button.new_from_icon_name("pan-start-symbolic") 644 | self.backButton.connect("clicked", self.goBack) 645 | 646 | topBox.append(self.backButton) 647 | 648 | self.stack.add_child(mainBox) 649 | self.stack.set_visible_child(mainBox) 650 | 651 | infoLabel.set_markup(f'{globalInfo}:') 652 | infoLabel.set_margin_bottom(12) 653 | infoLabel.set_halign(Gtk.Align.START) 654 | 655 | nameLabel.set_markup(f'{globalName}: {self.appName}') 656 | nameLabel.set_halign(Gtk.Align.START) 657 | 658 | binaryLabel.set_markup(f'{globalExecutable}: {self.binaryName}') 659 | binaryLabel.set_halign(Gtk.Align.START) 660 | binaryLabel.set_wrap(True) 661 | 662 | iconLabel.set_markup(f'{globalIcon}: {self.iconName}') 663 | iconLabel.set_halign(Gtk.Align.START) 664 | iconLabel.set_wrap(True) 665 | 666 | desktopLabel.set_markup(f'{globalDesktop}: {self.desktopFileLoc}') 667 | desktopLabel.set_halign(Gtk.Align.START) 668 | desktopLabel.set_wrap(True) 669 | 670 | shareLabel.set_markup(f'{globalShare}: {self.shareLoc}') 671 | shareLabel.set_size_request(100,-1) 672 | shareLabel.set_halign(Gtk.Align.START) 673 | shareLabel.set_wrap(True) 674 | 675 | libLabel.set_markup(f'{globalLib}: {self.libLoc}') 676 | libLabel.set_halign(Gtk.Align.START) 677 | libLabel.set_wrap(True) 678 | 679 | convertButton.connect('clicked', self.startConverting) 680 | convertButton.set_label(convertButtonLabel) 681 | convertButton.set_margin_top(12) 682 | convertButton.set_size_request(150, -1) 683 | convertButton.set_hexpand(False) 684 | 685 | flatpakInfoBox.append(infoLabel) 686 | flatpakInfoBox.append(nameLabel) 687 | flatpakInfoBox.append(binaryLabel) 688 | flatpakInfoBox.append(iconLabel) 689 | flatpakInfoBox.append(desktopLabel) 690 | flatpakInfoBox.append(shareLabel) 691 | flatpakInfoBox.append(libLabel) 692 | flatpakInfoBox.set_halign(Gtk.Align.START) 693 | flatpakInfoBox.set_hexpand(True) 694 | flatpakInfoBox.set_margin_top(12) 695 | flatpakInfoBox.set_margin_bottom(12) 696 | flatpakInfoBox.set_margin_end(12) 697 | 698 | centerBox.set_margin_top(12) 699 | centerBox.set_margin_bottom(12) 700 | centerBox.append(flatpakInfoBox) 701 | centerBox.set_halign(Gtk.Align.START) 702 | 703 | bottomBox.append(convertButton) 704 | 705 | mainBox.append(topBox) 706 | mainBox.append(centerBox) 707 | mainBox.append(bottomBox) 708 | 709 | def readFlatpakManifest(self): 710 | with open(self.jsonLoc, 'r') as f: 711 | d = json.load(f) 712 | try: 713 | self.command = d['command'] 714 | except: 715 | maybeBinary = f'{self.currentLocation}{self.filesLoc}/bin/{self.appName}' 716 | if os.path.exists(maybeBinary): 717 | self.command = f'{maybeBinary} ({executableNotProvidedByManifest})' 718 | else: 719 | self.command = f'{executableNotFoundInsideFlatpak}' 720 | 721 | 722 | def findIconLoc(self): 723 | iconDir = f'{self.currentLocation}{self.filesLoc}/share/icons/hicolor' 724 | icon128x128Dir = f'{iconDir}/128x128' 725 | iconSvgDir = f'{iconDir}/scalable' 726 | 727 | self.icon = "Can't find an icon" 728 | if os.path.exists(icon128x128Dir): 729 | self.iconDir = f'{self.appId}{self.filesLoc}/share/icons/hicolor/128x128/apps/' 730 | self.icon = f'{self.appId}.png' 731 | elif os.path.exists(iconSvgDir): 732 | self.iconDir = f'{self.appId}{self.filesLoc}/share/icons/hicolor/scalable/apps/' 733 | self.icon = f'{self.appId}.svg' 734 | 735 | 736 | def getApplicationFolders(self): 737 | self.binLoc = f'{self.appId}{self.filesLoc}/bin' 738 | self.shareLoc = f'{self.appId}{self.filesLoc}/share' 739 | self.libLoc = f'{self.appId}{self.filesLoc}/lib' 740 | self.desktopFileLoc = f'{self.sharedLoc}/share/applications/{self.appId}.desktop' 741 | 742 | def goBack(self, button): 743 | self.stack.set_visible_child(self.scrolled_window) 744 | page.set_title(globalNewImageTitle) 745 | 746 | def startConverting(self, button): 747 | 748 | libraryPath = settings.get_string("librarypath") 749 | if "~" in libraryPath: 750 | libraryPath = libraryPath.replace("~", str(pathlib.Path.home())) 751 | 752 | startConvertingFlatpak(page, libraryPath, self.appId, f'{self.flatpakLocation}/{self.desktopFileLoc}', self) 753 | 754 | 755 | flatpak = None 756 | normalRow = [] 757 | advancedRow = [] 758 | advancedSwitch = [] --------------------------------------------------------------------------------