Minor rather than patch: two of these change what the panel does, not only
what it gets right. Everything here was reported in thread 374940 on the
first day the dock existed.
-
The panel no longer comes back on screen at startup. thiago.eec asked
for it to stay hidden the way the EPUBCheck and ACE plugins do (#20) and
Doitsu agreed (#21). Those two are dialogs and get it for free; a dock does
not —QMainWindow.restoreStaterestores a dock's visibility along with
its area and size, so a session that ended with the panel open started the
next one with it open, over a book nothing had validated and with an empty
panel.The position is still remembered; only the visibility is not. That is
why this is a second, deferred close rather than dropping theobjectName
and giving up onrestoreState— one request is not worth trading for
another. calibre queuesrestore_stateaftercreate_actions(), which is
where this dock is built, so the close is queued to land behind it. If a
later calibre reorders that, the close simply happens early and the panel is
visible again, which is today's behaviour: a wrong guess costs the request,
not the plugin. A panel that already has findings in it is never closed
underneath the user, whatever the timers do. -
The settings are reachable from inside the editor. thiago.eec asked
for that (#20) and Doitsu suggested where (#21): the toolbar button now has
a dropdown. Clicking the button still validates —toolbar_button_popup_mode = 'button'is calibre'sMenuButtonPopup, so the click keeps the meaning
it had — and the arrow opens Validate now, Show the results panel and
epubveri settings…. The results panel's right-click menu has the settings
entry too, which is the other moment you want them: you are looking at the
rows a setting decides.It is the same page calibre builds under Preferences → Plugins →
Customize, in a dialog of our own — one page, two doors, so the two can
never drift into offering different things.Changing a setting re-lists the run already in hand, without validating
again: the switches decide what is listed and the whole report is already
here. Someone who turns usage notes on and sees nothing change would
reasonably conclude the setting does not work. The sort setting applies
immediately too, this once — it is otherwise applied only when a session's
first results arrive, so that a header click is not undone by validating
again, but a person who has just chosen an order in the dialog means now.Show the results panel exists because the dock is hidden at startup and
closable: without it, a user who has closed the panel has no way back to the
last run's findings except by validating a book that has not changed. -
Fixed before it shipped: the column you sorted by was not the one that
came back. The loop that tints each row reused the name holding the sort
column, so after a re-validation the table sorted by whichever column
happened to be last — Message. It looked plausible, because it was
sorted; it simply was not sorted by what the user had clicked. Found while
proving another test could fail, which is the argument for that habit: the
bug was in the same commit as the feature and no green suite would have
shown it. -
Rows can be selected, copied and exported. Doitsu asked for the three
together (#21) and they are one feature: a panel you cannot get text out of
makes people retype findings or photograph them. Ctrl+click and Shift+click
select; Ctrl+C copies the selection as tab-separated lines, in the order
on screen, because the two things people do with this are paste it into a
forum post and paste it into a spreadsheet. Right-click for the rest: copy
everything, select all, and the two exports.The clipboard write is retried with a read-back, which is not defensive
coding for its own sake — Doitsu's plugin documents the reason and it is a
fact about Windows rather than about Qt:SetClipboardDatafails outright
while another process has the clipboard open, nothing retries, and the copy
silently does nothing.The two exports answer different questions, on purpose. Save the table
as CSV writes what you are looking at — your display settings, your sort
order — through Python'scsvwriter, because epubveri's messages carry a
comma and a double quote in the same sentence and a handmade writer gets one
of them wrong. Save epubveri's full report as JSON writes the envelope
whole, filtered by nothing, in the format the other veripublica tools read.
That is the file to attach when something looks wrong, and someone who has
switched usage notes off must not send a report with the usage notes
missing.Ctrl+C and Ctrl+A are bound to the table rather than to the window: the
editor has its own Ctrl+C, and a shortcut that reaches past the widget it
belongs to takes it away from the text being edited. -
Sortable columns, opening severest first. thiago.eec asked for
sortable columns "particularly by severity" (#20); Doitsu agreed (#21).
Click any header to reorder, click again to reverse — and the first column
is called Severity now, because a column you are meant to click has to
say what it is.Two things a table like this gets wrong when it is simply handed to Qt, and
both are avoided here: severity would sort alphabetically, which orders
it ERROR, FATAL, INFO, USAGE, WARNING and puts a fatal below an error; and
the line number would sort as text, putting line 10 before line 9.
Sigil's own results table has the second one. Ranking is by severity with
advisories last — they never move the verdict — and every column breaks ties
on the order epubveri produced the findings in, so each severity group
still reads top-to-bottom, which is what epubveri's own--sort severity
promises.The panel now opens severest first, where before it opened in the order
the validator emitted. Three things already agreed on that order and this
plugin was the one out of step: epubveri's CLI shows a person severity-first
by default, calibre's own Check Book sorts(100 - level, name), and — the
one nobody had noticed — the Sigil plugin has always sorted by severity.
The JSON envelope is in document order on purpose, so that a tool never
inherits an order its user chose; picking one is the plugin's job and it had
not been done. -
A setting for that order: Preferences → Plugins → epubveri → Customize.
Three values, and they are epubveri's own--sortwords rather than a
vocabulary invented for plugins:severity(the default),severity-low,
document. It decides how the panel opens; a header click beats it for
the rest of the session and nothing about the order survives a restart. An
order chosen for one book is a passing thought, not a setting.documentis offered by not sorting at all — Qt has no unsorted state
once sorting is enabled — and clicking a header still works from there, so
choosing it does not cost the feature. -
The rows are tinted by severity again. thiago.eec asked for the line
colours he had in Doitsu's plugin (#20) and Doitsu posted the set from his
Sigil one (#21). The light palette is his, to the byte — pale red for
fatal and error, which share a colour there and share one here, pale yellow
for warning, pale cyan for info and usage — because the request is for the
colours people already know, and two plugins that look almost alike are
worse than two that look the same.The dark theme is where this differs from his, and deliberately. His
paints those pale rows in both themes and forces the text black on top of
them; that is what thiago's own 0.0.7 contribution had to do to keep them
readable, and it makes a dark editor grow bright bands. Here the tint
follows the theme — the same three hue families at dark lightness — and
no foreground is set at all, so the text stays whatever colour the
user's theme chose. Which theme is in use is read off the widget's own
palette rather than asked of calibre, so it is right for a version that has
nois_dark_theme, and right when someone switches theme without a
restart.Advisory findings take the calm cyan: they never move the verdict. A
severity the table does not know is left untinted rather than defaulted
into a family, and the colour is never the only signal — the first column
still says the word. -
A name in the way is reported as a name in the way. PeterT's first run
on Linux (#19) said "epubveri could not be downloaded. The first run needs
an internet connection" and carried[Errno 17] File existsin brackets.
His connection was fine — something was already sitting where the validator
goes (<calibre config>/plugins/epubveri), and the plugin blamed the
network for a problem on the disk. He worked it out himself and called it a
false alarm; the message was what was wrong.os.path.isdiris False both for a plain file and for a symlink whose
target is gone, andos.makedirsraises the sameEEXISTfor either. Both
now produce a sentence naming the path and saying to rename or remove it,
and nothing is installed or changed. The folder itself is created with
exist_ok=True, so two editor windows starting together cannot turn the
same errno into a second, unrelated version of that message. -
…and then the thing in the way turned out to be Doitsu's plugin, so we
moved. He was not guessed at: his 0.0.7 was read (it is in calibre's
plugin index,epubveri_plugin_dir()+epubveri_binary_name()), and it
keeps its copy of the binary in a file called
<calibre config>/plugins/epubveri— exactly the name this plugin wanted
for a folder, on Linux and macOS both. Windows was never affected; his file
isepubveri.exethere.The collision goes both ways: his file stopped our folder being created,
and our folder would have stopped hiscopy2— he would have ended up
executing a directory. Neither tool can win a name, so ours moves to
plugins/epubveri-data. A folder left by 0.2.0 is moved rather than
abandoned, which keeps the binary this plugin already verified and hands
the old name back to the plugin that owns it. A file at the old name is
his and is never touched; a folder that does not contain our binary is
somebody's data and is left alone too.This is the whole of what PeterT met, and it is not a false alarm: every
Linux and macOS user coming from Doitsu's plugin — which is to say most of
them — would have hit it. -
We had also been breaking his plugin, in his own preferences file.
calibre keys preferences by plugin name and both plugins are called
epubveri, so the two share oneplugins/epubveri.json. Nine of the ten
keys are distinct;last_update_checkis not. His istime.time()and he
computestime.time() - last_checked; ours was an ISO string, so his
update check raisedTypeErrorfor anyone who ran this plugin and then
his. It now writes the number he expects, and reads both spellings so no
existing install loses its stamp. Our reader was tolerant from the start,
which is exactly why this could only ever have shown up on his side.