312 lines
12 KiB
Python
Executable File
312 lines
12 KiB
Python
Executable File
#!/usr/bin/python3
|
|
""" GUI for python-qrcode """
|
|
|
|
# Copyright (C) 2022 Gwyn Ciesla
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
import tempfile
|
|
import os
|
|
import glob
|
|
from shutil import copyfile
|
|
import gettext
|
|
import gi
|
|
gi.require_version('Gtk', '3.0')
|
|
# pylint: disable=wrong-import-position
|
|
from gi.repository import Gtk, GdkPixbuf
|
|
import qrcode
|
|
|
|
import pyquearcode
|
|
|
|
VERSION = '0.2.7'
|
|
|
|
LOCALEDIR = os.path.dirname(pyquearcode.__file__) + '/locales'
|
|
LANGUAGE = os.environ['LANG']
|
|
|
|
if not os.path.isdir(LOCALEDIR + '/' + LANGUAGE):
|
|
LANGUAGE='en'
|
|
|
|
TRANS = gettext.translation('quearcode', localedir=LOCALEDIR, languages=[LANGUAGE])
|
|
TRANS.install()
|
|
|
|
_ = TRANS.gettext
|
|
|
|
LOGO_PATH = os.path.dirname(pyquearcode.__file__) + '/logo.png'
|
|
|
|
class QUEARCODE:
|
|
""" Main block """
|
|
# pylint: disable=too-many-instance-attributes
|
|
# pylint: disable=unused-argument
|
|
def delete_event(self, widget, event, data=None):
|
|
""" Quit button """
|
|
for temp in glob.glob(tempfile.gettempdir() + "/quearcode*.png"):
|
|
os.unlink(temp)
|
|
Gtk.main_quit()
|
|
return False
|
|
# pylint: disable=too-many-arguments
|
|
# pylint: disable=too-many-locals
|
|
def runthing(self, widget, data, error, box, border):
|
|
""" Generate a QR code from a file"""
|
|
filename = data.get_filename()
|
|
errorval = error.get_value()
|
|
|
|
#check file size
|
|
fileinfo = os.stat(filename)
|
|
filesize = fileinfo.st_size
|
|
toobig = 0
|
|
if filesize > 2953 and errorval == 1:
|
|
toobig = 1
|
|
sizelimit = 2953
|
|
if filesize > 2331 and errorval == 2:
|
|
toobig = 1
|
|
sizelimit = 2331
|
|
if filesize > 1663 and errorval == 3:
|
|
toobig = 1
|
|
sizelimit = 1663
|
|
if filesize > 1273 and errorval == 4:
|
|
toobig = 1
|
|
sizelimit = 1273
|
|
|
|
if toobig == 1:
|
|
message = 'Too large to create valid QR code. File is ' + str(filesize) + \
|
|
' bytes, must be less than ' + str(sizelimit)
|
|
# pylint: disable=attribute-defined-outside-init
|
|
self.messdial = Gtk.MessageDialog(parent=self.files, message_format=message, \
|
|
destroy_with_parent=True, type=Gtk.MessageType.ERROR, \
|
|
buttons=Gtk.ButtonsType.CLOSE)
|
|
self.messdial.set_title(_("File error"))
|
|
self.messdial.run()
|
|
self.messdial.destroy()
|
|
else:
|
|
with open(filename, 'r', encoding='utf-8') as file:
|
|
filedata = file.read()
|
|
if errorval == 1:
|
|
errorcol = qrcode.constants.ERROR_CORRECT_L
|
|
if errorval == 2:
|
|
errorcol = qrcode.constants.ERROR_CORRECT_M
|
|
if errorval == 3:
|
|
errorcol = qrcode.constants.ERROR_CORRECT_Q
|
|
if errorval == 4:
|
|
errorcol = qrcode.constants.ERROR_CORRECT_H
|
|
boxval = box.get_value()
|
|
borderval = border.get_value()
|
|
qr_image = qrcode.QRCode(version=None, \
|
|
error_correction=errorcol, \
|
|
box_size=boxval, \
|
|
border=borderval \
|
|
)
|
|
qr_image.add_data(filedata)
|
|
qr_image.make(fit=True)
|
|
|
|
img = qr_image.make_image()
|
|
|
|
for temp in glob.glob(tempfile.gettempdir() + "/quearcode*.png"):
|
|
os.unlink(temp)
|
|
tempf, name = tempfile.mkstemp(suffix=".png", prefix="quearcode")
|
|
img.save(name)
|
|
self.imgdial("clicked", name)
|
|
os.close(tempf)
|
|
|
|
def filehomedial(self, widget, event, data=None):
|
|
""" File selection """
|
|
# pylint: disable=attribute-defined-outside-init
|
|
self.files = Gtk.FileChooserDialog(Gtk.FileChooserAction.OPEN)
|
|
self.files.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, \
|
|
Gtk.ResponseType.OK)
|
|
self.files.set_filename("~/")
|
|
self.files.set_transient_for(self.window)
|
|
self.files.set_title(_("File Selection"))
|
|
self.response = self.files.run()
|
|
if self.response == Gtk.ResponseType.OK:
|
|
self.runthing(self.response, self.files, self.errorscale, \
|
|
self.boxscale, self.borderscale)
|
|
self.files.show()
|
|
self.files.destroy()
|
|
return False
|
|
|
|
def savedial(self, widget, event, imagepath):
|
|
""" File selection """
|
|
# pylint: disable=attribute-defined-outside-init
|
|
self.saves = Gtk.FileChooserDialog(_("File Selection"), self.window, \
|
|
Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, \
|
|
Gtk.STOCK_NEW, Gtk.ResponseType.OK))
|
|
self.saves.set_current_name("quearcode.png")
|
|
self.saves.set_do_overwrite_confirmation(True)
|
|
self.saves.set_transient_for(self.window)
|
|
response = self.saves.run()
|
|
if response == Gtk.ResponseType.OK:
|
|
copyfile(imagepath, self.saves.get_filename())
|
|
self.saves.show()
|
|
self.saves.destroy()
|
|
return False
|
|
|
|
def imgdial(self, event, imagepath):
|
|
""" Image display dialog """
|
|
# pylint: disable=attribute-defined-outside-init
|
|
qrs = Gtk.MessageDialog(parent=self.window, \
|
|
destroy_with_parent=True, message_type=Gtk.MessageType.ERROR)
|
|
qrs.add_buttons(_("Close"), Gtk.ButtonsType.CLOSE)
|
|
qrs.set_title("Quearcode © 2022 Gwyn Ciesla")
|
|
generated = Gtk.Image()
|
|
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(filename=imagepath, \
|
|
width=400, height=400, preserve_aspect_ratio=True)
|
|
generated = Gtk.Image.new_from_pixbuf(pixbuf)
|
|
qrs.set_image(generated)
|
|
|
|
dbox = qrs.get_content_area()
|
|
|
|
self.savebutton = Gtk.Button(label=_("Save..."))
|
|
self.savebutton.connect("clicked", self.savedial, None, imagepath)
|
|
self.savebutton.set_tooltip_markup(_("Save QR code to file"))
|
|
dbox.pack_end(self.savebutton, False, False, 0)
|
|
|
|
qrs.show_all()
|
|
qrs.run()
|
|
qrs.destroy()
|
|
|
|
return False
|
|
|
|
|
|
def generate_qrcode(self, widget, text, error, box, border):
|
|
""" Generate a QR code from text """
|
|
textract = text.get_text()
|
|
errorval = error.get_value()
|
|
if errorval == 1:
|
|
errorcol = qrcode.constants.ERROR_CORRECT_L
|
|
if errorval == 2:
|
|
errorcol = qrcode.constants.ERROR_CORRECT_M
|
|
if errorval == 3:
|
|
errorcol = qrcode.constants.ERROR_CORRECT_Q
|
|
if errorval == 4:
|
|
errorcol = qrcode.constants.ERROR_CORRECT_H
|
|
boxval = box.get_value()
|
|
borderval = border.get_value()
|
|
qr_image = qrcode.QRCode(version=None, \
|
|
error_correction=errorcol, \
|
|
box_size=boxval, \
|
|
border=borderval \
|
|
)
|
|
qr_image.add_data(textract)
|
|
qr_image.make(fit=True)
|
|
|
|
img = qr_image.make_image()
|
|
|
|
for temp in glob.glob(tempfile.gettempdir() + "/quearcode*.png"):
|
|
os.unlink(temp)
|
|
tempf, name = tempfile.mkstemp(suffix=".png", prefix="quearcode")
|
|
img.save(name)
|
|
self.imgdial("clicked", name)
|
|
os.close(tempf)
|
|
|
|
def __init__(self):
|
|
# pylint: disable=too-many-statements
|
|
""" Main loop """
|
|
self.window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
|
|
self.window.set_title("quearcode " + VERSION)
|
|
self.window.set_border_width(10)
|
|
self.window.connect("delete_event", self.delete_event, None)
|
|
|
|
self.mainbox = Gtk.HBox(homogeneous=False, spacing=0)
|
|
self.window.add(self.mainbox)
|
|
|
|
self.rightbox = Gtk.VBox(homogeneous=False, spacing=0)
|
|
self.mainbox.pack_start(self.rightbox, True, True, 0)
|
|
|
|
self.logo = Gtk.Image()
|
|
self.logo.set_from_file(LOGO_PATH)
|
|
self.logo.set_tooltip_markup(_("So meta it hurts."))
|
|
self.rightbox.pack_start(self.logo, True, True, 0)
|
|
|
|
self.errorlabel = Gtk.Label(label=_("Error correction"))
|
|
self.errorlabel.set_tooltip_markup(_("Amount of error correction to build into the code"))
|
|
self.rightbox.pack_start(self.errorlabel, True, True, 0)
|
|
|
|
self.errorscale = Gtk.Scale.new_with_range(0, 1.0, 4.0, 1.0)
|
|
self.errorscale.set_tooltip_markup(_("Amount of error correction to build into the code"))
|
|
self.errorscale.set_value(1.0)
|
|
self.rightbox.pack_start(self.errorscale, True, True, 0)
|
|
|
|
self.boxlabel = Gtk.Label(label=_("Box size in pixels"))
|
|
self.boxlabel.set_tooltip_markup(_("Size of boxes, make huge files, eats RAM like candy"))
|
|
self.rightbox.pack_start(self.boxlabel, True, True, 0)
|
|
|
|
self.boxscale = Gtk.Scale.new_with_range(0, 1.0, 50.0, 1.0)
|
|
self.boxscale.set_tooltip_markup(_("Size of boxes, make huge files, eats RAM like candy"))
|
|
self.boxscale.set_value(10.0)
|
|
self.rightbox.pack_start(self.boxscale, True, True, 0)
|
|
|
|
self.borderlabel = Gtk.Label(label=_("Border size in boxes"))
|
|
self.borderlabel.set_tooltip_markup(_("Size of border, specification minimum is 4."))
|
|
self.rightbox.pack_start(self.borderlabel, True, True, 0)
|
|
|
|
self.borderscale = Gtk.Scale.new_with_range(0, 4.0, 100.0, 1.0)
|
|
self.borderscale.set_tooltip_markup(_("Size of border, specification minimum is 4."))
|
|
self.borderscale.set_value(4.0)
|
|
self.rightbox.pack_start(self.borderscale, True, True, 0)
|
|
|
|
|
|
self.textentry = Gtk.Entry()
|
|
self.textentry.set_max_length(4296)
|
|
self.textentry.set_activates_default(True)
|
|
self.textentry.set_text('quearcode')
|
|
self.textentry.set_tooltip_markup(_("Content for QR Code"))
|
|
self.rightbox.pack_start(self.textentry, True, True, 0)
|
|
|
|
self.genbutton = Gtk.Button(label=_("Generate"))
|
|
self.genbutton.connect("clicked", self.generate_qrcode, self.textentry, \
|
|
self.errorscale, self.boxscale, self.borderscale)
|
|
self.genbutton.set_tooltip_markup(_("Generate QR Code"))
|
|
self.genbutton.set_can_default(True)
|
|
self.window.set_default(self.genbutton)
|
|
self.rightbox.pack_start(self.genbutton, True, True, 0)
|
|
|
|
|
|
self.filehomebutton = Gtk.Button(label=_("Encode file..."))
|
|
self.filehomebutton.connect("clicked", self.filehomedial, None, self.errorscale)
|
|
self.filehomebutton.set_tooltip_markup(_("Encode a file"))
|
|
self.rightbox.pack_start(self.filehomebutton, True, True, 0)
|
|
|
|
|
|
self.quitbutton = Gtk.Button(label=_("Quit"))
|
|
self.quitbutton.connect("clicked", self.delete_event, None)
|
|
self.quitbutton.set_tooltip_markup(_("Exit quearcode"))
|
|
self.rightbox.pack_start(self.quitbutton, True, True, 0)
|
|
|
|
self.quitbutton.show()
|
|
self.borderscale.show()
|
|
self.borderlabel.show()
|
|
self.boxscale.show()
|
|
self.boxlabel.show()
|
|
self.errorscale.show()
|
|
self.errorlabel.show()
|
|
self.genbutton.show()
|
|
self.filehomebutton.show()
|
|
self.textentry.show()
|
|
self.logo.show()
|
|
self.rightbox.show()
|
|
self.mainbox.show()
|
|
self.window.show()
|
|
|
|
|
|
|
|
|
|
def main():
|
|
""" Execute application """
|
|
Gtk.main()
|
|
|
|
if __name__ == "__main__":
|
|
HELLO = QUEARCODE()
|
|
main()
|