Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 77c312800a | |||
| 21e90b92dc | |||
| 2817d3c7c9 | |||
| a51b0ef02c | |||
| 7b19230366 | |||
| 26666ee36d | |||
| 74aee15f80 | |||
| fde1594086 | |||
| a9783f6030 |
@@ -20,6 +20,18 @@ FilesystemWidget::FilesystemWidget(QAbstractItemModel *model, QWidget *parent) :
|
||||
connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FilesystemWidget::fileClicked);
|
||||
}
|
||||
|
||||
void FilesystemWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
QMenu menu;
|
||||
menu.addAction(tr("Sort by filename"), [this](){ emit sortChanged(QDir::Name); });
|
||||
menu.addAction(tr("Sort by time"), [this](){ emit sortChanged(QDir::Time); });
|
||||
menu.addAction(tr("Sort by size"), [this](){ emit sortChanged(QDir::Size); });
|
||||
menu.addAction(tr("Sort by type"), [this](){ emit sortChanged(QDir::Type); });
|
||||
menu.addAction(tr("Reverse"), [this](){ emit reverseSort(); });
|
||||
|
||||
menu.exec(event->globalPos());
|
||||
}
|
||||
|
||||
void FilesystemWidget::selectFile(int row)
|
||||
{
|
||||
QModelIndex index = m_model->index(row, 0);
|
||||
|
||||
@@ -13,11 +13,14 @@ class FilesystemWidget : public QWidget
|
||||
QAbstractItemModel *m_model;
|
||||
public:
|
||||
explicit FilesystemWidget(QAbstractItemModel *model, QWidget *parent = nullptr);
|
||||
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||
private slots:
|
||||
void selectFile(int row);
|
||||
void fileClicked(const QModelIndex &index, const QModelIndex &);
|
||||
signals:
|
||||
void fileSelected(int row);
|
||||
void sortChanged(QDir::SortFlag sort);
|
||||
void reverseSort();
|
||||
};
|
||||
|
||||
class Filetree : public QTreeView
|
||||
|
||||
+6
-6
@@ -20,10 +20,10 @@ FITSRecord::FITSRecord(const QByteArray &key, const QVariant &value, const QByte
|
||||
|
||||
FITSRecord::FITSRecord(const LibXISF::FITSKeyword &record)
|
||||
{
|
||||
key = record.name.toUtf8();
|
||||
comment = record.comment.toUtf8();
|
||||
key = record.name.c_str();
|
||||
comment = record.comment.c_str();
|
||||
|
||||
QString string = record.value;
|
||||
QString string = record.value.c_str();
|
||||
if(string.startsWith('\'') && string.endsWith('\''))
|
||||
{
|
||||
string.chop(1);
|
||||
@@ -45,9 +45,9 @@ FITSRecord::FITSRecord(const LibXISF::FITSKeyword &record)
|
||||
|
||||
FITSRecord::FITSRecord(const LibXISF::Property &property)
|
||||
{
|
||||
key = property.id.toUtf8();
|
||||
value = property.value;
|
||||
comment = property.comment.toUtf8();
|
||||
key = property.id.c_str();
|
||||
value = QString::fromStdString(property.value.toString());
|
||||
comment = property.comment.c_str();
|
||||
}
|
||||
|
||||
QByteArray FITSRecord::valueToByteArray() const
|
||||
|
||||
+26
-1
@@ -129,7 +129,9 @@ bool ImageRingList::setDir(const QString path, const QString ¤tFile)
|
||||
|
||||
if(dir.exists())
|
||||
{
|
||||
QStringList list = dir.entryList(m_nameFilter, QDir::Files | QDir::Readable, m_liveMode ? QDir::Time : QDir::Name | QDir::IgnoreCase);
|
||||
QDir::SortFlags sortFlags = m_liveMode ? QDir::Time : m_sort | QDir::IgnoreCase;
|
||||
if(m_reversed)sortFlags |= QDir::Reversed;
|
||||
QStringList list = dir.entryList(m_nameFilter, QDir::Files | QDir::Readable, sortFlags);
|
||||
QStringList absolutePaths;
|
||||
foreach(const QString &file, list)
|
||||
{
|
||||
@@ -377,6 +379,29 @@ void ImageRingList::setPreload(int width)
|
||||
m_width = newWidth;
|
||||
}
|
||||
|
||||
void ImageRingList::setSort(QDir::SortFlag sort)
|
||||
{
|
||||
if(m_sort != sort)
|
||||
{
|
||||
m_sort = sort;
|
||||
if(m_images.size())
|
||||
{
|
||||
QString path = (*m_currImage)->name();
|
||||
setFile(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImageRingList::reverseSort()
|
||||
{
|
||||
m_reversed = !m_reversed;
|
||||
if(m_images.size())
|
||||
{
|
||||
QString path = (*m_currImage)->name();
|
||||
setFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageRingList::setFiles(const QStringList files, const QString ¤tFile)
|
||||
{
|
||||
QThreadPool::globalInstance()->clear();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QList>
|
||||
#include <QPixmap>
|
||||
#include <QDir>
|
||||
#include <memory>
|
||||
#include "imageinfo.h"
|
||||
#include "rawimage.h"
|
||||
@@ -58,6 +59,8 @@ class ImageRingList : public QAbstractItemModel
|
||||
QList<ImagePtr>::iterator m_lastImage;
|
||||
QFileSystemWatcher m_fileSystemWatcher;
|
||||
bool m_liveMode;
|
||||
QDir::SortFlag m_sort = QDir::Name;
|
||||
bool m_reversed = false;
|
||||
AnalyzeLevel m_analyzeLevel;
|
||||
QThreadPool *m_thumbPool;
|
||||
Database *m_database;
|
||||
@@ -91,6 +94,8 @@ public:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
public slots:
|
||||
void setPreload(int width);
|
||||
void setSort(QDir::SortFlag sort);
|
||||
void reverseSort();
|
||||
protected:
|
||||
void setFiles(const QStringList files, const QString ¤tFile = QString());
|
||||
QList<ImagePtr>::iterator increment(QList<ImagePtr>::iterator iter);
|
||||
|
||||
+118
-131
@@ -162,7 +162,9 @@ void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index)
|
||||
f->glDeleteTextures(1, &m_debayerTex);
|
||||
m_debayerTex = 0;
|
||||
}
|
||||
update();
|
||||
|
||||
if(m_bestFit)bestFit();
|
||||
else setOffset(m_dx, m_dy);
|
||||
}
|
||||
|
||||
void ImageWidget::setWCS(std::shared_ptr<WCSData> wcs)
|
||||
@@ -170,10 +172,35 @@ void ImageWidget::setWCS(std::shared_ptr<WCSData> wcs)
|
||||
m_wcs = wcs;
|
||||
}
|
||||
|
||||
void ImageWidget::setScale(float scale)
|
||||
void ImageWidget::zoom(int zoom, const QPointF &mousePos)
|
||||
{
|
||||
m_scale = scale;
|
||||
update();
|
||||
m_bestFit = false;
|
||||
if(zoom != 0)
|
||||
m_scaleStop = std::clamp(m_scaleStop + (zoom > 0 ? 1 : -1), -10, 10);
|
||||
else
|
||||
m_scaleStop = 0;
|
||||
|
||||
QPointF focus(m_width * 0.5f, m_height * 0.5f);
|
||||
if(!mousePos.isNull())
|
||||
focus = mousePos;
|
||||
|
||||
if(width() > m_image->width() * m_scale)
|
||||
m_dx = -width() * 0.5f + m_image->width() * m_scale * 0.5f;
|
||||
if(height() > m_image->height() * m_scale)
|
||||
m_dy = -height() * 0.5f + m_image->height() * m_scale * 0.5f;
|
||||
|
||||
float newScale = std::sqrt(std::pow(2.0f, (float)m_scaleStop));
|
||||
float r = newScale / m_scale;
|
||||
m_scale = newScale;
|
||||
|
||||
setOffset(m_dx * r + focus.x() * (r - 1), m_dy * r + focus.y() * (r - 1));
|
||||
}
|
||||
|
||||
void ImageWidget::bestFit()
|
||||
{
|
||||
m_bestFit = true;
|
||||
m_scale = std::min((float)m_width/m_imgWidth, (float)m_height/m_imgHeight);
|
||||
setOffset(0, 0);
|
||||
}
|
||||
|
||||
void ImageWidget::blockRepaint(bool block)
|
||||
@@ -203,6 +230,19 @@ void ImageWidget::allocateThumbnails(const QStringList &paths)
|
||||
m_thumbnailTexture->allocateStorage();
|
||||
}
|
||||
|
||||
QVector2D ImageWidget::getImagePixelCoord(const QVector2D &pos)
|
||||
{
|
||||
float dx = m_dx;
|
||||
float dy = m_dy;
|
||||
if(m_width > m_image->width()*m_scale)
|
||||
dx = -width()*0.5f + m_image->width()*m_scale*0.5f;
|
||||
if(m_height > m_image->height()*m_scale)
|
||||
dy = -height()*0.5f + m_image->height()*m_scale*0.5f;
|
||||
|
||||
QVector2D offset(dx, dy);
|
||||
return (pos + offset) / m_scale;
|
||||
}
|
||||
|
||||
void ImageWidget::setMTFParams(float low, float mid, float high)
|
||||
{
|
||||
m_low = low;
|
||||
@@ -211,10 +251,14 @@ void ImageWidget::setMTFParams(float low, float mid, float high)
|
||||
update();
|
||||
}
|
||||
|
||||
void ImageWidget::setOffset(int dx, int dy)
|
||||
void ImageWidget::setOffset(float dx, float dy)
|
||||
{
|
||||
m_dx = dx;
|
||||
m_dy = dy;
|
||||
m_dx = std::clamp(dx, 0.0f, std::max(0.0f, m_imgWidth * m_scale - m_width));
|
||||
if(m_showThumbnails)
|
||||
m_dy = std::clamp(dy, 0.0f, std::max(0.0f, (float)((m_thumbnailCount / (m_width / THUMB_SIZE_BORDER) + 2) * THUMB_SIZE_BORDER_Y - m_height)));
|
||||
else
|
||||
m_dy = std::clamp(dy, 0.0f, std::max(0.0f, m_imgHeight * m_scale - m_height));
|
||||
updateScrollBars();
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -269,7 +313,7 @@ void ImageWidget::thumbnailLoaded(const Image *image)
|
||||
void ImageWidget::showThumbnail(bool enable)
|
||||
{
|
||||
m_showThumbnails = enable;
|
||||
update();
|
||||
setOffset(m_dx, m_dy);
|
||||
}
|
||||
|
||||
void ImageWidget::paintGL()
|
||||
@@ -278,10 +322,10 @@ void ImageWidget::paintGL()
|
||||
|
||||
float dx = m_dx;
|
||||
float dy = m_dy;
|
||||
if(width() > m_image->width()*m_scale)
|
||||
dx = -width()*0.5f + m_image->width()*m_scale*0.5f;
|
||||
if(height() > m_image->height()*m_scale)
|
||||
dy = -height()*0.5f + m_image->height()*m_scale*0.5f;
|
||||
if(m_width > m_image->width() * m_scale)
|
||||
dx = -width() * 0.5f + m_image->width() * m_scale * 0.5f;
|
||||
if(m_height > m_image->height() * m_scale)
|
||||
dy = -height() * 0.5f + m_image->height() * m_scale * 0.5f;
|
||||
QBrush highlight = style()->standardPalette().highlight();
|
||||
|
||||
if(m_showThumbnails)
|
||||
@@ -354,7 +398,7 @@ void ImageWidget::paintGL()
|
||||
|
||||
m_program->bind();
|
||||
m_program->setUniformValue("viewport", (float)width(), (float)height());
|
||||
m_program->setUniformValue("offset", dx, dy);
|
||||
m_program->setUniformValue("offset", std::floor(dx), std::floor(dy));
|
||||
m_program->setUniformValue("mtf_param", m_low, m_mid, m_high);
|
||||
m_program->setUniformValue("zoom", 1.0f/m_scale);
|
||||
m_program->setUniformValue("bw", m_bwImg && !m_superpixel);
|
||||
@@ -374,6 +418,8 @@ void ImageWidget::resizeGL(int w, int h)
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
f->glViewport(0, 0, w, h);
|
||||
if(m_bestFit)bestFit();
|
||||
updateScrollBars();
|
||||
}
|
||||
|
||||
void ImageWidget::initializeGL()
|
||||
@@ -425,7 +471,7 @@ void ImageWidget::initializeGL()
|
||||
m_program = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram);
|
||||
m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/image.vert");
|
||||
m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/image.frag");
|
||||
if(f3)f3->glBindFragDataLocation(m_program->programId(), 0, "color");
|
||||
|
||||
if(!m_program->link())
|
||||
{
|
||||
qDebug() << "Link failed" << m_program->log();
|
||||
@@ -442,7 +488,7 @@ void ImageWidget::initializeGL()
|
||||
m_debayerProgram = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram);
|
||||
m_debayerProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/debayer.vert");
|
||||
m_debayerProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/debayer.frag");
|
||||
if(f3)f3->glBindFragDataLocation(m_debayerProgram->programId(), 0, "color");
|
||||
|
||||
m_debayerProgram->bind();
|
||||
m_debayerProgram->enableAttributeArray("qt_Vertex");
|
||||
m_debayerProgram->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 2, sizeof(float)*4);
|
||||
@@ -459,7 +505,7 @@ void ImageWidget::initializeGL()
|
||||
m_thumbnailProgram = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram);
|
||||
m_thumbnailProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/thumb.vert");
|
||||
m_thumbnailProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/thumb.frag");
|
||||
if(f3)f3->glBindFragDataLocation(m_thumbnailProgram->programId(), 0, "color");
|
||||
|
||||
m_thumbnailProgram->bind();
|
||||
m_thumbnailProgram->enableAttributeArray("qt_Vertex");
|
||||
m_thumbnailProgram->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 2, sizeof(float)*4);
|
||||
@@ -536,7 +582,10 @@ void ImageWidget::mousePressEvent(QMouseEvent *event)
|
||||
thumbSelect(event);
|
||||
}
|
||||
else
|
||||
event->ignore();
|
||||
{
|
||||
if(event->button() == Qt::LeftButton)
|
||||
m_lastPos = event->localPos();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
@@ -545,21 +594,17 @@ void ImageWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
thumbSelect(event);
|
||||
}
|
||||
else
|
||||
event->ignore();
|
||||
else if(!m_lastPos.isNull())
|
||||
{
|
||||
QPointF off = event->localPos() - m_lastPos;
|
||||
m_lastPos = event->localPos();
|
||||
setOffset(m_dx - off.x(), m_dy - off.y());
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_showThumbnails && m_rawImage)
|
||||
{
|
||||
float dx = m_dx;
|
||||
float dy = m_dy;
|
||||
if(width() > m_image->width()*m_scale)
|
||||
dx = -width()*0.5f + m_image->width()*m_scale*0.5f;
|
||||
if(height() > m_image->height()*m_scale)
|
||||
dy = -height()*0.5f + m_image->height()*m_scale*0.5f;
|
||||
|
||||
QVector2D offset(dx, dy);
|
||||
QVector2D pos = QVector2D(event->pos());
|
||||
QVector2D pix = (pos + offset) / m_scale;
|
||||
QVector2D pix = getImagePixelCoord(QVector2D(event->pos()));
|
||||
QVector3D rgb;
|
||||
|
||||
SkyPoint sky;
|
||||
@@ -604,7 +649,22 @@ void ImageWidget::mouseReleaseEvent(QMouseEvent *event)
|
||||
m_database->unmark(unmark);
|
||||
}
|
||||
else
|
||||
event->ignore();
|
||||
{
|
||||
m_lastPos = QPointF();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageWidget::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if(m_showThumbnails)
|
||||
{
|
||||
setOffset(0, m_dy - event->angleDelta().y());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(std::abs(event->angleDelta().y()) > 15)
|
||||
zoom(event->angleDelta().y(), event->modifiers() & Qt::ShiftModifier ? QPointF() : event->posF());
|
||||
}
|
||||
}
|
||||
|
||||
void ImageWidget::thumbSelect(QMouseEvent *event)
|
||||
@@ -671,6 +731,14 @@ void ImageWidget::debayer()
|
||||
m_whiteBalance[2] = maxRGB / pixel[2];
|
||||
}
|
||||
|
||||
void ImageWidget::updateScrollBars()
|
||||
{
|
||||
if(m_showThumbnails)
|
||||
emit scrollBarsUpdate(0, 0, -1, m_dy, m_height, (m_thumbnailCount / (m_width / THUMB_SIZE_BORDER) + 2) * THUMB_SIZE_BORDER_Y - m_height);
|
||||
else
|
||||
emit scrollBarsUpdate(m_dx, m_width, m_imgWidth * m_scale - m_width, m_dy, m_height, m_imgHeight * m_scale - m_height);
|
||||
}
|
||||
|
||||
ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
QGridLayout *layout = new QGridLayout(this);
|
||||
@@ -680,9 +748,6 @@ ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWid
|
||||
|
||||
m_verticalScrollBar = new QScrollBar(Qt::Vertical, this);
|
||||
m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this);
|
||||
m_scale = 1.0f;
|
||||
m_bestFit = false;
|
||||
m_thumbCount = 0;
|
||||
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_imageWidget, 0, 0);
|
||||
@@ -691,6 +756,7 @@ ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWid
|
||||
|
||||
connect(m_verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollEvent()));
|
||||
connect(m_horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollEvent()));
|
||||
connect(m_imageWidget, &ImageWidget::scrollBarsUpdate, this, &ImageScrollAreaGL::updateScrollbars);
|
||||
}
|
||||
|
||||
ImageScrollAreaGL::~ImageScrollAreaGL()
|
||||
@@ -704,10 +770,6 @@ void ImageScrollAreaGL::setImage(Image *image)
|
||||
{
|
||||
m_imageWidget->setImage(image->rawImage(), image->number());
|
||||
m_imageWidget->setWCS(image->info().wcs);
|
||||
m_imgWidth = image->rawImage()->width();
|
||||
m_imgHeight = image->rawImage()->height();
|
||||
if(m_bestFit)bestFit();
|
||||
updateScrollbars();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,124 +778,49 @@ ImageWidget *ImageScrollAreaGL::imageWidget()
|
||||
return m_imageWidget;
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::setThumbnails(int count)
|
||||
void ImageScrollAreaGL::updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV)
|
||||
{
|
||||
m_thumbCount = count;
|
||||
if(m_thumbCount)
|
||||
if(maxH > 0)
|
||||
{
|
||||
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
|
||||
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
|
||||
m_horizontalScrollBar->show();
|
||||
m_horizontalScrollBar->setRange(0, maxH);
|
||||
m_horizontalScrollBar->setPageStep(stepH);
|
||||
m_horizontalScrollBar->setValue(valueH);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_verticalScrollBar->setPageStep(m_imageWidget->height());
|
||||
m_horizontalScrollBar->setPageStep(m_imageWidget->width());
|
||||
}
|
||||
updateScrollbars();
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::updateScrollbars(bool zoom)
|
||||
{
|
||||
if(m_thumbCount)
|
||||
{
|
||||
m_horizontalScrollBar->hide();
|
||||
|
||||
if(maxV > 0)
|
||||
{
|
||||
m_verticalScrollBar->show();
|
||||
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
|
||||
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
|
||||
m_verticalScrollBar->setRange(0, maxV);
|
||||
m_verticalScrollBar->setPageStep(stepV);
|
||||
m_verticalScrollBar->setValue(valueV);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(zoom)
|
||||
{
|
||||
setScrollRange(m_verticalScrollBar, m_imgHeight*m_scale);
|
||||
setScrollRange(m_horizontalScrollBar, m_imgWidth*m_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_verticalScrollBar->setRange(0, m_imgHeight*m_scale - m_verticalScrollBar->pageStep());
|
||||
m_horizontalScrollBar->setRange(0, m_imgWidth*m_scale - m_horizontalScrollBar->pageStep());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
if(m_thumbCount)
|
||||
{
|
||||
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
|
||||
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_verticalScrollBar->setPageStep(m_imageWidget->height());
|
||||
m_horizontalScrollBar->setPageStep(m_imageWidget->width());
|
||||
}
|
||||
updateScrollbars();
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
QPoint delta = m_lastPos - event->pos();
|
||||
if(m_thumbCount == 0)m_horizontalScrollBar->setValue(m_horizontalScrollBar->value() + delta.x());
|
||||
m_verticalScrollBar->setValue(m_verticalScrollBar->value() + delta.y());
|
||||
m_lastPos = event->pos();
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
m_lastPos = event->pos();
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if(m_thumbCount)
|
||||
{
|
||||
m_verticalScrollBar->setValue(m_verticalScrollBar->value() - event->angleDelta().y());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bestFit = false;
|
||||
if(event->angleDelta().y() != 0)
|
||||
zoom(event->angleDelta().y() / 1200.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::zoom(float delta)
|
||||
{
|
||||
if((m_scale >= 8.0f && delta > 0) || (m_scale <= 0.1f && delta < 0))return;
|
||||
|
||||
m_scale += delta;
|
||||
m_imageWidget->blockRepaint(true);
|
||||
m_imageWidget->setScale(m_scale);
|
||||
updateScrollbars(true);
|
||||
m_imageWidget->blockRepaint(false);
|
||||
m_verticalScrollBar->hide();
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::zoomIn()
|
||||
{
|
||||
zoom(0.1f);
|
||||
m_bestFit = false;
|
||||
m_imageWidget->zoom(1);
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::zoomOut()
|
||||
{
|
||||
zoom(-0.1f);
|
||||
m_bestFit = false;
|
||||
m_imageWidget->zoom(-1);
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::bestFit()
|
||||
{
|
||||
m_bestFit = true;
|
||||
m_scale = std::min((float)m_imageWidget->width()/m_imgWidth, (float)m_imageWidget->height()/m_imgHeight);
|
||||
zoom(0.0f);
|
||||
m_horizontalScrollBar->hide();
|
||||
m_verticalScrollBar->hide();
|
||||
m_imageWidget->bestFit();
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::oneToOne()
|
||||
{
|
||||
m_scale = 1.0f;
|
||||
zoom(0.0f);
|
||||
m_bestFit = false;
|
||||
m_imageWidget->zoom(0);
|
||||
}
|
||||
|
||||
void ImageScrollAreaGL::scrollEvent()
|
||||
|
||||
+11
-14
@@ -52,6 +52,8 @@ class ImageWidget : public QOpenGLWidget
|
||||
float m_range;
|
||||
float m_dx, m_dy;
|
||||
float m_scale;
|
||||
int m_scaleStop = 0;
|
||||
bool m_bestFit = false;
|
||||
float m_whiteBalance[3] = {1.0f, 1.0f, 1.0f};
|
||||
bool m_blockRepaint;
|
||||
bool m_bwImg;
|
||||
@@ -66,18 +68,21 @@ class ImageWidget : public QOpenGLWidget
|
||||
int m_maxArrayLayers;
|
||||
QVector<ImageThumb> m_thumnails;
|
||||
Database *m_database;
|
||||
QPointF m_lastPos;
|
||||
public:
|
||||
explicit ImageWidget(Database *database, QWidget *parent = nullptr);
|
||||
~ImageWidget() override;
|
||||
void setImage(std::shared_ptr<RawImage> image, int index);
|
||||
void setImage(const QPixmap &pixmap);
|
||||
void setWCS(std::shared_ptr<WCSData> wcs);
|
||||
void setScale(float scale);
|
||||
void zoom(int zoom, const QPointF &mousePos = QPointF());
|
||||
void bestFit();
|
||||
void blockRepaint(bool block);
|
||||
void allocateThumbnails(const QStringList &paths);
|
||||
QVector2D getImagePixelCoord(const QVector2D &pos);
|
||||
public slots:
|
||||
void setMTFParams(float low, float mid, float high);
|
||||
void setOffset(int dx, int dy);
|
||||
void setOffset(float dx, float dy);
|
||||
void superPixel(bool enable);
|
||||
void invert(bool enable);
|
||||
QImage renderToImage();
|
||||
@@ -92,11 +97,14 @@ protected:
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void thumbSelect(QMouseEvent *event);
|
||||
void debayer();
|
||||
void updateScrollBars();
|
||||
signals:
|
||||
void fileDropped(const QString &path);
|
||||
void status(const QString &value, const QString &pixelCoords, const QString &celestialCoords);
|
||||
void scrollBarsUpdate(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV);
|
||||
};
|
||||
|
||||
class ImageScrollAreaGL : public QWidget
|
||||
@@ -105,24 +113,13 @@ class ImageScrollAreaGL : public QWidget
|
||||
QScrollBar *m_verticalScrollBar;
|
||||
QScrollBar *m_horizontalScrollBar;
|
||||
ImageWidget *m_imageWidget;
|
||||
int m_imgWidth, m_imgHeight;
|
||||
QPoint m_lastPos;
|
||||
float m_scale;
|
||||
bool m_bestFit;
|
||||
int m_thumbCount;
|
||||
public:
|
||||
explicit ImageScrollAreaGL(Database *database, QWidget *parent = nullptr);
|
||||
~ImageScrollAreaGL() override;
|
||||
void setImage(Image *image);
|
||||
ImageWidget* imageWidget();
|
||||
void setThumbnails(int count);
|
||||
protected:
|
||||
void updateScrollbars(bool zoom = false);
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void zoom(float delta);
|
||||
void updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV);
|
||||
public slots:
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
|
||||
+1
-1
Submodule libXISF updated: 2107d68e71...dafc26984e
+5
-5
@@ -290,7 +290,7 @@ bool loadXISF(const QString &path, ImageInfoData &info, RawImage **image)
|
||||
try
|
||||
{
|
||||
LibXISF::XISFReader xisf;
|
||||
xisf.open(path);
|
||||
xisf.open(path.toLocal8Bit().data());
|
||||
|
||||
const LibXISF::Image &xisfImage = xisf.getImage(0);
|
||||
|
||||
@@ -527,7 +527,7 @@ bool readXISFHeader(const QString &path, ImageInfoData &info)
|
||||
try
|
||||
{
|
||||
LibXISF::XISFReader xisf;
|
||||
xisf.open(path);
|
||||
xisf.open(path.toLocal8Bit().data());
|
||||
const LibXISF::Image &image = xisf.getImage(0, false);
|
||||
|
||||
auto fitskeywords = image.fitsKeywords();
|
||||
@@ -660,13 +660,13 @@ void ConvertRunable::run()
|
||||
for(auto &record : imageinfo.fitsHeader)
|
||||
{
|
||||
if(record.value.type() == QVariant::Bool)
|
||||
image.addFITSKeyword({record.key, record.value.toBool() ? "T" : "F", record.comment});
|
||||
image.addFITSKeyword({record.key.toStdString(), record.value.toBool() ? "T" : "F", record.comment.toStdString()});
|
||||
else
|
||||
image.addFITSKeyword({record.key, record.value.toString(), record.comment});
|
||||
image.addFITSKeyword({record.key.toStdString(), record.value.toString().toStdString(), record.comment.toStdString()});
|
||||
}
|
||||
|
||||
xisf.writeImage(image);
|
||||
xisf.save(m_outfile);
|
||||
xisf.save(m_outfile.toLocal8Bit().data());
|
||||
}
|
||||
catch(LibXISF::Error &err)
|
||||
{
|
||||
|
||||
+2
-1
@@ -88,6 +88,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
m_ringList = new ImageRingList(m_database, nameFilter, this);
|
||||
m_filesystem = new FilesystemWidget(m_ringList, this);
|
||||
connect(m_filesystem, SIGNAL(fileSelected(int)), this, SLOT(loadFile(int)));
|
||||
connect(m_filesystem, &FilesystemWidget::sortChanged, m_ringList, &ImageRingList::setSort);
|
||||
connect(m_filesystem, &FilesystemWidget::reverseSort, m_ringList, &ImageRingList::reverseSort);
|
||||
|
||||
m_filetree = new Filetree(this);
|
||||
connect(m_filetree, &Filetree::fileSelected, this, static_cast<void (MainWindow::*)(const QString &)>(&MainWindow::loadFile));
|
||||
@@ -158,7 +160,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
if(SettingsDialog::loadThumbsizes())m_ringList->clearThumbnails();
|
||||
m_imageGL->imageWidget()->allocateThumbnails(m_ringList->imageNames());
|
||||
m_imageGL->imageWidget()->showThumbnail(checked);
|
||||
m_imageGL->setThumbnails(checked ? m_ringList->imageCount() : 0);
|
||||
if(checked)m_ringList->loadThumbnails();
|
||||
else m_ringList->stopLoading();
|
||||
}, Qt::Key_F2);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
uniform sampler2D qt_Texture0;
|
||||
in vec2 qt_TexCoord0;
|
||||
in vec2 center;
|
||||
out vec4 color;
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
#define f(x, y) texelFetch(qt_Texture0, icenter + ivec2(x, y), 0).r
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ uniform bool invert;
|
||||
uniform bool srgb;
|
||||
uniform vec3 whiteBalance;
|
||||
in vec2 qt_TexCoord0;
|
||||
out vec4 color;
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
vec3 Linear2sRGB(vec3 color)
|
||||
{
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ uniform sampler2DArray qt_Texture0;
|
||||
uniform vec3 mtf_param;
|
||||
uniform bool invert;
|
||||
in vec3 qt_TexCoord0;
|
||||
out vec4 color;
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
vec4 MTF(vec4 x, vec3 m)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,17 @@
|
||||
</screenshots>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="20230419" date="2023-04-19">
|
||||
<description>
|
||||
<ul>
|
||||
<li>Add file sorting</li>
|
||||
<li>Improved zoom and scrolling.</li>
|
||||
<li>Shift modify if zoom on mouse position or center</li>
|
||||
<li>Fix issue with XISF from NINA</li>
|
||||
<li>Fix crash in flatpak version</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="20230212" date="2023-02-12">
|
||||
<description>
|
||||
<ul>
|
||||
|
||||
Binary file not shown.
@@ -41,6 +41,29 @@
|
||||
<translation>File name</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FilesystemWidget</name>
|
||||
<message>
|
||||
<source>Sort by filename</source>
|
||||
<translation>Sort by file name</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by time</source>
|
||||
<translation>Sort by time</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by size</source>
|
||||
<translation>Sort by size</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by type</source>
|
||||
<translation>Sort by type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reverse</source>
|
||||
<translation>Reverse order</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Filetree</name>
|
||||
<message>
|
||||
@@ -515,7 +538,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>Changes in settings will take effect after program restart.</source>
|
||||
<translation>Changes in settings will take effect after program restart.</translation>
|
||||
<translation type="vanished">Changes in settings will take effect after program restart.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Don't use native file dialog</source>
|
||||
|
||||
Binary file not shown.
@@ -41,6 +41,29 @@
|
||||
<translation>Nom de fichier</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FilesystemWidget</name>
|
||||
<message>
|
||||
<source>Sort by filename</source>
|
||||
<translation>Trier par nom de fichier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by time</source>
|
||||
<translation>Trier par heure</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by size</source>
|
||||
<translation>Trier par taille</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by type</source>
|
||||
<translation>Trier par type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reverse</source>
|
||||
<translation>Ordre inverse</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Filetree</name>
|
||||
<message>
|
||||
@@ -515,7 +538,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>Changes in settings will take effect after program restart.</source>
|
||||
<translation>Les changements de paramètres prendront effet après le redémarrage du programme.</translation>
|
||||
<translation type="vanished">Les changements de paramètres prendront effet après le redémarrage du programme.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Don't use native file dialog</source>
|
||||
|
||||
Binary file not shown.
@@ -42,6 +42,29 @@
|
||||
<translation>Meno súboru</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FilesystemWidget</name>
|
||||
<message>
|
||||
<source>Sort by filename</source>
|
||||
<translation>Zoradiť podľa názvu súboru</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by time</source>
|
||||
<translation>Zoradiť podľa času</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by size</source>
|
||||
<translation>Zoradiť podľa veľkosti</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort by type</source>
|
||||
<translation>Zoradiť podľa typu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reverse</source>
|
||||
<translation>Otočit poradie</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Filetree</name>
|
||||
<message>
|
||||
@@ -516,7 +539,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>Changes in settings will take effect after program restart.</source>
|
||||
<translation>Zmeny v nastaveniach sa prejavia po reštarte programu.</translation>
|
||||
<translation type="vanished">Zmeny v nastaveniach sa prejavia po reštarte programu.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Don't use native file dialog</source>
|
||||
|
||||
Reference in New Issue
Block a user