Add drag&drop .asm preview and force CSV output to repo root
Fase 5 now shows the distinta's .asm files already copied to raw/ as draggable icons, so they can be dropped straight onto Creo or Explorer without re-hitting the DB/share. The CSV from fase 2 is now always written to the repo root (found by walking up to CLAUDE.md) instead of next to the input file, wherever that happens to be. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8a8a7d0417
commit
0966e66232
3 files changed
+100
-12
No files matched your search
@@ -51,20 +51,28 @@ entrambi rimossi: ora l'unico programma è questo, con GUI e indicizzazione inte
|
|||||||
(`DBP_<codice>_<timestamp>`), l'assieme generale viene aggiunto come riga in più nel
|
(`DBP_<codice>_<timestamp>`), l'assieme generale viene aggiunto come riga in più nel
|
||||||
CSV stesso (il foglio elenca solo i componenti sotto l'assieme, non l'assieme in sé).
|
CSV stesso (il foglio elenca solo i componenti sotto l'assieme, non l'assieme in sé).
|
||||||
Da qui in avanti l'assieme generale è un componente come tutti gli altri, nessun
|
Da qui in avanti l'assieme generale è un componente come tutti gli altri, nessun
|
||||||
caso speciale nel resto del codice.
|
caso speciale nel resto del codice. Il CSV viene sempre scritto nella root del repo
|
||||||
|
(`Form1.TrovaRadiceRepo`, che risale da `AppContext.BaseDirectory` fino alla cartella
|
||||||
|
che contiene `CLAUDE.md`), indipendentemente da dove si trova il file `.xls`/`.xml`
|
||||||
|
di input scelto dall'utente.
|
||||||
3. **Crea cartella raw** — cerca nell'indice il percorso CAD di ogni componente del CSV
|
3. **Crea cartella raw** — cerca nell'indice il percorso CAD di ogni componente del CSV
|
||||||
(`TrovaPercorsiCad`) e lo copia in `raw/` (`CopiaFileTrovati`).
|
(`TrovaPercorsiCad`) e lo copia in `raw/` (`CopiaFileTrovati`).
|
||||||
4. **Trova componenti referenziati** — legge euristicamente i metadati binari dei `.asm`
|
4. **Trova componenti referenziati** — legge euristicamente i metadati binari dei `.asm`
|
||||||
già in `raw/` (`AssemblyComponentScanner`) per risolvere ricorsivamente i
|
già in `raw/` (`AssemblyComponentScanner`) per risolvere ricorsivamente i
|
||||||
sotto-assiemi/parti che contengono (`RisolviAlberoComponenti`), copiandoli anch'essi
|
sotto-assiemi/parti che contengono (`RisolviAlberoComponenti`), copiandoli anch'essi
|
||||||
in `raw/`.
|
in `raw/`.
|
||||||
5. **Verifica completezza e STEP** — "Verifica completezza assiemi" (ricorsivo sui
|
5. **Verifica completezza e STEP** — appena si entra nella fase, `AggiornaAnteprimaAsm`
|
||||||
percorsi originali in indice, non su `raw/`) e "Crea cartella step_finali": solo per i
|
mostra in una `ListView` a icone i file `.asm` della distinta importata (esclusi i
|
||||||
codici della distinta importata dal CSV (non i sotto-componenti di fase 4, che servono
|
sotto-assiemi di fase 4) già presenti in `raw/` — letti dal filesystem locale, non
|
||||||
solo a completare `raw/`) cerca in `step/` il file `<codice>.stp` e lo copia in
|
dall'indice/share — trascinabili (drag&drop, `ItemDrag` → `DoDragDrop` con
|
||||||
`step_finali/` se lo trova. Per i mancanti distingue, incrociando l'indice CAD,
|
`DataFormats.FileDrop`) direttamente su Creo o Esplora risorse. "Verifica completezza
|
||||||
`EsitoStep.StepMancante` (il CAD c'è, manca solo l'esportazione STEP) da
|
assiemi" (ricorsivo sui percorsi originali in indice, non su `raw/`) e "Crea cartella
|
||||||
`ComponenteNonTrovato` (il componente non è nemmeno nell'indice) — vedi `ReportStepForm`.
|
step_finali": solo per i codici della distinta importata dal CSV (non i
|
||||||
|
sotto-componenti di fase 4, che servono solo a completare `raw/`) cerca in `step/` il
|
||||||
|
file `<codice>.stp` e lo copia in `step_finali/` se lo trova. Per i mancanti distingue,
|
||||||
|
incrociando l'indice CAD, `EsitoStep.StepMancante` (il CAD c'è, manca solo
|
||||||
|
l'esportazione STEP) da `ComponenteNonTrovato` (il componente non è nemmeno
|
||||||
|
nell'indice) — vedi `ReportStepForm`.
|
||||||
- **Indexer.cs** — logica di scansione del disco e scrittura/aggiornamento del DB
|
- **Indexer.cs** — logica di scansione del disco e scrittura/aggiornamento del DB
|
||||||
SQLite (`Indexer.ScanAsync`). Cammina tutte le cartelle di primo livello trovate sotto
|
SQLite (`Indexer.ScanAsync`). Cammina tutte le cartelle di primo livello trovate sotto
|
||||||
la radice (scoperte dinamicamente con `Directory.GetDirectories`, non un elenco fisso)
|
la radice (scoperte dinamicamente con `Directory.GetDirectories`, non un elenco fisso)
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ static class DistintaBaseImporter
|
|||||||
Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (string PercorsoCsv, List<(string Componente, string Descrizione)> Righe) ConvertiInCsv(string percorsoInput)
|
public static (string PercorsoCsv, List<(string Componente, string Descrizione)> Righe) ConvertiInCsv(
|
||||||
|
string percorsoInput, string? cartellaOutput = null)
|
||||||
{
|
{
|
||||||
var righeGrezze = EImmagineSpreadsheetMl(percorsoInput)
|
var righeGrezze = EImmagineSpreadsheetMl(percorsoInput)
|
||||||
? LeggiRigheSpreadsheetMl(percorsoInput)
|
? LeggiRigheSpreadsheetMl(percorsoInput)
|
||||||
@@ -44,7 +45,7 @@ static class DistintaBaseImporter
|
|||||||
}
|
}
|
||||||
|
|
||||||
var percorsoCsv = Path.Combine(
|
var percorsoCsv = Path.Combine(
|
||||||
Path.GetDirectoryName(Path.GetFullPath(percorsoInput))!,
|
cartellaOutput ?? Path.GetDirectoryName(Path.GetFullPath(percorsoInput))!,
|
||||||
Path.GetFileNameWithoutExtension(percorsoInput) + ".csv");
|
Path.GetFileNameWithoutExtension(percorsoInput) + ".csv");
|
||||||
|
|
||||||
using var writer = new StreamWriter(percorsoCsv, false, Encoding.UTF8);
|
using var writer = new StreamWriter(percorsoCsv, false, Encoding.UTF8);
|
||||||
|
|||||||
+81
-2
@@ -12,6 +12,7 @@ public partial class Form1 : Form
|
|||||||
private readonly Button _btnReport = new();
|
private readonly Button _btnReport = new();
|
||||||
private readonly Button _btnVerifica = new();
|
private readonly Button _btnVerifica = new();
|
||||||
private readonly Button _btnCompletezza = new();
|
private readonly Button _btnCompletezza = new();
|
||||||
|
private readonly ListView _lstAnteprimaAsm = new();
|
||||||
private readonly Button _btnPulisci = new();
|
private readonly Button _btnPulisci = new();
|
||||||
private readonly Label _lblStatus = new();
|
private readonly Label _lblStatus = new();
|
||||||
private readonly Label _lblDb = new();
|
private readonly Label _lblDb = new();
|
||||||
@@ -41,6 +42,19 @@ public partial class Form1 : Form
|
|||||||
private static readonly string[] TipiPredefiniti = { "prt", "asm" };
|
private static readonly string[] TipiPredefiniti = { "prt", "asm" };
|
||||||
private const string RadiceDiscoDefault = @"X:\";
|
private const string RadiceDiscoDefault = @"X:\";
|
||||||
|
|
||||||
|
/// <summary>Risale da AppContext.BaseDirectory (variabile tra Debug/Release/publish) fino
|
||||||
|
/// alla cartella che contiene CLAUDE.md, cioè la root del repo; se non la trova (es. exe
|
||||||
|
/// pubblicato e spostato altrove) ripiega su AppContext.BaseDirectory.</summary>
|
||||||
|
private static string TrovaRadiceRepo()
|
||||||
|
{
|
||||||
|
for (var dir = new DirectoryInfo(AppContext.BaseDirectory); dir is not null; dir = dir.Parent)
|
||||||
|
{
|
||||||
|
if (File.Exists(Path.Combine(dir.FullName, "CLAUDE.md")))
|
||||||
|
return dir.FullName;
|
||||||
|
}
|
||||||
|
return AppContext.BaseDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
private string? _dbPath;
|
private string? _dbPath;
|
||||||
private string? _percorsoInputCorrente;
|
private string? _percorsoInputCorrente;
|
||||||
private List<(string Componente, string Descrizione)>? _righeCorrenti;
|
private List<(string Componente, string Descrizione)>? _righeCorrenti;
|
||||||
@@ -149,6 +163,47 @@ public partial class Form1 : Form
|
|||||||
_btnIndietro.Visible = _faseAttuale > 0;
|
_btnIndietro.Visible = _faseAttuale > 0;
|
||||||
_btnAvanti.Visible = _faseAttuale < NomiFasi.Length - 1;
|
_btnAvanti.Visible = _faseAttuale < NomiFasi.Length - 1;
|
||||||
AggiornaStatoAvanti();
|
AggiornaStatoAvanti();
|
||||||
|
|
||||||
|
if (_faseAttuale == 4)
|
||||||
|
AggiornaAnteprimaAsm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Popola le icone trascinabili (drag&drop) dei file .asm della distinta importata
|
||||||
|
/// (non i sotto-assiemi di fase 4, che in "raw" servono solo a completarla) già copiati in
|
||||||
|
/// "raw" (non riletti dal DB/share: sono già in locale), mostrate in fase 5 prima ancora di
|
||||||
|
/// avviare la verifica.</summary>
|
||||||
|
private void AggiornaAnteprimaAsm()
|
||||||
|
{
|
||||||
|
_lstAnteprimaAsm.Items.Clear();
|
||||||
|
_lstAnteprimaAsm.LargeImageList!.Images.Clear();
|
||||||
|
if (_ultimaCartellaRaw is null || !Directory.Exists(_ultimaCartellaRaw) || _righeCorrenti is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var codiciDistinta = _righeCorrenti.Select(r => r.Componente).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||||
|
var percorsiAsm = Directory.GetFiles(_ultimaCartellaRaw)
|
||||||
|
.Where(p =>
|
||||||
|
{
|
||||||
|
var (codice, tipo, _) = Indexer.ParseFilename(Path.GetFileName(p));
|
||||||
|
return tipo.Equals("asm", StringComparison.OrdinalIgnoreCase) && codiciDistinta.Contains(codice);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var percorso in percorsiAsm)
|
||||||
|
{
|
||||||
|
Icon? icona = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
icona = Icon.ExtractAssociatedIcon(percorso);
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or ArgumentException)
|
||||||
|
{
|
||||||
|
// ponytail: file irraggiungibile (share offline) -> icona generica, non blocca gli altri
|
||||||
|
}
|
||||||
|
|
||||||
|
int indice = _lstAnteprimaAsm.LargeImageList.Images.Count;
|
||||||
|
_lstAnteprimaAsm.LargeImageList.Images.Add(icona?.ToBitmap() ?? SystemIcons.WinLogo.ToBitmap());
|
||||||
|
icona?.Dispose();
|
||||||
|
_lstAnteprimaAsm.Items.Add(new ListViewItem(Path.GetFileName(percorso), indice) { Tag = percorso });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Condizione per cui la fase indicata è "conclusa" e si può passare alla successiva.</summary>
|
/// <summary>Condizione per cui la fase indicata è "conclusa" e si può passare alla successiva.</summary>
|
||||||
@@ -423,10 +478,34 @@ public partial class Form1 : Form
|
|||||||
|
|
||||||
_btnCompletezza.Text = "Verifica completezza assiemi";
|
_btnCompletezza.Text = "Verifica completezza assiemi";
|
||||||
_btnCompletezza.Size = new Size(220, 32);
|
_btnCompletezza.Size = new Size(220, 32);
|
||||||
_btnCompletezza.Margin = new Padding(0, 0, 0, 20);
|
_btnCompletezza.Margin = new Padding(0, 0, 0, 8);
|
||||||
_btnCompletezza.Click += (_, _) => VerificaCompletezzaAssiemi();
|
_btnCompletezza.Click += (_, _) => VerificaCompletezzaAssiemi();
|
||||||
contenuto.Controls.Add(_btnCompletezza);
|
contenuto.Controls.Add(_btnCompletezza);
|
||||||
|
|
||||||
|
var lblAnteprimaAsm = new Label
|
||||||
|
{
|
||||||
|
AutoSize = true,
|
||||||
|
ForeColor = SystemColors.GrayText,
|
||||||
|
Margin = new Padding(0, 0, 0, 4),
|
||||||
|
Text = "File .asm della distinta trovati nell'indice (trascinali su Creo/Esplora risorse):",
|
||||||
|
};
|
||||||
|
contenuto.Controls.Add(lblAnteprimaAsm);
|
||||||
|
|
||||||
|
_lstAnteprimaAsm.View = View.LargeIcon;
|
||||||
|
_lstAnteprimaAsm.MultiSelect = true;
|
||||||
|
_lstAnteprimaAsm.LargeImageList = new ImageList { ImageSize = new Size(32, 32) };
|
||||||
|
_lstAnteprimaAsm.Size = new Size(680, 160);
|
||||||
|
_lstAnteprimaAsm.Margin = new Padding(0, 0, 0, 20);
|
||||||
|
_lstAnteprimaAsm.ItemDrag += (_, e) =>
|
||||||
|
{
|
||||||
|
var percorsi = _lstAnteprimaAsm.SelectedItems.Cast<ListViewItem>()
|
||||||
|
.Select(item => (string)item.Tag!)
|
||||||
|
.ToArray();
|
||||||
|
if (percorsi.Length > 0)
|
||||||
|
_lstAnteprimaAsm.DoDragDrop(new DataObject(DataFormats.FileDrop, percorsi), DragDropEffects.Copy);
|
||||||
|
};
|
||||||
|
contenuto.Controls.Add(_lstAnteprimaAsm);
|
||||||
|
|
||||||
var lblIstruzioniStep = new Label
|
var lblIstruzioniStep = new Label
|
||||||
{
|
{
|
||||||
AutoSize = true,
|
AutoSize = true,
|
||||||
@@ -463,7 +542,7 @@ public partial class Form1 : Form
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var (csv, righe) = DistintaBaseImporter.ConvertiInCsv(percorso);
|
var (csv, righe) = DistintaBaseImporter.ConvertiInCsv(percorso, TrovaRadiceRepo());
|
||||||
_percorsoInputCorrente = percorso;
|
_percorsoInputCorrente = percorso;
|
||||||
_righeCorrenti = righe;
|
_righeCorrenti = righe;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user