Skip to content

Commit 4ac9def

Browse files
feat: add model type management for updating config types in database + bump version + fix license in package.json
1 parent 3a88653 commit 4ac9def

File tree

8 files changed

+231
-4
lines changed

8 files changed

+231
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ A tool for managing and analyzing InvokeAI database entries and PNG metadata.
1313
- **Metadata Extraction**: Automatic extraction and storage of InvokeAI metadata
1414
- **Workflow Detection**: Identification and flagging of images with workflow information
1515
- **Model Path Management**: Management of model paths in the database
16+
- **Model Type Management**: Management of model types in the database
1617

1718
### PNG Metadata Analysis
1819
- **Inspection**: Detailed analysis of PNG metadata, including InvokeAI-specific chunks

index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ <h3 data-i18n="pathReplacementTitle">Pfad-Ersetzung</h3>
6565
</div>
6666
</div>
6767
</div>
68+
69+
<div class="type-replacement-section">
70+
<h3 data-i18n="modelTypeManagementTitle">Model-Type-Verwaltung</h3>
71+
<p data-i18n="selectModelsHint">Wählen Sie die Models aus, deren config-type geändert werden soll:</p>
72+
<div class="replacement-inputs">
73+
<div class="input-group">
74+
<label for="new-type" data-i18n="newTypeLabel">Neuer Type:</label>
75+
<input type="text" id="new-type" placeholder="z.B. main">
76+
</div>
77+
</div>
78+
<div class="model-type-actions">
79+
<button id="update-types-button" class="primary-button" disabled data-i18n="updateTypesButton">Ausgewählte Types aktualisieren</button>
80+
</div>
81+
</div>
6882
</div>
6983

7084
<!-- Models-Ergebnisse -->

main.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,3 +1063,106 @@ ipcMain.handle('update-model-paths', async (event, { dbPath, oldPath, newPath })
10631063
return { success: false, message: error.message };
10641064
}
10651065
});
1066+
1067+
// IPC-Handler für das Aktualisieren von Model-Types
1068+
ipcMain.handle('update-model-types', async (event, { dbPath, modelIds, newType }) => {
1069+
try {
1070+
const db = new sqlite3.Database(dbPath);
1071+
1072+
return new Promise((resolve, reject) => {
1073+
// Validiere die Eingaben
1074+
if (!modelIds || !Array.isArray(modelIds) || modelIds.length === 0) {
1075+
db.close();
1076+
resolve({ success: false, message: 'Keine Models ausgewählt.' });
1077+
return;
1078+
}
1079+
1080+
if (!newType || newType.trim() === '') {
1081+
db.close();
1082+
resolve({ success: false, message: 'Neuer Type ist erforderlich.' });
1083+
return;
1084+
}
1085+
1086+
// Lade die ausgewählten Models
1087+
const placeholders = modelIds.map(() => '?').join(',');
1088+
db.all(`SELECT rowid as id, name, type, config FROM models WHERE rowid IN (${placeholders}) AND config IS NOT NULL`, modelIds, (err, rows) => {
1089+
if (err) {
1090+
db.close();
1091+
resolve({ success: false, message: `Fehler beim Laden der Models: ${err.message}` });
1092+
return;
1093+
}
1094+
1095+
const modelsToUpdate = [];
1096+
1097+
// Prüfe jedes ausgewählte Model
1098+
for (const row of rows) {
1099+
try {
1100+
const config = JSON.parse(row.config);
1101+
modelsToUpdate.push({
1102+
id: row.id,
1103+
name: row.name,
1104+
currentType: row.type,
1105+
config: config
1106+
});
1107+
} catch (jsonErr) {
1108+
console.warn(`Fehler beim Parsen der config für Model ID ${row.id}:`, jsonErr);
1109+
}
1110+
}
1111+
1112+
if (modelsToUpdate.length === 0) {
1113+
db.close();
1114+
resolve({
1115+
success: true,
1116+
message: 'Keine gültigen Models zum Aktualisieren gefunden.',
1117+
updatedCount: 0
1118+
});
1119+
return;
1120+
}
1121+
1122+
let updatedCount = 0;
1123+
let completedUpdates = 0;
1124+
1125+
const updateModel = (model) => {
1126+
// Aktualisiere den type in der config
1127+
const updatedConfig = { ...model.config };
1128+
const oldConfigType = updatedConfig.type || 'unbekannt';
1129+
updatedConfig.type = newType;
1130+
1131+
const updatedConfigJson = JSON.stringify(updatedConfig);
1132+
1133+
db.run(
1134+
`UPDATE models SET config = ? WHERE rowid = ?`,
1135+
[updatedConfigJson, model.id],
1136+
function(updateErr) {
1137+
completedUpdates++;
1138+
1139+
if (updateErr) {
1140+
console.error(`Fehler beim Aktualisieren von Model ${model.name}:`, updateErr);
1141+
} else {
1142+
updatedCount++;
1143+
console.log(`Model "${model.name}" config-type von "${oldConfigType}" zu "${newType}" geändert`);
1144+
}
1145+
1146+
// Wenn alle Updates abgeschlossen sind
1147+
if (completedUpdates === modelsToUpdate.length) {
1148+
db.close();
1149+
resolve({
1150+
success: true,
1151+
message: `${updatedCount} von ${modelsToUpdate.length} Models erfolgreich aktualisiert.`,
1152+
updatedCount: updatedCount,
1153+
totalModels: modelsToUpdate.length
1154+
});
1155+
}
1156+
}
1157+
);
1158+
};
1159+
1160+
// Starte alle Updates
1161+
modelsToUpdate.forEach(updateModel);
1162+
});
1163+
});
1164+
} catch (error) {
1165+
console.error('Fehler beim Aktualisieren der Model-Types:', error);
1166+
return { success: false, message: error.message };
1167+
}
1168+
});

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sqlite-electron-tool",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"description": "Electron-App zum Abgleich von InvokeAI DB mit Bilddateien",
55
"main": "main.js",
66
"scripts": {
@@ -14,7 +14,7 @@
1414
"png-analyzer": "node png-metadata-analyzer.js"
1515
},
1616
"author": "Pfannkuchensack",
17-
"license": "ISC",
17+
"license": "MIT",
1818
"devDependencies": {
1919
"@electron-forge/cli": "^7.8.1",
2020
"@electron-forge/maker-deb": "^7.8.1",

preload.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ contextBridge.exposeInMainWorld('electronAPI', {
1111
syncThumbnails: (params) => ipcRenderer.invoke('sync-thumbnails', params),
1212
restoreThumbnails: (params) => ipcRenderer.invoke('restore-thumbnails', params),
1313
loadModels: (params) => ipcRenderer.invoke('load-models', params),
14-
updateModelPaths: (params) => ipcRenderer.invoke('update-model-paths', params)
14+
updateModelPaths: (params) => ipcRenderer.invoke('update-model-paths', params),
15+
updateModelTypes: (params) => ipcRenderer.invoke('update-model-types', params)
1516
});
1617

1718
// Stelle die Übersetzungen im Renderer-Prozess zur Verfügung

renderer.js

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ const newPathInput = document.getElementById('new-path');
3939
const modelsList = document.getElementById('models-list');
4040
const modelsCount = document.getElementById('models-count');
4141

42+
// Model-Type-Management DOM-Elemente
43+
const updateTypesButton = document.getElementById('update-types-button');
44+
const newTypeInput = document.getElementById('new-type');
45+
4246
// Feste Werte für Tabelle und Spalte
4347
const MODELS_TABLE = 'models';
4448
const PATH_COLUMN = 'path';
@@ -371,6 +375,67 @@ updatePathsButton.addEventListener('click', async () => {
371375
}
372376
});
373377

378+
// Event-Handler für Model-Type-Update
379+
updateTypesButton.addEventListener('click', async () => {
380+
try {
381+
if (!dbPath) {
382+
setStatus(window.translations[currentLanguage].noDbSelected || 'Bitte wählen Sie zuerst eine Datenbank aus.', true);
383+
return;
384+
}
385+
386+
const newType = newTypeInput.value.trim();
387+
388+
if (!newType) {
389+
setStatus(window.translations[currentLanguage].newTypeRequired || 'Bitte geben Sie den neuen Type ein.', true);
390+
return;
391+
}
392+
393+
// Sammle die ausgewählten Model-IDs
394+
const selectedModelIds = [];
395+
const checkboxes = document.querySelectorAll('.model-checkbox:checked');
396+
397+
checkboxes.forEach(checkbox => {
398+
const index = parseInt(checkbox.id.replace('model-', ''));
399+
if (modelsData[index] && modelsData[index].id) {
400+
selectedModelIds.push(modelsData[index].id);
401+
}
402+
});
403+
404+
if (selectedModelIds.length === 0) {
405+
setStatus(window.translations[currentLanguage].noModelsSelected || 'Bitte wählen Sie mindestens ein Model aus.', true);
406+
return;
407+
}
408+
409+
// Bestätigungsdialog
410+
const confirmMessage = (window.translations[currentLanguage].confirmUpdateTypes || 'Möchten Sie wirklich den config-type von {count} ausgewählten Models zu "{newType}" ändern?')
411+
.replace('{count}', selectedModelIds.length)
412+
.replace('{newType}', newType);
413+
414+
if (!confirm(confirmMessage)) {
415+
return;
416+
}
417+
418+
setStatus(window.translations[currentLanguage].updatingTypes || 'Aktualisiere Model-Types...');
419+
420+
const result = await window.electronAPI.updateModelTypes({
421+
dbPath: dbPath,
422+
modelIds: selectedModelIds,
423+
newType: newType
424+
});
425+
426+
if (result.success) {
427+
setStatus(window.translations[currentLanguage].typesUpdated + ` (${result.updatedCount} von ${selectedModelIds.length} Models aktualisiert)`);
428+
// Models neu laden um aktualisierte Types anzuzeigen
429+
loadModelsButton.click();
430+
} else {
431+
setStatus(result.message, true);
432+
}
433+
434+
} catch (error) {
435+
setStatus(`Fehler beim Aktualisieren der Model-Types: ${error.message}`, true);
436+
}
437+
});
438+
374439
// Hilfsfunktion zum Anzeigen der Models
375440
function displayModels() {
376441
if (!modelsData || modelsData.length === 0) {
@@ -400,9 +465,17 @@ function displayModels() {
400465

401466
const modelInfo = document.createElement('div');
402467
modelInfo.className = 'model-info';
468+
469+
// Extrahiere config-Type falls vorhanden
470+
let configType = 'Unbekannt';
471+
if (model.config && model.config.type) {
472+
configType = model.config.type;
473+
}
474+
403475
modelInfo.innerHTML = `
404476
<strong>${model.name || 'Unbenannt'}</strong><br>
405-
<span>Typ: ${model.type || 'Unbekannt'}</span><br>
477+
<span>DB-Typ: ${model.type || 'Unbekannt'}</span><br>
478+
<span>Config-Typ: ${configType}</span><br>
406479
<span>Pfad: ${model.path || 'Kein Pfad'}</span>
407480
`;
408481

@@ -418,6 +491,7 @@ function updateSyncButtonState() {
418491
syncButton.disabled = !dbPath || !outputDir;
419492
syncThumbnailsButton.disabled = !dbPath || !outputDir;
420493
loadModelsButton.disabled = !dbPath;
494+
updateTypesButton.disabled = !dbPath;
421495
}
422496

423497
// Hilfsfunktion zum Anzeigen der Synchronisierungsergebnisse

styles.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,18 @@ button:disabled {
250250
color: #2c3e50;
251251
}
252252

253+
.model-type-actions {
254+
margin-top: 15px;
255+
display: flex;
256+
gap: 10px;
257+
}
258+
259+
.type-replacement-section {
260+
margin-top: 20px;
261+
padding-top: 20px;
262+
border-top: 1px solid #eee;
263+
}
264+
253265
#status-bar {
254266
background-color: #2c3e50;
255267
color: white;

translations.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ const translationsjs = {
6969
oldPathRequired: 'Bitte geben Sie den alten Pfad ein.',
7070
newPathRequired: 'Bitte geben Sie den neuen Pfad ein.',
7171

72+
// Model Type Management
73+
modelTypeManagementTitle: 'Model-Type-Verwaltung',
74+
updateTypesButton: 'Ausgewählte Types aktualisieren',
75+
selectModelsHint: 'Wählen Sie die Models aus, deren config-type geändert werden soll:',
76+
newTypeLabel: 'Neuer Type:',
77+
updatingTypes: 'Aktualisiere Model-Types...',
78+
typesUpdated: 'Model-Types wurden erfolgreich aktualisiert.',
79+
noModelsSelected: 'Bitte wählen Sie mindestens ein Model aus.',
80+
confirmUpdateTypes: 'Möchten Sie wirklich den config-type von {count} ausgewählten Models zu "{newType}" ändern?',
81+
newTypeRequired: 'Bitte geben Sie den neuen Type ein.',
82+
7283
// Sprachauswahl
7384
languageLabel: 'Sprache:',
7485
languageDE: 'Deutsch',
@@ -143,6 +154,17 @@ const translationsjs = {
143154
oldPathRequired: 'Please enter the old path.',
144155
newPathRequired: 'Please enter the new path.',
145156

157+
// Model Type Management
158+
modelTypeManagementTitle: 'Model Type Management',
159+
updateTypesButton: 'Update Selected Types',
160+
selectModelsHint: 'Select the models whose config-type should be changed:',
161+
newTypeLabel: 'New Type:',
162+
updatingTypes: 'Updating model types...',
163+
typesUpdated: 'Model types updated successfully.',
164+
noModelsSelected: 'Please select at least one model.',
165+
confirmUpdateTypes: 'Do you really want to change the config-type of {count} selected models to "{newType}"?',
166+
newTypeRequired: 'Please enter the new type.',
167+
146168
// Language selection
147169
languageLabel: 'Language:',
148170
languageDE: 'German',

0 commit comments

Comments
 (0)