Export JPEG: a zoomable full-size preview, its buttons and the View menu's zoom keys (13.4b)

This commit is contained in:
ZacharyZhang-NY committed 2026-10-01 08:53:43 -04:00
1 parent bc49b722eb
commit 64ebd1cdf9
17 files changed
+702 -74

No files matched your search

+60 -2
View File
@@ -1,7 +1,9 @@
#pragma once
#include "Document/ColorPalette.h"
#include "IO/ImageExporter.h"
#include <QAbstractScrollArea>
#include <QWidget>
#include <array>
#include <atomic>
#include <functional>
#include <memory>
@@ -9,12 +11,58 @@
class QLabel;
class QProgressBar;
class QShortcut;
class QPushButton;
class QSlider;
class QTimer;
class DialogColorSwatch;
class EditorSession;
// Swift's JPEGPreview: the encoded JPEG, fitted or zoomed, dragged.
class JPEGPreview : public QAbstractScrollArea {
Q_OBJECT
public:
static constexpr QSize frame{560, 330};
static constexpr std::array<double, 6> steps{0.25, 0.5, 1, 2, 4, 8};
// The zoom at which the whole image fits `frame`.
static double fitZoom(int width, int height, QSizeF frame, double displayScale);
// The next step past `zoom`: 1 in, −1 out.
static std::optional<double> step(double zoom, int direction);
// `pixels`: the export's size, which the image may undercut.
JPEGPreview(QSize pixels, std::function<void()> zoomChanged, QWidget *parent);
void setImage(const QImage &image, bool updating);
// None fits; 1 is a screen pixel a pixel.
std::optional<double> zoom() const { return m_zoom; }
void setZoom(std::optional<double> zoom);
double shownZoom() const;
void zoomBy(int direction);
protected:
void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
private:
QSizeF shownSize(double zoom) const;
void updateRanges();
void showCursor(bool grabbing);
const QSize m_pixels;
// Each change of zoom, for the sheet's buttons.
const std::function<void()> m_zoomChanged;
QImage m_image;
// The image shrunk to the size last drawn.
QImage m_reduced;
bool m_updating = false;
std::optional<double> m_zoom;
// A drag's press and the scroll it began from.
std::optional<std::pair<QPoint, QPoint>> m_drag;
};
// Swift's JPEGExportSheet: quality, matte and the encoded preview.
class JPEGExportSheet : public QWidget {
Q_OBJECT
@@ -25,12 +73,17 @@ public:
JPEGExportSheet(ExportRaster raster, EditorSession &session, std::function<void(std::optional<QByteArray>)> finish, QWidget *parent = nullptr);
~JPEGExportSheet() override;
protected:
// The zoom glyphs follow the theme.
void changeEvent(QEvent *event) override;
private:
class Preview;
void request();
void encode();
void setMatte(const PaletteColor &matte);
void synchronize();
// The View menu's zoom keys, as remapped, zoom the preview.
void bindZoomKeys();
const ExportRaster m_raster;
EditorSession &m_session;
@@ -42,7 +95,7 @@ private:
// The newest request's flag, Swift's task cancellation.
std::shared_ptr<std::atomic_bool> m_cancelled;
QTimer *const m_wait;
Preview *const m_preview;
JPEGPreview *const m_preview;
QProgressBar *const m_spinner;
QSlider *const m_quality;
QLabel *const m_percent;
@@ -51,4 +104,9 @@ private:
QLabel *const m_bytes;
QLabel *const m_note;
QPushButton *const m_export;
QPushButton *const m_fit;
QPushButton *const m_zoomIn;
QPushButton *const m_zoomOut;
// Fit, Actual Pixels, Zoom In and Zoom Out.
std::array<QShortcut *, 4> m_zoomKeys{};
};