Files
OmaPhoto/src/ContentView+Panels.cpp
T

207 lines
8.8 KiB
C++

#include "ContentView.h"
#include "UI/ColorRangeSheet.h"
#include "UI/LassoControls.h"
#include "UI/EffectsSheet.h"
#include "UI/FilterSheet.h"
#include "UI/HueSaturationSheet.h"
#include "UI/LevelsSheet.h"
#include "UI/RawDevelopSheet.h"
#include <QFileDialog>
#include <QVBoxLayout>
#include <QMessageBox>
void ContentView::synchronizePanels()
{
// A panel opens with its edit; close and Escape cancel.
if (m_levelsShown != m_session.levels().has_value()) {
m_levelsShown = m_session.levels().has_value();
if (m_levelsShown) {
m_levelsPanel.onClose = [this] { m_session.cancelLevels(); };
m_levelsPanel.show(QStringLiteral("Levels"), new LevelsSheet(m_session));
} else {
m_levelsPanel.close();
}
}
if (m_hueSaturationShown != m_session.hueSaturation().has_value()) {
m_hueSaturationShown = m_session.hueSaturation().has_value();
if (m_hueSaturationShown) {
m_adjustmentPanel.onClose = [this] { m_session.cancelHueSaturation(); };
m_adjustmentPanel.show(QStringLiteral("Hue/Saturation"), new HueSaturationSheet(m_session));
} else {
m_adjustmentPanel.close();
}
}
// Swift's onChange of the amount's question: a sheet per question.
if (m_selectionAmountShown != m_session.selectionAmountOperation()) {
m_selectionAmountShown = m_session.selectionAmountOperation();
if (m_selectionAmountShown) {
m_selectionAmountPanel.onClose = [this] { m_session.setSelectionAmountOperation(std::nullopt); };
m_selectionAmountPanel.show(rawValue(*m_selectionAmountShown) + QStringLiteral(" Selection"),
new SelectionAmountSheet(m_session, *m_selectionAmountShown));
} else {
m_selectionAmountPanel.close();
}
}
// Swift's onChange of colorRange == nil.
if (m_colorRangeShown != m_session.colorRange().has_value()) {
m_colorRangeShown = m_session.colorRange().has_value();
if (m_colorRangeShown) {
m_colorRangePanel.onClose = [this] { m_session.cancelColorRange(); };
m_colorRangePanel.show(QStringLiteral("Color Range"), new ColorRangeSheet(m_session));
} else {
m_colorRangePanel.close();
}
}
// Last Filter applies without the panel.
const bool filtering = m_session.filterEdit() && !m_session.filterEdit()->repeating;
if (m_filterShown != filtering) {
m_filterShown = filtering;
if (m_filterShown) {
m_filterPanel.onClose = [this] { m_session.cancelFilter(); };
const FilterKind kind = m_session.filterEdit()->kind;
m_filterPanel.show(rawValue(kind), new FilterSheet(m_session), kind == FilterKind::cameraRaw ? m_dock : nullptr);
} else {
m_filterPanel.close();
}
}
// Swift's onChange of the layers: a vanished effect's panel goes.
if (const std::optional<LayerEffectSelection> editing = m_session.effectsEditing()) {
const std::vector<ImageLayer> &layers = m_session.document() ? m_session.document()->layers : std::vector<ImageLayer>();
const int index = indexOf(layers, editing->layerID);
if (index < 0 || !layers[size_t(index)].effects || !layers[size_t(index)].effects->contains(editing->kind)) {
if (m_session.colorPicker() && m_session.colorPicker()->target.kind == ColorPickerTarget::Kind::effect)
m_session.closeColorPicker(false);
m_session.setEffectsEditing(std::nullopt);
m_session.setEffectsEditingOriginal(std::nullopt);
}
}
// Swift's onChange of effectsEditing: a panel for each choice.
if (m_effectsShown != m_session.effectsEditing()) {
m_effectsShown = m_session.effectsEditing();
if (m_effectsShown) {
m_effectsPanel.onClose = [this] { m_session.finishEffectsEditing(false); };
m_effectsPanel.show(rawValue(m_effectsShown->kind), new EffectsSheet(m_session, m_effectsShown->kind));
} else {
m_effectsPanel.close();
}
}
}
void ContentView::showImporter()
{
if (!m_session.showsImporter()) {
// Dismissed from elsewhere, as a cleared binding dismisses Swift's.
if (QFileDialog *panel = std::exchange(m_importer, nullptr))
panel->reject();
return;
}
if (m_importer)
return;
m_importer = new QFileDialog(this);
m_importer->setAttribute(Qt::WA_DeleteOnClose);
m_importer->setFileMode(QFileDialog::ExistingFiles);
m_importer->setNameFilter(QStringLiteral("Images (*.jpg *.jpeg *.png *.heic *.tif *.tiff *.psd *.psb *.svg *.svgz %1)").arg(RawImporter::globs().join(' ')));
connect(m_importer, &QDialog::finished, this, [this, panel = m_importer.data()](int result) {
// Ours no longer: the flag must not reject it again.
if (m_importer != panel)
return;
m_importer = nullptr;
m_session.setShowsImporter(false);
if (result == QDialog::Accepted)
m_session.importImages(panel->selectedUrls());
});
m_importer->open();
}
void ContentView::showAlert(QPointer<QMessageBox> &alert, const QString &title, const std::optional<QString> &message,
const std::function<void()> &dismiss)
{
if (!message) {
if (QMessageBox *shown = std::exchange(alert, nullptr))
shown->reject();
return;
}
// SwiftUI's alert shows its message as it stands.
if (alert) {
alert->setInformativeText(*message);
return;
}
alert = new QMessageBox(this);
alert->setAttribute(Qt::WA_DeleteOnClose);
alert->setIcon(QMessageBox::Warning);
alert->setText(title);
alert->setInformativeText(*message);
alert->addButton(QStringLiteral("OK"), QMessageBox::AcceptRole);
connect(alert, &QDialog::finished, this, [&alert, shown = alert.data(), dismiss] {
if (alert != shown)
return;
alert = nullptr;
dismiss();
});
alert->open();
}
void ContentView::showConversionSheet()
{
const std::optional<PSDConversionRequest> &request = m_session.conversionRequest();
if (!m_session.showsConversionSheet() || !request) {
// Ours no longer, so the close answers nothing.
if (QDialog *shown = std::exchange(m_conversionSheet, nullptr))
shown->reject();
return;
}
if (m_conversionSheet && m_conversionShown == *request)
return;
m_conversionShown = *request;
if (!m_conversionSheet) {
m_conversionSheet = new QDialog(this);
m_conversionSheet->setObjectName(QStringLiteral("conversionSheet"));
m_conversionSheet->setAttribute(Qt::WA_DeleteOnClose);
auto *layout = new QVBoxLayout(m_conversionSheet);
layout->setContentsMargins(0, 0, 0, 0);
// Escape and the close button cancel, as Swift's dismissal.
connect(m_conversionSheet, &QDialog::finished, this, [this, shown = m_conversionSheet.data()] {
if (m_conversionSheet != shown)
return;
m_session.finishConversion(false);
});
}
// Reading gives way to the list: new content.
for (PSDConversionSheet *old : m_conversionSheet->findChildren<PSDConversionSheet *>(Qt::FindDirectChildrenOnly)) {
old->hide();
old->deleteLater();
}
m_conversionSheet->setWindowTitle(request->title);
m_conversionSheet->layout()->addWidget(new PSDConversionSheet(*request, [this](bool confirmed) { m_session.finishConversion(confirmed); }, m_conversionSheet));
m_conversionSheet->open();
}
void ContentView::showRawDevelopSheet()
{
const std::optional<RawDevelopRequest> &request = m_session.rawDevelop();
if (!request) {
// Ours no longer, so the close answers nothing.
if (QDialog *shown = std::exchange(m_rawSheet, nullptr))
shown->reject();
return;
}
if (m_rawSheet) {
m_rawSheet->findChild<RawDevelopSheet *>()->setImporting(m_session.rawImporting());
return;
}
m_rawSheet = new QDialog(this);
m_rawSheet->setObjectName(QStringLiteral("rawDevelopSheet"));
m_rawSheet->setAttribute(Qt::WA_DeleteOnClose);
m_rawSheet->setWindowTitle(QStringLiteral("Develop RAW"));
auto *layout = new QVBoxLayout(m_rawSheet);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSizeConstraint(QLayout::SetFixedSize);
// Escape and the close button cancel, as Swift's dismissal.
connect(m_rawSheet, &QDialog::finished, this, [this, shown = m_rawSheet.data()] {
if (m_rawSheet == shown)
m_session.finishRawDevelop(std::nullopt);
});
layout->addWidget(new RawDevelopSheet(*request, [this](std::optional<RawDevelopSettings> settings) { m_session.finishRawDevelop(settings); }, m_rawSheet));
m_rawSheet->open();
}