diff --git a/CadSearchGui/Form1.cs b/CadSearchGui/Form1.cs index 05345c2..99cb14c 100644 --- a/CadSearchGui/Form1.cs +++ b/CadSearchGui/Form1.cs @@ -5,21 +5,13 @@ namespace CadSearchGui; public partial class Form1 : Form { - private readonly TextBox _txtCerca = new(); - private readonly ComboBox _cmbTipo = new(); - private readonly ComboBox _cmbCartella = new(); - private readonly CheckBox _chkUltima = new(); - private readonly Button _btnCerca = new(); private readonly Button _btnApriDb = new(); private readonly Button _btnAggiorna = new(); - private readonly DataGridView _grid = new(); private readonly Label _lblStatus = new(); private readonly Label _lblDb = new(); private readonly DataGridView _gridImport = new(); private readonly Label _lblImportStatus = new(); - private const string OpzionePrtAsm = "Solo prt/asm (predefinito)"; - private const string OpzioneTuttiTipi = "Tutti i tipi"; private static readonly string[] TipiPredefiniti = { "prt", "asm" }; private const string RadiceDiscoDefault = @"X:\"; @@ -34,122 +26,53 @@ public partial class Form1 : Form private void BuildUi() { + AllowDrop = true; + Text = "Distinta Base -> CSV con percorsi CAD"; + var topPanel = new TableLayoutPanel { Dock = DockStyle.Top, - Height = 76, - ColumnCount = 7, + Height = 108, + ColumnCount = 3, + RowCount = 3, Padding = new Padding(8), - RowCount = 2, }; - topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40)); - topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 15)); - topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20)); + topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 130)); - topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90)); - topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 110)); topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 130)); - _txtCerca.Dock = DockStyle.Fill; - _txtCerca.Font = new Font(_txtCerca.Font!.FontFamily, 11f); - _txtCerca.PlaceholderText = "Cerca per codice o nome file (es. 9231000036)..."; - _txtCerca.KeyDown += (_, e) => + var lblIstruzioni = new Label { - if (e.KeyCode == Keys.Enter) - { - e.SuppressKeyPress = true; - EseguiRicerca(); - } + Dock = DockStyle.Fill, + AutoSize = false, + Text = "Trascina qui il file .xls/.xml esportato dal gestionale (foglio 'Distinta " + + "Base'), oppure scegli il file col pulsante 'Scegli file...'. Viene generato " + + "un CSV con Componente/Descrizione e, per ogni componente, il percorso del " + + "file CAD corrispondente trovato nell'indice.", }; + topPanel.SetColumnSpan(lblIstruzioni, 3); + topPanel.Controls.Add(lblIstruzioni, 0, 0); - _cmbTipo.Dock = DockStyle.Fill; - _cmbTipo.DropDownStyle = ComboBoxStyle.DropDownList; - _cmbTipo.Items.Add(OpzionePrtAsm); - _cmbTipo.Items.Add(OpzioneTuttiTipi); - - _cmbCartella.Dock = DockStyle.Fill; - _cmbCartella.DropDownStyle = ComboBoxStyle.DropDownList; - _cmbCartella.Items.Add("Tutte le cartelle"); - _cmbCartella.Items.AddRange(new object[] { "__Accessori", "__B.end", "__Corpi", "__Fondi" }); - _cmbCartella.SelectedIndex = 0; - - _chkUltima.Text = "Solo ultima versione"; - _chkUltima.Dock = DockStyle.Fill; - _chkUltima.TextAlign = ContentAlignment.MiddleLeft; - _chkUltima.Checked = true; - - _btnCerca.Text = "Cerca"; - _btnCerca.Dock = DockStyle.Fill; - _btnCerca.Click += (_, _) => EseguiRicerca(); + var btnSfoglia = new Button { Text = "Scegli file distinta...", Dock = DockStyle.Fill }; + btnSfoglia.Click += (_, _) => ScegliFileDistinta(); + topPanel.Controls.Add(btnSfoglia, 0, 1); _btnApriDb.Text = "Apri DB..."; _btnApriDb.Dock = DockStyle.Fill; _btnApriDb.Click += (_, _) => ScegliDatabase(); + topPanel.Controls.Add(_btnApriDb, 1, 1); _btnAggiorna.Text = "Aggiorna indice"; _btnAggiorna.Dock = DockStyle.Fill; _btnAggiorna.Click += (_, _) => AggiornaIndice(); - - topPanel.Controls.Add(_txtCerca, 0, 0); - topPanel.Controls.Add(_cmbTipo, 1, 0); - topPanel.Controls.Add(_cmbCartella, 2, 0); - topPanel.Controls.Add(_chkUltima, 3, 0); - topPanel.Controls.Add(_btnCerca, 4, 0); - topPanel.Controls.Add(_btnApriDb, 5, 0); - topPanel.Controls.Add(_btnAggiorna, 6, 0); - topPanel.SetColumnSpan(_lblDb, 7); + topPanel.Controls.Add(_btnAggiorna, 2, 1); _lblDb.Dock = DockStyle.Fill; _lblDb.AutoSize = false; _lblDb.ForeColor = SystemColors.GrayText; _lblDb.TextAlign = ContentAlignment.MiddleLeft; - topPanel.Controls.Add(_lblDb, 0, 1); - - _grid.Dock = DockStyle.Fill; - _grid.ReadOnly = true; - _grid.AllowUserToAddRows = false; - _grid.AllowUserToDeleteRows = false; - _grid.AllowUserToResizeRows = false; - _grid.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - _grid.MultiSelect = false; - _grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; - _grid.CellDoubleClick += (_, e) => ApriCartellaFileSelezionato(); - - var statusPanel = new Panel { Dock = DockStyle.Bottom, Height = 28 }; - _lblStatus.Dock = DockStyle.Fill; - _lblStatus.TextAlign = ContentAlignment.MiddleLeft; - _lblStatus.Padding = new Padding(8, 0, 0, 0); - _lblStatus.Text = "Pronto."; - statusPanel.Controls.Add(_lblStatus); - - var tabRicerca = new TabPage("Ricerca CAD"); - tabRicerca.Controls.Add(_grid); - tabRicerca.Controls.Add(statusPanel); - tabRicerca.Controls.Add(topPanel); - - var tabs = new TabControl { Dock = DockStyle.Fill }; - tabs.TabPages.Add(BuildTabImportaDistinta()); - tabs.TabPages.Add(tabRicerca); - - Controls.Add(tabs); - } - - private TabPage BuildTabImportaDistinta() - { - var tab = new TabPage("Importa Distinta Base") { AllowDrop = true }; - - var lblIstruzioni = new Label - { - Dock = DockStyle.Top, - Height = 60, - Padding = new Padding(8), - Text = "Trascina qui il file .xls/.xml esportato dal gestionale (foglio 'Distinta " - + "Base'), oppure scegli il file col pulsante sotto. VerrĂ  generato un CSV con " - + "le colonne Componente e Descrizione, con anteprima qui sotto.", - }; - - var btnSfoglia = new Button { Text = "Scegli file...", Dock = DockStyle.Top, Height = 32 }; - btnSfoglia.Click += (_, _) => ScegliFileDistinta(); + topPanel.SetColumnSpan(_lblDb, 3); + topPanel.Controls.Add(_lblDb, 0, 2); _lblImportStatus.Dock = DockStyle.Top; _lblImportStatus.Height = 24; @@ -160,26 +83,35 @@ public partial class Form1 : Form _gridImport.ReadOnly = true; _gridImport.AllowUserToAddRows = false; _gridImport.AllowUserToDeleteRows = false; + _gridImport.SelectionMode = DataGridViewSelectionMode.FullRowSelect; + _gridImport.MultiSelect = false; _gridImport.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; _gridImport.Columns.Add("componente", "Componente"); _gridImport.Columns.Add("descrizione", "Descrizione"); + _gridImport.Columns.Add("percorso", "Percorso CAD"); + _gridImport.CellDoubleClick += (_, _) => ApriCartellaFileSelezionato(); - tab.Controls.Add(_gridImport); - tab.Controls.Add(_lblImportStatus); - tab.Controls.Add(btnSfoglia); - tab.Controls.Add(lblIstruzioni); + var statusPanel = new Panel { Dock = DockStyle.Bottom, Height = 28 }; + _lblStatus.Dock = DockStyle.Fill; + _lblStatus.TextAlign = ContentAlignment.MiddleLeft; + _lblStatus.Padding = new Padding(8, 0, 0, 0); + _lblStatus.Text = "Pronto."; + statusPanel.Controls.Add(_lblStatus); - tab.DragEnter += (_, e) => + Controls.Add(_gridImport); + Controls.Add(_lblImportStatus); + Controls.Add(statusPanel); + Controls.Add(topPanel); + + DragEnter += (_, e) => e.Effect = e.Data?.GetDataPresent(DataFormats.FileDrop) == true ? DragDropEffects.Copy : DragDropEffects.None; - tab.DragDrop += (_, e) => + DragDrop += (_, e) => { if (e.Data?.GetData(DataFormats.FileDrop) is string[] { Length: > 0 } file) ImportaDistinta(file[0]); }; - - return tab; } private void ScegliFileDistinta() @@ -198,13 +130,22 @@ public partial class Form1 : Form try { var (csv, righe) = DistintaBaseImporter.ConvertiInCsv(percorso); + var percorsiTrovati = TrovaPercorsiCad(righe.Select(r => r.Componente)); + _gridImport.Rows.Clear(); + int trovati = 0; foreach (var (componente, descrizione) in righe) { - _gridImport.Rows.Add(componente, descrizione); + string percorsoCad = percorsiTrovati.TryGetValue(componente, out var lista) + ? string.Join("; ", lista) + : ""; + if (percorsoCad.Length > 0) + trovati++; + _gridImport.Rows.Add(componente, descrizione, percorsoCad); } + _lblImportStatus.ForeColor = Color.DarkGreen; - _lblImportStatus.Text = $"CSV generato ({righe.Count} righe): {csv}"; + _lblImportStatus.Text = $"CSV generato ({righe.Count} righe, {trovati} con percorso CAD trovato): {csv}"; } catch (Exception ex) { @@ -214,6 +155,46 @@ public partial class Form1 : Form } } + /// Cerca, per ogni codice componente, i percorsi dei file CAD (ultima versione, + /// solo prt/asm) corrispondenti nell'indice. + private Dictionary> TrovaPercorsiCad(IEnumerable codici) + { + var risultato = new Dictionary>(); + if (_dbPath is null) + return risultato; + + using var connection = new SqliteConnection($"Data Source={_dbPath};Mode=ReadOnly"); + connection.Open(); + + var nomiParametri = TipiPredefiniti.Select((_, i) => $"@tipo{i}"); + using var command = connection.CreateCommand(); + command.CommandText = $""" + SELECT percorso_completo FROM files_ultima_versione + WHERE codice = @codice AND tipo_file IN ({string.Join(",", nomiParametri)}) + ORDER BY tipo_file + """; + var pCodice = command.Parameters.Add("@codice", Microsoft.Data.Sqlite.SqliteType.Text); + for (int i = 0; i < TipiPredefiniti.Length; i++) + { + command.Parameters.AddWithValue($"@tipo{i}", TipiPredefiniti[i]); + } + + foreach (var codice in codici.Distinct()) + { + pCodice.Value = codice; + using var reader = command.ExecuteReader(); + var percorsi = new List(); + while (reader.Read()) + { + percorsi.Add(reader.GetString(0)); + } + if (percorsi.Count > 0) + risultato[codice] = percorsi; + } + + return risultato; + } + private void InizializzaDatabase() { var candidati = new[] @@ -253,20 +234,6 @@ public partial class Form1 : Form using var connection = new SqliteConnection($"Data Source={path};Mode=ReadOnly"); connection.Open(); - _cmbTipo.Items.Clear(); - _cmbTipo.Items.Add(OpzionePrtAsm); - _cmbTipo.Items.Add(OpzioneTuttiTipi); - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "SELECT DISTINCT tipo_file FROM files ORDER BY tipo_file"; - using var reader = cmd.ExecuteReader(); - while (reader.Read()) - { - _cmbTipo.Items.Add(reader.GetString(0)); - } - } - _cmbTipo.SelectedIndex = 0; - long totale = (long)(new SqliteCommand("SELECT COUNT(*) FROM files", connection).ExecuteScalar() ?? 0L); _dbPath = path; @@ -292,7 +259,6 @@ public partial class Form1 : Form } _btnAggiorna.Enabled = false; - _btnCerca.Enabled = false; _lblStatus.Text = "Aggiornamento indice in corso..."; using var cts = new CancellationTokenSource(); @@ -332,160 +298,24 @@ public partial class Form1 : Form finally { _btnAggiorna.Enabled = true; - _btnCerca.Enabled = true; - } - } - - private void EseguiRicerca() - { - if (_dbPath is null) - { - _lblStatus.Text = "Nessun database caricato. Usa 'Apri DB...'."; - return; - } - - string testo = _txtCerca.Text.Trim(); - string? tipoSelezionato = (string?)_cmbTipo.SelectedItem; - string[]? tipi = tipoSelezionato switch - { - OpzionePrtAsm => TipiPredefiniti, - OpzioneTuttiTipi => null, - null => TipiPredefiniti, - _ => new[] { tipoSelezionato }, - }; - string? cartella = _cmbCartella.SelectedIndex > 0 ? (string)_cmbCartella.SelectedItem! : null; - bool soloUltima = _chkUltima.Checked; - - if (testo.Length == 0 && tipi is null && cartella is null) - { - _lblStatus.Text = "Inserisci un termine di ricerca o imposta un filtro."; - return; - } - - Cursor = Cursors.WaitCursor; - _btnCerca.Enabled = false; - try - { - var (colonne, righe, troncato) = Cerca(_dbPath, testo, soloUltima, cartella, tipi); - PopolaGriglia(colonne, righe); - _lblStatus.Text = $"{righe.Count} risultat{(righe.Count == 1 ? "o" : "i")}" - + (troncato ? " (troncato a 500, affina la ricerca)" : ""); - } - catch (Exception ex) - { - MessageBox.Show(this, $"Errore durante la ricerca:\n{ex.Message}", "Errore", - MessageBoxButtons.OK, MessageBoxIcon.Error); - } - finally - { - Cursor = Cursors.Default; - _btnCerca.Enabled = true; - } - } - - private static (string[] colonne, List righe, bool troncato) Cerca( - string dbPath, string testo, bool soloUltimaVersione, string? cartella, string[]? tipi) - { - using var connection = new SqliteConnection($"Data Source={dbPath};Mode=ReadOnly"); - connection.Open(); - - string tabella = soloUltimaVersione ? "files_ultima_versione" : "files"; - string filtroTipo = "1=1"; - if (tipi is { Length: > 0 }) - { - var nomiParametri = tipi.Select((_, i) => $"@tipo{i}"); - filtroTipo = $"tipo_file IN ({string.Join(",", nomiParametri)})"; - } - - var sql = $""" - SELECT percorso_completo, cartella_radice, famiglia, codice, tipo_file, versione, - dimensione_byte, data_modifica - FROM {tabella} - WHERE (@testo = '' OR codice LIKE @like OR nome_file LIKE @like) - AND (@cartella IS NULL OR cartella_radice = @cartella) - AND ({filtroTipo}) - ORDER BY codice, tipo_file, versione - LIMIT 500 - """; - - using var command = connection.CreateCommand(); - command.CommandText = sql; - command.Parameters.AddWithValue("@testo", testo); - command.Parameters.AddWithValue("@like", $"%{testo}%"); - command.Parameters.AddWithValue("@cartella", (object?)cartella ?? DBNull.Value); - if (tipi is { Length: > 0 }) - { - for (int i = 0; i < tipi.Length; i++) - { - command.Parameters.AddWithValue($"@tipo{i}", tipi[i]); - } - } - - using var reader = command.ExecuteReader(); - var righe = new List(); - while (reader.Read()) - { - righe.Add(new[] - { - reader.GetString(0), - reader.IsDBNull(2) ? "" : reader.GetString(2), - reader.IsDBNull(3) ? "" : reader.GetString(3), - reader.IsDBNull(4) ? "" : reader.GetString(4), - reader.IsDBNull(5) ? "" : reader.GetInt64(5).ToString(), - FormatSize(reader.IsDBNull(6) ? 0 : reader.GetInt64(6)), - reader.IsDBNull(7) ? "" : reader.GetString(7), - }); - } - - var colonne = new[] { "percorso", "famiglia", "codice", "tipo", "ver", "dimensione", "data modifica" }; - return (colonne, righe, righe.Count == 500); - } - - private static string FormatSize(long bytes) - { - string[] unita = { "B", "KB", "MB", "GB" }; - double value = bytes; - int i = 0; - while (value >= 1024 && i < unita.Length - 1) - { - value /= 1024; - i++; - } - return $"{value:0.#} {unita[i]}"; - } - - private void PopolaGriglia(string[] colonne, List righe) - { - _grid.Rows.Clear(); - _grid.Columns.Clear(); - foreach (var nome in colonne) - { - _grid.Columns.Add(nome, nome); - } - foreach (var riga in righe) - { - _grid.Rows.Add(riga); - } - if (_grid.Columns.Count > 0) - { - _grid.Columns[0].FillWeight = 220; } } private void ApriCartellaFileSelezionato() { - if (_grid.CurrentRow is null) + if (_gridImport.CurrentRow is null) { return; } - string? percorso = _grid.CurrentRow.Cells[0].Value as string; - if (string.IsNullOrEmpty(percorso)) + string? percorsi = _gridImport.CurrentRow.Cells[2].Value as string; + if (string.IsNullOrEmpty(percorsi)) { return; } + string primoPercorso = percorsi.Split("; ", 2)[0]; try { - Process.Start("explorer.exe", $"/select,\"{percorso}\""); + Process.Start("explorer.exe", $"/select,\"{primoPercorso}\""); } catch (Exception ex) {