Added support for on-the-fly image creation
This commit is contained in:
		
							parent
							
								
									fbfba8d05c
								
							
						
					
					
						commit
						50f31ec1c3
					
				
					 6 changed files with 78 additions and 17 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					images/cache/*
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@ with open('unicode_list.txt', 'w') as target:
 | 
				
			||||||
                num = int(code, 16)
 | 
					                num = int(code, 16)
 | 
				
			||||||
            except ValueError:
 | 
					            except ValueError:
 | 
				
			||||||
                print('could not convert ' + code)
 | 
					                print('could not convert ' + code)
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
            index = locate_block(num)
 | 
					            index = locate_block(num)
 | 
				
			||||||
            if index is not None:
 | 
					            if index is not None:
 | 
				
			||||||
                target.write(name + '\t' + code + '\t' + blocks[index] + '\n')
 | 
					                target.write(name + '\t' + code + '\t' + blocks[index] + '\n')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										26
									
								
								images/unicode.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								images/unicode.svg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
				
			||||||
 | 
					<svg
 | 
				
			||||||
 | 
					   xmlns:svg="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					   xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					   width="7.601603mm"
 | 
				
			||||||
 | 
					   height="7.715291mm"
 | 
				
			||||||
 | 
					   viewBox="0 0 7.601603 7.715291"
 | 
				
			||||||
 | 
					   version="1.1"
 | 
				
			||||||
 | 
					   id="svg8">
 | 
				
			||||||
 | 
					  <g
 | 
				
			||||||
 | 
					     inkscape:label="Layer 1"
 | 
				
			||||||
 | 
					     inkscape:groupmode="layer"
 | 
				
			||||||
 | 
					     id="layer1"
 | 
				
			||||||
 | 
					     transform="translate(-66.505356,-78.373996)">
 | 
				
			||||||
 | 
					    <text
 | 
				
			||||||
 | 
					       xml:space="preserve"
 | 
				
			||||||
 | 
					       style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
 | 
				
			||||||
 | 
					       x="70.303574"
 | 
				
			||||||
 | 
					       y="86.089287"
 | 
				
			||||||
 | 
					       id="unicode_symbol"><tspan
 | 
				
			||||||
 | 
					         id="tspan815"
 | 
				
			||||||
 | 
					         x="70.303574"
 | 
				
			||||||
 | 
					         y="86.089287"
 | 
				
			||||||
 | 
					         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:{font};stroke-width:0.26458332px">{symbol}</tspan></text>
 | 
				
			||||||
 | 
					  </g>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1 KiB  | 
							
								
								
									
										61
									
								
								main.py
									
										
									
									
									
								
							
							
						
						
									
										61
									
								
								main.py
									
										
									
									
									
								
							| 
						 | 
					@ -1,7 +1,9 @@
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
sys.path.append('/home/zen/.local/lib/python2.7/site-packages/')
 | 
					
 | 
				
			||||||
 | 
					sys.path.append("/home/zen/.local/lib/python2.7/site-packages/")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import codecs
 | 
				
			||||||
from fuzzywuzzy import process
 | 
					from fuzzywuzzy import process
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ulauncher.api.client.Extension import Extension
 | 
					from ulauncher.api.client.Extension import Extension
 | 
				
			||||||
| 
						 | 
					@ -13,17 +15,18 @@ from ulauncher.api.shared.action.CopyToClipboardAction import CopyToClipboardAct
 | 
				
			||||||
from ulauncher.api.shared.action.HideWindowAction import HideWindowAction
 | 
					from ulauncher.api.shared.action.HideWindowAction import HideWindowAction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DemoExtension(Extension):
 | 
					FILE_PATH = os.path.dirname(sys.argv[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UnicodeCharExtension(Extension):
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        super(DemoExtension, self).__init__()
 | 
					        super(UnicodeCharExtension, self).__init__()
 | 
				
			||||||
        self.subscribe(KeywordQueryEvent, KeywordQueryEventListener())
 | 
					        self.subscribe(KeywordQueryEvent, KeywordQueryEventListener())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class KeywordQueryEventListener(EventListener):
 | 
					class KeywordQueryEventListener(EventListener):
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        f = open(os.path.dirname(sys.argv[0]) + '/unicode_list.txt', 'r')
 | 
					        f = open(os.path.dirname(sys.argv[0]) + "/unicode_list.txt", "r")
 | 
				
			||||||
        data = f.readlines()
 | 
					        data = f.readlines()
 | 
				
			||||||
        self.data = {}
 | 
					        self.data = {}
 | 
				
			||||||
        # self.names = []
 | 
					        # self.names = []
 | 
				
			||||||
| 
						 | 
					@ -31,9 +34,9 @@ class KeywordQueryEventListener(EventListener):
 | 
				
			||||||
        # self.blocks = []
 | 
					        # self.blocks = []
 | 
				
			||||||
        for item in data:
 | 
					        for item in data:
 | 
				
			||||||
            item = item.strip()
 | 
					            item = item.strip()
 | 
				
			||||||
            name, code, block = item.split('\t')
 | 
					            name, code, block = item.split("\t")
 | 
				
			||||||
            self.data[name + ' ' + block] = (name, block, code)
 | 
					            self.data[name + " " + block] = (name, block, code)
 | 
				
			||||||
            self.items.append(name + ' ' + block)
 | 
					            self.items.append(name + " " + block)
 | 
				
			||||||
            # self.names.append(name)
 | 
					            # self.names.append(name)
 | 
				
			||||||
            # self.blocks.append(block)
 | 
					            # self.blocks.append(block)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,14 +45,46 @@ class KeywordQueryEventListener(EventListener):
 | 
				
			||||||
        arg = event.get_argument()
 | 
					        arg = event.get_argument()
 | 
				
			||||||
        if arg:
 | 
					        if arg:
 | 
				
			||||||
            matches = process.extract(arg, self.items, limit=15)
 | 
					            matches = process.extract(arg, self.items, limit=15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for m in matches:
 | 
					            for m in matches:
 | 
				
			||||||
                name, block, code = self.data[m[0]]
 | 
					                name, block, code = self.data[m[0]]
 | 
				
			||||||
                items.append(ExtensionResultItem(icon='images/bookmark.svg',
 | 
					                image_path = self.create_icon_image(code)
 | 
				
			||||||
                                                 name=name + ' - ' + unichr(int(code, 16)),
 | 
					                items.append(
 | 
				
			||||||
 | 
					                    ExtensionResultItem(
 | 
				
			||||||
 | 
					                        icon=image_path,
 | 
				
			||||||
 | 
					                        name=name + " - " + unichr(int(code, 16)),
 | 
				
			||||||
                        description=block,
 | 
					                        description=block,
 | 
				
			||||||
                                                 on_enter=CopyToClipboardAction(unichr(int(code, 16)))))
 | 
					                        on_enter=CopyToClipboardAction(unichr(int(code, 16))),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return RenderResultListAction(items)
 | 
					        return RenderResultListAction(items)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == '__main__':
 | 
					    def create_icon_image(self, code):
 | 
				
			||||||
    DemoExtension().run()
 | 
					        path = sys.argv[0] + "images/cache/icon_%s.svg" % code
 | 
				
			||||||
 | 
					        if os.path.isfile(path):
 | 
				
			||||||
 | 
					            return path
 | 
				
			||||||
 | 
					        return create_character_icon(code)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def load_icon_template():
 | 
				
			||||||
 | 
					    with open(os.path.join(FILE_PATH, "images/unicode.svg"), "r") as i:
 | 
				
			||||||
 | 
					        return i.read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def is_icon_cached(code):
 | 
				
			||||||
 | 
					    return os.path.isfile(os.path.join(FILE_PATH, "images/cache/icon_%s.svg" % code))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def create_character_icon(code, font='sans-serif'):
 | 
				
			||||||
 | 
					    template = load_icon_template()
 | 
				
			||||||
 | 
					    icon = template.replace("{symbol}", unichr(int(code, 16))).replace('{font}', font)
 | 
				
			||||||
 | 
					    with codecs.open(
 | 
				
			||||||
 | 
					        os.path.join(FILE_PATH, "images/cache/icon_%s.svg" % code), "w", "utf-8"
 | 
				
			||||||
 | 
					    ) as target:
 | 
				
			||||||
 | 
					        target.write(icon)
 | 
				
			||||||
 | 
					    return os.path.join(FILE_PATH, "images/cache/icon_%s.svg" % code)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    UnicodeCharExtension().run()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
  "developer_name": "John Doe",
 | 
					  "developer_name": "John Doe",
 | 
				
			||||||
  "icon": "images/bookmark.svg",
 | 
					  "icon": "images/bookmark.svg",
 | 
				
			||||||
  "options": {
 | 
					  "options": {
 | 
				
			||||||
    "query_debounce": 0.1
 | 
					    "query_debounce": 0.5
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "preferences": [
 | 
					  "preferences": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -531,7 +531,6 @@ bernoulli function	212C	Letterlike Symbols
 | 
				
			||||||
BET SYMBOL	2136	Letterlike Symbols
 | 
					BET SYMBOL	2136	Letterlike Symbols
 | 
				
			||||||
BETA SYMBOL, GREEK	03D0	Greek and Coptic
 | 
					BETA SYMBOL, GREEK	03D0	Greek and Coptic
 | 
				
			||||||
beta, curled	03D0	Greek and Coptic
 | 
					beta, curled	03D0	Greek and Coptic
 | 
				
			||||||
Betty	BOOP	Greek and Coptic
 | 
					 | 
				
			||||||
BETWEEN	226C	Mathematical Operators
 | 
					BETWEEN	226C	Mathematical Operators
 | 
				
			||||||
Beverage Symbols	1F375	Miscellaneous Symbols and Pictographs
 | 
					Beverage Symbols	1F375	Miscellaneous Symbols and Pictographs
 | 
				
			||||||
BEVERAGE, HOT	2615	Miscellaneous Symbols
 | 
					BEVERAGE, HOT	2615	Miscellaneous Symbols
 | 
				
			||||||
| 
						 | 
					@ -5449,7 +5448,6 @@ Thai Digits	0E50	Thai
 | 
				
			||||||
Thai Marks and Signs	0E48	Thai
 | 
					Thai Marks and Signs	0E48	Thai
 | 
				
			||||||
Thai Vowels	0E30	Thai
 | 
					Thai Vowels	0E30	Thai
 | 
				
			||||||
THANTHAKHAT, THAI CHARACTER	0E4C	Thai
 | 
					THANTHAKHAT, THAI CHARACTER	0E4C	Thai
 | 
				
			||||||
the	DOOD	Thai
 | 
					 | 
				
			||||||
theater masks	1F3AD	Miscellaneous Symbols and Pictographs
 | 
					theater masks	1F3AD	Miscellaneous Symbols and Pictographs
 | 
				
			||||||
THERE DOES NOT EXIST	2204	Mathematical Operators
 | 
					THERE DOES NOT EXIST	2204	Mathematical Operators
 | 
				
			||||||
THERE EXISTS	2203	Mathematical Operators
 | 
					THERE EXISTS	2203	Mathematical Operators
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Reference in a new issue