Compare commits

..

6 Commits

9 changed files with 109 additions and 112 deletions

View File

@ -1,14 +1,16 @@
Appname:=$(shell cat appname.txt)
prefix:=/usr
temp:=/tmp/fpm-jolla
sourcePath:=$(shell pwd)
output:=$(sourcePath)/output
dependencies=$(shell for file in `cat dependencies.txt`;do echo "-d "$${file};done;)
version:=0.4.5
iteration:=5
version:=0.5.0
iteration:=0
fpmExec:=$(shell echo "$${FPM_BIN:=fpm}")
all: clean build-tmp rpm-i686 rpm-jolla rpm-aarch64
build-tmp:
mkdir -p $(output)
mkdir -p $(temp)/usr/share/applications
mkdir -p $(temp)/usr/share/icons/hicolor/86x86/apps
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
install -m 755 ./dat/$(Appname).sh $(temp)/usr/bin/$(Appname)
rpm-i686: arch:=i686
rpm-i686: rpmname:=$(Appname)-$(version)-$(iteration).$(arch).rpm
rpm-i686: build-tmp
cd $(temp);fpm -f -s dir -t rpm \
build: rpmname=$(Appname)-$(version)-$(iteration).$(arch).rpm
build: build-tmp
cd $(temp); \
$(fpmExec) -f -s dir -t rpm \
--after-install $(sourcePath)/dat/upgradeScript.sh \
--after-remove $(sourcePath)/dat/removeScript.sh \
--rpm-changelog $(sourcePath)/changelog.txt \
@ -33,39 +35,17 @@ rpm-i686: build-tmp
-p $(temp)/$(rpmname) \
-n $(Appname) \
-a $(arch) \
--prefix / *
--prefix / *; \
mv $(temp)/*.rpm $(output)
rpm-jolla: arch:=armv7hl
rpm-jolla: rpmname:=$(Appname)-$(version)-$(iteration).$(arch).rpm
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-i686: arch=i686
rpm-i686: build
rpm-aarch64: arch:=aarch64
rpm-aarch64: rpmname:=$(Appname)-$(version)-$(iteration).$(arch).rpm
rpm-aarch64: 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-jolla: arch=armv7hl
rpm-jolla: build
rpm-aarch64: arch=aarch64
rpm-aarch64: build
clean:
rm -rf $(temp)

View File

@ -1,5 +1,7 @@
# 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
## 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/)
## 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. Build the package.
1. Build the package:
1. armv7hl: `make rpm-jolla`
1. i686: `make rpm-virt`
1. i686: `make rpm-i686`
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
- [x] Support to aarch64 arquitecture
- [x] Choice non-transparent color to fill the empty spaces
- [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 restore the original icon
- [ ] Make all icons in the main grid the same size

View File

@ -4,7 +4,8 @@ X-Nemo-Application-Type=silica-qt5
Name=Muchkin
Icon=harbour-muchkin
Exec=sailfish-qml harbour-muchkin
[X-Sailjail]
Sandboxing=Disabled
OrganizationName=org.kirbylife
ApplicationName=harbour-muchkin
OrganizationName=dev.kirbylife
ApplicationName=harbour-muchkin

View File

@ -1,5 +1,5 @@
#!/bin/sh
echo "removing /usr/share/harbour-muchkin"
rm -rf /usr/share/harbour-muchkin
# echo "removing /usr/share/harbour-muchkin"
# rm -rf /usr/share/harbour-muchkin

View File

@ -1,5 +1,7 @@
libsailfishapp-launcher
sailfish-svg2png
pyotherside-qml-plugin-python3-qt5
python3-base
python3-imaging
python3-requests
python3-lxml

View File

@ -11,28 +11,28 @@ Page {
anchors.top: header.bottom
anchors.horizontalCenter: parent.horizontalCenter
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
}
Button {
id: btnCode
anchors.bottom: btnTwitter.top
anchors.bottom: btnMastodon.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottomMargin: 50
text: "Code"
onClicked: {
Qt.openUrlExternally("https://gitlab.com/kirbylife/harbour-muchkin")
Qt.openUrlExternally("https://git.kirbylife.dev/kirbylife/harbour-muchkin")
}
}
Button {
id: btnTwitter
id: btnMastodon
anchors.bottom: btnDonate.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottomMargin: 50
text: "Twitter"
text: "Mastodon"
onClicked: {
Qt.openUrlExternally("https://twitter.com/kirbylife")
Qt.openUrlExternally("https://mstdn.mx/@kirbylife")
}
}
Button {

View File

@ -47,7 +47,7 @@ Page {
activated = !activated
iconEditor.corners[idCell] = activated
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
})
})
@ -62,10 +62,30 @@ Page {
height: width
}
Button {
Slider {
id: size
anchors.top: icon.bottom
anchors.horizontalCenter: parent.horizontalCenter
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"
onClicked: {
if(iconEditor.attrs.old_icon === undefined) {
@ -89,7 +109,7 @@ Page {
Component.onCompleted: {
py.addImportPath(Qt.resolvedUrl("../src"));
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
})
})

View File

@ -49,6 +49,8 @@ Page {
Image {
anchors.centerIn: parent
source: attrs.Icon
width: parent.width
height: width
}
onClicked: {

View File

@ -4,34 +4,59 @@ from PIL.Image import Image as ImageType
from io import BytesIO
from glob import glob
from collections import Counter
from subprocess import getstatusoutput
from urllib.parse import urlparse
from functools import lru_cache
import requests
import base64
import os
import shutil
import logging
import tempfile
ICON_SIZE = (256, 256)
logging_filename = os.path.join(os.path.expanduser("~"),
".local",
"share",
"org.kirbylife",
"dev.kirbylife",
"harbour-muchkin",
"muchkin.log")
os.makedirs(os.path.dirname(logging_filename), exist_ok=True)
logging.basicConfig(filename=logging_filename, filemode="w", level=logging.DEBUG)
@lru_cache(maxsize=50)
def download_icon(url) -> ImageType:
response = requests.get(url)
img = Image.open(BytesIO(response.content))
img.thumbnail(ICON_SIZE)
img = img.convert("RGBA")
return img
@lru_cache(maxsize=50)
def base64_to_img(base64_bytes: bytes) -> ImageType:
img_bytes = base64.b64decode(base64_bytes)
img_buffer = BytesIO(img_bytes)
img = Image.open(img_buffer)
img.thumbnail(ICON_SIZE)
img = img.convert("RGBA")
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):
counter = Counter()
width, height = img.size
@ -42,9 +67,12 @@ def avg_colors(img):
counter[pixel] += 1
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.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
def crop_to_circle(im, template):
@ -70,9 +98,7 @@ def parse_file(desktop_path):
output = {}
with open(desktop_path, "r") as f:
for line in f:
if not line:
continue
if line.startswith("["):
if not line or line.startswith("["):
continue
key, value = line.split("=", 1)
output[key] = value.strip()
@ -97,21 +123,23 @@ def get_web_icons():
return list(map(parse_file, apps))
def sailify(raw_str, pattern):
try:
# New versions of Sailfish has the url on the icons
img = download_icon(raw_str)
logging.info("Downloaded from url: " + raw_str)
except requests.exceptions.InvalidSchema:
def sailify(raw_str, pattern, size) -> str:
url_parsed = urlparse(raw_str)
if url_parsed.scheme == "data":
# The old ones converted the icon to base64
base64_bytes = raw_str.replace("data:image/png;base64,", "", 1).encode()
img = base64_to_img(base64_bytes)
logging.info("Converted from base64")
except Exception as e:
logging.error(e)
raise e
# New versions of Sailfish has the url on the icons
elif url_parsed.path.split("/")[-1].split(".")[-1].upper() == "SVG":
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)
img = add_background(img, bg_tuple)
img = add_background(img, bg_tuple, size)
img = crop_to_circle(img, pattern)
output_buffer = BytesIO()
img.save(output_buffer, format="PNG")
@ -133,43 +161,3 @@ def save_icon(app):
f.write(new_content)
logging.info("Icon saved on: " + app["path"])
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()