Add version 0.8
This commit is contained in:
parent
3f3fa383cb
commit
42482c5a99
15
NEWS.md
15
NEWS.md
|
@ -1,5 +1,20 @@
|
||||||
# Cozy Catalog news
|
# Cozy Catalog news
|
||||||
|
|
||||||
|
## [0.8] - 2024-02-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Toolbar icons
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Modify (Ctrl-M) is now Update (Ctrl-U).
|
||||||
|
* File dialogs now use Zenity under X11 if available.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
* Shorcut keys from toolbar buttons
|
||||||
|
|
||||||
## [0.7] - 2023-01-26
|
## [0.7] - 2023-01-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -10,7 +10,7 @@ Cozy Catalog is a little personal database, mainly for media libraries and the l
|
||||||
|
|
||||||
The user interface should be fairly obvious.
|
The user interface should be fairly obvious.
|
||||||
|
|
||||||
As of 26 January 2023, the code has been used in production for a week or two without issues. Please back up your data.
|
As of early 2024, the code has been used in production for almost a year with no new issues. Please back up your data anyway.
|
||||||
|
|
||||||
## System requirements
|
## System requirements
|
||||||
|
|
||||||
|
@ -22,4 +22,4 @@ Recommended screen resolution: 1024x768.
|
||||||
|
|
||||||
Cozy Catalog is open source under the MIT license. See source code for details.
|
Cozy Catalog is open source under the MIT license. See source code for details.
|
||||||
|
|
||||||
You can usually find me on IRC, in the #ctrl-c channel of tilde.chat, or else as @notimetoplay on the elekk.xyz Mastodon instance. Would love to hear from you.
|
You can find native builds on itch.io, and the source code on tildegit. Feedback is welcome in either place.
|
||||||
|
|
167
catalog.tcl
167
catalog.tcl
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env tclsh
|
#!/usr/bin/env tclsh
|
||||||
#
|
#
|
||||||
# Cozy Catalog: a little personal database for media libraries.
|
# Cozy Catalog: a little personal database for media libraries.
|
||||||
# Copyright 2023 Felix Pleșoianu <https://felix.plesoianu.ro/>
|
# Copyright 2023, 2024 Felix Pleșoianu <https://felix.plesoianu.ro/>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -27,7 +27,7 @@ package require Tk 8.5
|
||||||
package require try
|
package require try
|
||||||
package require csv
|
package require csv
|
||||||
|
|
||||||
set about_text "A personal database\nVersion 0.7a (9 Mar 2023)\nMIT License"
|
set about_text "A personal database\nVersion 0.8 (4 Feb 2024)\nMIT License"
|
||||||
set credits_text "Made by No Time To Play\nbased on knowledge\nfrom TkDocs.com"
|
set credits_text "Made by No Time To Play\nbased on knowledge\nfrom TkDocs.com"
|
||||||
set site_link "https://ctrl-c.club/~nttp/toys/catalog/"
|
set site_link "https://ctrl-c.club/~nttp/toys/catalog/"
|
||||||
|
|
||||||
|
@ -116,20 +116,19 @@ wm title . "Cozy Catalog"
|
||||||
option add *tearOff 0
|
option add *tearOff 0
|
||||||
. configure -padx 4
|
. configure -padx 4
|
||||||
|
|
||||||
set icon_data "
|
image create photo app_icon -data "
|
||||||
R0lGODdhIAAgALEAAAAAAP8AAMzMAP/MzCH5BAEAAAEALAAAAAAgACAAAAKFjI+py+0Po5y0VoCz
|
R0lGODdhIAAgALEAAAAAAP8AAMzMAP/MzCH5BAEAAAEALAAAAAAgACAAAAKFjI+py+0Po5y0VoCz
|
||||||
xjYAAYYiCFzjGZbSdw4Dqj7s6LqwfGL1gOXOlxGwNCRhL7aYFWEjZGLYE+ZIUedBicqmGFht1mro
|
xjYAAYYiCFzjGZbSdw4Dqj7s6LqwfGL1gOXOlxGwNCRhL7aYFWEjZGLYE+ZIUedBicqmGFht1mro
|
||||||
en3J8RjsyXWjInQ6tVwq3W95Oy78NddYN4BnlsPD5SKm9TeYVGMoWEi4aIboqLizYSk5qWAJsdnh
|
en3J8RjsyXWjInQ6tVwq3W95Oy78NddYN4BnlsPD5SKm9TeYVGMoWEi4aIboqLizYSk5qWAJsdnh
|
||||||
+QkaKmpQAAA7
|
+QkaKmpQAAA7
|
||||||
"
|
"
|
||||||
image create photo app_icon -data $icon_data
|
|
||||||
wm iconphoto . app_icon
|
wm iconphoto . app_icon
|
||||||
|
|
||||||
if {[tk windowingsystem] eq "x11"} {
|
if {[tk windowingsystem] eq "x11"} {
|
||||||
ttk::style theme use "clam"
|
ttk::style theme use "clam"
|
||||||
}
|
}
|
||||||
|
|
||||||
pack [ttk::frame .toolbar] -side top -pady 4
|
pack [ttk::frame .tools] -side top -pady 4
|
||||||
|
|
||||||
ttk::frame .status
|
ttk::frame .status
|
||||||
ttk::label .status.line -relief sunken -textvar status
|
ttk::label .status.line -relief sunken -textvar status
|
||||||
|
@ -173,35 +172,68 @@ ttk::treeview .tabs.search.results -selectmode browse -height 20 \
|
||||||
.tabs.search.results heading "tags" -text "Tags"
|
.tabs.search.results heading "tags" -text "Tags"
|
||||||
tk_util::pack_scrolled .tabs.search.results
|
tk_util::pack_scrolled .tabs.search.results
|
||||||
|
|
||||||
ttk::button .toolbar.new -text "New" -width 8 -under 0 -command do_new
|
image create photo i_new -data "
|
||||||
ttk::button .toolbar.bOpen -text "Open" -width 8 -under 0 -command do_open
|
R0lGODdhEAAQALEAAAAAAP8AAP//////ACH5BAEAAAEALAAAAAAQABAAAAItjI+JwK0romDPADkH
|
||||||
ttk::button .toolbar.save -text "Save" -width 8 -under 0 -command do_save
|
qFeCoT1d1FDJiE0Kim1n6q0wKc8uZNfwfbDxWQpWhoYCADs=
|
||||||
|
"
|
||||||
|
image create photo i_open -data "
|
||||||
|
R0lGODdhEAAQALEAAAAAAP8AAP//////ACH5BAEAAAEALAAAAAAQABAAAAIwjI+pu+CMgJiuKjlz
|
||||||
|
Bgnr3W3VyBkYMKSqWp7r2wroyx7STA9l4OTpbiKNIMSikVgAADs=
|
||||||
|
"
|
||||||
|
image create photo i_props -data "
|
||||||
|
R0lGODdhEAAQALEAAAAAAP8AAP//////ACH5BAEAAAEALAAAAAAQABAAAAIzjI9pwO0KhJwSQOEY
|
||||||
|
vnTaFGUh122gF1UcMAwis3jtPH8pRtN21b57dfsgbh3hwQdTKJUFADs=
|
||||||
|
"
|
||||||
|
image create photo i_rev -data "
|
||||||
|
R0lGODdhEAAQALEAAAAAAP8AAP//////ACH5BAEAAAEALAAAAAAQABAAAAI2jI9pwK0IhBTsrUkH
|
||||||
|
sHGCoT2d1FTJiFEKOm6np5VO0H3gfbs1zuuwDPJ5PDZhilJayJKW5qEAADs=
|
||||||
|
"
|
||||||
|
image create photo i_save -data "
|
||||||
|
R0lGODdhEAAQALEAAAAAAP8AAP//////ACH5BAEAAAEALAAAAAAQABAAAAI+jI95wOLOEhvgVUAR
|
||||||
|
plZssAzc44lZsFHMZIKoCcduuq6t8ZGQOPN6ecrpPjjfkFfE1CZKXCrGc6GWVIU1UQAAOw==
|
||||||
|
"
|
||||||
|
image create photo i_ch -data "
|
||||||
|
R0lGODdhEAAQALEAAAAAAP8AAP//////ACH5BAEAAAEALAAAAAAQABAAAAIsjI+pywrfDhgDtlnr
|
||||||
|
pRiwzn1cuIBaOZ5O6pXCQ7qvWgLCG1C6bjyQD2xFFAUAOw==
|
||||||
|
"
|
||||||
|
image create photo i_del -data "
|
||||||
|
R0lGODdhEAAQALEAAAAAAP8AAP////+A/yH5BAEAAAEALAAAAAAQABAAAAI4jI+pMT17nHzKiStc
|
||||||
|
arhnanBANzbRgI2C+oVoyrbMewGxOac1hudxCcp5Lj0X7RM8TZIbDeSJKAAAOw==
|
||||||
|
"
|
||||||
|
image create photo i_ins -data "
|
||||||
|
R0lGODdhEAAQALEAAAAAAP8AAP//////ACH5BAEAAAEALAAAAAAQABAAAAIvjI+pAe29zJh0rgej
|
||||||
|
rENjp3GUxmQJtnUKIAhACSJs+wbcMbv11bqMRyMZYsLioQAAOw==
|
||||||
|
"
|
||||||
|
|
||||||
ttk::separator .toolbar.sep1 -orient vertical
|
ttk::button .tools.new -text "New" -w 7 -im i_new -comp left -comm do_new
|
||||||
|
ttk::button .tools.bOpen -text "Open" -w 7 -im i_open -comp left -comm do_open
|
||||||
|
ttk::button .tools.save -text "Save" -w 7 -im i_save -comp left -comm do_save
|
||||||
|
|
||||||
ttk::button .toolbar.reload -text "Reload" -width 8 -under 0 -command do_reload
|
ttk::separator .tools.sep1 -orient vertical
|
||||||
ttk::button .toolbar.stats -text "Stats" -width 8 -under 1 -command show_stats
|
|
||||||
|
|
||||||
ttk::separator .toolbar.sep2 -orient vertical
|
ttk::button .tools.reload -text "Reload" -w 7 -im i_rev -comp left -comm do_rev
|
||||||
|
ttk::button .tools.stat -text "Stats" -w 7 -im i_props -comp left -comm do_stat
|
||||||
|
|
||||||
ttk::button .toolbar.ins -text "Insert" -width 8 -under 3 -command do_insert
|
ttk::separator .tools.sep2 -orient vertical
|
||||||
ttk::button .toolbar.ren -text "Modify" -width 8 -under 0 -command do_modify
|
|
||||||
ttk::button .toolbar.del -text "Delete" -width 8 -under 0 -command do_delete
|
|
||||||
|
|
||||||
pack .toolbar.new -side left
|
ttk::button .tools.ins -text "Insert" -w 7 -im i_ins -comp left -comm do_insert
|
||||||
pack .toolbar.bOpen -side left
|
ttk::button .tools.ren -text "Update" -w 7 -im i_ch -comp left -comm do_modify
|
||||||
pack .toolbar.save -side left
|
ttk::button .tools.del -text "Delete" -w 7 -im i_del -comp left -comm do_delete
|
||||||
|
|
||||||
pack .toolbar.sep1 -side left -padx 4 -pady 4 -fill y
|
pack .tools.new -side left
|
||||||
|
pack .tools.bOpen -side left
|
||||||
|
pack .tools.save -side left
|
||||||
|
|
||||||
pack .toolbar.reload -side left
|
pack .tools.sep1 -side left -padx 4 -pady 4 -fill y
|
||||||
pack .toolbar.stats -side left
|
|
||||||
|
|
||||||
pack .toolbar.sep2 -side left -padx 4 -pady 4 -fill y
|
pack .tools.reload -side left
|
||||||
|
pack .tools.stat -side left
|
||||||
|
|
||||||
pack .toolbar.ins -side left
|
pack .tools.sep2 -side left -padx 4 -pady 4 -fill y
|
||||||
pack .toolbar.ren -side left
|
|
||||||
pack .toolbar.del -side left
|
pack .tools.ins -side left
|
||||||
|
pack .tools.ren -side left
|
||||||
|
pack .tools.del -side left
|
||||||
|
|
||||||
. configure -menu [menu .menubar]
|
. configure -menu [menu .menubar]
|
||||||
|
|
||||||
|
@ -211,15 +243,15 @@ $m add command -label "Open..." -command do_open -under 0 -accel "Ctrl-O"
|
||||||
$m add command -label "Save" -command do_save -under 0 -accel "Ctrl-S"
|
$m add command -label "Save" -command do_save -under 0 -accel "Ctrl-S"
|
||||||
$m add separator
|
$m add separator
|
||||||
$m add command -label "Save as..." -command do_save_as -under 5
|
$m add command -label "Save as..." -command do_save_as -under 5
|
||||||
$m add command -label "Reload" -command do_reload -under 0 -accel "Ctrl-R"
|
$m add command -label "Reload" -command do_rev -under 0 -accel "Ctrl-R"
|
||||||
$m add command -label "Statistics" -command show_stats -under 1 -accel "Ctrl-T"
|
$m add command -label "Statistics" -command do_stat -under 1 -accel "Ctrl-T"
|
||||||
$m add separator
|
$m add separator
|
||||||
$m add command -label "Quit" -command do_quit -under 0 -accel "Ctrl-Q"
|
$m add command -label "Quit" -command do_quit -under 0 -accel "Ctrl-Q"
|
||||||
.menubar add cascade -menu .menubar.mFile -label "File" -underline 0
|
.menubar add cascade -menu .menubar.mFile -label "File" -underline 0
|
||||||
|
|
||||||
set m [menu .menubar.item]
|
set m [menu .menubar.item]
|
||||||
$m add command -label "Insert" -command do_insert -under 0 -accel "Ctrl-I"
|
$m add command -label "Insert" -command do_insert -under 0 -accel "Ctrl-I"
|
||||||
$m add command -label "Modify" -command do_modify -under 4 -accel "Ctrl-M"
|
$m add command -label "Update" -command do_modify -under 4 -accel "Ctrl-U"
|
||||||
$m add command -label "Delete" -command do_delete -under 4 -accel "Ctrl-D"
|
$m add command -label "Delete" -command do_delete -under 4 -accel "Ctrl-D"
|
||||||
$m add separator
|
$m add separator
|
||||||
$m add command -label "Copy details" -under 0 -accel "Ctrl-C" \
|
$m add command -label "Copy details" -under 0 -accel "Ctrl-C" \
|
||||||
|
@ -253,15 +285,15 @@ bind .tabs.search.term <Return> {search_for $search_term}
|
||||||
bind . <Control-n> do_new
|
bind . <Control-n> do_new
|
||||||
bind . <Control-o> do_open
|
bind . <Control-o> do_open
|
||||||
bind . <Control-s> do_save
|
bind . <Control-s> do_save
|
||||||
bind . <Control-r> do_reload
|
bind . <Control-r> do_rev
|
||||||
bind . <Control-t> show_stats
|
bind . <Control-t> do_stat
|
||||||
bind . <Control-q> do_quit
|
bind . <Control-q> do_quit
|
||||||
|
|
||||||
bind . <Command-n> do_new
|
bind . <Command-n> do_new
|
||||||
bind . <Command-o> do_open
|
bind . <Command-o> do_open
|
||||||
bind . <Command-s> do_save
|
bind . <Command-s> do_save
|
||||||
bind . <Command-r> do_reload
|
bind . <Command-r> do_rev
|
||||||
bind . <Command-t> show_stats
|
bind . <Command-t> do_stat
|
||||||
bind . <Command-q> do_quit
|
bind . <Command-q> do_quit
|
||||||
|
|
||||||
bind . <Control-i> do_insert
|
bind . <Control-i> do_insert
|
||||||
|
@ -406,10 +438,16 @@ proc do_open {} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set choice [tk_getOpenFile -parent . \
|
|
||||||
-title "Open existing database" \
|
if {[tk windowingsystem] == "x11" && [auto_execok "zenity"] ne ""} {
|
||||||
-initialdir [file_dir $file_name] \
|
set choice [open_with_zenity $file_name]
|
||||||
-filetypes $file_types]
|
} else {
|
||||||
|
set choice [tk_getOpenFile -parent . \
|
||||||
|
-title "Open existing database" \
|
||||||
|
-initialdir [file_dir $file_name] \
|
||||||
|
-filetypes $file_types]
|
||||||
|
}
|
||||||
|
|
||||||
if {[string length $choice] == 0} {
|
if {[string length $choice] == 0} {
|
||||||
set status "Opening canceled."
|
set status "Opening canceled."
|
||||||
} elseif {![file isfile $choice]} {
|
} elseif {![file isfile $choice]} {
|
||||||
|
@ -423,6 +461,25 @@ proc do_open {} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc open_with_zenity file_name {
|
||||||
|
try {
|
||||||
|
if {$file_name ne ""} {
|
||||||
|
return [exec zenity --file-selection \
|
||||||
|
--title "Open existing database" \
|
||||||
|
--filename $file_name \
|
||||||
|
--file-filter "All files | *" \
|
||||||
|
--file-filter "CSV files | *.csv"]
|
||||||
|
} else {
|
||||||
|
return [exec zenity --file-selection \
|
||||||
|
--title "Open existing database" \
|
||||||
|
--file-filter "All files | *" \
|
||||||
|
--file-filter "CSV files | *.csv"]
|
||||||
|
}
|
||||||
|
} trap CHILDSTATUS {results options} {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
proc load_file full_path {
|
proc load_file full_path {
|
||||||
global status modified
|
global status modified
|
||||||
|
|
||||||
|
@ -496,10 +553,15 @@ proc do_save {} {
|
||||||
proc do_save_as {} {
|
proc do_save_as {} {
|
||||||
global file_name file_types status
|
global file_name file_types status
|
||||||
|
|
||||||
set choice [tk_getSaveFile -parent . \
|
if {[tk windowingsystem] == "x11" && [auto_execok "zenity"] ne ""} {
|
||||||
-title "Save file as..." \
|
set choice [save_with_zenity $file_name]
|
||||||
-initialdir [file_dir $file_name] \
|
} else {
|
||||||
-filetypes $file_types]
|
set choice [tk_getSaveFile -parent . \
|
||||||
|
-title "Save database as..." \
|
||||||
|
-initialdir [file_dir $file_name] \
|
||||||
|
-filetypes $file_types]
|
||||||
|
}
|
||||||
|
|
||||||
if {[string length $choice] == 0} {
|
if {[string length $choice] == 0} {
|
||||||
set status "Save canceled."
|
set status "Save canceled."
|
||||||
} elseif {[save_file $choice]} {
|
} elseif {[save_file $choice]} {
|
||||||
|
@ -507,6 +569,27 @@ proc do_save_as {} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc save_with_zenity file_name {
|
||||||
|
try {
|
||||||
|
if {$file_name ne ""} {
|
||||||
|
return [exec zenity --file-selection \
|
||||||
|
--title "Save database as..." \
|
||||||
|
--save --confirm-overwrite \
|
||||||
|
--filename $file_name \
|
||||||
|
--file-filter "All files | *" \
|
||||||
|
--file-filter "CSV files | *.csv"]
|
||||||
|
} else {
|
||||||
|
return [exec zenity --file-selection \
|
||||||
|
--title "Save database as..." \
|
||||||
|
--save --confirm-overwrite \
|
||||||
|
--file-filter "All files | *" \
|
||||||
|
--file-filter "CSV files | *.csv"]
|
||||||
|
}
|
||||||
|
} trap CHILDSTATUS {results options} {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
proc save_file full_path {
|
proc save_file full_path {
|
||||||
global columns modified status
|
global columns modified status
|
||||||
|
|
||||||
|
@ -532,7 +615,7 @@ proc save_file full_path {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc do_reload {} {
|
proc do_rev {} {
|
||||||
global file_name status
|
global file_name status
|
||||||
if {$file_name eq ""} {
|
if {$file_name eq ""} {
|
||||||
tk_messageBox -parent . \
|
tk_messageBox -parent . \
|
||||||
|
@ -554,7 +637,7 @@ proc do_reload {} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc show_stats {} {
|
proc do_stat {} {
|
||||||
set cats [llength [dict keys $db::index]]
|
set cats [llength [dict keys $db::index]]
|
||||||
set items [llength $db::records]
|
set items [llength $db::records]
|
||||||
set average [expr {$items / $cats}]
|
set average [expr {$items / $cats}]
|
||||||
|
|
Loading…
Reference in New Issue