Skip to content

Commit

Permalink
Merge pull request #287 from Ghini/ghini-1.0-dev
Browse files Browse the repository at this point in the history
publish early - postscript labels
  • Loading branch information
mfrasca authored Oct 9, 2017
2 parents d9fbb46 + b71c3dc commit 4041b81
Show file tree
Hide file tree
Showing 47 changed files with 2,044 additions and 1,359 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Ghini
======

.. |travis| image:: https://travis-ci.org/Ghini/ghini.desktop.svg
.. |travis| image:: https://travis-ci.org/Ghini/ghini.desktop.svg?branch=ghini-1.0-dev
.. |pypi| image:: https://img.shields.io/pypi/v/bauble.svg
.. |coveralls| image:: https://coveralls.io/repos/Ghini/ghini.desktop/badge.svg?branch=ghini-1.0-dev&service=github

Expand Down
42 changes: 36 additions & 6 deletions bauble/plugins/garden/acc_editor.glade
Original file line number Diff line number Diff line change
Expand Up @@ -3416,16 +3416,46 @@
<property name="yalign">0</property>
<property name="yscale">0</property>
<child>
<object class="GtkButton" id="ver_remove_button">
<object class="GtkVBox" id="vbox9">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="image6">
<object class="GtkButton" id="ver_remove_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-remove</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkImage" id="image6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-remove</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ver_copy_to_taxon_general">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkImage" id="image16">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-go-back</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
Expand Down
19 changes: 19 additions & 0 deletions bauble/plugins/garden/accession.py
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,11 @@ def cell_data_func(col, cell, model, treeiter):
self._sid = self.presenter().view.connect(
button, 'clicked', self.on_remove_button_clicked)

# copy to general tab
button = self.widgets.ver_copy_to_taxon_general
self._sid = self.presenter().view.connect(
button, 'clicked', self.on_copy_to_taxon_general_clicked)

self.update_label()

def on_date_entry_changed(self, entry, data=None):
Expand All @@ -1326,6 +1331,20 @@ def on_date_entry_changed(self, entry, data=None):
self.presenter().remove_problem(PROBLEM, entry)
self.set_model_attr('date', value)

def on_copy_to_taxon_general_clicked(self, button):
if self.model.species is None:
return
parent = self.get_parent()
msg = _("Are you sure you want to copy this verification to the general taxon?")
if not utils.yes_no_dialog(msg):
return
# copy verification species to general tab
if self.model.accession:
self.presenter().parent_ref().view.widgets.acc_species_entry.\
set_text(utils.utf8(self.model.species))
self.presenter()._dirty = True
self.presenter().parent_ref().refresh_sensitivity()

def on_remove_button_clicked(self, button):
parent = self.get_parent()
msg = _("Are you sure you want to remove this verification?")
Expand Down
2 changes: 1 addition & 1 deletion bauble/plugins/garden/plant.py
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ def on_response(button, response):
box.show()
self.view.add_box(box)

def dirty(self):
def is_dirty(self):
return (self.pictures_presenter.is_dirty() or
self.notes_presenter.is_dirty() or
self.prop_presenter.is_dirty() or
Expand Down
33 changes: 30 additions & 3 deletions bauble/plugins/report/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# Copyright 2008-2010 Brett Adams
# Copyright 2012-2017 Mario Frasca <[email protected]>.
# Copyright 2017 Ross Demuth
#
# This file is part of ghini.desktop.
#
Expand Down Expand Up @@ -42,7 +43,7 @@
from bauble.prefs import prefs
import bauble.pluginmgr as pluginmgr
from bauble.plugins.plants import Family, Genus, Species, VernacularName
from bauble.plugins.garden import Accession, Plant, Location
from bauble.plugins.garden import Accession, Plant, Location, Source, Contact
from bauble.plugins.tag import Tag

# TODO: this module should depend on PlantPlugin, GardenPlugin,
Expand Down Expand Up @@ -108,6 +109,9 @@ def get_plant_query(obj, session):
return q.join('accession').filter_by(id=obj.id)
elif isinstance(obj, Location):
return q.filter_by(location_id=obj.id)
elif isinstance(obj, Contact):
return q.join('accession', 'source', 'source_detail').\
filter_by(id=obj.id)
elif isinstance(obj, Tag):
plants = get_plants_pertinent_to(obj.objects, session)
return q.filter(Plant.id.in_([p.id for p in plants]))
Expand Down Expand Up @@ -145,6 +149,8 @@ def get_accession_query(obj, session):
return q.filter_by(id=obj.id)
elif isinstance(obj, Location):
return q.join('plants').filter_by(location_id=obj.id)
elif isinstance(obj, Contact):
return q.join('source', 'source_detail').filter_by(id=obj.id)
elif isinstance(obj, Tag):
acc = get_accessions_pertinent_to(obj.objects, session)
return q.filter(Accession.id.in_([a.id for a in acc]))
Expand Down Expand Up @@ -185,6 +191,9 @@ def get_species_query(obj, session):
elif isinstance(obj, Location):
return q.join('accessions', 'plants', 'location').\
filter_by(id=obj.id)
elif isinstance(obj, Contact):
return q.join('accessions', 'source', 'source_detail').\
filter_by(id=obj.id)
elif isinstance(obj, Tag):
acc = get_species_pertinent_to(obj.objects, session)
return q.filter(Species.id.in_([a.id for a in acc]))
Expand Down Expand Up @@ -215,6 +224,24 @@ def get_location_query(obj, session):
return q.join('plants').filter_by(id=obj.id)
elif isinstance(obj, Accession):
return q.join('plants', 'accession').filter_by(id=obj.id)
elif isinstance(obj, Family):
return q.join('plants', 'accession', 'species', 'genus', 'family').\
filter_by(id=obj.id)
elif isinstance(obj, Genus):
return q.join('plants', 'accession', 'species', 'genus').\
filter_by(id=obj.id)
elif isinstance(obj, Species):
return q.join('plants', 'accession', 'species').\
filter_by(id=obj.id)
elif isinstance(obj, VernacularName):
return q.join('plants', 'accession', 'species', 'vernacular_names').\
filter_by(id=obj.id)
elif isinstance(obj, Contact):
return q.join('plants', 'accession', 'source', 'source_detail').\
filter_by(id=obj.id)
elif isinstance(obj, Tag):
locs = get_locations_pertinent_to(obj.objects, session)
return q.filter(Location.id.in_([l.id for l in locs]))
else:
raise BaubleError(_("Can't get Location from a %s") %
type(obj).__name__)
Expand All @@ -225,7 +252,7 @@ def get_locations_pertinent_to(objs, session=None):
:param objs: an instance of a mapped object
:param session: the session to use for the queries
Return all the species found in objs.
Return all the locations found in objs.
"""
return sorted(
_get_pertinent_objects(Location, get_location_query, objs, session),
Expand Down Expand Up @@ -394,7 +421,7 @@ def set_prefs_for(self, name, formatter_title, settings):
def on_new_button_clicked(self, *args):
# TODO: don't set the OK button as sensitive in the name dialog
# if the name already exists
# TOD0: make "Enter" in the entry fire the default response
# TODO: make "Enter" in the entry fire the default response
d = gtk.Dialog(_("Formatter Name"), self.view.dialog,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
Expand Down
42 changes: 28 additions & 14 deletions bauble/plugins/report/mako/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@


font = {
'\u200b': 0,
u'!': 20, u'A': 36, u'a': 31, u'á': 31, u'Á': 38,
u'"': 23, u'B': 34, u'b': 32, u'à': 31, u'À': 38,
u'#': 40, u'C': 35, u'c': 28, u'â': 31, u'Â': 38,
Expand Down Expand Up @@ -145,10 +146,6 @@ class Code39:
# and end with a single special symbol (we call it '!') which isn't
# included in the 45 encodable characters.

# we only need the 13 chars ' !.0123456789', and they all contain 9
# black units and 6 white units, plus the final separator. this makes
# things a lot easier.

MAP = {'!': 'b b bbb bbb b',
'7': 'b b b bbb bbb',
'-': 'b b b bbb bbb',
Expand Down Expand Up @@ -225,27 +222,44 @@ def letter(cls, letter, height, translate=None, colour='#0000ff'):
class add_qr_functor:
import pyqrcode
def __init__(self):
import io
import StringIO
import re
self.buffer = io.BytesIO()
self.pattern = re.compile('<svg.*height="([0-9]*)".*>(<path.*>)</svg>')
self.buffer = StringIO.StringIO()
self.pattern = {
'svg': re.compile('<svg.*height="([0-9]*)".*>(<path.*>)</svg>'),
'ps': re.compile('.* ([0-9]*).*(^/M.*)%%EOF.*', re.MULTILINE | re.DOTALL),
}

def __call__(self, x, y, text, scale=1, side=None):
def __call__(self, x, y, text, scale=1, side=None, format='svg'):
qr = self.pyqrcode.create(text)
self.buffer.truncate(0)
self.buffer.seek(0)
qr.svg(self.buffer, xmldecl=False, quiet_zone=0, scale=scale)
match = self.pattern.match(self.buffer.getvalue())
if format == 'svg':
qr.svg(self.buffer, xmldecl=False, quiet_zone=0, scale=scale)
else:
qr.eps(self.buffer, quiet_zone=0)
match = self.pattern[format].match(self.buffer.getvalue())
result_list = [match.group(2)]
transform = []
if x != 0 or y != 0:
transform.append("translate(%s,%s)" % (x, y))
if format == 'ps':
transform.append("%s %s translate" % (x, y))
else:
transform.append("translate(%s,%s)" % (x, y))
if side is not None:
orig_side = float(match.group(1))
transform.append("scale(%s)" % (side / orig_side))
if format == 'ps':
transform.append("%s %s scale" % (side / orig_side, side / orig_side))
else:
transform.append("scale(%s)" % (side / orig_side))
if transform:
result_list.insert(0, '<g transform="%s">' % (''.join(transform)))
result_list.append('</g>')
if format == 'ps':
result_list = transform + result_list
else:
result_list.insert(0, '<g transform="%s">' % (''.join(transform)))
result_list.append('</g>')
if format == 'ps':
result_list = ['gsave'] + result_list + ["grestore"]
return '\n'.join(result_list)

add_qr = add_qr_functor()
Expand Down
Binary file not shown.
28 changes: 21 additions & 7 deletions bauble/plugins/report/mako/templates/accession-label-qr.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions bauble/plugins/report/mako/templates/accession-label.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion bauble/plugins/report/mako/templates/label-engraving.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 4041b81

Please sign in to comment.