2424# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2525# SOFTWARE.
2626#
27- # Release version: 2018.11.17
2827# Donate if you find this app useful, educational or you like to motivate more projects like this.
2928#
3029# XMR: 4B6YQvbL9jqY3r1cD3ZvrDgGrRpKvifuLVb5cQnYZtapWUNovde7K5rc1LVGw3HhmTiijX21zHKSqjQtwxesBEe6FhufRGS
4241from kivy .lang import Builder
4342from kivy .config import Config
4443from kivy .uix .behaviors import ButtonBehavior
44+ from kivy .uix .textinput import TextInput
4545from kivy .uix .image import Image
4646from kivy .properties import ConfigParser
4747# Python Imaging Library
4848from kivy .core .image import Image as CoreImage
4949from PIL import Image as pilImage
5050from PIL import ImageDraw , ImageFont , PILLOW_VERSION
5151# Threading
52- from kivy .clock import mainthread
52+ from kivy .clock import mainthread , Clock
5353from threading import Thread , Event
5454from time import sleep
5555import datetime
6363import shutil
6464
6565name = 'labelpush'
66+ version = '2018.11.26'
6667def_iconfiles = [
6768 os .path .join (sys .prefix , 'local/share/pixmaps/labelpush.png' ),
6869 os .path .join (sys .prefix , 'share/pixmaps/labelpush.png' ),
9899 { "type": "bool", "title": "More image cycle modi", "desc": "When clicking the image, you get 4 print choices instead of 2",
99100 "section": "settings", "key": "multimod" },
100101 { "type": "numeric", "title": "Font height correction", "desc": "For adjusting the vertical offset, use caps when in doubt",
101- "section": "settings", "key": "focorr" }
102+ "section": "settings", "key": "focorr" },
103+ { "type": "title", "title": "Release version: ''' + version + ''' - Matteljay" }
102104 ]'''
103105Builder .load_string ('''
104106<RootWidget>:
115117 padding: 30
116118 spacing: 30
117119 orientation: 'vertical'
118- TextInput :
120+ TextInput_multi_retsel :
119121 id: id_textbox
120122 text: ''
121- multiline: True
122123 font_size: 20
123124 focus: True
124- unfocus_on_touch: False
125- text_validate_unfocus: False
126- input_filter: root.textbox_filter
125+ on_text_validate: root.press_btn_PRINT()
127126 ImageButton:
128127 id: id_beeld
129- on_press: root.btn_IMG()
128+ on_press: root.btn_IMG(self )
130129 allow_stretch: True
131130 keep_ratio: True
132131 canvas.before:
150149 on_press: root.press_btn_PRINT()
151150 text: 'PRINT'
152151 font_size: 20
152+ background_down: self.background_normal
153153''' )
154154
155155class GLO (): # global variables: status and config
@@ -160,6 +160,9 @@ class GLO(): # global variables: status and config
160160 confpath = '' # will hold the system path to the user's config file
161161 font_pool = {} # used as a dict and will be populated with fontname/fontpath pairs
162162 immode = 0
163+ processed_immode = 0
164+ processed_text = ''
165+ dispatch_printaction = False
163166 defaultcfg = def_defaultcfg
164167 jsondata = def_jsondata
165168
@@ -171,26 +174,54 @@ def fatal_lockdown(txt):
171174class ImageButton (ButtonBehavior , Image ):
172175 pass
173176
174- class RootWidget (BoxLayout ):
175- imbytes = ''
176- def textbox_filter (self , substring , from_undo ):
177+ class TextInput_multi_retsel (TextInput ):
178+ multiline = True
179+ unfocus_on_touch = False
180+ text_validate_unfocus = False
181+ def keyboard_on_key_down (self , window , keycode , text , modifiers ):
182+ if keycode [0 ] in (9 , 10 , 11 , 12 ): # hor tab, line feed, vert tab, form feed
183+ keycode = (None , None )
184+ elif keycode [0 ] == 13 :
185+ keycode = (None , None )
186+ self .dispatch ('on_text_validate' )
187+ return super (type (self ), self ).keyboard_on_key_down (window , keycode , text , modifiers )
188+ def insert_text (self , substring , from_undo = False ):
177189 ret = substring
178190 if len (substring ) == 1 : # probably key press or single paste
179- if substring in '\t \n \r \f \v ' :
191+ if substring in '\t \r \v \f \n ' :
180192 ret = ''
181193 else : # probably paste from clipboard
182- ret = re .sub (r'[\t\n\r\f\v]' , '' , substring )
183- return ret
184- def press_btn_PRINT (self ):
194+ ret = re .sub (r'[\t\r\v\f\n]' , '' , substring )
195+ return super (type (self ), self ).insert_text (ret , from_undo )
196+
197+ class RootWidget (BoxLayout ):
198+ imbytes = ''
199+ def execute_print (self ):
185200 self .textbox .select_all ()
186201 lpname = ConfigParser .get_configparser ('app' ).get ('settings' , 'lpname' )
187- if not lpname or lpname == 'default' : #hasattr(CONF, 'lpname')
202+ if not lpname or lpname == 'default' :
188203 p = Popen (['lp' ], stdin = PIPE )
189204 else :
190205 p = Popen (['lp' , '-d' , lpname ], stdin = PIPE )
191206 p .stdin .write (self .imbytes )
192207 p .stdin .close ()
193- def btn_IMG (self ):
208+ def press_btn_PRINT (self ):
209+ btn = self .btn_PRINT
210+ # spam control: alternative to Kivy's min_state_time button
211+ if btn .background_color [1 ] == 2 : return
212+ btn .background_color [1 ] = 2
213+ def greenback (dt ): btn .background_color [1 ] = 1
214+ Clock .schedule_once (greenback , 0.5 )
215+ # spam control: check if finished drawing
216+ if GLO .processed_text != btn .text :
217+ GLO .dispatch_printaction = True
218+ return
219+ self .execute_print ()
220+ def btn_IMG (self , btn ):
221+ # spam control: wait for cycle to get drawn
222+ if GLO .processed_immode != GLO .immode :
223+ return
224+ # cycle image
194225 GLO .immode += 1
195226 config = ConfigParser .get_configparser ('app' )
196227 multimod = int (config .get ('settings' , 'multimod' ))
@@ -216,6 +247,12 @@ def update_elements(self, im):
216247 self .statuslabel .text = 'First time run, welcome! Wrote config {} ---> press F1 to see the settings page' .format (GLO .confpath )
217248 else :
218249 self .statuslabel .text = 'Ready to print, click the image to cycle'
250+ # allow button to work instantly
251+ GLO .processed_immode = GLO .immode
252+ GLO .processed_text = self .textbox .text
253+ if GLO .dispatch_printaction :
254+ GLO .dispatch_printaction = False
255+ self .execute_print ()
219256 def canvas_drawtext (self , canvas_img , maxw , maxh , txt ):
220257 # read config settings
221258 # alternative: config = App.get_running_app().config
@@ -276,7 +313,7 @@ def clock_thread(self):
276313 # super(RightClickTextInput,self).on_touch_down(touch)
277314 # if touch.button == 'right':
278315 #def __init__(self, **kwargs):
279- # super(RootWidget , self).__init__(**kwargs)
316+ # super(type(self) , self).__init__(**kwargs)
280317 # self.textbox.text = 'example'
281318 # self.textbox.select_all()
282319 # Thread(target=self.clock_thread).start()
@@ -357,7 +394,7 @@ def populate_fonts(self):
357394 self .config .set ('settings' , 'font' , list (GLO .font_pool .keys ())[0 ])
358395 self .config .write ()
359396 def get_application_config (self ):
360- confpath = super (LabelPushApp , self ).get_application_config ('~/.config/%(appname)s.ini' )
397+ confpath = super (type ( self ) , self ).get_application_config ('~/.config/%(appname)s.ini' )
361398 GLO .confpath = confpath
362399 if os .access (confpath , os .R_OK ):
363400 GLO .firstrun = False
@@ -382,7 +419,7 @@ def build_config(self, config):
382419 #config.setdefaults('settings', {}) # read newly created config into memory
383420 config .setdefaults ('settings' , GLO .defaultcfg )
384421 def close_settings (self , * largs ):
385- ret = super (LabelPushApp , self ).close_settings (* largs )
422+ ret = super (type ( self ) , self ).close_settings (* largs )
386423 GLO .firstrun = False # config window was opened, no more need for this
387424 self .root .textbox .focus = True
388425 self .root .textbox .select_all ()
0 commit comments