diff options
-rw-r--r-- | ptgui.glade | 112 | ||||
-rw-r--r-- | ptgui.py | 76 | ||||
-rw-r--r-- | ptlayout.py | 44 | ||||
-rw-r--r-- | pttarget.py | 16 |
4 files changed, 180 insertions, 68 deletions
diff --git a/ptgui.glade b/ptgui.glade index f1fc0fa..8715537 100644 --- a/ptgui.glade +++ b/ptgui.glade @@ -10,6 +10,11 @@ <column type="GObject"/> </columns> </object> + <object class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-cut</property> + </object> <object class="GtkWindow" id="mainwnd"> <property name="can_focus">False</property> <child> @@ -39,6 +44,7 @@ <object class="GtkBox" id="box2"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="spacing">3</property> <child> <object class="GtkLabel" id="statuslabel"> <property name="visible">True</property> @@ -54,18 +60,86 @@ </packing> </child> <child> + <object class="GtkSeparator" id="separator2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="numcopies"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">•</property> + <property name="width_chars">3</property> + <property name="text" translatable="yes">1</property> + <property name="xalign">1</property> + <property name="input_purpose">digits</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-copy</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="cuttoggle"> + <property name="label" translatable="yes">feed & cut last</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="image">image1</property> + <property name="active">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkSeparator" id="separator1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + <child> <object class="GtkButton" id="printbtn"> <property name="label">gtk-print</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_stock">True</property> + <property name="focus_on_click">False</property> <signal name="clicked" handler="on_print" swapped="no"/> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">6</property> </packing> </child> </object> @@ -91,7 +165,7 @@ <property name="visible">True</property> <property name="can_focus">False</property> <child> - <object class="GtkDrawingArea" id="resultimg"> + <object class="GtkDrawingArea" id="img"> <property name="height_request">128</property> <property name="visible">True</property> <property name="can_focus">False</property> @@ -163,41 +237,11 @@ <property name="can_focus">True</property> <property name="shadow_type">in</property> <child> - <object class="GtkViewport" id="viewport2"> + <object class="GtkViewport" id="tabviewport"> <property name="visible">True</property> <property name="can_focus">False</property> <child> - <object class="GtkGrid" id="ctlgrid"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - </object> + <placeholder/> </child> </object> </child> @@ -7,6 +7,7 @@ ml = GLib.MainLoop() import pttarget, ptlayout from ptlayout import PTLText import time +import usb.core class MainWindow(object): def __init__(self): @@ -19,11 +20,11 @@ class MainWindow(object): self.wnd = builder.get_object('mainwnd') self.wnd.connect("delete-event", Gtk.main_quit) - self.statuslabel = builder.get_object('statuslabel') - self.ctlgrid = builder.get_object('ctlgrid') - self.printbtn = builder.get_object('printbtn') - self.color_fg = builder.get_object('color_fg') - self.color_bg = builder.get_object('color_bg') + for name in ['statuslabel', 'tabviewport', 'img', 'printbtn', + 'color_fg', 'color_bg', 'numcopies', 'cuttoggle', 'devbox']: + self.__dict__[name] = builder.get_object(name) + self.ctlgrid = Gtk.Table() + self.tabviewport.add(self.ctlgrid) self.layout = ptlayout.PTLHSeq() self.layout.spacing = 0 @@ -55,13 +56,11 @@ class MainWindow(object): self.layout.add(PTLText()) self.layout_put_controls() - self.img = builder.get_object('resultimg') self.sizing_apply() self.img.connect('draw', self.draw) # help(self.img) self.devlist = Gtk.ListStore(str, object) - self.devbox = builder.get_object('devbox') self.devbox.set_model(self.devlist) self.scan() self.dev_select() @@ -86,18 +85,25 @@ class MainWindow(object): def dev_select(self): itr = self.devbox.get_active_iter() + if itr is None: + return dev = self.devlist[itr][1] dev.setup() self.status_update() def status_update(self): itr = self.devbox.get_active_iter() + if itr is None: + return dev = self.devlist[itr][1] - if dev.last_status is None or time.time() - dev.last_status >= 1: - dev.refresh_status() - else: - dev.check_status() + try: + if dev.last_status is None or time.time() - dev.last_status >= 1: + dev.refresh_status() + else: + dev.check_status() + except usb.core.USBError, e: + print 'problem while status refresh:', str(e) if dev.err1 == 0 and dev.err2 == 0: self.printbtn.set_sensitive(True) @@ -183,6 +189,9 @@ class MainWindow(object): ctx.fill() def layout_update(self): + if self.label_surface is None: + return + w, h = self.layout.prep_size(self.label_surface.get_height()) if w < 32: w = 32 @@ -213,24 +222,57 @@ class MainWindow(object): def layout_put_controls(self): nodes = [self.layout] + rows = -1 while len(nodes) > 0: + rows += 1 # separator node = nodes.pop(0) - nodes.extend(reversed(node.children())) - for p in reversed(node.properties()): + nodes.extend(node.children()) + for p in node.properties(): + rows += 1 + + self.ctlgrid.resize(rows, 2) + + nodes = [self.layout] + row = 0 + first = True + while len(nodes) > 0: + if not first: + hs = Gtk.HSeparator() + self.ctlgrid.attach(hs, 0, 2, row, row + 1, ypadding = 3.0, + xoptions = Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions = 0) + row += 1 + first = False + + node = nodes.pop(0) + nodes.extend(node.children()) + for p in node.properties(): elem = self.layout_control(node, p[0], p[1]) - self.ctlgrid.insert_row(0) - self.ctlgrid.attach(Gtk.Label(p[0]), 0, 0, 1, 1) - self.ctlgrid.attach(elem, 1, 0, 1, 1) + lbl = Gtk.Label(p[0]) + lbl.set_alignment(0.0, 0.5) + self.ctlgrid.attach(lbl, 0, 1, row, row + 1, + xoptions = Gtk.AttachOptions.FILL, yoptions = 0) + self.ctlgrid.attach(elem, 1, 2, row, row + 1, + xoptions = Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions = 0) + row += 1 def on_print(self, *args): if self.label_surface is None: return + + copies = self.numcopies.get_buffer().get_text() + if copies.strip() == '': + copies = 1 + else: + copies = int(copies) + feedlast = self.cuttoggle.get_active() + data = pttarget.PTLabelData() data.addcairo(self.label_surface, offset = self.tape.offset) itr = self.devbox.get_active_iter() dev = self.devlist[itr][1] - dev.send(data.get()) + for i in range(0, copies): + dev.send(data.get(feedlast and i == copies - 1)) mw = MainWindow() Gtk.main() diff --git a/ptlayout.py b/ptlayout.py index f9518b7..2d0a3ea 100644 --- a/ptlayout.py +++ b/ptlayout.py @@ -58,14 +58,19 @@ class PTLText(PTLayoutElem): w = size[0] matrix = cctx.get_matrix() - if self.mode == 'left': + if self.mode == 'right': cctx.rotate(90. * pi / 180.) cctx.translate((h - size[0]) / 2, -size[1]) w = size[1] - elif self.mode == 'right': + elif self.mode == 'left': cctx.rotate(-90. * pi / 180.) cctx.translate(-h + (h - size[0]) / 2, 0) w = size[1] + elif self.mode == 'down': + cctx.rotate(pi) + cctx.translate(-size[0], -(h + size[1]) / 2) + else: + cctx.translate(0, (h - size[1]) / 2) pctx.update_layout(layout) pctx.show_layout(layout) @@ -78,7 +83,8 @@ class PTLQRCode(PTLayoutElem): super(PTLQRCode, self).__init__() self.qrcontent = '' self.hborder = 4 - self.invert = True + self.vborder = 4 + self.invert = False def properties(self): return [ @@ -92,16 +98,16 @@ class PTLQRCode(PTLayoutElem): return self._render(cctx, False, h) def _render(self, cctx, sizeonly, h): - qr = qrcode.QRCode(border = 0) + qr = qrcode.QRCode(border = 0, error_correction = qrcode.ERROR_CORRECT_L) qr.add_data(self.qrcontent) qr.make(fit = True) qm = qr.get_matrix() qmlen = len(qm) - bpp = h / qmlen - if sizeonly: return (bpp * qmlen + self.hborder * 2, bpp * qmlen) + bpp = (h - self.vborder) / qmlen + if sizeonly: return (bpp * qmlen + self.hborder * 2, bpp * qmlen + self.vborder * 2) if self.invert: - cctx.rectangle(0, 0, bpp * qmlen + self.hborder * 2, h) + cctx.rectangle(0, 0, bpp * qmlen + self.hborder * 2, h + self.vborder * 2) cctx.fill() cctx.set_source_rgba(1.0, 1.0, 1.0, 0.0) @@ -113,7 +119,7 @@ class PTLQRCode(PTLayoutElem): cctx.fill() cctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - return bpp * qmlen + return bpp * qmlen + self.hborder * 2 class PTLContainer(PTLayoutElem): def __init__(self): @@ -126,13 +132,31 @@ class PTLContainer(PTLayoutElem): def add(self, child): self._children.append(child) +class PTLHSpace(PTLContainer): + def __init__(self): + super(PTLHSpace, self).__init__() + self.spacing = '5' + + def prep_size(self, hh): + return (int(self.spacing), 0) + + def render(self, cctx, h): + return int(self.spacing) + + def properties(self): + return [ + ('spacing', 'text'), + ] + class PTLHSeq(PTLContainer): def __init__(self): super(PTLHSeq, self).__init__() self.spacing = 5 def prep_size(self, hh): - w, h = len(self._children) * self.spacing, 0 + if len(self._children) == 0: + return (0,0) + w, h = (len(self._children) - 1) * self.spacing, 0 for k in self._children: cw, ch = k.prep_size(hh) w += cw @@ -164,7 +188,7 @@ class PTLVStack(PTLContainer): for i, k in enumerate(self._children): vpos = int(h / float(len(self._children)) * i) cctx.translate(0, vpos) - cw = k.render(cctx, h) + cw = k.render(cctx, h / float(len(self._children))) w = max(cw, w) cctx.translate(0, -vpos) return w diff --git a/pttarget.py b/pttarget.py index 48c2bee..ff05a1e 100644 --- a/pttarget.py +++ b/pttarget.py @@ -90,6 +90,7 @@ class PTUSB(PTPrinter): self.usbdev.bus, self.usbdev.address) def setup(self): + self.usbdev.default_timeout = 1000 for cfg in self.usbdev: iface = usb.util.find_descriptor(cfg, bInterfaceClass = 7) if iface is not None: @@ -116,12 +117,14 @@ class PTUSB(PTPrinter): self.if_wr.write('\x1biS') ar = array.array('B') start = time.time() - while len(ar) < 32 or time.time() > start + 0.1: + while len(ar) < 32 and time.time() < start + 0.25: ar += self.if_rd.read(16) if len(ar) != 32: raise IOError, 'failed to get status' if ar[0] != 0x80 or ar[1] != 32: raise IOError, 'invalid status (hdr: %02x %02x)' % (ar[0], ar[1]) + else: + ar = data self.err1 = ar[8] self.err2 = ar[9] @@ -139,7 +142,7 @@ class PTUSB(PTPrinter): if len(ar) == 0: return start = time.time() - while len(ar) < 32 or time.time() > start + 0.1: + while len(ar) < 32 and time.time() < start + 0.25: ar += self.if_rd.read(16) self.refresh_status(ar) @@ -202,10 +205,8 @@ class PTUSB(PTPrinter): class PTLabelData(object): def __init__(self): # margins: '\x1bid\x00\x00' + - self.init = '\x1biR\x01' + '\x1biM\x00' + self.init = '\x1biR\x01' + '\x1biM\x40' + '\x1bid\x00\x00' + '\x1biK\x00' self.raw = '' - # self.fini = '\x1a' # Z / feed ? - self.fini = '\x0c' def addpixels(self, raw): row = 'G' + struct.pack('<H', len(raw)) + raw @@ -236,8 +237,9 @@ class PTLabelData(object): pixels[py / 8] |= 1 << (7 - (py & 7)) self.addpixels(pixels) - def get(self): - return self.init + self.raw + self.fini + def get(self, feedncut = True): + fini = '\x1a' if feedncut else '\x0c' + return self.init + self.raw + fini class PTTape(object): tapes = [] |