Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8990ff29d | ||
|
|
e3b810b4ff | ||
|
|
337392bb6d |
@@ -1893,7 +1893,27 @@ func (a *App) GetDBConnectionInfo() DBConnectionInfo {
|
||||
}
|
||||
return DBConnectionInfo{Backend: "mysql", Label: "MySQL"}
|
||||
}
|
||||
return DBConnectionInfo{Backend: "sqlite", Label: a.dbPath}
|
||||
// The LOGBOOK file, not the settings database.
|
||||
//
|
||||
// This reported a.dbPath — the settings/profile database — under a tooltip
|
||||
// reading "Local SQLite logbook". The two are separate files since the logbook
|
||||
// split, so an operator checking where their QSOs live, or which file to back
|
||||
// up, was pointed at the wrong one.
|
||||
//
|
||||
// Same resolution order as connectLogbook: the active profile's own file if it
|
||||
// names one, then the default logbook.db, and only if neither exists does the
|
||||
// settings db genuinely serve as the logbook.
|
||||
lp := ""
|
||||
if p, err := a.profiles.Active(a.ctx); err == nil {
|
||||
lp = strings.TrimSpace(p.DB.Path)
|
||||
}
|
||||
if lp == "" {
|
||||
lp = a.logbookPath
|
||||
}
|
||||
if lp == "" {
|
||||
lp = a.dbPath
|
||||
}
|
||||
return DBConnectionInfo{Backend: "sqlite", Label: lp}
|
||||
}
|
||||
|
||||
// connectLogbook opens the logbook connection for a profile's DB target: a
|
||||
|
||||
+6
-2
@@ -14,7 +14,9 @@
|
||||
"Switching the CAT backend back to a Yaesu no longer risks leaving the serial port held. Each reconnect opened a new handle without closing the previous one, and Windows opens a serial port exclusively, so the next attempt could fail with \"port busy\".",
|
||||
"A Yaesu that is switched off is reported as such. Opening the serial port used to be logged as \"connected\", with the model name left over from the previous session, so a radio that was simply powered down looked like a software fault.",
|
||||
"Yaesu: moving RX and TX together to the SUB receiver is no longer shown as split. That is simplex on the sub VFO, but the rig reports its split flag anyway, so OpsLog now works split out from which VFO transmits and which receives.",
|
||||
"Auto-call CW now waits the gap you set AFTER the message, not from the moment it starts. With a WinKeyer or serial keyer the wait could end before the call had finished, so a 6 s gap gave about 2 s of silence after a 4 s CQ."
|
||||
"Auto-call CW now waits the gap you set AFTER the message, not from the moment it starts. With a WinKeyer or serial keyer the wait could end before the call had finished, so a 6 s gap gave about 2 s of silence after a 4 s CQ.",
|
||||
"The Antenna Genius and Tuner Genius settings entries carry a small 4O3A mark, so the panels driving that hardware are recognisable at a glance in the sidebar.",
|
||||
"The database shown in the status bar is the LOGBOOK file. On a local SQLite setup it named the settings database instead, so anyone checking where their QSOs live — or which file to back up — was pointed at the wrong one."
|
||||
],
|
||||
"fr": [
|
||||
"Cliquer sur un spot du cluster en écoutant sur le VFO SUB ne ramène plus la radio sur le VFO principal. La commande utilisée pour s'accorder agit par définition sur le VFO principal ; sur SUB, c'est désormais le VFO secondaire qui est écrit, sans toucher à la sélection.",
|
||||
@@ -28,7 +30,9 @@
|
||||
"Repasser le backend CAT sur un Yaesu ne risque plus de laisser le port série occupé. Chaque reconnexion ouvrait une nouvelle poignée sans fermer la précédente, et Windows ouvre un port série en exclusivité : la tentative suivante pouvait échouer avec « port occupé ».",
|
||||
"Un Yaesu éteint est signalé comme tel. L'ouverture du port série était journalisée comme « connecté », avec le nom de modèle hérité de la session précédente : une radio simplement hors tension ressemblait à un défaut du logiciel.",
|
||||
"Yaesu : passer RX et TX ensemble sur le récepteur SUB n'est plus affiché comme un split. C'est du simplex sur le VFO secondaire, mais la radio lève quand même son indicateur de split ; OpsLog le déduit désormais du VFO qui émet et de celui qui reçoit.",
|
||||
"L'appel automatique en CW attend désormais l'intervalle réglé APRÈS le message, et non depuis son début. Avec un WinKeyer ou un keyer série, l'attente pouvait se terminer avant la fin de l'appel : un intervalle de 6 s ne laissait qu'environ 2 s de silence après un CQ de 4 s."
|
||||
"L'appel automatique en CW attend désormais l'intervalle réglé APRÈS le message, et non depuis son début. Avec un WinKeyer ou un keyer série, l'attente pouvait se terminer avant la fin de l'appel : un intervalle de 6 s ne laissait qu'environ 2 s de silence après un CQ de 4 s.",
|
||||
"Les entrées de réglages Antenna Genius et Tuner Genius portent une petite marque 4O3A : les panneaux pilotant ce matériel se repèrent d'un coup d'œil dans le menu.",
|
||||
"La base affichée dans la barre d'état est bien le fichier du CARNET. En SQLite local, elle désignait la base des réglages : qui vérifiait où résident ses QSO — ou quel fichier sauvegarder — était orienté vers le mauvais."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -198,7 +198,35 @@ type SectionId =
|
||||
|
||||
type TreeNode =
|
||||
| { kind: 'group'; label: string; icon?: any; defaultOpen?: boolean; children: TreeNode[] }
|
||||
| { kind: 'item'; label: string; id: SectionId; disabled?: boolean };
|
||||
| { kind: 'item'; label: string; id: SectionId; disabled?: boolean; vendor?: 'o3a' };
|
||||
|
||||
// A compact 4O3A wordmark for the sidebar, drawn here rather than shipped as an
|
||||
// image: an inline SVG scales with the row, follows the theme (currentColor), and
|
||||
// adds no binary asset. It marks which panels drive 4O3A hardware — the same
|
||||
// reason the language picker draws its flags inline.
|
||||
//
|
||||
// This is a plain wordmark, NOT the manufacturer's logo artwork. If you would
|
||||
// rather show the official mark, drop the SVG in and swap this component out.
|
||||
function VendorMark({ vendor }: { vendor: 'o3a' }) {
|
||||
if (vendor !== 'o3a') return null;
|
||||
// The 4O3A mark: "4", the green waveform, "3A". Drawn inline rather than
|
||||
// shipped as an image — it scales with the row, keeps the sidebar's own type
|
||||
// for the digits, and adds no binary asset. The waveform is the part that
|
||||
// carries the brand, so only it is SVG; the characters stay HTML text so they
|
||||
// match the surrounding menu at any theme or zoom.
|
||||
const lens = [3.2, 5.2, 7.4, 9.5, 7.4, 5.2, 3.2]; // half-heights, tallest in the middle
|
||||
return (
|
||||
<span className="ml-1.5 flex shrink-0 items-center gap-[1px] text-[10px] font-bold leading-none opacity-80" title="4O3A Signature">
|
||||
<span>4</span>
|
||||
<svg viewBox="0 0 26 22" className="h-[13px] w-[15px]" aria-hidden="true">
|
||||
{lens.map((ry, i) => (
|
||||
<ellipse key={i} cx={3 + i * 3.3} cy={11} rx={1.5} ry={ry} fill="#1f9d3a" />
|
||||
))}
|
||||
</svg>
|
||||
<span>3A</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
// buildTree returns the settings sidebar. The FlexRadio item only appears when
|
||||
// the active CAT backend is a Flex (per-band antenna config is Flex-specific).
|
||||
@@ -208,8 +236,8 @@ function buildTree(flexAvailable: boolean, t: (k: string) => string): TreeNode[]
|
||||
{ kind: 'item', label: t('sec.rotator'), id: 'rotator' },
|
||||
{ kind: 'item', label: t('sec.winkeyer'), id: 'winkeyer' },
|
||||
{ kind: 'item', label: t('sec.antenna'), id: 'antenna' },
|
||||
{ kind: 'item', label: t('sec.antgenius'), id: 'antgenius' },
|
||||
{ kind: 'item', label: t('sec.tunergenius'), id: 'tunergenius' },
|
||||
{ kind: 'item', label: t('sec.antgenius'), id: 'antgenius', vendor: 'o3a' },
|
||||
{ kind: 'item', label: t('sec.tunergenius'), id: 'tunergenius', vendor: 'o3a' },
|
||||
{ kind: 'item', label: t('sec.pgxl'), id: 'pgxl' },
|
||||
...(flexAvailable ? [{ kind: 'item', label: t('sec.flex'), id: 'flex' } as TreeNode] : []),
|
||||
{ kind: 'item', label: t('sec.relayauto'), id: 'relayauto' },
|
||||
@@ -325,6 +353,7 @@ function TreeNodeView({
|
||||
style={{ paddingLeft: 8 + depth * 14 }}
|
||||
>
|
||||
<span className="truncate">{node.label}</span>
|
||||
{node.vendor && !node.disabled && <VendorMark vendor={node.vendor} />}
|
||||
{node.disabled && (
|
||||
<Construction className="ml-auto size-3 shrink-0 opacity-60" />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user