feat(gui): show the per-user file limits a server advertises - #841
Conversation
Since you are at this, can I ask you to also stream server's TCP and UDP flags over EC to amulegui? Thanks |
Closes amule-project#840. Servers cap how many of a user's shared files they will index -- some at 9,000, others at 100,000 or more -- and nothing in aMule surfaced it, so a user sharing 37,000 files had no way to tell whether a server was publishing all of them. Adds Soft Files, Hard Files and Max Users to the server list. All three were already parsed from server.met, kept on CServer and refreshed by the periodic UDP status ping that fills Users and Files; only the display was missing. Soft and Hard files are now streamed over EC as well, so the remote GUI has them too -- Max Users already was. Zero renders blank, not "0". These fields only arrive once a status reply has come back, and the reply is parsed progressively by size: Max Users needs 16 bytes, the two limits 24. A server that sends a short reply, or has not answered yet, advertises nothing -- and showing that as a limit of zero would be a lie about the server rather than an absence of data. Three fixes to the column layer came out of building this. Two predate it: - Drag-resizing a column was never persisted. The idle poll that stands in for wxDataViewCtrl's missing end-of-drag event called a virtual that defaulted to doing nothing, so a width survived only if the user happened to sort or toggle a column afterwards. It now saves, for every list on the dataview layer; CSearchListCtrl's override chains to the base so it keeps syncing widths across search tabs as well. - The remote GUI never sized its server columns to their contents at all. The core fits them when a bulk load finishes, via Notify_ServerThaw() from CServerList -- a path amulegui does not take, since its list arrives over EC. It now fits once, after the first populated update: refitting on every update would undo a width the user had dragged. And one this work introduced: the column ids have to stay in the order the columns are appended, because FitColumnsToContent() walks a single index and uses it as both a model column and a view position. Moving Max Users next to Users without renumbering sized every column after it against a different one's content, which read as columns collapsing to nothing. The ids now match the append order, and the constraint is written down next to them -- as is the reason the two flag columns must stay last, being the pair the remote GUI does not append.
… id order The two column fixes in this branch interact badly. Making drag-resize persist gave the auto-fit something to destroy: FitColumnsToContent() runs after LoadColumnSettings() on both paths -- the core's bulk-load notification and the remote GUI's first populated update -- so a width the user dragged was saved, then overwritten on the next launch. On the monolithic side that clobber came in with the dataview port and was harmless only because nothing was ever saved; the remote path added here would have done it every start. The fit is now gated on the profile having no stored widths, inside FitColumnsToContent() rather than at either call site, so both binaries are covered by one check. CListColumnStore::LoadSettings() reports whether it restored anything to make that decidable; it returned void before. Also asserts what was previously only a comment: every appended column must sit at the view position matching its model id. FitColumnsToContent() walks a single index as both, the hidden-state vector and the header menu are keyed by view position, and RegisterColumn() by model id -- they agree only because the orders have always coincided. Inserting a column mid-list broke that earlier in this branch and showed up as columns sizing against each other's content, with nothing failing at the point of the mistake. wxDataViewColumn::GetModelColumn() makes the check a one-liner in InitColumnState(), covering every list on the layer rather than the one whose header carried the note.
The rebase took master's catalogs wholesale -- hand-merging 37 files against a Weblate import discards translations -- so the three new column labels had to be re-extracted on top. Pure regeneration: no msgid is added or removed beyond those three, and every catalog still compiles.
afe1e16 to
2f4a432
Compare
… binaries Requested by danim7 on the PR. The TCP/UDP flag columns existed only in the monolithic app: appended and registered behind a CLIENT_GUI gate, because nothing carried the values to the remote GUI. They are now streamed like the file limits -- both server-tag builders, the accessors and the remote reader -- so amulegui can offer the same columns with real data behind them. The gate around appending and registering them is gone, and the hidden-by-default rule keys on the build type alone (#ifndef __DEBUG__) rather than on which binary is running, so both behave identically: present in the header's show/hide menu, off unless the user asks for them or it is a debug build. Two comments claiming the remote GUI has no data for these columns went with the gate, being no longer true.
|
@danim7 done — the flags are streamed now, and it turned into something a bit broader than the original ask. The TCP/UDP flag columns previously existed only in the monolithic app: appended and registered behind a So in both aMule and amulegui the flag columns behave the same way: present in the header's show/hide menu, off by default in a release build, on in a debug build. Same wiring as the file limits in this PR — both Worth knowing they are only as fresh as the last UDP status reply, like the other server-reported values here: a server that has not answered, or answers with a short packet, shows nothing rather than zero. |
The menu offers one entry per column from a fixed MP_LISTCOL_1..MP_LISTCOL_15 range, and clamped to it with std::min. The server list reached 16 columns here, so the last one was dropped from the menu with no other symptom: no assert, no log, just a column that could not be shown or hidden. Extends the range to 20 and asserts when a list still exceeds it, so the next one to grow fails at the point of the mistake rather than losing an entry quietly.
…obbering them Two reasons amulegui showed the flag columns but never any values. The switch that renders them was still inside a CLIENT_GUI gate, so the remote GUI had no case for either column and fell through to an empty string. That was the last of four such gates around these columns -- appending, registering, rendering and hiding -- each of which failed differently: missing columns, a missing menu entry, and blank cells. The reader also wiped what did arrive. It assigned the return value of GetTCPFlags()/GetUDPFlags(), which is 0 for an absent tag, while the valuemap builder omits any tag whose value has not changed since the last update. So a flag arrived once and was zeroed by the next update that did not resend it. Reading through the pointer, as the neighbouring fields do, leaves the current value alone when the tag is missing. Found by probing both ends rather than reading: the receiver reported correct per-server soft limits beside flags that were zero for every server but the first, which is the signature of an overwrite rather than a transport fault.
Closes #840.
Servers cap how many of a user's shared files they will index — some at 9,000, others at 100,000 or more — and nothing in aMule surfaced it. A user sharing 37,000 files had no way to tell whether a given server was publishing all of them.
Adds Soft Files, Hard Files and Max Users to the server list.
Mostly already there
All three values were already parsed from
server.met, kept onCServer, persisted on save, and refreshed by the periodic UDP status ping (OP__GlobServStatReq) that fills the existing Users and Files columns. Only the display was missing. Soft and Hard files are now streamed over EC as well so the remote GUI has them; Max Users already was.Zero renders blank
These only arrive once a status reply comes back, and the reply is parsed progressively by size — Max Users needs 16 bytes, the two limits 24. A server that sends a short reply, or has not answered yet, advertises nothing. Showing that as a limit of
0would be a claim about the server rather than an absence of data, so it stays empty, as Users and Files already do.Column-layer fixes that came out of building this
Two predate this work, both from the #811 dataview port:
CSearchListCtrl's override chains to the base so it still syncs widths across search tabs.Notify_ServerThaw()fromCServerList— a path amulegui never takes, since its list arrives over EC. It now fits after the first populated update.Those two interact, and the combination is worse than either alone. Making resize persist gave the auto-fit something to destroy: the fit runs after
LoadColumnSettings()on both paths, so a dragged width was saved and then overwritten on the next launch. On the monolithic side that clobber arrived with #811 and was harmless only because nothing was ever saved. The fit is therefore gated on the profile having no stored widths, insideFitColumnsToContent()rather than at either call site, so both binaries are covered by one check.CListColumnStore::LoadSettings()now reports whether it restored anything, to make that decidable — it returnedvoidbefore.One was introduced here and is worth knowing about: column ids must stay in the order the columns are appended, because
FitColumnsToContent()walks one index and uses it as both a model column and a view position. Moving Max Users next to Users without renumbering sized every later column against a different one's content — which looked like columns collapsing to nothing. Ids now match append order, and the invariant is asserted inInitColumnState()viawxDataViewColumn::GetModelColumn()rather than left as a comment — the assumption is layer-wide (the hidden-state vector and header menu are keyed by view position,RegisterColumn()by model id) and its failure is invisible at runtime, so it fails loudly at the point of the mistake instead. The two flag columns must also stay last, being the pair the remote GUI does not append; an id at or aboveRealColumnCount()renders blank.Testing
Interactive on macOS, monolithic and amulegui, against live servers — values populate, blanks stay blank for non-reporting servers, auto-fit works from an empty config, and resized widths now survive a restart.
Note the new assert is not exercised by
ctest: nothing there constructs these widgets, andwxASSERTis a no-op without awxApp. It only fires in a Debug GUI, and so far only the Servers list has been opened —CSearchListCtrluses the same base.ctest33/33, clang-format 18 clean, Tier-2 clang-tidy clean on the diff with 0 compiler errors.Not verified on Linux or Windows. The EC and column code is platform-independent, but the auto-fit measures text with a
wxClientDCand I have only seen it on macOS.Not included
The warning falcogiallo also suggested — telling the user when their shared-file count exceeds a server's hard limit — is not here. It needs a rule for when it fires (on connect, on share-count change, once per server) or it becomes nagware, and the values it would key on are as stale as the last UDP reply. Worth its own discussion.