Compare commits
	
		
			6 Commits 
		
	
	
		
			55d4d67f1c
			...
			f4c8564f75
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						f4c8564f75 | |
| 
							
							
								
								 | 
						ab970dd485 | |
| 
							
							
								
								 | 
						ef2fcc80a5 | |
| 
							
							
								
								 | 
						a17a764f3a | |
| 
							
							
								
								 | 
						d9792187fd | |
| 
							
							
								
								 | 
						bb13ef5937 | 
							
								
								
									
										56
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										56
									
								
								Makefile
								
								
								
								
							| 
						 | 
					@ -1,14 +1,16 @@
 | 
				
			||||||
Appname:=$(shell cat appname.txt)
 | 
					Appname:=$(shell cat appname.txt)
 | 
				
			||||||
prefix:=/usr
 | 
					 | 
				
			||||||
temp:=/tmp/fpm-jolla
 | 
					temp:=/tmp/fpm-jolla
 | 
				
			||||||
sourcePath:=$(shell pwd)
 | 
					sourcePath:=$(shell pwd)
 | 
				
			||||||
 | 
					output:=$(sourcePath)/output
 | 
				
			||||||
dependencies=$(shell for file in `cat dependencies.txt`;do echo "-d "$${file};done;)
 | 
					dependencies=$(shell for file in `cat dependencies.txt`;do echo "-d "$${file};done;)
 | 
				
			||||||
version:=0.4.5
 | 
					version:=0.5.0
 | 
				
			||||||
iteration:=5
 | 
					iteration:=0
 | 
				
			||||||
 | 
					fpmExec:=$(shell echo "$${FPM_BIN:=fpm}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
all: clean build-tmp rpm-i686 rpm-jolla rpm-aarch64
 | 
					all: clean build-tmp rpm-i686 rpm-jolla rpm-aarch64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
build-tmp:
 | 
					build-tmp:
 | 
				
			||||||
 | 
						mkdir -p $(output)
 | 
				
			||||||
	mkdir -p $(temp)/usr/share/applications
 | 
						mkdir -p $(temp)/usr/share/applications
 | 
				
			||||||
	mkdir -p $(temp)/usr/share/icons/hicolor/86x86/apps
 | 
						mkdir -p $(temp)/usr/share/icons/hicolor/86x86/apps
 | 
				
			||||||
	mkdir -p $(temp)/usr/share/$(Appname)/src
 | 
						mkdir -p $(temp)/usr/share/$(Appname)/src
 | 
				
			||||||
| 
						 | 
					@ -19,10 +21,10 @@ build-tmp:
 | 
				
			||||||
	cp -ar ./dat/appicon.png $(temp)/usr/share/icons/hicolor/86x86/apps/$(Appname).png
 | 
						cp -ar ./dat/appicon.png $(temp)/usr/share/icons/hicolor/86x86/apps/$(Appname).png
 | 
				
			||||||
	install -m 755 ./dat/$(Appname).sh $(temp)/usr/bin/$(Appname)
 | 
						install -m 755 ./dat/$(Appname).sh $(temp)/usr/bin/$(Appname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rpm-i686: arch:=i686
 | 
					build: rpmname=$(Appname)-$(version)-$(iteration).$(arch).rpm
 | 
				
			||||||
rpm-i686: rpmname:=$(Appname)-$(version)-$(iteration).$(arch).rpm
 | 
					build: build-tmp
 | 
				
			||||||
rpm-i686: build-tmp
 | 
						cd $(temp); \
 | 
				
			||||||
	cd $(temp);fpm -f -s dir -t rpm \
 | 
						$(fpmExec) -f -s dir -t rpm \
 | 
				
			||||||
		--after-install $(sourcePath)/dat/upgradeScript.sh \
 | 
							--after-install $(sourcePath)/dat/upgradeScript.sh \
 | 
				
			||||||
		--after-remove $(sourcePath)/dat/removeScript.sh \
 | 
							--after-remove $(sourcePath)/dat/removeScript.sh \
 | 
				
			||||||
		--rpm-changelog $(sourcePath)/changelog.txt \
 | 
							--rpm-changelog $(sourcePath)/changelog.txt \
 | 
				
			||||||
| 
						 | 
					@ -33,39 +35,17 @@ rpm-i686: build-tmp
 | 
				
			||||||
		-p $(temp)/$(rpmname) \
 | 
							-p $(temp)/$(rpmname) \
 | 
				
			||||||
		-n $(Appname) \
 | 
							-n $(Appname) \
 | 
				
			||||||
		-a $(arch) \
 | 
							-a $(arch) \
 | 
				
			||||||
		--prefix / *
 | 
							--prefix / *; \
 | 
				
			||||||
 | 
						mv $(temp)/*.rpm $(output)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rpm-jolla: arch:=armv7hl
 | 
					rpm-i686: arch=i686
 | 
				
			||||||
rpm-jolla: rpmname:=$(Appname)-$(version)-$(iteration).$(arch).rpm
 | 
					rpm-i686: build
 | 
				
			||||||
rpm-jolla: build-tmp
 | 
					 | 
				
			||||||
	cd $(temp);fpm -f -s dir -t rpm \
 | 
					 | 
				
			||||||
		--after-install $(sourcePath)/dat/upgradeScript.sh \
 | 
					 | 
				
			||||||
		--after-remove $(sourcePath)/dat/removeScript.sh \
 | 
					 | 
				
			||||||
		--rpm-changelog $(sourcePath)/changelog.txt \
 | 
					 | 
				
			||||||
		--directories "/usr/share/$(Appname)" \
 | 
					 | 
				
			||||||
		-v $(version) \
 | 
					 | 
				
			||||||
		--iteration $(iteration) \
 | 
					 | 
				
			||||||
		$(dependencies) \
 | 
					 | 
				
			||||||
		-p $(temp)/$(rpmname) \
 | 
					 | 
				
			||||||
		-n $(Appname) \
 | 
					 | 
				
			||||||
		-a $(arch) \
 | 
					 | 
				
			||||||
		--prefix / *
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
rpm-aarch64: arch:=aarch64
 | 
					rpm-jolla: arch=armv7hl
 | 
				
			||||||
rpm-aarch64: rpmname:=$(Appname)-$(version)-$(iteration).$(arch).rpm
 | 
					rpm-jolla: build
 | 
				
			||||||
rpm-aarch64: build-tmp
 | 
					
 | 
				
			||||||
	cd $(temp);fpm -f -s dir -t rpm \
 | 
					rpm-aarch64: arch=aarch64
 | 
				
			||||||
		--after-install $(sourcePath)/dat/upgradeScript.sh \
 | 
					rpm-aarch64: build
 | 
				
			||||||
		--after-remove $(sourcePath)/dat/removeScript.sh \
 | 
					 | 
				
			||||||
		--rpm-changelog $(sourcePath)/changelog.txt \
 | 
					 | 
				
			||||||
		--directories "/usr/share/$(Appname)" \
 | 
					 | 
				
			||||||
		-v $(version) \
 | 
					 | 
				
			||||||
		--iteration $(iteration) \
 | 
					 | 
				
			||||||
		$(dependencies) \
 | 
					 | 
				
			||||||
		-p $(temp)/$(rpmname) \
 | 
					 | 
				
			||||||
		-n $(Appname) \
 | 
					 | 
				
			||||||
		-a $(arch) \
 | 
					 | 
				
			||||||
		--prefix / *
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
clean:
 | 
					clean:
 | 
				
			||||||
	rm -rf $(temp)
 | 
						rm -rf $(temp)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								README.md
								
								
								
								
							
							
						
						
									
										14
									
								
								README.md
								
								
								
								
							| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
# Muchkin icons
 | 
					# Muchkin icons
 | 
				
			||||||
 | 
					
 | 
				
			||||||
==============
 | 
					==============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Make your webapps icons in the app box look better with the rest of your native apps by choosing whether the corners are rounded or pointed
 | 
					Make your webapps icons in the app box look better with the rest of your native apps by choosing whether the corners are rounded or pointed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Dependencies
 | 
					## Dependencies
 | 
				
			||||||
| 
						 | 
					@ -12,19 +14,21 @@ Make your webapps icons in the app box look better with the rest of your native
 | 
				
			||||||
- [rpm-tools](http://rpm.org/)
 | 
					- [rpm-tools](http://rpm.org/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Build your own RPM package
 | 
					## Build your own RPM package
 | 
				
			||||||
1. Clone the repository: `git clone https://gitlab.com/kirbylife/harbour-muchkin`
 | 
					1. Clone the repository: `git clone https://git.kirbylife.dev/kirbylife/harbour-muchkin`
 | 
				
			||||||
1. Go to the directory: `cd harbour-muchkin`
 | 
					1. Go to the directory: `cd harbour-muchkin`
 | 
				
			||||||
1. Build the package.
 | 
					1. Build the package:
 | 
				
			||||||
  1. armv7hl: `make rpm-jolla`
 | 
					  1. armv7hl: `make rpm-jolla`
 | 
				
			||||||
  1. i686: `make rpm-virt`
 | 
					  1. i686: `make rpm-i686`
 | 
				
			||||||
  1. aarch64: `make rpm-aarch64`
 | 
					  1. aarch64: `make rpm-aarch64`
 | 
				
			||||||
1. the .rpm file will be on `/tmp/fpm-jolla/`
 | 
					1. (if fpm is not in `PATH` or has a different name you can set the env var "FPM_BIN" with the path to the binary).
 | 
				
			||||||
 | 
					1. the .rpm file will be on `output/`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## TO-DO
 | 
					## TO-DO
 | 
				
			||||||
- [x] Support to aarch64 arquitecture
 | 
					- [x] Support to aarch64 arquitecture
 | 
				
			||||||
- [x] Choice non-transparent color to fill the empty spaces
 | 
					- [x] Choice non-transparent color to fill the empty spaces
 | 
				
			||||||
- [x] Fix the issue with sailjail
 | 
					- [x] Fix the issue with sailjail
 | 
				
			||||||
- [ ] Make betters Make commands
 | 
					- [x] Make betters Make commands
 | 
				
			||||||
 | 
					- [ ] Add SVG support
 | 
				
			||||||
- [ ] Add option to request favicon
 | 
					- [ ] Add option to request favicon
 | 
				
			||||||
- [ ] Add option to restore the original icon
 | 
					- [ ] Add option to restore the original icon
 | 
				
			||||||
- [ ] Make all icons in the main grid the same size
 | 
					- [ ] Make all icons in the main grid the same size
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,8 @@ X-Nemo-Application-Type=silica-qt5
 | 
				
			||||||
Name=Muchkin
 | 
					Name=Muchkin
 | 
				
			||||||
Icon=harbour-muchkin
 | 
					Icon=harbour-muchkin
 | 
				
			||||||
Exec=sailfish-qml harbour-muchkin
 | 
					Exec=sailfish-qml harbour-muchkin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[X-Sailjail]
 | 
					[X-Sailjail]
 | 
				
			||||||
Sandboxing=Disabled
 | 
					Sandboxing=Disabled
 | 
				
			||||||
OrganizationName=org.kirbylife
 | 
					OrganizationName=dev.kirbylife
 | 
				
			||||||
ApplicationName=harbour-muchkin
 | 
					ApplicationName=harbour-muchkin
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
#!/bin/sh
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "removing /usr/share/harbour-muchkin"
 | 
					# echo "removing /usr/share/harbour-muchkin"
 | 
				
			||||||
rm -rf /usr/share/harbour-muchkin
 | 
					# rm -rf /usr/share/harbour-muchkin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
libsailfishapp-launcher
 | 
					libsailfishapp-launcher
 | 
				
			||||||
 | 
					sailfish-svg2png
 | 
				
			||||||
pyotherside-qml-plugin-python3-qt5
 | 
					pyotherside-qml-plugin-python3-qt5
 | 
				
			||||||
python3-base
 | 
					python3-base
 | 
				
			||||||
python3-imaging
 | 
					python3-imaging
 | 
				
			||||||
python3-requests
 | 
					python3-requests
 | 
				
			||||||
 | 
					python3-lxml
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,28 +11,28 @@ Page {
 | 
				
			||||||
        anchors.top: header.bottom
 | 
					        anchors.top: header.bottom
 | 
				
			||||||
        anchors.horizontalCenter: parent.horizontalCenter
 | 
					        anchors.horizontalCenter: parent.horizontalCenter
 | 
				
			||||||
        width: parent.width
 | 
					        width: parent.width
 | 
				
			||||||
        text: "this application was created by\nkirbylife\nunder the GPL V2.0 license,\nanyone is free to view\nthe code and modify it."
 | 
					        text: "this application was created by\nkirbylife\nunder the GPL V3 license,\nanyone is free to view\nthe code and modify it."
 | 
				
			||||||
        truncationMode: TruncationMode.Elide
 | 
					        truncationMode: TruncationMode.Elide
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Button {
 | 
					    Button {
 | 
				
			||||||
        id: btnCode
 | 
					        id: btnCode
 | 
				
			||||||
        anchors.bottom: btnTwitter.top
 | 
					        anchors.bottom: btnMastodon.top
 | 
				
			||||||
        anchors.horizontalCenter: parent.horizontalCenter
 | 
					        anchors.horizontalCenter: parent.horizontalCenter
 | 
				
			||||||
        anchors.bottomMargin: 50
 | 
					        anchors.bottomMargin: 50
 | 
				
			||||||
        text: "Code"
 | 
					        text: "Code"
 | 
				
			||||||
        onClicked: {
 | 
					        onClicked: {
 | 
				
			||||||
            Qt.openUrlExternally("https://gitlab.com/kirbylife/harbour-muchkin")
 | 
					            Qt.openUrlExternally("https://git.kirbylife.dev/kirbylife/harbour-muchkin")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Button {
 | 
					    Button {
 | 
				
			||||||
        id: btnTwitter
 | 
					        id: btnMastodon
 | 
				
			||||||
        anchors.bottom: btnDonate.top
 | 
					        anchors.bottom: btnDonate.top
 | 
				
			||||||
        anchors.horizontalCenter: parent.horizontalCenter
 | 
					        anchors.horizontalCenter: parent.horizontalCenter
 | 
				
			||||||
        anchors.bottomMargin: 50
 | 
					        anchors.bottomMargin: 50
 | 
				
			||||||
        text: "Twitter"
 | 
					        text: "Mastodon"
 | 
				
			||||||
        onClicked: {
 | 
					        onClicked: {
 | 
				
			||||||
            Qt.openUrlExternally("https://twitter.com/kirbylife")
 | 
					            Qt.openUrlExternally("https://mstdn.mx/@kirbylife")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Button {
 | 
					    Button {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										26
									
								
								qml/Icon.qml
								
								
								
								
							
							
						
						
									
										26
									
								
								qml/Icon.qml
								
								
								
								
							| 
						 | 
					@ -47,7 +47,7 @@ Page {
 | 
				
			||||||
                activated = !activated
 | 
					                activated = !activated
 | 
				
			||||||
                iconEditor.corners[idCell] = activated
 | 
					                iconEditor.corners[idCell] = activated
 | 
				
			||||||
                py.importModule("main", function(){
 | 
					                py.importModule("main", function(){
 | 
				
			||||||
                    py.call("main.sailify", [(iconEditor.attrs.old_icon || iconEditor.attrs.Icon).toString(), iconEditor.corners], function(result){
 | 
					                    py.call("main.sailify", [(iconEditor.attrs.old_icon || iconEditor.attrs.Icon).toString(), iconEditor.corners, size.value], function(result){
 | 
				
			||||||
                        icon.source = result
 | 
					                        icon.source = result
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
| 
						 | 
					@ -62,10 +62,30 @@ Page {
 | 
				
			||||||
        height: width
 | 
					        height: width
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Button {
 | 
					    Slider {
 | 
				
			||||||
 | 
					        id: size
 | 
				
			||||||
        anchors.top: icon.bottom
 | 
					        anchors.top: icon.bottom
 | 
				
			||||||
        anchors.horizontalCenter: parent.horizontalCenter
 | 
					        anchors.horizontalCenter: parent.horizontalCenter
 | 
				
			||||||
        anchors.topMargin: 10
 | 
					        anchors.topMargin: 10
 | 
				
			||||||
 | 
					        label: "Size:"
 | 
				
			||||||
 | 
					        width: parent.width
 | 
				
			||||||
 | 
					        minimumValue: 0
 | 
				
			||||||
 | 
					        maximumValue: 100
 | 
				
			||||||
 | 
					        stepSize: 10
 | 
				
			||||||
 | 
					        value: 100
 | 
				
			||||||
 | 
					        onReleased: {
 | 
				
			||||||
 | 
					            py.importModule("main", function(){
 | 
				
			||||||
 | 
					                py.call("main.sailify", [(iconEditor.attrs.old_icon || iconEditor.attrs.Icon).toString(), iconEditor.corners, size.value], function(result){
 | 
				
			||||||
 | 
					                    icon.source = result
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Button {
 | 
				
			||||||
 | 
					        anchors.top: size.bottom
 | 
				
			||||||
 | 
					        anchors.horizontalCenter: parent.horizontalCenter
 | 
				
			||||||
 | 
					        anchors.topMargin: 20
 | 
				
			||||||
        text: "Save"
 | 
					        text: "Save"
 | 
				
			||||||
        onClicked: {
 | 
					        onClicked: {
 | 
				
			||||||
            if(iconEditor.attrs.old_icon === undefined) {
 | 
					            if(iconEditor.attrs.old_icon === undefined) {
 | 
				
			||||||
| 
						 | 
					@ -89,7 +109,7 @@ Page {
 | 
				
			||||||
        Component.onCompleted: {
 | 
					        Component.onCompleted: {
 | 
				
			||||||
            py.addImportPath(Qt.resolvedUrl("../src"));
 | 
					            py.addImportPath(Qt.resolvedUrl("../src"));
 | 
				
			||||||
            py.importModule("main", function(){
 | 
					            py.importModule("main", function(){
 | 
				
			||||||
                py.call("main.sailify", [(iconEditor.attrs.old_icon || iconEditor.attrs.Icon).toString(), [1, 1, 1, 1]], function(result){
 | 
					                py.call("main.sailify", [(iconEditor.attrs.old_icon || iconEditor.attrs.Icon).toString(), [1, 1, 1, 1], size.value], function(result){
 | 
				
			||||||
                    icon.source = result
 | 
					                    icon.source = result
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,8 @@ Page {
 | 
				
			||||||
                Image {
 | 
					                Image {
 | 
				
			||||||
                    anchors.centerIn: parent
 | 
					                    anchors.centerIn: parent
 | 
				
			||||||
                    source: attrs.Icon
 | 
					                    source: attrs.Icon
 | 
				
			||||||
 | 
					                    width: parent.width
 | 
				
			||||||
 | 
					                    height: width
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                onClicked: {
 | 
					                onClicked: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										100
									
								
								src/main.py
								
								
								
								
							
							
						
						
									
										100
									
								
								src/main.py
								
								
								
								
							| 
						 | 
					@ -4,34 +4,59 @@ from PIL.Image import Image as ImageType
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
from glob import glob
 | 
					from glob import glob
 | 
				
			||||||
from collections import Counter
 | 
					from collections import Counter
 | 
				
			||||||
 | 
					from subprocess import getstatusoutput
 | 
				
			||||||
 | 
					from urllib.parse import urlparse
 | 
				
			||||||
 | 
					from functools import lru_cache
 | 
				
			||||||
import requests
 | 
					import requests
 | 
				
			||||||
import base64
 | 
					import base64
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import shutil
 | 
					import shutil
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					import tempfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ICON_SIZE = (256, 256)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logging_filename = os.path.join(os.path.expanduser("~"),
 | 
					logging_filename = os.path.join(os.path.expanduser("~"),
 | 
				
			||||||
                                ".local",
 | 
					                                ".local",
 | 
				
			||||||
                                "share",
 | 
					                                "share",
 | 
				
			||||||
                                "org.kirbylife",
 | 
					                                "dev.kirbylife",
 | 
				
			||||||
                                "harbour-muchkin",
 | 
					                                "harbour-muchkin",
 | 
				
			||||||
                                "muchkin.log")
 | 
					                                "muchkin.log")
 | 
				
			||||||
os.makedirs(os.path.dirname(logging_filename), exist_ok=True)
 | 
					os.makedirs(os.path.dirname(logging_filename), exist_ok=True)
 | 
				
			||||||
logging.basicConfig(filename=logging_filename, filemode="w", level=logging.DEBUG)
 | 
					logging.basicConfig(filename=logging_filename, filemode="w", level=logging.DEBUG)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@lru_cache(maxsize=50)
 | 
				
			||||||
def download_icon(url) -> ImageType:
 | 
					def download_icon(url) -> ImageType:
 | 
				
			||||||
    response = requests.get(url)
 | 
					    response = requests.get(url)
 | 
				
			||||||
    img = Image.open(BytesIO(response.content))
 | 
					    img = Image.open(BytesIO(response.content))
 | 
				
			||||||
 | 
					    img.thumbnail(ICON_SIZE)
 | 
				
			||||||
    img = img.convert("RGBA")
 | 
					    img = img.convert("RGBA")
 | 
				
			||||||
    return img
 | 
					    return img
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@lru_cache(maxsize=50)
 | 
				
			||||||
def base64_to_img(base64_bytes: bytes) -> ImageType:
 | 
					def base64_to_img(base64_bytes: bytes) -> ImageType:
 | 
				
			||||||
    img_bytes = base64.b64decode(base64_bytes)
 | 
					    img_bytes = base64.b64decode(base64_bytes)
 | 
				
			||||||
    img_buffer = BytesIO(img_bytes)
 | 
					    img_buffer = BytesIO(img_bytes)
 | 
				
			||||||
    img = Image.open(img_buffer)
 | 
					    img = Image.open(img_buffer)
 | 
				
			||||||
 | 
					    img.thumbnail(ICON_SIZE)
 | 
				
			||||||
    img = img.convert("RGBA")
 | 
					    img = img.convert("RGBA")
 | 
				
			||||||
    return img
 | 
					    return img
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@lru_cache(maxsize=50)
 | 
				
			||||||
 | 
					def svg_to_img(svg_url: str) -> ImageType:
 | 
				
			||||||
 | 
					    response = requests.get(svg_url)
 | 
				
			||||||
 | 
					    with tempfile.TemporaryDirectory() as d:
 | 
				
			||||||
 | 
					        with open(os.path.join(d, "icon.svg"), "w") as f:
 | 
				
			||||||
 | 
					            f.write(response.text)
 | 
				
			||||||
 | 
					        status, output = getstatusoutput(f"sailfish_svg2png -z 16 {d} {d}")
 | 
				
			||||||
 | 
					        logging.info("Converted svg to png")
 | 
				
			||||||
 | 
					        logging.info(f"sailfish_svg2png status {status}: {output}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        img = Image.open(os.path.join(d, "icon.png"))
 | 
				
			||||||
 | 
					        img.thumbnail(ICON_SIZE)
 | 
				
			||||||
 | 
					        img = img.convert("RGBA")
 | 
				
			||||||
 | 
					    return img
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def avg_colors(img):
 | 
					def avg_colors(img):
 | 
				
			||||||
    counter = Counter()
 | 
					    counter = Counter()
 | 
				
			||||||
    width, height = img.size
 | 
					    width, height = img.size
 | 
				
			||||||
| 
						 | 
					@ -42,9 +67,12 @@ def avg_colors(img):
 | 
				
			||||||
                counter[pixel] += 1
 | 
					                counter[pixel] += 1
 | 
				
			||||||
    return counter.most_common(1)[0][0]
 | 
					    return counter.most_common(1)[0][0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def add_background(img: ImageType, bg_tuple: tuple) -> ImageType:
 | 
					def add_background(img: ImageType, bg_tuple: tuple, size: float) -> ImageType:
 | 
				
			||||||
 | 
					    img = img.copy()
 | 
				
			||||||
 | 
					    size = size / 100
 | 
				
			||||||
    bg = Image.new("RGBA", img.size, bg_tuple)
 | 
					    bg = Image.new("RGBA", img.size, bg_tuple)
 | 
				
			||||||
    bg.paste(img, (0, 0), img)
 | 
					    img.thumbnail((value * size for value in img.size))
 | 
				
			||||||
 | 
					    bg.paste(img, ((bg.size[0] - img.size[0]) // 2, (bg.size[1] - img.size[1]) // 2), img)
 | 
				
			||||||
    return bg
 | 
					    return bg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def crop_to_circle(im, template):
 | 
					def crop_to_circle(im, template):
 | 
				
			||||||
| 
						 | 
					@ -70,9 +98,7 @@ def parse_file(desktop_path):
 | 
				
			||||||
    output = {}
 | 
					    output = {}
 | 
				
			||||||
    with open(desktop_path, "r") as f:
 | 
					    with open(desktop_path, "r") as f:
 | 
				
			||||||
        for line in f:
 | 
					        for line in f:
 | 
				
			||||||
            if not line:
 | 
					            if not line or line.startswith("["):
 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            if line.startswith("["):
 | 
					 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            key, value = line.split("=", 1)
 | 
					            key, value = line.split("=", 1)
 | 
				
			||||||
            output[key] = value.strip()
 | 
					            output[key] = value.strip()
 | 
				
			||||||
| 
						 | 
					@ -97,21 +123,23 @@ def get_web_icons():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return list(map(parse_file, apps))
 | 
					    return list(map(parse_file, apps))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def sailify(raw_str, pattern):
 | 
					def sailify(raw_str, pattern, size) -> str:
 | 
				
			||||||
    try:
 | 
					    url_parsed = urlparse(raw_str)
 | 
				
			||||||
        # New versions of Sailfish has the url on the icons
 | 
					    if url_parsed.scheme == "data":
 | 
				
			||||||
        img = download_icon(raw_str)
 | 
					 | 
				
			||||||
        logging.info("Downloaded from url: " + raw_str)
 | 
					 | 
				
			||||||
    except requests.exceptions.InvalidSchema:
 | 
					 | 
				
			||||||
        # The old ones converted the icon to base64
 | 
					        # The old ones converted the icon to base64
 | 
				
			||||||
        base64_bytes = raw_str.replace("data:image/png;base64,", "", 1).encode()
 | 
					        base64_bytes = raw_str.replace("data:image/png;base64,", "", 1).encode()
 | 
				
			||||||
        img = base64_to_img(base64_bytes)
 | 
					        img = base64_to_img(base64_bytes)
 | 
				
			||||||
        logging.info("Converted from base64")
 | 
					        logging.info("Converted from base64")
 | 
				
			||||||
    except Exception as e:
 | 
					    # New versions of Sailfish has the url on the icons
 | 
				
			||||||
        logging.error(e)
 | 
					    elif url_parsed.path.split("/")[-1].split(".")[-1].upper() == "SVG":
 | 
				
			||||||
        raise e
 | 
					        img = svg_to_img(raw_str)
 | 
				
			||||||
 | 
					        logging.info("Downloaded from url: " + raw_str)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        img = download_icon(raw_str)
 | 
				
			||||||
 | 
					        logging.info("Downloaded from url: " + raw_str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bg_tuple = avg_colors(img)
 | 
					    bg_tuple = avg_colors(img)
 | 
				
			||||||
    img = add_background(img, bg_tuple)
 | 
					    img = add_background(img, bg_tuple, size)
 | 
				
			||||||
    img = crop_to_circle(img, pattern)
 | 
					    img = crop_to_circle(img, pattern)
 | 
				
			||||||
    output_buffer = BytesIO()
 | 
					    output_buffer = BytesIO()
 | 
				
			||||||
    img.save(output_buffer, format="PNG")
 | 
					    img.save(output_buffer, format="PNG")
 | 
				
			||||||
| 
						 | 
					@ -133,43 +161,3 @@ def save_icon(app):
 | 
				
			||||||
        f.write(new_content)
 | 
					        f.write(new_content)
 | 
				
			||||||
    logging.info("Icon saved on: " + app["path"])
 | 
					    logging.info("Icon saved on: " + app["path"])
 | 
				
			||||||
    return True
 | 
					    return True
 | 
				
			||||||
 | 
					 | 
				
			||||||
def main():
 | 
					 | 
				
			||||||
    import shutil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while True:
 | 
					 | 
				
			||||||
        apps = get_web_icons()
 | 
					 | 
				
			||||||
        while True:
 | 
					 | 
				
			||||||
            for n, app in enumerate(apps):
 | 
					 | 
				
			||||||
                print(f"{n}) {app['Name']}")
 | 
					 | 
				
			||||||
            index = input("select an application (the index):\n>>> ")
 | 
					 | 
				
			||||||
            index = int(index)
 | 
					 | 
				
			||||||
            if index >= len(apps):
 | 
					 | 
				
			||||||
                print("Select a valid index")
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            break
 | 
					 | 
				
			||||||
        app = apps[index]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if app["Icon"] == "icon-launcher-bookmark":
 | 
					 | 
				
			||||||
            print("this webapp is using the generic icon of a bookmark and not a favicon so it is not possible to modify")
 | 
					 | 
				
			||||||
            continue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        while True:
 | 
					 | 
				
			||||||
            pattern = input("Enter the pattern (0 = round, 1 = peak):\n>>> ")
 | 
					 | 
				
			||||||
            if len(pattern) != 4:
 | 
					 | 
				
			||||||
                print("it is necessary to enter 4 characters")
 | 
					 | 
				
			||||||
            pattern = tuple(map(int, pattern))
 | 
					 | 
				
			||||||
            new_icon = sailify(app.get("old_icon", app["Icon"]), pattern)
 | 
					 | 
				
			||||||
            # Backup the original .desktop
 | 
					 | 
				
			||||||
            shutil.copyfile(app["path"], app["path"] + "_backup")
 | 
					 | 
				
			||||||
            app["old_icon"] = app.get("old_icon", app["Icon"])
 | 
					 | 
				
			||||||
            app["Icon"] = new_icon
 | 
					 | 
				
			||||||
            new_content = deparse_file(app)
 | 
					 | 
				
			||||||
            with open(app["path"], "w") as f:
 | 
					 | 
				
			||||||
                f.write(new_content)
 | 
					 | 
				
			||||||
            print(f"{app['Name']} sailified correctly")
 | 
					 | 
				
			||||||
            break
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == "__main__":
 | 
					 | 
				
			||||||
    main()
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue