Happy half-way through Devember (almost, kinda). Time for another update!
It has been a frustrating couple of weeks working on the tagging system. However, I do now have something that works. Let’s start from the top.
The tagging system is implemented using a pair of tables - in addition to the “images” table that I already had - in the SQLite database. These are tags, which holds the mapping from tag id to tag name, and image_tags, which contains a mapping from image id to tag id. I am vaguely aware that there are other methods for implementing tagging systems, but I wanted something simple that works. The tables I have added look like this:
image_tags tags
id | imageID |tagID id | name
----+---------+------ ----+-------
1 | 1 | 1 1 | "tag1"
2 | 1 | 2 2 | "tag2"
(I really hope my formatting doesn’t get messed up here.) The sample data in these tables indicates that the image with ID 1 is tagged with the tags “tag1” and “tag2”, with tagIDs 1 and 2, respectively.
Now that I have a working table structure I need a way of adding new tags to an image. I’ve changed the layout of the main window slightly here to add a new button for editing tags:
I have one image in my list (at ID 1) - indeed this is the screenshot from my previous post :D. Below the caption editor box there are now two buttons, the “Edit tags” button and the old save button. Clicking the edit tags button brings up a new dialog:

At the top is a text box for writing the name of a new tag to associate with the current image (the one selected in the main window). Below this is a list view that lists all of the tags that are currently associated with the list. This is using a Qt relational model, which was the source of endless pain when trying to get this to work. To the right are three buttons for adding a new tag (using the text from the text box as the name), removing the selected tag, and reverting changes. At the bottom are buttons for canceling current changes or accepting (OK) changes. Both of these buttons close the dialog.
The text box has a completion based on tags that are already in the tags table - including those that are not linked to the current image (otherwise it would be pretty useless) - and all changes are local to the dialog until the OK button is clicked to accept the changes, the changes are reverted using the revert button, or the whole editing session is cancelled (and changes reverted). At present, there isn’t a way to modify tags in-place, but I’m not sure there should be.
The problems I encountered were trying to get the QSqlRelationalTableModel
to update the correct tables when adding tags. Indeed, the relational table establishes a correlation between the tagID column of the image_tags table, and the name (via id) of the tags table. I assumed, seemingly wrongly, that adding a new name associated with the current image ID through the model would also perform the insert into the tags table. Unfortunately, neither case seemed to work properly. When the tag name didn’t already exist, the model failed to insert a new entry into tags. When the tag did exist, the relation of the model would not allow me to insert a tagID, imageID pair into the image_tags table. Moreover, when I tried to insert an imageID, name pair, it didn’t associate the tagID with the requested name. (Nightmare!)
In the end I gave up trying to use the model to perform the inserts and instead wrote the SQL code by hand which is ugly, but does what I need it to. I asked on StackOverflow for a more idiomatic solution, but as of yet I’ve had no responses. I did worry that not using the model would not allow me to make use of the transactional nature of models, but I managed to get around this by using the transaction
function from the database handle itself.
I still have a fair amount of work to do. I haven’t yet implemented rendering PDFs or any other export functionality. I also need to implement the filtering function for the main window, which will also involve some SQL madness and creating a new dialog box. However, I am feeling quite a lot more comfortable with the Qt framework. I also need to figure out how to build a Windows installer for this eventually, in order to make the process of installing it simpler for my mother.
Here is the GitHub link for the code at this point in time: GitHub - inakleinbottle/caption_manager at 44efc2954bf76664f1444e8ccac2feb874baf0c9
I would appreciate any feedback or advice about how to proceed from knowledgeable and/or opinionated members.