On 2017-01-30 12:28, Tobias Ellinghaus wrote:
Am Montag, 30. Januar 2017, 12:04:03 CET schrieb René Seindal:
Hi
Ho do I make a long running Lua extension not block the darktable GUI?
It depends on what your code does and from where it is called. Some things
have to run in the gui thread and can't be unblocked, others can.
When you export files the export runs in the background somehow.
Exports are an example of what gets run in its own thread. So maybe show some
sample code.
The code takes the currently selected image in darktable, looks them up
in a shotwell sqlite3 database using luasql and updates ratings and tags
in darktable.
It is not something that can be handed off to a sub-process since it
updates darktable.
I have put in a progress bar (background job) but the progress bar
doesn't update and the cancel button doesn't work, because I can't find
a way to hand off control to the gui to update, while looping through
the images, looking stuff up in the other sqlite3 database.
The script is attached.
--
René Seindal - [email protected]
____________________________________________________________________________
darktable user mailing list
to unsubscribe send a mail to [email protected]
#!/usr/bin/lua
local dt = require "darktable"
dt.configuration.check_version(...,{4,0,0})
dt.preferences.register(
"sync-shotwell-tags-and-rating",
"database",
"file",
"location of shotwell database photo.db",
"enter the location of your shotwell database here",
"~/.shotwell/data/photo.db")
local function printf(fmt, ...) dt.print_error(string.format(fmt, ...)) end
local function sprintf(fmt, ...) return string.format(fmt, ...) end
local function shotwell_tag_to_dt(tag)
return (string.gsub((string.gsub(tag, '/', '', 1)), '/', '|'))
end
local function shotwell_lookup(conn, file)
local sql = sprintf('select id,rating from PhotoTable where filename = "%s"', conn:escape(file))
-- printf('sql = %s', sql)
local cur = assert(conn:execute(sql))
local row = cur:fetch({}, "a")
if not row then return end
-- printf("id: %d, rating %d, filename: %s", row.id, row.rating, file)
local id = row.id
local rating = row.rating
cur:close()
-- get tags for photo
local sql = sprintf('select id,name from TagTable where photo_id_list like "%%thumb%016x,%%" order by name desc', id)
-- printf('sql = %s', sql)
local cur = assert(conn:execute(sql))
local tags = {}
local lasttag;
local row = cur:fetch({}, "a")
while row do
-- printf("id: %d, name %s, last %s", row.id, row.name, lasttag)
if not (lasttag and string.find(lasttag, row.name, 0, true) == 1) then
-- printf('match last %s cur %s dt %s', lasttag, row.name, shotwell_tag_to_dt(row.name))
table.insert(tags, shotwell_tag_to_dt(row.name))
lasttag = row.name
end
row = cur:fetch(row, "a")
end
cur:close()
return rating, tags
end
local function shotwell_sync_images(images)
local db = dt.preferences.read("sync-shotwell-tags-and-rating", "database", "string")
-- printf('database file %s', db)
if not db then dt.print("shotwell database location not defined") return end
db = string.gsub(db, '^~', os.getenv('HOME'), 1)
local driver = require 'luasql.sqlite3'
local env = assert(driver.sqlite3())
local conn, err = env:connect(db, "READONLY")
if not conn then dt.print("can't open shotwell database " .. db) env:close() return end
local cancelled = false
local progress = dt.gui.create_job('Sync from shotwell', true, function() cancelled = true; end)
local total = #images
progress.percent = 0;
for count, image in ipairs(images) do
local file = image.path .. '/' .. image.filename
-- printf('file %s', file)
local rating, tags = shotwell_lookup(conn, file)
if rating then
-- printf('\trating %d', rating)
image.rating = rating
for _, tag in pairs(tags) do
-- printf('\ttag %s', tag)
image:attach_tag(dt.tags.create(tag))
end
else
dt.print(sprintf('file %s not found in shotwell database', file))
end
progress.percent = total / count
if cancelled then break end
-- dt.control.sleep(1)
-- coroutine.yield('WAIT_MS', 1)
end
progress.valid = false
conn:close()
env:close()
end
dt.register_event(
"shortcut",
function(event, shortcut) shotwell_sync_images(dt.gui.action_images) end,
"sync rating and tags from shotwell"
)
dt.gui.libs.image.register_action(
"sync shotwell",
function(event, images) shotwell_sync_images(images) end,
"sync rating and tags from shotwell"
)