diff --git a/README.md b/README.md index a48a5c40..b6884065 100644 --- a/README.md +++ b/README.md @@ -51,11 +51,11 @@ The following prefixes are currently available to use: - [**FontAwesome**](https://fontawesome.com): - - FA 5.4.2 features 1,393 free icons in different styles: + - FA 5.6.3 features 1,480 free icons in different styles: - - `fa5` prefix has [151 icons in the "**regular**" style.](https://fontawesome.com/icons?d=gallery&s=regular&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2&m=free) - - `fa5s` prefix has [852 icons in the "**solid**" style.](https://fontawesome.com/icons?d=gallery&s=solid&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2&m=free) - - `fa5b` prefix has [390 icons of various **brands**.](https://fontawesome.com/icons?d=gallery&s=brands&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2&m=free) + - `fa5` prefix has [151 icons in the "**regular**" style.](https://fontawesome.com/icons?d=gallery&s=regular&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2,5.5.0,5.6.0,5.6.1,5.6.3&m=free) + - `fa5s` prefix has [915 icons in the "**solid**" style.](https://fontawesome.com/icons?d=gallery&s=solid&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2,5.5.0,5.6.0,5.6.1,5.6.3&m=free) + - `fa5b` prefix has [414 icons of various **brands**.](https://fontawesome.com/icons?d=gallery&s=brands&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2,5.5.0,5.6.0,5.6.1,5.6.3&m=free) - `fa` is the legacy [FA 4.7 version with its 675 icons](https://fontawesome.com/v4.7.0/icons/) but **all** of them (*and more!*) are part of FA 5.x so you should probably use the newer version above. diff --git a/UPDATE.md b/UPDATE.md index 49054a01..2f9cc832 100644 --- a/UPDATE.md +++ b/UPDATE.md @@ -1,8 +1,21 @@ -To update font-awesome or elusive icons, one must +# How to update font packs + +## FontAwesome + +To update _FontAwesome_ icons, one must: + +- check what is the latest released version here: https://github.com/FortAwesome/Font-Awesome/releases/ +- run: python setup.py update_fa5 --fa-version X.X.X +- update FA version number, icon counts and URLs inside: + - README.md + - qtawesome/docs/source/usage.rst + +## Elusive Icons + +To update _Elusive Icons_, one must: - replace the ttf font file with the new version -- regenerate the json charmap with the `icons.yml` file from the upstream - repository: +- regenerate the json charmap with the `icons.yml` file from the upstream repository: ```Python import yaml, json @@ -21,10 +34,13 @@ with open('charmap.json', 'w') as file: json.dump(charmap, file, indent=4, sort_keys=True) ``` -To update material design icons, you must: - - download ttf from https://github.com/Templarian/MaterialDesign-Webfont - - regenerate the json charmap with the `materialdesignicons.css` file - +## Material Design Icons + +To update _Material Design Icons_, you must: + +- download ttf from https://github.com/Templarian/MaterialDesign-Webfont +- regenerate the json charmap with the `materialdesignicons.css` file. + ```Python import re import json diff --git a/docs/source/usage.rst b/docs/source/usage.rst index 37715330..1269315f 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -10,11 +10,11 @@ The following prefixes are currently available to use: - `FontAwesome`_: - - FA 5.4.2 features 1,393 free icons in different styles: + - FA 5.6.3 features 1,480 free icons in different styles: - ``fa5`` prefix has `151 icons in the "regular" style.`_ - - ``fa5s`` prefix has `852 icons in the "solid" style.`_ - - ``fa5b`` prefix has `390 icons of various brands.`_ + - ``fa5s`` prefix has `915 icons in the "solid" style.`_ + - ``fa5b`` prefix has `414 icons of various brands.`_ - ``fa`` is the legacy `FA 4.7 version with its 675 icons`_ but **all** of them (*and more!*) are part of FA 5.x so you should @@ -26,9 +26,9 @@ The following prefixes are currently available to use: icons.`_ .. _FontAwesome: https://fontawesome.com -.. _151 icons in the "regular" style.: https://fontawesome.com/icons?d=gallery&s=regular&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2&m=free -.. _852 icons in the "solid" style.: https://fontawesome.com/icons?d=gallery&s=solid&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2&m=free -.. _390 icons of various brands.: https://fontawesome.com/icons?d=gallery&s=brands&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2&m=free +.. _151 icons in the "regular" style.: https://fontawesome.com/icons?d=gallery&s=regular&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2,5.5.0,5.6.0,5.6.1,5.6.3&m=free +.. _915 icons in the "solid" style.: https://fontawesome.com/icons?d=gallery&s=solid&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2,5.5.0,5.6.0,5.6.1,5.6.3&m=free +.. _414 icons of various brands.: https://fontawesome.com/icons?d=gallery&s=brands&v=5.0.0,5.0.1,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.0.10,5.0.11,5.0.12,5.0.13,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2,5.5.0,5.6.0,5.6.1,5.6.3&m=free .. _FA 4.7 version with its 675 icons: https://fontawesome.com/v4.7.0/icons/ .. _Elusive Icons 2.0 with its 304 icons: http://elusiveicons.com/icons/ .. _Material Design Icons 2.7.94 with its 2794 icons.: https://cdn.materialdesignicons.com/2.7.94/ diff --git a/qtawesome/fonts/fontawesome5-brands-webfont-charmap.json b/qtawesome/fonts/fontawesome5-brands-webfont-charmap.json index a4caabbe..eca58cd8 100644 --- a/qtawesome/fonts/fontawesome5-brands-webfont-charmap.json +++ b/qtawesome/fonts/fontawesome5-brands-webfont-charmap.json @@ -4,6 +4,7 @@ "accusoft": "f369", "acquisitions-incorporated": "f6af", "adn": "f170", + "adobe": "f778", "adversal": "f36a", "affiliatetheme": "f36b", "algolia": "f36c", @@ -20,7 +21,9 @@ "apper": "f371", "apple": "f179", "apple-pay": "f415", + "artstation": "f77a", "asymmetrik": "f372", + "atlassian": "f77b", "audible": "f373", "autoprefixer": "f41c", "avianex": "f374", @@ -42,6 +45,7 @@ "btc": "f15a", "buromobelexperte": "f37f", "buysellads": "f20d", + "canadian-maple-leaf": "f785", "cc-amazon-pay": "f42d", "cc-amex": "f1f3", "cc-apple-pay": "f416", @@ -53,12 +57,14 @@ "cc-stripe": "f1f5", "cc-visa": "f1f0", "centercode": "f380", + "centos": "f789", "chrome": "f268", "cloudscale": "f383", "cloudsmith": "f384", "cloudversify": "f385", "codepen": "f1cb", "codiepie": "f284", + "confluence": "f78d", "connectdevelop": "f20e", "contao": "f26d", "cpanel": "f388", @@ -88,6 +94,8 @@ "deskpro": "f38f", "dev": "f6cc", "deviantart": "f1bd", + "dhl": "f790", + "diaspora": "f791", "digg": "f1a6", "digital-ocean": "f391", "discord": "f392", @@ -117,6 +125,9 @@ "facebook-messenger": "f39f", "facebook-square": "f082", "fantasy-flight-games": "f6dc", + "fedex": "f797", + "fedora": "f798", + "figma": "f799", "firefox": "f269", "first-order": "f2b0", "first-order-alt": "f50a", @@ -180,13 +191,16 @@ "hubspot": "f3b2", "imdb": "f2d8", "instagram": "f16d", + "intercom": "f7af", "internet-explorer": "f26b", + "invision": "f7b0", "ioxhost": "f208", "itunes": "f3b4", "itunes-note": "f3b5", "java": "f4e4", "jedi-order": "f50e", "jenkins": "f3b6", + "jira": "f7b1", "joget": "f3b7", "joomla": "f1aa", "js": "f3b8", @@ -221,6 +235,7 @@ "medrt": "f3c8", "meetup": "f2e0", "megaport": "f5a3", + "mendeley": "f7b3", "microsoft": "f3ca", "mix": "f3cb", "mixcloud": "f289", @@ -270,14 +285,17 @@ "quinscape": "f459", "quora": "f2c4", "r-project": "f4f7", + "raspberry-pi": "f7bb", "ravelry": "f2d9", "react": "f41b", + "reacteurope": "f75d", "readme": "f4d5", "rebel": "f1d0", "red-river": "f3e3", "reddit": "f1a1", "reddit-alien": "f281", "reddit-square": "f1a2", + "redhat": "f7bc", "renren": "f18b", "replyd": "f3e6", "researchgate": "f4f8", @@ -298,6 +316,7 @@ "simplybuilt": "f215", "sistrix": "f3ee", "sith": "f512", + "sketch": "f7c6", "skyatlas": "f216", "skype": "f17e", "slack": "f198", @@ -307,6 +326,7 @@ "snapchat-ghost": "f2ac", "snapchat-square": "f2ad", "soundcloud": "f1be", + "sourcetree": "f7d3", "speakap": "f3f3", "spotify": "f1bc", "squarespace": "f5be", @@ -325,6 +345,7 @@ "stumbleupon-circle": "f1a3", "superpowers": "f2dd", "supple": "f3f9", + "suse": "f7d6", "teamspeak": "f4f9", "telegram": "f2c6", "telegram-plane": "f3fe", @@ -343,10 +364,13 @@ "twitter-square": "f081", "typo3": "f42b", "uber": "f402", + "ubuntu": "f7df", "uikit": "f403", "uniregistry": "f404", "untappd": "f405", + "ups": "f7e0", "usb": "f287", + "usps": "f7e1", "ussunnah": "f407", "vaadin": "f408", "viacoin": "f237", @@ -384,6 +408,7 @@ "yahoo": "f19e", "yandex": "f413", "yandex-international": "f414", + "yarn": "f7e3", "yelp": "f1e9", "yoast": "f2b1", "youtube": "f167", diff --git a/qtawesome/fonts/fontawesome5-brands-webfont.ttf b/qtawesome/fonts/fontawesome5-brands-webfont.ttf index 218ff47f..0a307750 100644 Binary files a/qtawesome/fonts/fontawesome5-brands-webfont.ttf and b/qtawesome/fonts/fontawesome5-brands-webfont.ttf differ diff --git a/qtawesome/fonts/fontawesome5-regular-webfont.ttf b/qtawesome/fonts/fontawesome5-regular-webfont.ttf index 4adbd66d..b5414de9 100644 Binary files a/qtawesome/fonts/fontawesome5-regular-webfont.ttf and b/qtawesome/fonts/fontawesome5-regular-webfont.ttf differ diff --git a/qtawesome/fonts/fontawesome5-solid-webfont-charmap.json b/qtawesome/fonts/fontawesome5-solid-webfont-charmap.json index 3af13bb8..602bef7b 100644 --- a/qtawesome/fonts/fontawesome5-solid-webfont-charmap.json +++ b/qtawesome/fonts/fontawesome5-solid-webfont-charmap.json @@ -47,6 +47,8 @@ "atom": "f5d2", "audio-description": "f29e", "award": "f559", + "baby": "f77c", + "baby-carriage": "f77d", "backspace": "f55a", "backward": "f04a", "balance-scale": "f24e", @@ -70,10 +72,12 @@ "bible": "f647", "bicycle": "f206", "binoculars": "f1e5", + "biohazard": "f780", "birthday-cake": "f1fd", "blender": "f517", "blender-phone": "f6b6", "blind": "f29d", + "blog": "f781", "bold": "f032", "bolt": "f0e7", "bomb": "f1e2", @@ -107,12 +111,15 @@ "calendar": "f133", "calendar-alt": "f073", "calendar-check": "f274", + "calendar-day": "f783", "calendar-minus": "f272", "calendar-plus": "f271", "calendar-times": "f273", + "calendar-week": "f784", "camera": "f030", "camera-retro": "f083", "campground": "f6bb", + "candy-cane": "f786", "cannabis": "f55f", "capsules": "f46b", "car": "f1b9", @@ -128,8 +135,10 @@ "caret-square-right": "f152", "caret-square-up": "f151", "caret-up": "f0d8", + "carrot": "f787", "cart-arrow-down": "f218", "cart-plus": "f217", + "cash-register": "f788", "cat": "f6be", "certificate": "f0a3", "chair": "f6c0", @@ -173,8 +182,13 @@ "closed-captioning": "f20a", "cloud": "f0c2", "cloud-download-alt": "f381", + "cloud-meatball": "f73b", "cloud-moon": "f6c3", + "cloud-moon-rain": "f73c", + "cloud-rain": "f73d", + "cloud-showers-heavy": "f740", "cloud-sun": "f6c4", + "cloud-sun-rain": "f743", "cloud-upload-alt": "f382", "cocktail": "f561", "code": "f121", @@ -194,6 +208,7 @@ "compact-disc": "f51f", "compass": "f14e", "compress": "f066", + "compress-arrows-alt": "f78c", "concierge-bell": "f562", "cookie": "f563", "cookie-bite": "f564", @@ -212,6 +227,7 @@ "cut": "f0c4", "database": "f1c0", "deaf": "f2a4", + "democrat": "f747", "desktop": "f108", "dharmachakra": "f655", "diagnoses": "f470", @@ -246,6 +262,8 @@ "drum-steelpan": "f56a", "drumstick-bite": "f6d7", "dumbbell": "f44b", + "dumpster": "f793", + "dumpster-fire": "f794", "dungeon": "f6d9", "edit": "f044", "eject": "f052", @@ -257,6 +275,7 @@ "envelope-square": "f199", "equals": "f52c", "eraser": "f12d", + "ethernet": "f796", "euro-sign": "f153", "exchange-alt": "f362", "exclamation": "f12a", @@ -305,12 +324,14 @@ "filter": "f0b0", "fingerprint": "f577", "fire": "f06d", + "fire-alt": "f7e4", "fire-extinguisher": "f134", "first-aid": "f479", "fish": "f578", "fist-raised": "f6de", "flag": "f024", "flag-checkered": "f11e", + "flag-usa": "f74d", "flask": "f0c3", "flushed": "f579", "folder": "f07b", @@ -333,13 +354,17 @@ "genderless": "f22d", "ghost": "f6e2", "gift": "f06b", + "gifts": "f79c", + "glass-cheers": "f79f", "glass-martini": "f000", "glass-martini-alt": "f57b", + "glass-whiskey": "f7a0", "glasses": "f530", "globe": "f0ac", "globe-africa": "f57c", "globe-americas": "f57d", "globe-asia": "f57e", + "globe-europe": "f7a2", "golf-ball": "f450", "gopuram": "f664", "graduation-cap": "f19d", @@ -360,7 +385,10 @@ "grin-tongue-wink": "f58b", "grin-wink": "f58c", "grip-horizontal": "f58d", + "grip-lines": "f7a4", + "grip-lines-vertical": "f7a5", "grip-vertical": "f58e", + "guitar": "f7a6", "h-square": "f0fd", "hammer": "f6e3", "hamsa": "f665", @@ -391,6 +419,7 @@ "headphones-alt": "f58f", "headset": "f590", "heart": "f004", + "heart-broken": "f7a9", "heartbeat": "f21e", "helicopter": "f533", "highlighter": "f591", @@ -398,8 +427,10 @@ "hippo": "f6ed", "history": "f1da", "hockey-puck": "f453", + "holly-berry": "f7aa", "home": "f015", "horse": "f6f0", + "horse-head": "f7ab", "hospital": "f0f8", "hospital-alt": "f47d", "hospital-symbol": "f47e", @@ -412,9 +443,11 @@ "house-damage": "f6f1", "hryvnia": "f6f2", "i-cursor": "f246", + "icicles": "f7ad", "id-badge": "f2c1", "id-card": "f2c2", "id-card-alt": "f47f", + "igloo": "f7ae", "image": "f03e", "images": "f302", "inbox": "f01c", @@ -493,6 +526,7 @@ "memory": "f538", "menorah": "f676", "mercury": "f223", + "meteor": "f753", "microchip": "f2db", "microphone": "f130", "microphone-alt": "f3c9", @@ -502,6 +536,7 @@ "minus": "f068", "minus-circle": "f056", "minus-square": "f146", + "mitten": "f7b5", "mobile": "f10b", "mobile-alt": "f3cd", "money-bill": "f0d6", @@ -517,6 +552,7 @@ "motorcycle": "f21c", "mountain": "f6fc", "mouse-pointer": "f245", + "mug-hot": "f7b6", "music": "f001", "network-wired": "f6ff", "neuter": "f22c", @@ -555,6 +591,7 @@ "people-carry": "f4ce", "percent": "f295", "percentage": "f541", + "person-booth": "f756", "phone": "f095", "phone-slash": "f3dd", "phone-square": "f098", @@ -575,6 +612,7 @@ "poll": "f681", "poll-h": "f682", "poo": "f2fe", + "poo-storm": "f75a", "poop": "f619", "portrait": "f3e0", "pound-sign": "f154", @@ -595,6 +633,9 @@ "quote-left": "f10d", "quote-right": "f10e", "quran": "f687", + "radiation": "f7b9", + "radiation-alt": "f7ba", + "rainbow": "f75b", "random": "f074", "receipt": "f543", "recycle": "f1b8", @@ -603,6 +644,8 @@ "registered": "f25d", "reply": "f3e5", "reply-all": "f122", + "republican": "f75e", + "restroom": "f7bd", "retweet": "f079", "ribbon": "f4d6", "ring": "f70b", @@ -621,10 +664,13 @@ "rupee-sign": "f156", "sad-cry": "f5b3", "sad-tear": "f5b4", + "satellite": "f7bf", + "satellite-dish": "f7c0", "save": "f0c7", "school": "f549", "screwdriver": "f54a", "scroll": "f70e", + "sd-card": "f7c2", "search": "f002", "search-dollar": "f688", "search-location": "f689", @@ -653,17 +699,27 @@ "sign-out-alt": "f2f5", "signal": "f012", "signature": "f5b7", + "sim-card": "f7c4", "sitemap": "f0e8", + "skating": "f7c5", + "skiing": "f7c9", + "skiing-nordic": "f7ca", "skull": "f54c", "skull-crossbones": "f714", "slash": "f715", + "sleigh": "f7cc", "sliders-h": "f1de", "smile": "f118", "smile-beam": "f5b8", "smile-wink": "f4da", + "smog": "f75f", "smoking": "f48d", "smoking-ban": "f54d", + "sms": "f7cd", + "snowboarding": "f7ce", "snowflake": "f2dc", + "snowman": "f7d0", + "snowplow": "f7d2", "socks": "f696", "solar-panel": "f5ba", "sort": "f0dc", @@ -731,6 +787,9 @@ "taxi": "f1ba", "teeth": "f62e", "teeth-open": "f62f", + "temperature-high": "f769", + "temperature-low": "f76b", + "tenge": "f7d7", "terminal": "f120", "text-height": "f034", "text-width": "f035", @@ -755,8 +814,10 @@ "tired": "f5c8", "toggle-off": "f204", "toggle-on": "f205", + "toilet": "f7d8", "toilet-paper": "f71e", "toolbox": "f552", + "tools": "f7d9", "tooth": "f5c9", "torah": "f6a0", "torii-gate": "f6a1", @@ -764,6 +825,7 @@ "trademark": "f25c", "traffic-light": "f637", "train": "f238", + "tram": "f7da", "transgender": "f224", "transgender-alt": "f225", "trash": "f1f8", @@ -830,10 +892,12 @@ "volume-mute": "f6a9", "volume-off": "f026", "volume-up": "f028", + "vote-yea": "f772", "vr-cardboard": "f729", "walking": "f554", "wallet": "f555", "warehouse": "f494", + "water": "f773", "weight": "f496", "weight-hanging": "f5cd", "wheelchair": "f193", diff --git a/qtawesome/fonts/fontawesome5-solid-webfont.ttf b/qtawesome/fonts/fontawesome5-solid-webfont.ttf index c6818494..53c8f366 100644 Binary files a/qtawesome/fonts/fontawesome5-solid-webfont.ttf and b/qtawesome/fonts/fontawesome5-solid-webfont.ttf differ diff --git a/qtawesome/iconic_font.py b/qtawesome/iconic_font.py index 1ef7f058..871697d5 100644 --- a/qtawesome/iconic_font.py +++ b/qtawesome/iconic_font.py @@ -32,6 +32,15 @@ # use system fonts SYSTEM_FONTS = False +# MD5 Hashes for font files bundled with qtawesome: +MD5_HASHES = { + 'fontawesome4.7-webfont.ttf': 'b06871f281fee6b241d60582ae9369b9', + 'fontawesome5-regular-webfont.ttf': 'f1994ecd58b56afa035ae3da39213357', + 'fontawesome5-solid-webfont.ttf': '80c404ff42e52d9e7589e83fe21307b4', + 'fontawesome5-brands-webfont.ttf': 'd6ac6c968cff1abcbf5d548828b9f6c6', + 'elusiveicons-webfont.ttf': '207966b04c032d5b873fd595a211582e', + 'materialdesignicons-webfont.ttf': '023db9122f66b7d693bc52bcdf09e6b3', +} _default_options = { 'color': QColor(50, 50, 50), @@ -227,19 +236,7 @@ def hook(obj): # Verify that vendorized fonts are not corrupt if not SYSTEM_FONTS: - md5_hashes = {'fontawesome4.7-webfont.ttf': - 'b06871f281fee6b241d60582ae9369b9', - 'fontawesome5-regular-webfont.ttf': - '0e2e26fb3527ae47f9eb1c217592b706', - 'fontawesome5-solid-webfont.ttf': - 'e143b57de78138e6d5963908afa7e393', - 'fontawesome5-brands-webfont.ttf': - 'dec02372212aab5a2e5294f1a11756ed', - 'elusiveicons-webfont.ttf': - '207966b04c032d5b873fd595a211582e', - 'materialdesignicons-webfont.ttf': - '023db9122f66b7d693bc52bcdf09e6b3'} - ttf_hash = md5_hashes.get(ttf_filename, None) + ttf_hash = MD5_HASHES.get(ttf_filename, None) if ttf_hash is not None: hasher = hashlib.md5() with open(os.path.join(directory, ttf_filename), diff --git a/setup.py b/setup.py index 37ca0a81..a2e7aef0 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import os import io + try: from setuptools import setup from setuptools.command.install import install @@ -8,18 +9,22 @@ from distutils.core import setup from distutils.core.command.install import install -here = os.path.abspath(os.path.dirname(__file__)) +# Code to add custom build commands comes from here: +import setupbase + +HERE = os.path.abspath(os.path.dirname(__file__)) -version_ns = {} -with open(os.path.join(here, 'qtawesome', '_version.py')) as f: - exec(f.read(), {}, version_ns) +VERSION_NS = {} +with open(os.path.join(HERE, 'qtawesome', '_version.py')) as f: + exec(f.read(), {}, VERSION_NS) -with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f: +with io.open(os.path.join(HERE, 'README.md'), encoding='utf-8') as f: LONG_DESCRIPTION = f.read() + setup( name='QtAwesome', - version=version_ns['__version__'], + version=VERSION_NS['__version__'], description='FontAwesome icons in PyQt and PySide applications', long_description=LONG_DESCRIPTION, long_description_content_type='text/markdown', @@ -39,5 +44,8 @@ 'License :: OSI Approved :: MIT License', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3',] + 'Programming Language :: Python :: 3', ], + cmdclass={ + 'update_fa5': setupbase.UpdateFA5Command, + } ) diff --git a/setupbase.py b/setupbase.py new file mode 100644 index 00000000..25e21e59 --- /dev/null +++ b/setupbase.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +import os +import re +import io +import json +import hashlib +import zipfile +try: + # Python 2 + from urllib2 import urlopen +except ImportError: + # Python 3 + from urllib.request import urlopen + +import distutils.cmd +import distutils.log + +HERE = os.path.abspath(os.path.dirname(__file__)) + + +class UpdateFA5Command(distutils.cmd.Command): + """A custom command to make updating FontAwesome 5.x easy!""" + description = 'Try to update the FontAwesome 5.x data in the project.' + user_options = [ + ('fa-version=', None, 'FA version.'), + ('zip-path=', None, 'Read from local zip file path.'), + ] + + # Update these below if the FontAwesome changes their structure: + FA_STYLES = ('regular', 'solid', 'brands') + CHARMAP_PATH_TEMPLATE = os.path.join(HERE, 'qtawesome', 'fonts', 'fontawesome5-{style}-webfont-charmap.json') + TTF_PATH_TEMPLATE = os.path.join(HERE, 'qtawesome', 'fonts', 'fontawesome5-{style}-webfont.ttf') + ICONIC_FONT_PY_PATH = os.path.join(HERE, 'qtawesome', 'iconic_font.py') + URL_TEMPLATE = 'https://github.com/FortAwesome/Font-Awesome/' \ + 'releases/download/{version}/fontawesome-free-{version}-web.zip' + + def initialize_options(self): + """Set default values for the command options.""" + self.fa_version = '' + self.zip_path = '' + + def finalize_options(self): + """Validate the command options.""" + assert bool(self.fa_version), 'FA version is mandatory for this command.' + if self.zip_path: + assert os.path.exists(self.zip_path), ( + 'Local zipfile does not exist: %s' % self.zip_path) + + def __print(self, msg): + """Shortcut for printing with the distutils logger.""" + self.announce(msg, level=distutils.log.INFO) + + def __get_charmap_path(self, style): + """Get the project FA charmap path for a given style.""" + return self.CHARMAP_PATH_TEMPLATE.format(style=style) + + def __get_ttf_path(self, style): + """Get the project FA font path for a given style.""" + return self.TTF_PATH_TEMPLATE.format(style=style) + + @property + def __release_url(self): + """Get the release URL.""" + return self.URL_TEMPLATE.format(version=self.fa_version) + + @property + def __zip_file(self): + """Get a file object of the FA zip file.""" + if self.zip_path: + # If using a local file, just open it: + self.__print('Opening local zipfile: %s' % self.zip_path) + return open(self.zip_path, 'rb') + + # Otherwise, download it and make a file object in-memory: + url = self.__release_url + self.__print('Downloading from URL: %s' % url) + response = urlopen(url) + return io.BytesIO(response.read()) + + @property + def __zipped_files_data(self): + """Get a dict of all files of interest from the FA release zipfile.""" + files = {} + with zipfile.ZipFile(self.__zip_file) as thezip: + for zipinfo in thezip.infolist(): + if zipinfo.filename.endswith('metadata/icons.json'): + with thezip.open(zipinfo) as compressed_file: + files['icons.json'] = compressed_file.read() + elif zipinfo.filename.endswith('.ttf'): + # For the record, the paths usually look like this: + # webfonts/fa-brands-400.ttf + # webfonts/fa-regular-400.ttf + # webfonts/fa-solid-900.ttf + name = os.path.basename(zipinfo.filename) + tokens = name.split('-') + style = tokens[1] + if style in self.FA_STYLES: + with thezip.open(zipinfo) as compressed_file: + files[style] = compressed_file.read() + + # Safety checks: + assert all(style in files for style in self.FA_STYLES), \ + 'Not all FA styles found! Update code is broken.' + assert 'icons.json' in files, 'icons.json not found! Update code is broken.' + + return files + + def run(self): + """Run command.""" + files = self.__zipped_files_data + hashes = {} + icons = {} + + # Read icons.json (from the webfont zip download) + data = json.loads(files['icons.json']) + + # Group icons by style, since not all icons exist for all styles: + for icon, info in data.iteritems(): + for style in info['styles']: + icons.setdefault(str(style), {}) + icons[str(style)][icon] = str(info['unicode']) + + # For every FA "style": + for style, details in icons.iteritems(): + # Dump a .json charmap file: + charmapPath = self.__get_charmap_path(style) + self.__print('Dumping updated "%s" charmap: %s' % (style, charmapPath)) + with open(charmapPath, 'w+') as f: + json.dump(details, f, indent=4, sort_keys=True) + + # Dump a .ttf font file: + fontPath = self.__get_ttf_path(style) + data = files[style] + hashes[style] = hashlib.md5(data).hexdigest() + self.__print('Dumping updated "%s" font: %s' % (style, fontPath)) + with open(fontPath, 'w+') as f: + f.write(data) + + # Now it's time to patch "iconic_font.py": + iconic_path = self.ICONIC_FONT_PY_PATH + self.__print('Patching new MD5 hashes in: %s' % iconic_path) + with open(iconic_path, 'r') as iconic_file: + contents = iconic_file.read() + # We read it in full, then use regex substitution: + for style, md5 in hashes.iteritems(): + self.__print('New "%s" hash is: %s' % (style, md5)) + regex = r"('fontawesome5-%s-webfont.ttf':\s+)'(\w+)'" % style + subst = r"\g<1>'" + md5 + "'" + contents = re.sub(regex, subst, contents, 1) + # and finally overwrite with the modified file: + self.__print('Dumping updated file: %s' % iconic_path) + with open(iconic_path, 'w') as iconic_file: + iconic_file.write(contents) + + self.__print( + '\nFinished!\n' + 'Please check the git diff to make sure everything went okay.\n' + 'You should also edit README.md and ' + 'qtawesome/docs/source/usage.rst to reflect the changes.')