summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ptgui.glade112
-rw-r--r--ptgui.py76
-rw-r--r--ptlayout.py44
-rw-r--r--pttarget.py16
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 &amp; 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>
diff --git a/ptgui.py b/ptgui.py
index c3a0f0b..d5356d7 100644
--- a/ptgui.py
+++ b/ptgui.py
@@ -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 = []