ACMX 2.139.0
Dual-Backend Real-Time GPU Video Synthesis
Loading...
Searching...
No Matches
stable-diffusion-settings.cpp
Go to the documentation of this file.
2
3#include "custom_style.hpp"
4
5#include <QCheckBox>
6#include <QComboBox>
7#include <QCoreApplication>
8#include <QDialogButtonBox>
9#include <QDoubleSpinBox>
10#include <QFileDialog>
11#include <QFileInfo>
12#include <QFormLayout>
13#include <QGroupBox>
14#include <QHBoxLayout>
15#include <QLabel>
16#include <QLineEdit>
17#include <QListWidget>
18#include <QMessageBox>
19#include <QProcess>
20#include <QPushButton>
21#include <QRegularExpression>
22#include <QScrollArea>
23#include <QSettings>
24#include <QSignalBlocker>
25#include <QSpinBox>
26#include <QVBoxLayout>
27
28#include <limits>
29
30namespace {
31 constexpr int STABLE_DIMENSION_MINIMUM = 64;
32 constexpr int STABLE_DIMENSION_MAXIMUM = 2048;
33 constexpr int LORA_PATH_ROLE = Qt::UserRole;
34 constexpr int LORA_MULTIPLIER_ROLE = Qt::UserRole + 1;
35
36 bool parse_stable_resolution(const QString &text, int &width, int &height) {
37 static const QRegularExpression RESOLUTION_PATTERN(QStringLiteral("^\\s*(\\d+)\\s*[xX]\\s*(\\d+)\\s*$"));
38 const QRegularExpressionMatch match = RESOLUTION_PATTERN.match(text);
39 if (!match.hasMatch()) {
40 return false;
41 }
42
43 bool width_ok = false;
44 bool height_ok = false;
45 const int parsed_width = match.captured(1).toInt(&width_ok);
46 const int parsed_height = match.captured(2).toInt(&height_ok);
47 if (!width_ok || !height_ok) {
48 return false;
49 }
50
51 width = parsed_width;
52 height = parsed_height;
53 return true;
54 }
55
56 QString resolution_text(int width, int height) { return QStringLiteral("%1x%2").arg(width).arg(height); }
57
59#ifdef _WIN32
60 const QFileInfo bundled_server(QDir(QCoreApplication::applicationDirPath()).filePath(QStringLiteral("sd-server.exe")));
61 if (bundled_server.isFile()) {
62 return bundled_server.absoluteFilePath();
63 }
64 return QStringLiteral("sd-server.exe");
65#else
66 const QFileInfo bundled_server(QStringLiteral("/app/bin/sd-server"));
67 if (bundled_server.isExecutable()) {
68 return bundled_server.absoluteFilePath();
69 }
70 return QStringLiteral("sd-server");
71#endif
72 }
73} // namespace
74
76 setWindowTitle("Stable Diffusion Settings");
77 setMinimumSize(600, 600);
78
79 enable_check_box = new QCheckBox("Enable Stable Diffusion", this);
80 model_file_edit = new QLineEdit(this);
81 model_file_edit->setReadOnly(true);
82 model_file_edit->setPlaceholderText("Select a safetensors model...");
83 browse_model_button = new QPushButton("Browse...", this);
84 prompt_edit = new QLineEdit(this);
85 prompt_edit->setPlaceholderText("Describe the desired image style...");
86 negative_prompt_edit = new QLineEdit(this);
87 negative_prompt_edit->setPlaceholderText("Optional unwanted features...");
88 lora_list_widget = new QListWidget(this);
89 lora_list_widget->setSelectionMode(QAbstractItemView::ExtendedSelection);
90 lora_list_widget->setMinimumHeight(100);
91 add_lora_button = new QPushButton("Add...", this);
92 remove_lora_button = new QPushButton("Remove", this);
93 lora_multiplier_spin_box = new QDoubleSpinBox(this);
94 lora_multiplier_spin_box->setRange(-10.0, 10.0);
95 lora_multiplier_spin_box->setDecimals(3);
96 lora_multiplier_spin_box->setSingleStep(0.05);
97 lora_multiplier_spin_box->setValue(1.0);
98
99 server_edit = new QLineEdit(this);
100 server_edit->setPlaceholderText(default_stable_diffusion_server());
101 server_arguments_edit = new QLineEdit(this);
102 server_arguments_edit->setPlaceholderText("Optional flags, for example --vae-tiling --offload-to-cpu");
103 server_arguments_edit->setToolTip("Additional command-line arguments passed directly to sd-server. "
104 "Use quotes around values containing spaces.");
105 browse_server_button = new QPushButton("Browse...", this);
106 server_port_spin_box = new QSpinBox(this);
107 server_port_spin_box->setRange(1024, 65535);
108
109 resolution_combo_box = new QComboBox(this);
110 resolution_combo_box->setEditable(true);
111 resolution_combo_box->setInsertPolicy(QComboBox::NoInsert);
112 resolution_combo_box->lineEdit()->setPlaceholderText("WIDTHxHEIGHT");
113 resolution_combo_box->addItems({"512x512", "576x320", "640x384", "704x448", "768x448", "768x512", "832x512", "896x512", "1024x576", "1024x1024", "1152x640", "1280x768", "1344x768", "1536x896", "1920x1088"});
114 resolution_combo_box->setToolTip("Choose a preset or enter WIDTHxHEIGHT. Both dimensions must be "
115 "multiples of 64 between 64 and 2048 pixels.");
116 steps_spin_box = new QSpinBox(this);
117 steps_spin_box->setRange(1, 150);
118 strength_spin_box = new QDoubleSpinBox(this);
119 strength_spin_box->setRange(0.01, 1.0);
120 strength_spin_box->setDecimals(3);
121 strength_spin_box->setSingleStep(0.05);
122 cfg_scale_spin_box = new QDoubleSpinBox(this);
123 cfg_scale_spin_box->setRange(0.0, 50.0);
124 cfg_scale_spin_box->setDecimals(2);
125 cfg_scale_spin_box->setSingleStep(0.5);
126 seed_spin_box = new QSpinBox(this);
127 seed_spin_box->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
128 sampler_combo_box = new QComboBox(this);
129 sampler_combo_box->setEditable(true);
130 sampler_combo_box->addItems({"euler_a", "euler", "dpm++2m", "dpm++2mv2", "lcm"});
131 scheduler_combo_box = new QComboBox(this);
132 scheduler_combo_box->setEditable(true);
133 scheduler_combo_box->addItems({"discrete", "karras", "exponential", "ays"});
134 upscale_check_box = new QCheckBox("High-quality Vulkan compute upscale before shaders", this);
135 upscale_check_box->setToolTip("Keep the native Stable Diffusion image size and run ACMXVK's "
136 "bicubic detail-preserving compute stage before user shaders.");
137 upscale_only_check_box = new QCheckBox("Use ESRGAN upscale only before shaders (no image-to-image model)", this);
138 upscale_only_check_box->setToolTip("Run the selected ESRGAN model through sd-server before the ACMXVK shader chain. "
139 "No diffusion model, prompt, sampler, or LoRA is used.");
140 server_upscale_check_box = new QCheckBox("Use an sd-server ESRGAN upscale model", this);
141 server_upscale_check_box->setToolTip("Load an ESRGAN or RealESRGAN model in sd-server and use its neural "
142 "upscaler instead of ACMXVK's Vulkan compute upscaler.");
143 upscale_model_edit = new QLineEdit(this);
144 upscale_model_edit->setReadOnly(true);
145 upscale_model_edit->setPlaceholderText("Select an ESRGAN/RealESRGAN model...");
146 browse_upscale_model_button = new QPushButton("Browse...", this);
147 upscale_working_resolution_edit = new QLineEdit(this);
148 upscale_working_resolution_edit->setPlaceholderText("Auto (output capped at 1280x720)");
149 upscale_working_resolution_edit->setToolTip("Optional ESRGAN working resolution, WIDTHxHEIGHT. "
150 "The neural upscaler runs at this size before ACMXVK resizes to the final output.");
151
152 auto *model_group = new QGroupBox("Image-to-Image Model", this);
153 auto *model_layout = new QFormLayout(model_group);
154 auto *model_row = new QHBoxLayout;
155 model_row->addWidget(model_file_edit, 1);
156 model_row->addWidget(browse_model_button);
157 model_layout->addRow("Safetensors model:", model_row);
158 model_layout->addRow("Prompt:", prompt_edit);
159 model_layout->addRow("Negative prompt:", negative_prompt_edit);
160
161 auto *lora_group = new QGroupBox("LoRA Models", this);
162 lora_group->setToolTip("Optional adapters applied by sd-server. All selected LoRA files "
163 "must be in the same folder.");
164 auto *lora_layout = new QVBoxLayout(lora_group);
165 lora_layout->addWidget(lora_list_widget);
166 auto *lora_controls = new QHBoxLayout;
167 lora_controls->addWidget(add_lora_button);
168 lora_controls->addWidget(remove_lora_button);
169 lora_controls->addStretch();
170 lora_controls->addWidget(new QLabel("Selected multiplier:", this));
171 lora_controls->addWidget(lora_multiplier_spin_box);
172 lora_layout->addLayout(lora_controls);
173
174 auto *generation_group = new QGroupBox("Generation", this);
175 auto *generation_layout = new QFormLayout(generation_group);
176 generation_layout->addRow("Resolution:", resolution_combo_box);
177 generation_layout->addRow("Steps:", steps_spin_box);
178 generation_layout->addRow("Denoising strength:", strength_spin_box);
179 generation_layout->addRow("CFG scale:", cfg_scale_spin_box);
180 generation_layout->addRow("Seed:", seed_spin_box);
181 generation_layout->addRow("Sampler:", sampler_combo_box);
182 generation_layout->addRow("Scheduler:", scheduler_combo_box);
183 generation_layout->addRow(upscale_check_box);
184 generation_layout->addRow(upscale_only_check_box);
185 generation_layout->addRow(server_upscale_check_box);
186 auto *upscale_model_row = new QHBoxLayout;
187 upscale_model_row->addWidget(upscale_model_edit, 1);
188 upscale_model_row->addWidget(browse_upscale_model_button);
189 generation_layout->addRow("Upscale model:", upscale_model_row);
190 generation_layout->addRow("ESRGAN working resolution:", upscale_working_resolution_edit);
191
192 auto *server_group = new QGroupBox("Local sd-server", this);
193 auto *server_layout = new QFormLayout(server_group);
194 auto *server_row = new QHBoxLayout;
195 server_row->addWidget(server_edit, 1);
196 server_row->addWidget(browse_server_button);
197 server_layout->addRow("Executable:", server_row);
198 server_layout->addRow("Extra flags:", server_arguments_edit);
199 server_layout->addRow("Loopback port:", server_port_spin_box);
200
201 auto *contents = new QWidget(this);
202 auto *contents_layout = new QVBoxLayout(contents);
203 contents_layout->addWidget(enable_check_box);
204 contents_layout->addWidget(model_group);
205 contents_layout->addWidget(lora_group);
206 contents_layout->addWidget(generation_group);
207 contents_layout->addWidget(server_group);
208 contents_layout->addStretch();
209
210 auto *scroll_area = new QScrollArea(this);
211 scroll_area->setWidgetResizable(true);
212 scroll_area->setWidget(contents);
213
214 auto *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel, this);
215 auto *layout = new QVBoxLayout(this);
216 layout->addWidget(scroll_area, 1);
217 layout->addWidget(buttons);
218
219 connect(enable_check_box, &QCheckBox::toggled, this, [this](bool) { update_enabled_state(); });
220 connect(browse_model_button, &QPushButton::clicked, this, &StableDiffusionSettingsDialog::browse_model);
221 connect(add_lora_button, &QPushButton::clicked, this, &StableDiffusionSettingsDialog::add_lora_models);
222 connect(remove_lora_button, &QPushButton::clicked, this, &StableDiffusionSettingsDialog::remove_lora_models);
223 connect(lora_list_widget, &QListWidget::itemSelectionChanged, this, &StableDiffusionSettingsDialog::select_lora_model);
224 connect(lora_multiplier_spin_box, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &StableDiffusionSettingsDialog::update_lora_multiplier);
226 connect(upscale_check_box, &QCheckBox::toggled, this, [this](bool checked) {
227 if (checked) {
228 server_upscale_check_box->setChecked(false);
229 }
231 });
232 connect(upscale_only_check_box, &QCheckBox::toggled, this, [this](bool checked) {
233 if (checked) {
234 server_upscale_check_box->setChecked(true);
235 upscale_check_box->setChecked(false);
236 }
238 });
239 connect(server_upscale_check_box, &QCheckBox::toggled, this, [this](bool checked) {
240 if (checked) {
241 upscale_check_box->setChecked(false);
242 }
244 });
245 connect(browse_server_button, &QPushButton::clicked, this, &StableDiffusionSettingsDialog::browse_server);
246 connect(buttons, &QDialogButtonBox::accepted, this, &StableDiffusionSettingsDialog::accept_settings);
247 connect(buttons->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &StableDiffusionSettingsDialog::apply_settings);
248 connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
249
253}
254
257 result.enabled = enable_check_box->isChecked();
258 result.model_file = model_file_edit->text().trimmed();
259 for (int row = 0; row < lora_list_widget->count(); ++row) {
260 const QListWidgetItem *item = lora_list_widget->item(row);
261 result.lora_files.append(item->data(LORA_PATH_ROLE).toString());
262 result.lora_multipliers.append(item->data(LORA_MULTIPLIER_ROLE).toDouble());
263 }
264 if (server_upscale_check_box->isChecked() || upscale_only_check_box->isChecked()) {
265 result.upscale_model_file = upscale_model_edit->text().trimmed();
266 }
267 result.prompt = prompt_edit->text().trimmed();
268 result.negative_prompt = negative_prompt_edit->text().trimmed();
269 result.server_executable = server_edit->text().trimmed();
270 result.server_arguments = server_arguments_edit->text().trimmed();
271 result.server_port = server_port_spin_box->value();
272 parse_stable_resolution(resolution_combo_box->currentText(), result.width, result.height);
273 parse_stable_resolution(upscale_working_resolution_edit->text(), result.upscale_working_width, result.upscale_working_height);
274 result.steps = steps_spin_box->value();
275 result.strength = strength_spin_box->value();
276 result.cfg_scale = cfg_scale_spin_box->value();
277 result.seed = seed_spin_box->value();
278 result.sampler = sampler_combo_box->currentText().trimmed();
279 result.scheduler = scheduler_combo_box->currentText().trimmed();
280 result.upscale = upscale_check_box->isChecked();
281 result.upscale_only = upscale_only_check_box->isChecked();
282 return result;
283}
284
286 QSettings settings("LostSideDead", "acmx2");
287 const QString directory = settings.value("stable_diffusion/last_model_directory").toString();
288 const QString filename = QFileDialog::getOpenFileName(this, "Select Stable Diffusion Model", directory, "Safetensors Models (*.safetensors);;All Files (*)");
289 if (filename.isEmpty()) {
290 return;
291 }
292 model_file_edit->setText(QFileInfo(filename).absoluteFilePath());
293 settings.setValue("stable_diffusion/last_model_directory", QFileInfo(filename).absolutePath());
294}
295
296void StableDiffusionSettingsDialog::add_lora_item(const QString &filename, double multiplier) {
297 const QString absolute_file = QFileInfo(filename).absoluteFilePath();
298 for (int row = 0; row < lora_list_widget->count(); ++row) {
299 if (lora_list_widget->item(row)->data(LORA_PATH_ROLE).toString() == absolute_file) {
300 return;
301 }
302 }
303 auto *item = new QListWidgetItem(lora_list_widget);
304 item->setData(LORA_PATH_ROLE, absolute_file);
305 item->setData(LORA_MULTIPLIER_ROLE, multiplier);
306 item->setToolTip(absolute_file);
308}
309
311 QListWidgetItem *item = lora_list_widget->item(row);
312 if (item == nullptr) {
313 return;
314 }
315 const QString filename = QFileInfo(item->data(LORA_PATH_ROLE).toString()).fileName();
316 const double multiplier = item->data(LORA_MULTIPLIER_ROLE).toDouble();
317 item->setText(QStringLiteral("%1 — %2").arg(filename).arg(multiplier, 0, 'f', 3));
318}
319
321 QSettings settings("LostSideDead", "acmx2");
322 const QString directory = settings.value("stable_diffusion/last_lora_directory").toString();
323 const QStringList filenames = QFileDialog::getOpenFileNames(this, "Select LoRA Models", directory, "LoRA Models (*.safetensors *.ckpt *.pt *.pth *.gguf);;All Files (*)");
324 if (filenames.isEmpty()) {
325 return;
326 }
327 for (const QString &filename : filenames) {
328 add_lora_item(filename, 1.0);
329 }
330 settings.setValue("stable_diffusion/last_lora_directory", QFileInfo(filenames.first()).absolutePath());
331 lora_list_widget->setCurrentRow(lora_list_widget->count() - 1);
332}
333
335 const QList<QListWidgetItem *> selected = lora_list_widget->selectedItems();
336 for (QListWidgetItem *item : selected) {
337 delete lora_list_widget->takeItem(lora_list_widget->row(item));
338 }
340}
341
343 const QList<QListWidgetItem *> selected = lora_list_widget->selectedItems();
344 const bool one_selected = selected.size() == 1;
345 remove_lora_button->setEnabled(enable_check_box->isChecked() && !selected.isEmpty());
346 lora_multiplier_spin_box->setEnabled(enable_check_box->isChecked() && one_selected);
347 if (one_selected) {
348 const QSignalBlocker blocker(lora_multiplier_spin_box);
349 lora_multiplier_spin_box->setValue(selected.front()->data(LORA_MULTIPLIER_ROLE).toDouble());
350 }
351}
352
354 const QList<QListWidgetItem *> selected = lora_list_widget->selectedItems();
355 if (selected.size() != 1) {
356 return;
357 }
358 QListWidgetItem *item = selected.front();
359 item->setData(LORA_MULTIPLIER_ROLE, multiplier);
361}
362
364 QSettings settings("LostSideDead", "acmx2");
365 const QString directory = settings.value("stable_diffusion/last_upscale_model_directory").toString();
366 const QString filename = QFileDialog::getOpenFileName(this, "Select ESRGAN Upscale Model", directory, "Upscale Models (*.safetensors *.pth *.pt);;All Files (*)");
367 if (filename.isEmpty()) {
368 return;
369 }
370 upscale_model_edit->setText(QFileInfo(filename).absoluteFilePath());
371 server_upscale_check_box->setChecked(true);
372 settings.setValue("stable_diffusion/last_upscale_model_directory", QFileInfo(filename).absolutePath());
373}
374
376#ifdef _WIN32
377 const QString filter = QStringLiteral("Windows Executables (*.exe);;All Files (*)");
378#else
379 const QString filter = QStringLiteral("All Files (*)");
380#endif
381 const QString filename = QFileDialog::getOpenFileName(this, "Select sd-server Executable", QFileInfo(server_edit->text()).absolutePath(), filter);
382 if (!filename.isEmpty()) {
383 server_edit->setText(QFileInfo(filename).absoluteFilePath());
384 }
385}
386
388 if (!validate_settings()) {
389 return;
390 }
392 emit settingsApplied();
393}
394
396 if (!validate_settings()) {
397 return;
398 }
400 emit settingsApplied();
401 accept();
402}
403
405 if (!enable_check_box->isChecked()) {
406 return true;
407 }
408 if (!upscale_only_check_box->isChecked() && !QFileInfo(model_file_edit->text().trimmed()).isFile()) {
409 QMessageBox::warning(this, "Stable Diffusion Model Required", "Select an existing safetensors model file.");
410 return false;
411 }
412 QString lora_directory;
413 for (int row = 0; !upscale_only_check_box->isChecked() && row < lora_list_widget->count(); ++row) {
414 const QString filename = lora_list_widget->item(row)->data(LORA_PATH_ROLE).toString();
415 const QFileInfo file_info(filename);
416 if (!file_info.isFile()) {
417 QMessageBox::warning(this, "LoRA Model Not Found", QStringLiteral("The selected LoRA model does not exist:\n%1").arg(filename));
418 return false;
419 }
420 if (lora_directory.isEmpty()) {
421 lora_directory = file_info.absolutePath();
422 } else if (lora_directory != file_info.absolutePath()) {
423 QMessageBox::warning(this,
424 "LoRA Folder Mismatch",
425 "All selected LoRA models must be in the same folder. "
426 "sd-server scans one LoRA model directory per launch.");
427 return false;
428 }
429 }
430 if (!upscale_only_check_box->isChecked() && prompt_edit->text().trimmed().isEmpty()) {
431 QMessageBox::warning(this, "Stable Diffusion Prompt Required", "Enter an image-to-image prompt.");
432 return false;
433 }
434 if (server_edit->text().trimmed().isEmpty()) {
435 QMessageBox::warning(this, "sd-server Required", "Enter sd-server or select its executable.");
436 return false;
437 }
438 const QStringList server_arguments = QProcess::splitCommand(server_arguments_edit->text());
439 constexpr int MAX_SERVER_ARGUMENTS = 256;
440 constexpr int MAX_SERVER_ARGUMENT_BYTES = 8192;
441 if (server_arguments.size() > MAX_SERVER_ARGUMENTS) {
442 QMessageBox::warning(this, "Too Many sd-server Flags", "Extra sd-server flags are limited to 256 arguments.");
443 return false;
444 }
445 for (const QString &argument : server_arguments) {
446 if (argument.isEmpty() || argument.toUtf8().size() > MAX_SERVER_ARGUMENT_BYTES) {
447 QMessageBox::warning(this,
448 "Invalid sd-server Flag",
449 "Each extra sd-server argument must be non-empty and no "
450 "larger than 8192 UTF-8 bytes.");
451 return false;
452 }
453 }
454 if (server_upscale_check_box->isChecked() && !QFileInfo(upscale_model_edit->text().trimmed()).isFile()) {
455 QMessageBox::warning(this, "Upscale Model Required", "Select an existing ESRGAN or RealESRGAN model.");
456 return false;
457 }
458 if (upscale_only_check_box->isChecked() && !server_upscale_check_box->isChecked()) {
459 QMessageBox::warning(this, "Upscale Model Required", "Enable the sd-server ESRGAN model and select an existing model.");
460 return false;
461 }
462 const QString working_resolution = upscale_working_resolution_edit->text().trimmed();
463 if (!working_resolution.isEmpty()) {
464 int working_width = 0;
465 int working_height = 0;
466 if (!parse_stable_resolution(working_resolution, working_width, working_height) || working_width < 64 || working_width > 4096 || working_height < 64 || working_height > 4096) {
467 QMessageBox::warning(this, "Invalid ESRGAN Working Resolution", "Enter WIDTHxHEIGHT between 64 and 4096 pixels, or leave this field blank for automatic sizing.");
468 return false;
469 }
470 upscale_working_resolution_edit->setText(resolution_text(working_width, working_height));
471 }
472 int width = 0;
473 int height = 0;
474 if (!parse_stable_resolution(resolution_combo_box->currentText(), width, height)) {
475 QMessageBox::warning(this, "Invalid Stable Diffusion Resolution", "Enter the resolution as WIDTHxHEIGHT, for example 640x384.");
476 return false;
477 }
478 if (width < STABLE_DIMENSION_MINIMUM || width > STABLE_DIMENSION_MAXIMUM || height < STABLE_DIMENSION_MINIMUM || height > STABLE_DIMENSION_MAXIMUM || (width % 64) != 0 || (height % 64) != 0) {
479 QMessageBox::warning(this,
480 "Invalid Stable Diffusion Resolution",
481 "Width and height must be multiples of 64 between 64 and 2048 "
482 "pixels.");
483 return false;
484 }
485 resolution_combo_box->setCurrentText(resolution_text(width, height));
486 if (!upscale_only_check_box->isChecked() && (sampler_combo_box->currentText().trimmed().isEmpty() || scheduler_combo_box->currentText().trimmed().isEmpty())) {
487 QMessageBox::warning(this, "Generation Method Required", "Enter both a sampler and scheduler.");
488 return false;
489 }
490 return true;
491}
492
494 QSettings settings("LostSideDead", "acmx2");
495 enable_check_box->setChecked(settings.value("stable_diffusion/enabled", false).toBool());
496 model_file_edit->setText(settings.value("stable_diffusion/model_file").toString());
497 const QStringList lora_files = settings.value("stable_diffusion/lora_files").toStringList();
498 const QStringList lora_multiplier_values = settings.value("stable_diffusion/lora_multipliers").toStringList();
499 for (int index = 0; index < lora_files.size(); ++index) {
500 bool multiplier_ok = false;
501 const double saved_multiplier = index < lora_multiplier_values.size() ? lora_multiplier_values.at(index).toDouble(&multiplier_ok) : 1.0;
502 add_lora_item(lora_files.at(index), multiplier_ok ? saved_multiplier : 1.0);
503 }
504 prompt_edit->setText(settings.value("stable_diffusion/prompt").toString());
505 negative_prompt_edit->setText(settings.value("stable_diffusion/negative_prompt").toString());
506 server_edit->setText(settings.value("stable_diffusion/server", default_stable_diffusion_server()).toString());
507 server_arguments_edit->setText(settings.value("stable_diffusion/server_arguments").toString());
508 server_port_spin_box->setValue(settings.value("stable_diffusion/port", 1234).toInt());
509 const int width = settings.value("stable_diffusion/width", 576).toInt();
510 const int height = settings.value("stable_diffusion/height", 320).toInt();
511 const QString saved_resolution = settings.value("stable_diffusion/resolution", resolution_text(width, height)).toString();
512 int saved_width = 0;
513 int saved_height = 0;
514 if (parse_stable_resolution(saved_resolution, saved_width, saved_height)) {
515 resolution_combo_box->setCurrentText(resolution_text(saved_width, saved_height));
516 } else {
517 resolution_combo_box->setCurrentText(resolution_text(width, height));
518 }
519 steps_spin_box->setValue(settings.value("stable_diffusion/steps", 12).toInt());
520 strength_spin_box->setValue(settings.value("stable_diffusion/strength", 0.35).toDouble());
521 cfg_scale_spin_box->setValue(settings.value("stable_diffusion/cfg_scale", 5.0).toDouble());
522 seed_spin_box->setValue(settings.value("stable_diffusion/seed", 1234).toInt());
523 sampler_combo_box->setCurrentText(settings.value("stable_diffusion/sampler", "euler_a").toString());
524 scheduler_combo_box->setCurrentText(settings.value("stable_diffusion/scheduler", "discrete").toString());
525 upscale_model_edit->setText(settings.value("stable_diffusion/upscale_model_file").toString());
526 const int upscale_working_width = settings.value("stable_diffusion/upscale_working_width", 0).toInt();
527 const int upscale_working_height = settings.value("stable_diffusion/upscale_working_height", 0).toInt();
528 if (upscale_working_width > 0 && upscale_working_height > 0) {
529 upscale_working_resolution_edit->setText(resolution_text(upscale_working_width, upscale_working_height));
530 }
531 server_upscale_check_box->setChecked(settings.value("stable_diffusion/server_upscale", false).toBool());
532 upscale_check_box->setChecked(settings.value("stable_diffusion/upscale", false).toBool());
533 upscale_only_check_box->setChecked(settings.value("stable_diffusion/upscale_only", false).toBool());
534}
535
538 QSettings settings("LostSideDead", "acmx2");
539 settings.setValue("stable_diffusion/enabled", current.enabled);
540 settings.setValue("stable_diffusion/model_file", current.model_file);
541 settings.setValue("stable_diffusion/lora_files", current.lora_files);
542 QStringList lora_multiplier_values;
543 for (const double multiplier : current.lora_multipliers) {
544 lora_multiplier_values.append(QString::number(multiplier, 'g', 12));
545 }
546 settings.setValue("stable_diffusion/lora_multipliers", lora_multiplier_values);
547 settings.setValue("stable_diffusion/prompt", current.prompt);
548 settings.setValue("stable_diffusion/negative_prompt", current.negative_prompt);
549 settings.setValue("stable_diffusion/server", current.server_executable);
550 settings.setValue("stable_diffusion/server_arguments", current.server_arguments);
551 settings.setValue("stable_diffusion/port", current.server_port);
552 settings.setValue("stable_diffusion/width", current.width);
553 settings.setValue("stable_diffusion/height", current.height);
554 settings.setValue("stable_diffusion/resolution", resolution_text(current.width, current.height));
555 settings.setValue("stable_diffusion/steps", current.steps);
556 settings.setValue("stable_diffusion/strength", current.strength);
557 settings.setValue("stable_diffusion/cfg_scale", current.cfg_scale);
558 settings.setValue("stable_diffusion/seed", current.seed);
559 settings.setValue("stable_diffusion/sampler", current.sampler);
560 settings.setValue("stable_diffusion/scheduler", current.scheduler);
561 settings.setValue("stable_diffusion/upscale", current.upscale);
562 settings.setValue("stable_diffusion/upscale_only", current.upscale_only);
563 settings.setValue("stable_diffusion/server_upscale", server_upscale_check_box->isChecked());
564 settings.setValue("stable_diffusion/upscale_model_file", upscale_model_edit->text().trimmed());
565 settings.setValue("stable_diffusion/upscale_working_width", current.upscale_working_width);
566 settings.setValue("stable_diffusion/upscale_working_height", current.upscale_working_height);
567 settings.sync();
568}
569
571 const bool enabled = enable_check_box->isChecked();
572 const bool image_to_image = enabled && !upscale_only_check_box->isChecked();
573 model_file_edit->setEnabled(image_to_image);
574 browse_model_button->setEnabled(image_to_image);
575 prompt_edit->setEnabled(image_to_image);
576 negative_prompt_edit->setEnabled(image_to_image);
577 lora_list_widget->setEnabled(image_to_image);
578 add_lora_button->setEnabled(image_to_image);
579 remove_lora_button->setEnabled(image_to_image && !lora_list_widget->selectedItems().isEmpty());
581 server_edit->setEnabled(enabled);
582 server_arguments_edit->setEnabled(enabled);
583 browse_server_button->setEnabled(enabled);
584 server_port_spin_box->setEnabled(enabled);
585 resolution_combo_box->setEnabled(image_to_image);
586 steps_spin_box->setEnabled(image_to_image);
587 strength_spin_box->setEnabled(image_to_image);
588 cfg_scale_spin_box->setEnabled(image_to_image);
589 seed_spin_box->setEnabled(image_to_image);
590 sampler_combo_box->setEnabled(image_to_image);
591 scheduler_combo_box->setEnabled(image_to_image);
592 upscale_check_box->setEnabled(image_to_image);
593 upscale_only_check_box->setEnabled(enabled);
594 server_upscale_check_box->setEnabled(enabled && !upscale_only_check_box->isChecked());
595 const bool server_upscale_enabled = enabled && (server_upscale_check_box->isChecked() || upscale_only_check_box->isChecked());
596 upscale_model_edit->setEnabled(server_upscale_enabled);
597 browse_upscale_model_button->setEnabled(server_upscale_enabled);
598 upscale_working_resolution_edit->setEnabled(server_upscale_enabled);
599}
StableDiffusionConfiguration configuration() const
StableDiffusionSettingsDialog(QWidget *parent=nullptr)
void add_lora_item(const QString &filename, double multiplier)
void applyCustomStyleIfEnabled(QWidget *widget)
bool parse_stable_resolution(const QString &text, int &width, int &height)