Ok, I have python app where I have used tkinter, this app reads /data/pictures.jpg and /data/questions.txt I do not know how to create *.snap file. I read the docs, the tuts, but nothing worked for me. My glued yaml is this probably WRONG piece:
name: autoskola-free8 # you probably want to 'snapcraft register <name>'
version: '8' # just for humans, typically '1.2+git' or '1.3.2'
summary: Program autoskola-free8 for the schools of drive # 79 char long summary
description: |
Simply study your school of drive questions.
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots
apps:
autoskola-free8:
command: python autoskola-free8.py
plugs:
- network
parts:
autoskola-free8.py:
plugin: python
source: ""
source-tag: v8
stage-packages:
- tk
- tk-inter
The app tkinter code is similar to this, which needs to read /data folder in snap and write to sqlite db in snap folder. How to do that snap? I can’t create snap in linux getting errors. THANKS FOR HELP!
# !/usr/bin/python3
#License: MIT, free software
#author: lesna.vevericka@gmail.com
from tkinter import *
from tkinter import filedialog as fd
from tkinter import ttk
from tkinter.messagebox import showinfo
import datetime
import sqlite3
from sqlite3 import Error
# Some variables defined to see if db file is selected
filename1 = None
filename2=None
db_create_dir = None
# Generate new database file based on current date and time
def generate_new_database_file_name():
now = datetime.datetime.now()
# Generating random database name based on date and time
rnd_db_name="db_"+str(now.day)+"_"+str(now.month)+"_"+str(now.year)+"_"+str(now.hour)+"_"+str(now.minute)+"_"+str(now.second)+".sqlite"
# Returning random database name:
return str(rnd_db_name)
#const: no file name selected
def no_file_name_selected():
return "No file selected..."
# Select file dialog to load database *.sqlite
def select_file():
filetypes = (
('Databases sqlite3', '*.sqlite'),
)
global filename1
filename1 = fd.askopenfilename(
title='Open a database file:',
initialdir='./',
filetypes=filetypes)
if str(filename1).strip()=="":
filename1=str(no_file_name_selected())
showinfo(
title='Selected File',
message=filename1
)
# Procedure for menu item to load database file
def load_store():
select_file()
global filename2
if str(filename1).strip()!=str(no_file_name_selected()):
filename2=filename1 # due to function save_edited_items() filename2 is not None
msg_to_load_or_create.after(1000, msg_to_load_or_create.destroy())
print("Loading store from database file: "+str(filename1))
try:
conn = None
conn = sqlite3.connect(filename1) # It's dir with generated filename path
sql1="SELECT * FROM items"
c = conn.cursor()
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured reading database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
# Ask for directory to create new empty database file layout with 1 example item
def create_empty_db():
global db_create_dir
db_create_dir = fd.askdirectory(
title="Select directory for new empty database:",
initialdir="./"
)
print("Creating empty database for Stores program: " + str(db_create_dir))
if str(db_create_dir).strip()!="":
msg_to_load_or_create.after(1000, msg_to_load_or_create.destroy())
db_create_dir=str(db_create_dir)
db_create_dir+="/"+generate_new_database_file_name() #Now it is directory with filename path
global filename2 #this is intersection between filename1 and db_create_dir, always set one of them
filename2=db_create_dir # due to function save_edited_items() filename2 is not None
print("New database: "+db_create_dir)
showinfo(
title='Database will be saved here:',
message=str(db_create_dir)
)
try:
conn = None
conn = sqlite3.connect(db_create_dir) # It's dir with generated filename path
print("Using sqlite version: "+sqlite3.version)
sql_create_items_table = """ CREATE TABLE IF NOT EXISTS items (
id integer PRIMARY KEY,
item text NOT NULL,
remark1 text NOT NULL,
remark2 text NOT NULL,
remark3 text NOT NULL
); """
c = conn.cursor()
c.execute(sql_create_items_table)
conn.commit()
qry="insert into items (id, item, remark1, remark2, remark3) values(null, 'Example item JH4285', 'Rem1', 'Rem2', 'Rem3');"
c.execute(qry)
conn.commit()
sql1="SELECT * FROM items"
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured creating database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
#Searches in databse for mentioned item, this is executable function for db and listbox
def search_in_database():
if search_text_box.get().strip()=="":
showinfo(
title='Database query operation:',
message='Please add at least 1 character into the search box.'
)
return
else:
print("In search box: "+search_text_box.get()+" | selected db column: "+str(value_in_search_radio.get()))
if str(value_in_search_radio.get())=='1':
try:
conn = None
conn = sqlite3.connect(filename2) # It's dir with generated filename path
c = conn.cursor()
sql1="SELECT * FROM items WHERE item LIKE '%"+search_text_box.get()+"%';"
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured searching database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
if str(value_in_search_radio.get())=='2':
try:
conn = None
conn = sqlite3.connect(filename2) # It's dir with generated filename path
c = conn.cursor()
sql1="SELECT * FROM items WHERE remark1 LIKE '%"+search_text_box.get()+"%';"
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured searching database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
if str(value_in_search_radio.get())=='3':
try:
conn = None
conn = sqlite3.connect(filename2) # It's dir with generated filename path
c = conn.cursor()
sql1="SELECT * FROM items WHERE remark2 LIKE '%"+search_text_box.get()+"%';"
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured searching database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
if str(value_in_search_radio.get())=='4':
try:
conn = None
conn = sqlite3.connect(filename2) # It's dir with generated filename path
c = conn.cursor()
sql1="SELECT * FROM items WHERE remark3 LIKE '%"+search_text_box.get()+"%';"
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured searching database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
# Searches the store for mentioned item search_query1, this is the form of search
def search_this_store():
if filename2 is None:
showinfo(
title='Database query operation:',
message='Please load or create database in the menu first.'
)
return
global root4
root4 = Toplevel()
root4.grab_set()
root4.title('Searching in database')
root4.geometry('400x300')
root4.minsize(400, 300)
root4.maxsize(400, 300)
entry_width=45
search_label=Label(root4,text='Select search query:')
search_label.pack()
global search_text_box
search_text_box = ttk.Entry(root4, width=entry_width)
search_text_box.delete(0,END)
search_text_box.pack()
global value_in_search_radio
value_in_search_radio=StringVar()
chart_type_1 = ttk.Radiobutton(root4, text="search item column in database",variable=value_in_search_radio,value='1')#
chart_type_1.pack()
chart_type_2 = ttk.Radiobutton(root4, text="search remark1 column in database",variable=value_in_search_radio,value='2')#
chart_type_2.pack()
chart_type_3 = ttk.Radiobutton(root4, text="search remark2 column in database", variable=value_in_search_radio, value='3') #
chart_type_3.pack()
chart_type_4=ttk.Radiobutton(root4,text="search remark3 column in database",variable=value_in_search_radio,value='4')
chart_type_4.pack()
value_in_search_radio.set('1') # intended to be set as default
search_btn = Button(root4, text = "Search in database", command= search_in_database)
search_btn.pack()
# Insert items from form to the database
def insert_items():
inserts2=[]
inserts2.append('null')
inserts2.append(item_text_box2.get())
inserts2.append(rem1_text_box2.get())
inserts2.append(rem2_text_box2.get())
inserts2.append(rem3_text_box2.get())
print(str(inserts2))
try:
conn = None
conn = sqlite3.connect(filename2) # It's dir with generated filename path
sql_insert = """ INSERT INTO items
(id, item, remark1, remark2, remark3)
VALUES( """+inserts2[0]+""",
'"""+inserts2[1]+"""',
'"""+inserts2[2]+"""',
'"""+inserts2[3]+"""',
'"""+inserts2[4]+"""'
); """
c = conn.cursor()
c.execute(sql_insert)
conn.commit()
showinfo(
title='Database insert operation:',
message='Database inserted with added inserts.'
)
root3.destroy()
sql1="SELECT * FROM items"
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured inserting values into database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
# Add new item to the store via given form, id is autoincrement
def add_item_to_this_store():
if filename2 is None:
showinfo(
title='Database operation error:',
message='Please create or load database to use.'
)
return
global inserts2
inserts2=[]
global root3
root3 = Toplevel()
# Grab Set makes initial window root blank, so you can have open only 1 toplevel
root3.grab_set()
root3.title('Adding item to database')
root3.geometry('400x300')
root3.minsize(400, 300)
root3.maxsize(400, 300)
entry_width=45
ID_label2=Label(root3,text='ID (stays as autoincrement key):')
ID_label2.pack()
item_label2=Label(root3,text='Item:')
item_label2.pack()
global item_text_box2
item_text_box2 = ttk.Entry(root3, width=entry_width)
item_text_box2.delete(0,END)
item_text_box2.pack()
rem1_label2=Label(root3,text='Remark 1:')
rem1_label2.pack()
global rem1_text_box2
rem1_text_box2 = ttk.Entry(root3, width=entry_width)
rem1_text_box2.delete(0,END)
rem1_text_box2.pack()
rem2_label2=Label(root3,text='Remark 2:')
rem2_label2.pack()
global rem2_text_box2
rem2_text_box2 = ttk.Entry(root3, width=entry_width)
rem2_text_box2.delete(0,END)
rem2_text_box2.pack()
rem3_label2=Label(root3,text='Remark 3:')
rem3_label2.pack()
global rem3_text_box2
rem3_text_box2 = ttk.Entry(root3, width=entry_width)
rem3_text_box2.delete(0,END)
rem3_text_box2.pack()
save_edited_item2 = Button(root3, text = "Insert these values", command= insert_items)
save_edited_item2.pack()
def edit_item_in_this_store():
showinfo(
title='Edit item in this store:',
message="Please, double click selected item in the listbox."
)
# Sql commands for database to update current selection of edited item cs in entries=what_to_update, filename1 or db_create_dir=what_filename
def update_edited_items_in_db(what_to_update, what_filename):
try:
conn = None
conn = sqlite3.connect(what_filename) # It's dir with generated filename path
sql_insert = """ UPDATE items
SET id = '"""+what_to_update[0]+"""',
item = '"""+what_to_update[1]+"""',
remark1 = '"""+what_to_update[2]+"""',
remark2 = '"""+what_to_update[3]+"""',
remark3 = '"""+what_to_update[4]+"""'
WHERE
id = """+what_to_update[0]+"""; """
c = conn.cursor()
c.execute(sql_insert)
conn.commit()
showinfo(
title='Database update operation:',
message='Database updated with current selection entries.'
)
root2.destroy()
sql1="SELECT * FROM items"
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured updating database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
# Saves entries from editing the item values form called root2
def save_edited_items():
entries=[]
entries.append(ID_text_box.get())
entries.append(item_text_box.get())
entries.append(rem1_text_box.get())
entries.append(rem2_text_box.get())
entries.append(rem3_text_box.get())
# Save entries[0] which is ID for update statement in db, can't change/load from form entry
entries[0]=init_entries.split(",")[0].strip()
print(str(entries))
if filename2 is not None:
# If you loaded/created store db, use this name path
update_edited_items_in_db(entries, filename2)
# Deletes item from editing form based on the id key which is not being edited but constant id for manipulation
def delete_edited_items():
try:
# init_entries contains comma separated values from double click on the list box, so one row
# we can split init_entries string by comma and get 0 value which is ID
print("Deleting ID from database: "+str(init_entries.split(",")[0].strip()))
conn = None
conn = sqlite3.connect(filename2) # It's dir with generated filename path
sql_insert = """ DELETE FROM items
WHERE id = """+init_entries.split(",")[0].strip()+""";"""
c = conn.cursor()
c.execute(sql_insert)
conn.commit()
showinfo(
title='Database delete operation:',
message='Database deleted for ID='+str(init_entries.split(",")[0].strip())
)
root2.destroy()
sql1="SELECT * FROM items"
c.execute(sql1)
items=c.fetchall()
current_items.delete(1,END)
for rec in items:
current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
except Error as e:
print("Error occured deleting from database file: "+str(e))
showinfo(
title='Database operation error:',
message=str(e)
)
finally:
if conn:
conn.close()
# Will edit selected item in the listbox after double click in edit window
# cs is current selection containing one selected row from listbox with item
def edit_selected_item_in_the_listbox(cs):
global init_entries
init_entries = cs # Saving state of ID, ID can not be changed, we are editing item
if (cs.split(",")[0]) == "ID":
showinfo(
title='Double clicked description item:',
message="Please, select some REAL item. Not the legend."
)
else:
global root2
root2 = Toplevel()
root2.grab_set()
root2.title('Editing item')
root2.geometry('400x300')
root2.minsize(400, 300)
root2.maxsize(400, 300)
entry_width=45
ID_label=Label(root2,text='ID (stays unedited as key):')
ID_label.pack()
global ID_text_box
ID_text_box = ttk.Entry(root2, width=entry_width)
ID_text_box.delete(0,END)
ID_text_box.insert(0,cs.split(",")[0].strip())
ID_text_box.pack()
item_label=Label(root2,text='Item:')
item_label.pack()
global item_text_box
item_text_box = ttk.Entry(root2, width=entry_width)
item_text_box.delete(0,END)
item_text_box.insert(0,cs.split(",")[1].strip())
item_text_box.pack()
rem1_label=Label(root2,text='Remark 1:')
rem1_label.pack()
global rem1_text_box
rem1_text_box = ttk.Entry(root2, width=entry_width)
rem1_text_box.delete(0,END)
rem1_text_box.insert(0,cs.split(",")[2].strip())
rem1_text_box.pack()
rem2_label=Label(root2,text='Remark 2:')
rem2_label.pack()
global rem2_text_box
rem2_text_box = ttk.Entry(root2, width=entry_width)
rem2_text_box.delete(0,END)
rem2_text_box.insert(0,cs.split(",")[3].strip())
rem2_text_box.pack()
rem3_label=Label(root2,text='Remark 3:')
rem3_label.pack()
global rem3_text_box
rem3_text_box = ttk.Entry(root2, width=entry_width)
rem3_text_box.delete(0,END)
rem3_text_box.insert(0,cs.split(",")[4].strip())
rem3_text_box.pack()
save_edited_item = Button(root2, text = "Save these values", command= save_edited_items)
save_edited_item.pack()
delete_edited_item = Button(root2, text = "Delete these values", command= delete_edited_items)
delete_edited_item.pack()
# Function called after double click on the item in the listbox
def dbl_clicked_item_in_listbox(event):
try:
# cs is current selection in the list box to work with after double click
cs=current_items.selection_get()
print("Selected to edit: "+str(cs))
if filename1 is None and db_create_dir is None:
print("No database file created or selected. Please click menu for this.")
showinfo(
title='Double clicked item:',
message="No database file created or selected. Please click menu for this."
)
else:
edit_selected_item_in_the_listbox(cs)
except Error as e:
print(str(e))
root = Tk()
root.title('Stores v22.3-codename: Jirmejahu')
root.geometry('400x300')
# set minimum window size value
root.minsize(400, 300)
# set maximum window size value
root.maxsize(400, 300)
# Creating Menubar
menubar = Menu(root)
# Adding Home Menu
home = Menu(menubar, tearoff = 0)
menubar.add_cascade(label ='Load store', menu = home)
home.add_command(label="Load store from file", command=load_store)
home.add_command(label="Create empty database file", command=create_empty_db)
searchit = Menu(menubar, tearoff = 0)
menubar.add_cascade(label ='Search store', menu = searchit)
global search_query1
search_query1=""
searchit.add_command(label="Search items in this store", command=search_this_store)
searchit.add_command(label="Add new item to this store", command=add_item_to_this_store)
searchit.add_command(label="Edit item in this store=double click", command=edit_item_in_this_store)
# display Menu
root.config(menu = menubar)
#Display message to load or create database first
global msg_to_load_or_create
msg_to_load_or_create=Label(
root,
text='Load or create database file, please.',
)
msg_to_load_or_create.pack(side="top")
# Setting scrollbars and Listbox
scrollbar1 = Scrollbar(root, orient=VERTICAL)
scrollbar2 = Scrollbar(root, orient=HORIZONTAL)
current_items = Listbox(root, height=15, width=60, yscrollcommand=scrollbar1.set)
current_items.insert(0, 'ID, Item Name, Remark1, Remark2, Remark3')
current_items.bind('<Double-1>', dbl_clicked_item_in_listbox)
scrollbar1.config(command=current_items.yview)
scrollbar1.pack(side=RIGHT, fill=Y)
scrollbar2.config(command=current_items.xview)
scrollbar2.pack(side=BOTTOM, fill=X)
current_items.pack()
root.mainloop()