Compare commits

..

18 Commits

Author SHA1 Message Date
nou a4cfc65d4b Wrap reindex into transaction 2022-05-20 22:57:36 +02:00
nou b4746be190 Update help about marking images 2022-05-20 22:41:00 +02:00
nou 9ceb7556f9 Add marking and unmark from thumbnails view 2022-05-20 22:27:53 +02:00
nou 41b29f0701 Show marked files in database view 2022-05-20 12:10:06 +02:00
nou 67ae2d4b62 Mark unmark files from database view 2022-05-20 11:07:18 +02:00
nou b6b6863331 Add override keyword 2022-05-20 10:34:23 +02:00
nou 571fa57af2 Update translations 2022-05-19 09:58:01 +02:00
nou abb3d631bf Double click in file tree open file 2022-05-19 09:51:47 +02:00
nou b65911943e Fix in context menu 2022-05-19 09:47:42 +02:00
nou 9d9f8db499 Fix crash 2022-05-18 17:43:19 +02:00
nou 3060b17c0c Translations update 2022-05-18 17:39:59 +02:00
nou fcf336d63a Second call to QTranslator::load() seem to clear translation 2022-05-18 17:34:15 +02:00
nou 54ef8e990c Selecting thumbnails 2022-05-18 17:33:20 +02:00
nou 94466a6b9b Draw file name under thumbnail 2022-05-09 22:56:06 +02:00
nou b84d8127ad Add copy, move and index action to File tree 2022-05-09 18:14:10 +02:00
nou c971a919ec Add Filetree dock 2022-05-09 15:58:23 +02:00
nou 8c248b7cfc Add French tranlation, credit Patrick Chevalley 2022-05-08 00:18:42 +02:00
nou 43b510a78c Try load translation from application dir 2022-05-08 00:16:11 +02:00
28 changed files with 993 additions and 100 deletions
+3
View File
@@ -65,6 +65,9 @@ Following the slider are 5 buttons for automatic stretching:
This dialog can be useful to clear marks from images. Marked images show a <b>*</b> character in the title bar of the main window.
Marked images can be copied or moved to a selected directory with <i>File->Copy/Move marked files</i>.
After copying or moving, the list of marked files is cleared. The list of marked files will be remembered after quitting the program.</p>
<p>Another way to mark images is in database view where you can select rows and then select mark or unmark action in context menu. Marked
files will be shown with bold text. Third way to mark files is from thumnails view where you can press press <i>Shift</i> and click with left
mouse button and drag across thumbnails to mark them. Holding <i>Ctrl</i> will unmark files.</p>
<h3>Database of FITS/XISF files</h3>
<p>Tenmon can scan a directory of FITS/XISF files and index metadata from FITS headers into it's internal database. This allows searching and sorting images based on that metadata.</p>
+4
View File
@@ -59,6 +59,10 @@ Posledné tlačidlo zapína a vypína nastavovanie optimálnych hodnôt úrovní
obrázkoch zobrazuje znak * v záhlaví hlavného okna. Takto označené obrázky je potom možné skopírovať alebo
presunúť do vybraného adresára pomocou <i>Súbor->Skopírovať/Presunúť označené súbory</i>. Po skopírovaní alebo
presunutú sa zoznam označených obrázkov vymaže. Program si tento zoznam pamätá aj po svojom ukončení.</p>
<p>Ďalší spôsob ako označiť obrázky je cez databázu FITS/XISF kde je možné vybrať jednotlivé riadky. Potom stačí
vybrať označit alebo odznačiť v kontextovom menu. Označené súbory budú zobrazené tučným textom. Tretí spôsob na označenie
obrázkov je možné cez náhľady. Držaním <i>Shift</i> a následne kliknutím ľavým tlačítkom myši sa daný obrázok označí.
Pre odznačenie je treba držať <i>Ctrl</i></p>
<h3>Databáza FITS/XISF súborov</h3>
<p>Program vie prehľadať adresár a indexovať meta údaje z FIST a XISF obrázkov do internej databázy v ktorej sa dá
+21
View File
@@ -76,6 +76,20 @@ bool Database::unmark(const QString &filename)
return checkError(m_unmarkQuery);
}
bool Database::mark(const QStringList &filenames)
{
m_markQuery.bindValue(0, filenames);
m_markQuery.execBatch();
return checkError(m_markQuery);
}
bool Database::unmark(const QStringList &filenames)
{
m_unmarkQuery.bindValue(0, filenames);
m_unmarkQuery.execBatch();
return checkError(m_unmarkQuery);
}
bool Database::isMarked(const QString &filename)
{
m_isMarkedQuery.bindValue(":name", filename);
@@ -143,6 +157,7 @@ void Database::reindex(QProgressDialog *progress)
{
QVariantList deleteids;
QSqlDatabase database = QSqlDatabase::database();
database.transaction();
QSqlQuery files = database.exec("SELECT id,file,mtime FROM fits_files");
progress->setMaximum(files.size());
int i = 0;
@@ -155,10 +170,16 @@ void Database::reindex(QProgressDialog *progress)
if(!file.exists())
deleteids.append(files.value(0));
progress->setValue(i++);
if(progress->wasCanceled())
{
database.rollback();
return;
}
}
QSqlQuery deleteFiles("DELETE FROM fits_files WHERE id = ?", database);
deleteFiles.bindValue(0, deleteids);
deleteFiles.execBatch();
database.commit();
}
QStringList Database::getFitsKeywords()
+2
View File
@@ -26,6 +26,8 @@ public:
bool init();
bool mark(const QString &filename);
bool unmark(const QString &filename);
bool mark(const QStringList &filenames);
bool unmark(const QStringList &filenames);
bool isMarked(const QString &filename);
QStringList getMarkedFiles();
void clearMarkedFiles();
+85 -5
View File
@@ -6,6 +6,8 @@
#include <QHeaderView>
#include <QSqlError>
#include <QDebug>
#include <QMenu>
#include <QContextMenuEvent>
#include <iostream>
const QStringList DEFAULT_COLUMNS = {"EXPTIME", "OBJECT", "RA", "DEC"};
@@ -47,9 +49,9 @@ QStringList SelectColumnsDialog::selectedColumns()
return ret;
}
FITSFileModel::FITSFileModel(QObject *parent) : QSqlQueryModel(parent)
FITSFileModel::FITSFileModel(Database *database, QObject *parent) : QSqlQueryModel(parent)
, m_database(database)
{
}
void FITSFileModel::sort(int column, Qt::SortOrder order)
@@ -86,6 +88,44 @@ void FITSFileModel::setFilter(const QStringList &key, const QStringList &value)
prepareQuery();
}
QVariant FITSFileModel::data(const QModelIndex &index, int role) const
{
if(role == Qt::FontRole && index.column() == 0)
{
QFont font;
QString file = index.data().toString();
font.setBold(m_markedFiles.contains(file));
return font;
}
return QSqlQueryModel::data(index, role);
}
void FITSFileModel::filesMarked(const QModelIndexList &indexes)
{
for(auto &index : indexes)
{
QString file = index.data().toString();
if(!m_markedFiles.contains(file))
{
m_markedFiles.insert(file);
emit dataChanged(index, index, {Qt::FontRole});
}
}
}
void FITSFileModel::filesUnmarked(const QModelIndexList &indexes)
{
for(auto &index : indexes)
{
QString file = index.data().toString();
if(m_markedFiles.contains(file))
{
m_markedFiles.remove(file);
emit dataChanged(index, index, {Qt::FontRole});
}
}
}
void FITSFileModel::prepareQuery()
{
QString cols;
@@ -122,6 +162,31 @@ void FITSFileModel::prepareQuery()
std::cout << sql.toStdString() << std::endl;
if(lastError().type() != QSqlError::NoError)
qDebug() << lastError();
m_markedFiles = m_database->getMarkedFiles().toSet();
}
DatabaseTableView::DatabaseTableView(QWidget *parent) : QTableView(parent)
{
}
void DatabaseTableView::contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu;
QAction *mark = menu.addAction(tr("Mark"));
QAction *unmark = menu.addAction(tr("Unmark"));
QAction *a = menu.exec(event->globalPos());
if(a == nullptr)
return;
QModelIndexList indexes = selectionModel()->selectedRows();
if(a == mark)
emit filesMarked(indexes);
else if(a == unmark)
emit filesUnmarked(indexes);
}
DataBaseView::DataBaseView(Database *database, QWidget *parent) : QWidget(parent)
@@ -130,14 +195,15 @@ DataBaseView::DataBaseView(Database *database, QWidget *parent) : QWidget(parent
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
m_tableView = new QTableView(this);
m_tableView = new DatabaseTableView(this);
m_tableView->verticalHeader()->setDefaultSectionSize(1);
m_tableView->setSortingEnabled(true);
m_tableView->horizontalHeader()->setSortIndicatorShown(true);
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
layout->addWidget(m_tableView);
connect(m_tableView, &QTableView::activated, this, &DataBaseView::itemActivated);
m_model = new FITSFileModel(this);
m_model = new FITSFileModel(m_database, this);
QSettings settings;
m_tableView->setModel(m_model);
@@ -151,6 +217,21 @@ DataBaseView::DataBaseView(Database *database, QWidget *parent) : QWidget(parent
hlayout->addWidget(selectColumnsButton);
connect(selectColumnsButton, &QPushButton::pressed, this, &DataBaseView::selectColumns);
connect(m_tableView, &DatabaseTableView::filesMarked, [this](QModelIndexList indexes){
QStringList files;
for(auto &index : indexes)
files.append(index.data().toString());
m_database->mark(files);
m_model->filesMarked(indexes);
});
connect(m_tableView, &DatabaseTableView::filesUnmarked, [this](QModelIndexList indexes){
QStringList files;
for(auto &index : indexes)
files.append(index.data().toString());
m_database->unmark(files);
m_model->filesUnmarked(indexes);
});
for(int i=0; i<3; i++)
{
m_filterKeyword[i] = new QComboBox(this);
@@ -214,4 +295,3 @@ void DataBaseView::applyFilter()
}
m_model->setFilter(keys, values);
}
+22 -5
View File
@@ -15,7 +15,7 @@ class SelectColumnsDialog : public QDialog
Q_OBJECT
QListWidget *m_listWidget;
public:
SelectColumnsDialog(QWidget *parent = nullptr);
explicit SelectColumnsDialog(QWidget *parent = nullptr);
void setColumns(QStringList columns);
QStringList selectedColumns();
};
@@ -27,26 +27,43 @@ class FITSFileModel : public QSqlQueryModel
QString m_sort;
QStringList m_key;
QStringList m_value;
QSet<QString> m_markedFiles;
Database *m_database;
public:
FITSFileModel(QObject *parent = nullptr);
void sort(int column, Qt::SortOrder order);
explicit FITSFileModel(Database *database, QObject *parent = nullptr);
void sort(int column, Qt::SortOrder order) override;
void setColumns(const QStringList &columns);
void setFilter(const QStringList &key, const QStringList &value);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void filesMarked(const QModelIndexList &indexes);
void filesUnmarked(const QModelIndexList &indexes);
protected:
void prepareQuery();
};
class DatabaseTableView : public QTableView
{
Q_OBJECT
public:
explicit DatabaseTableView(QWidget *parent = nullptr);
protected:
void contextMenuEvent(QContextMenuEvent *event) override;
signals:
void filesMarked(QModelIndexList indexes);
void filesUnmarked(QModelIndexList indexes);
};
class DataBaseView : public QWidget
{
Q_OBJECT
Database *m_database;
QTableView *m_tableView;
DatabaseTableView *m_tableView;
FITSFileModel *m_model;
QComboBox *m_filterKeyword[3];
QLineEdit *m_search[3];
public:
explicit DataBaseView(Database *database, QWidget *parent = nullptr);
~DataBaseView();
~DataBaseView() override;
public slots:
void selectColumns();
void loadDatabase();
+98
View File
@@ -1,6 +1,10 @@
#include "filesystemwidget.h"
#include <QSettings>
#include <QVBoxLayout>
#include <QContextMenuEvent>
#include <QMenu>
#include <QSettings>
#include <QHeaderView>
FilesystemWidget::FilesystemWidget(QAbstractItemModel *model, QWidget *parent) : QWidget(parent)
, m_model(model)
@@ -34,3 +38,97 @@ void FilesystemWidget::fileClicked(const QModelIndex &index)
{
emit fileSelected(index.row());
}
Filetree::Filetree(QWidget *parent) : QTreeView(parent)
{
QSettings settings;
m_rootDir = settings.value("filetree/rootDir", QDir::homePath()).toString();
m_fileSystemModel = new QFileSystemModel(this);
m_fileSystemModel->setRootPath(m_rootDir);
m_fileSystemModel->setNameFilters({"*.fits", "*.fit", "*.xisf", "*.jpg", "*.jpeg", "*.png"});
m_fileSystemModel->setNameFilterDisables(false);
setModel(m_fileSystemModel);
setRootIndex(m_fileSystemModel->index(m_rootDir));
header()->restoreState(settings.value("filetree/header").toByteArray());
}
Filetree::~Filetree()
{
QSettings settings;
settings.setValue("filetree/rootDir", m_rootDir);
settings.setValue("filetree/header", header()->saveState());
}
void Filetree::contextMenuEvent(QContextMenuEvent *event)
{
QModelIndex index = indexAt(event->pos());
QFileInfo info = m_fileSystemModel->fileInfo(index);
QMenu menu;
QAction *open = nullptr;
QAction *setRoot = nullptr;
QAction *copy = nullptr;
QAction *move = nullptr;
QAction *indexDir = nullptr;
if(info.isFile())
open = menu.addAction(tr("Open"));
if(info.isDir())
{
open = menu.addAction(tr("Open"));
setRoot = menu.addAction(tr("Set as root"));
copy = menu.addAction(tr("Copy marked files"));
move = menu.addAction(tr("Move marked files"));
indexDir = menu.addAction(tr("Index directory"));
}
menu.addSeparator();
QAction *resetRoot = menu.addAction(tr("Reset root"));
QAction *goUp = menu.addAction(tr("Go up"));
QAction *a = menu.exec(event->globalPos());
if(a == nullptr)
return;
if(a == open)
{
emit fileSelected(m_fileSystemModel->filePath(index));
}
else if(a == setRoot && index.isValid())
{
setRootIndex(index);
m_rootDir = m_fileSystemModel->filePath(index);
}
else if(a == resetRoot)
{
setRootIndex(QModelIndex());
m_rootDir = QDir::rootPath();
}
else if(a == goUp)
{
setRootIndex(rootIndex().parent());
m_rootDir = m_fileSystemModel->filePath(rootIndex().parent());
}
else if(a == copy)
{
emit copyFiles(m_fileSystemModel->filePath(index));
}
else if(a == move)
{
emit moveFiles(m_fileSystemModel->filePath(index));
}
else if(a == indexDir)
{
emit indexDirectory(m_fileSystemModel->filePath(index));
}
}
void Filetree::mouseDoubleClickEvent(QMouseEvent *event)
{
QModelIndex index = indexAt(event->pos());
QFileInfo info = m_fileSystemModel->fileInfo(index);
if(info.isFile())
emit fileSelected(info.filePath());
else
QTreeView::mouseDoubleClickEvent(event);
}
+18
View File
@@ -4,6 +4,7 @@
#include <QWidget>
#include <QFileSystemModel>
#include <QListView>
#include <QTreeView>
class FilesystemWidget : public QWidget
{
@@ -20,4 +21,21 @@ signals:
void fileSelected(int row);
};
class Filetree : public QTreeView
{
Q_OBJECT
QFileSystemModel *m_fileSystemModel;
QString m_rootDir;
public:
explicit Filetree(QWidget *parent = nullptr);
~Filetree() override;
void contextMenuEvent(QContextMenuEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
signals:
void fileSelected(const QString &path);
void copyFiles(const QString &path);
void moveFiles(const QString &path);
void indexDirectory(const QString &path);
};
#endif // FILESYSTEMWIDGET_H
+1 -1
View File
@@ -32,7 +32,7 @@ class ImageInfo : public QTreeWidget
Q_OBJECT
public:
explicit ImageInfo(QWidget *parent);
~ImageInfo();
~ImageInfo() override;
public slots:
void setInfo(const ImageInfoData &info);
};
+8
View File
@@ -257,6 +257,14 @@ int ImageRingList::imageCount() const
return m_images.size();
}
QStringList ImageRingList::imageNames() const
{
QStringList ret;
for(auto &img : m_images)
ret.push_back(img->name());
return ret;
}
QModelIndex ImageRingList::index(int row, int column, const QModelIndex &parent) const
{
return createIndex(row, column, m_images.at(row).get());
+2 -1
View File
@@ -59,7 +59,7 @@ class ImageRingList : public QAbstractItemModel
QThreadPool *m_thumbPool;
public:
explicit ImageRingList(QObject *parent = 0);
~ImageRingList();
~ImageRingList() override;
bool setDir(const QString path, const QString &currentFile = QString());
void setFile(const QString &file);
ImagePtr currentImage();
@@ -74,6 +74,7 @@ public:
void loadThumbnails();
void stopLoading();
int imageCount() const;
QStringList imageNames() const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
+6 -6
View File
@@ -21,12 +21,12 @@ public slots:
void bestFit();
void oneToOne();
protected:
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void resizeEvent(QResizeEvent *event);
void wheelEvent(QWheelEvent *event);
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
};
#endif // IMAGESCROLLAREA_H
+140 -40
View File
@@ -9,6 +9,8 @@
#include <QMimeData>
#include <QMessageBox>
#include <QCoreApplication>
#include <QPainter>
#include <QFileInfo>
struct RawImageType
{
@@ -44,7 +46,8 @@ void setScrollRange(QScrollBar *scrollBar, int newRange)
scrollBar->setValue(relPos*newRange - page/2);
}
ImageWidget::ImageWidget(QWidget *parent) : QOpenGLWidget(parent)
ImageWidget::ImageWidget(Database *database, QWidget *parent) : QOpenGLWidget(parent)
, m_database(database)
{
setFocusPolicy(Qt::ClickFocus);
m_range = UINT16_MAX;
@@ -58,6 +61,7 @@ ImageWidget::ImageWidget(QWidget *parent) : QOpenGLWidget(parent)
m_imgWidth = m_imgHeight = -1;
m_superpixel = m_invert = false;
m_showThumbnails = false;
m_selecting = false;
m_thumbnailCount = 0;
m_updateTimer = new QTimer(this);
m_updateTimer->setInterval(500);
@@ -78,12 +82,13 @@ ImageWidget::~ImageWidget()
makeCurrent();
}
void ImageWidget::setImage(const RawImage *image)
void ImageWidget::setImage(const RawImage *image, int index)
{
if(image == nullptr)return;
m_imgWidth = image->width();
m_imgHeight = image->height();
m_currentImg = index;
const RawImageType &rawImageType = rawImageTypes[image->type()];
@@ -102,22 +107,6 @@ void ImageWidget::setImage(const RawImage *image)
update();
}
void ImageWidget::setImage(const QPixmap &pixmap)
{
QImage img = pixmap.toImage();
m_imgWidth = pixmap.width();
m_imgHeight = pixmap.height();
m_image->destroy();
m_image->setData(img);
m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
m_image->setWrapMode(QOpenGLTexture::ClampToBorder);
m_image->setBorderColor(0, 0, 0, 0);
m_bwImg = false;
update();
}
void ImageWidget::setScale(float scale)
{
m_scale = scale;
@@ -130,20 +119,29 @@ void ImageWidget::blockRepaint(bool block)
if(!block)update();
}
void ImageWidget::allocateThumbnails(int count)
void ImageWidget::allocateThumbnails(const QStringList &paths)
{
int count = paths.size();
m_thumbnailCount = count;
m_thumnails.clear();
QStringList marked = m_database->getMarkedFiles();
for(auto &path : paths)
{
QString name = QFileInfo(path).fileName();
m_thumnails.push_back({name, path, QSize(0, 0), marked.contains(path), false});
}
m_thumbnailTexture->destroy();
m_thumbnailTexture->create();
m_thumbnailTexture->setFormat(QOpenGLTexture::RGB16_UNorm);
m_thumbnailTexture->setSize(THUMB_SIZE, THUMB_SIZE);
m_thumbnailTexture->setLayers(count);
m_thumbnailTexture->setLayers(paths.size());
m_thumbnailTexture->allocateStorage();
m_bufferSizes->bind();
float *tmp = new float[count*3];
memset(tmp, 0, count * sizeof(float)*3);
m_bufferSizes->allocate(tmp, count * sizeof(float)*3);
delete [] tmp;
m_thumbnailCount = count;
}
void ImageWidget::setMTFParams(float low, float mid, float high)
@@ -203,6 +201,7 @@ void ImageWidget::thumbnailLoaded(const Image *image)
int sizes[3] = { std::max(1, a > 1.0f ? THUMB_SIZE : (int)(THUMB_SIZE * a)), std::max(1, a < 1.0f ? THUMB_SIZE : (int)(THUMB_SIZE / a)), image->number() };
m_bufferSizes->bind();
m_bufferSizes->write(image->number() * sizeof(sizes), sizes, sizeof(sizes));
m_thumnails[image->number()].size = QSize(sizes[0], sizes[1]);
if(!m_updateTimer->isActive())m_updateTimer->start();
}
@@ -222,6 +221,7 @@ void ImageWidget::paintGL()
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;
QBrush highlight = style()->standardPalette().highlight();
if(m_showThumbnails)
{
@@ -237,6 +237,34 @@ void ImageWidget::paintGL()
mvp.ortho(rect());
m_thumbnailProgram->setUniformValue("mvp", mvp);
if(f3)f3->glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_thumbnailCount);
QPainter painter(this);
const int w = width()/THUMB_SIZE_BORDER;
const int off = (THUMB_SIZE_BORDER - THUMB_SIZE) / 2;
for(int i=0; i < m_thumbnailCount; i++)
{
float x = (i % w) * THUMB_SIZE_BORDER;
float y = i / w * THUMB_SIZE_BORDER_Y + THUMB_SIZE - m_dy + off;
QRectF rect(x, y, THUMB_SIZE_BORDER, 32);
painter.drawText(rect, Qt::AlignCenter | Qt::TextWrapAnywhere, QString(m_thumnails[i].name));
if(m_thumnails[i].selected)
{
painter.save();
QRectF thumbRect;
painter.setPen(Qt::red);
thumbRect.setSize(m_thumnails[i].size);
thumbRect.moveCenter(QPointF(x + THUMB_SIZE_BORDER / 2, y - THUMB_SIZE / 2));
painter.drawRect(thumbRect);
painter.restore();
}
if(m_currentImg == i)
{
painter.save();
painter.setPen(QPen(highlight, 2.0));
painter.drawRect((i % w) * THUMB_SIZE_BORDER + off, i / w * THUMB_SIZE_BORDER_Y - m_dy + off, THUMB_SIZE, THUMB_SIZE);
painter.restore();
}
}
}
else
{
@@ -389,12 +417,93 @@ void ImageWidget::dropEvent(QDropEvent *event)
event->ignore();
}
ImageScrollAreaGL::ImageScrollAreaGL(QWidget *parent) : QWidget(parent)
void ImageWidget::mousePressEvent(QMouseEvent *event)
{
if(m_thumbnailCount && event->button() == Qt::LeftButton && event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier))
m_selecting = true;
if(m_selecting)
{
thumbSelect(event);
}
else
event->ignore();
}
void ImageWidget::mouseMoveEvent(QMouseEvent *event)
{
if(m_selecting)
{
thumbSelect(event);
}
else
event->ignore();
}
void ImageWidget::mouseReleaseEvent(QMouseEvent *event)
{
if(m_selecting)
{
m_selecting = false;
event->accept();
QStringList mark;
QStringList unmark;
for(auto &thumb : m_thumnails)
{
if(thumb.dirty)
{
if(thumb.selected)
mark.append(thumb.path);
else
unmark.append(thumb.path);
thumb.dirty = false;
}
}
if(!mark.isEmpty())
m_database->mark(mark);
if(!unmark.isEmpty())
m_database->unmark(unmark);
}
else
event->ignore();
}
void ImageWidget::thumbSelect(QMouseEvent *event)
{
QPoint p = event->pos();
const int off = (THUMB_SIZE_BORDER - THUMB_SIZE) / 2;
p.ry() += m_dy;
const int w = width()/THUMB_SIZE_BORDER;
int x = p.x() / THUMB_SIZE_BORDER;
int y = p.y() / THUMB_SIZE_BORDER_Y;
int i = y * w + x;
event->accept();
QRect rect(x * THUMB_SIZE_BORDER + off, y * THUMB_SIZE_BORDER_Y + off, THUMB_SIZE, THUMB_SIZE);
if(x < w && i < m_thumbnailCount && rect.contains(p, true))
{
bool oldVal = m_thumnails[i].selected;
bool newVal = oldVal;
if(event->modifiers() == Qt::ShiftModifier)
newVal = true;
if(event->modifiers() == Qt::ControlModifier)
newVal = false;
if(newVal != oldVal)
{
m_thumnails[i].selected = newVal;
m_thumnails[i].dirty = true;
update();
}
}
}
ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWidget(parent)
{
QGridLayout *layout = new QGridLayout(this);
setLayout(layout);
m_imageWidget = new ImageWidget(this);
m_imageWidget = new ImageWidget(database, this);
m_verticalScrollBar = new QScrollBar(Qt::Vertical, this);
m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this);
@@ -416,24 +525,15 @@ ImageScrollAreaGL::~ImageScrollAreaGL()
}
void ImageScrollAreaGL::setImage(RawImage *image)
void ImageScrollAreaGL::setImage(RawImage *image, int index)
{
m_imageWidget->setImage(image);
m_imageWidget->setImage(image, index);
m_imgWidth = image->width();
m_imgHeight = image->height();
if(m_bestFit)bestFit();
updateScrollbars();
}
void ImageScrollAreaGL::setImage(const QPixmap &pixmap)
{
m_imageWidget->setImage(pixmap);
m_imgWidth = pixmap.width();
m_imgHeight = pixmap.height();
if(m_bestFit)bestFit();
updateScrollbars();
}
ImageWidget *ImageScrollAreaGL::imageWidget()
{
return m_imageWidget;
@@ -444,8 +544,8 @@ void ImageScrollAreaGL::setThumbnails(int count)
m_thumbCount = count;
if(m_thumbCount)
{
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER);
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
}
else
{
@@ -461,8 +561,8 @@ void ImageScrollAreaGL::updateScrollbars(bool zoom)
{
m_horizontalScrollBar->hide();
m_verticalScrollBar->show();
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER);
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
}
else
{
@@ -484,8 +584,8 @@ 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);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER);
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
}
else
{
+32 -24
View File
@@ -13,15 +13,16 @@
#include <QTimer>
#include "rawimage.h"
#include "imageringlist.h"
#include "database.h"
typedef enum
struct ImageThumb
{
Linear,
Log,
Sqrt,
Power,
Asinh,
}StretchFunc;
QString name;
QString path;
QSize size;
bool selected;
bool dirty;
};
class ImageWidget : public QOpenGLWidget
{
@@ -40,6 +41,7 @@ class ImageWidget : public QOpenGLWidget
std::unique_ptr<QOpenGLTexture> m_thumbnailTexture;
int m_width, m_height;
int m_imgWidth, m_imgHeight;
int m_currentImg;
float m_low;
float m_mid;
float m_high;
@@ -51,15 +53,18 @@ class ImageWidget : public QOpenGLWidget
bool m_invert;
bool m_superpixel;
bool m_showThumbnails;
bool m_selecting;
int m_thumbnailCount;
QVector<ImageThumb> m_thumnails;
Database *m_database;
public:
explicit ImageWidget(QWidget *parent = nullptr);
~ImageWidget();
void setImage(const RawImage *image);
explicit ImageWidget(Database *database, QWidget *parent = nullptr);
~ImageWidget() override;
void setImage(const RawImage *image, int index);
void setImage(const QPixmap &pixmap);
void setScale(float scale);
void blockRepaint(bool block);
void allocateThumbnails(int count);
void allocateThumbnails(const QStringList &paths);
public slots:
void setMTFParams(float low, float mid, float high);
void setOffset(int dx, int dy);
@@ -69,11 +74,15 @@ public slots:
void thumbnailLoaded(const Image *image);
void showThumbnail(bool enable);
protected:
void paintGL();
void resizeGL(int w, int h);
void initializeGL();
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
void paintGL() override;
void resizeGL(int w, int h) override;
void initializeGL() override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void thumbSelect(QMouseEvent *event);
signals:
void fileDropped(const QString &path);
};
@@ -90,18 +99,17 @@ class ImageScrollAreaGL : public QWidget
bool m_bestFit;
int m_thumbCount;
public:
explicit ImageScrollAreaGL(QWidget *parent = nullptr);
~ImageScrollAreaGL();
void setImage(RawImage *image);
void setImage(const QPixmap &pixmap);
explicit ImageScrollAreaGL(Database *database, QWidget *parent = nullptr);
~ImageScrollAreaGL() override;
void setImage(RawImage *image, int index);
ImageWidget* imageWidget();
void setThumbnails(int count);
protected:
void updateScrollbars(bool zoom = false);
void resizeEvent(QResizeEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
void resizeEvent(QResizeEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void zoom(float delta);
public slots:
void zoomIn();
+2 -1
View File
@@ -248,7 +248,8 @@ bool loadFITS(const QString path, ImageInfoData &info, RawImage **image)
}
}
noload:
loadFITSHeader(file, info);
if(file)
loadFITSHeader(file, info);
fits_close_file(file, &status);
if(status)
+2 -2
View File
@@ -18,7 +18,7 @@ class LoadRunable : public QRunnable
bool m_thumbnail;
public:
LoadRunable(const QString &file, Image *receiver, AnalyzeLevel level, bool thumbnail = false);
void run();
void run() override;
};
class ConvertRunable : public QRunnable
@@ -27,7 +27,7 @@ class ConvertRunable : public QRunnable
QString m_outfile;
public:
ConvertRunable(const QString &in, const QString &out);
void run();
void run() override;
};
#endif // LOADRUNABLE_H
+3
View File
@@ -18,8 +18,11 @@ int main(int argc, char *argv[])
a.setWindowIcon(QIcon(":/org.nou.tenmon.png"));
QTranslator translator;
QTranslator translator2;
if(translator.load(QLocale(), "tenmon", "_", ":/translations"))
a.installTranslator(&translator);
if(translator2.load(QLocale(), "tenmon", "_", a.applicationDirPath()))
a.installTranslator(&translator2);
MainWindow w;
w.show();
+31 -8
View File
@@ -42,7 +42,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
//setCentralWidget(m_image);
resize(800, 600);
m_imageGL = new ImageScrollAreaGL(this);
m_database = new Database(this);
if(!m_database->init())
QMessageBox::critical(this, tr("Can't open DB"), tr("Can't open SQLITE database"));
m_imageGL = new ImageScrollAreaGL(m_database, this);
setCentralWidget(m_imageGL);
m_stretchPanel = new StretchToolbar(this);
@@ -55,9 +59,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
m_filesystem = new FilesystemWidget(m_ringList, this);
connect(m_filesystem, SIGNAL(fileSelected(int)), this, SLOT(loadFile(int)));
m_database = new Database(this);
if(!m_database->init())
QMessageBox::critical(this, tr("Can't open DB"), tr("Can't open SQLITE database"));
m_filetree = new Filetree(this);
connect(m_filetree, &Filetree::fileSelected, this, static_cast<void (MainWindow::*)(const QString &)>(&MainWindow::loadFile));
connect(m_filetree, &Filetree::copyFiles, [this](const QString &path){ copyOrMove(true, path); });
connect(m_filetree, &Filetree::moveFiles, [this](const QString &path){ copyOrMove(false, path); });
connect(m_filetree, &Filetree::indexDirectory, this, static_cast<void (MainWindow::*)(const QString &)>(&MainWindow::indexDir));
m_databaseView = new DataBaseView(m_database, this);
connect(m_databaseView, SIGNAL(loadFile(QString)), this, SLOT(loadFile(QString)));
@@ -75,6 +81,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
databaseViewDock->hide();
addDockWidget(Qt::BottomDockWidgetArea, databaseViewDock);
QDockWidget *filetreeDock = new QDockWidget(tr("File tree"), this);
filetreeDock->setWidget(m_filetree);
filetreeDock->setObjectName("filetreeDock");
databaseViewDock->hide();
addDockWidget(Qt::LeftDockWidgetArea, filetreeDock);
setWindowTitle(tr("Tenmon"));
connect(m_ringList, SIGNAL(pixmapLoaded(Image*)), this, SLOT(pixmapLoaded(Image*)));
@@ -108,7 +120,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
viewMenu->addAction(tr("100%"), m_imageGL, SLOT(oneToOne()));
viewMenu->addAction(tr("Fullscreen"), this, SLOT(toggleFullScreen()), Qt::CTRL + Qt::Key_F11);
QAction *thumbnailsAction = viewMenu->addAction(tr("Thumbnails"), [this](bool checked){
m_imageGL->imageWidget()->allocateThumbnails(m_ringList->imageCount());
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();
@@ -141,7 +153,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
QAction *statsAction = analyzeGroup->addAction(tr("Image statistics"));
QAction *peakAction = analyzeGroup->addAction(tr("Peak finder"));
QAction *starAction = analyzeGroup->addAction("Star finder");
QAction *starAction = analyzeGroup->addAction(tr("Star finder"));
statsAction->setCheckable(true);
peakAction->setCheckable(true);
starAction->setCheckable(true);
@@ -156,6 +168,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
dockMenu->addAction(m_stretchPanel->toggleViewAction());
dockMenu->addAction(filesystemDock->toggleViewAction());
dockMenu->addAction(databaseViewDock->toggleViewAction());
dockMenu->addAction(filetreeDock->toggleViewAction());
menuBar()->addMenu(dockMenu);
QMenu *helpMenu = menuBar()->addMenu(tr("Help"));
@@ -259,6 +272,11 @@ void MainWindow::closeEvent(QCloseEvent *event)
void MainWindow::copyOrMove(bool copy)
{
QString dest = QFileDialog::getExistingDirectory(this, tr("Select destination"), _lastDir);
copyOrMove(copy, dest);
}
void MainWindow::copyOrMove(bool copy, const QString &dest)
{
QDir dir(dest);
if(!dest.isEmpty() && dir.exists())
{
@@ -303,8 +321,8 @@ void MainWindow::copyOrMove(bool copy)
#endif
progress.setValue(i++);
}
m_database->clearMarkedFiles();
}
m_database->clearMarkedFiles();
}
void MainWindow::socketNotify()
@@ -321,7 +339,7 @@ void MainWindow::pixmapLoaded(Image *image)
//m_image->setImage(image->pixmap());
if(image->rawImage())
{
m_imageGL->setImage(image->rawImage());
m_imageGL->setImage(image->rawImage(), image->number());
}
}
@@ -356,6 +374,11 @@ void MainWindow::loadFile(int row)
void MainWindow::indexDir()
{
QString dir = QFileDialog::getExistingDirectory(this, tr("Index directory"), _lastDir);
indexDir(dir);
}
void MainWindow::indexDir(const QString &dir)
{
if(!dir.isEmpty())
{
QProgressDialog progressDialog(tr("Indexing FITS files"), tr("Cancel"), 0, 1, this);
+7 -4
View File
@@ -22,6 +22,7 @@ class MainWindow : public QMainWindow
Database *m_database;
ImageInfo *m_info;
FilesystemWidget *m_filesystem;
Filetree *m_filetree;
DataBaseView *m_databaseView;
static int socketPair[2];
QSocketNotifier *socketNotifier;
@@ -29,14 +30,15 @@ class MainWindow : public QMainWindow
bool _maximized;
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
~MainWindow() override;
protected:
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
void setupSigterm();
static void signalHandler(int);
void closeEvent(QCloseEvent *event);
void closeEvent(QCloseEvent *event) override;
void copyOrMove(bool copy);
void copyOrMove(bool copy, const QString &dest);
protected slots:
void socketNotify();
void updateWindowTitle();
@@ -45,6 +47,7 @@ protected slots:
void loadFile(const QString &path);
void loadFile(int row);
void indexDir();
void indexDir(const QString &dir);
void reindex();
void saveAs();
void convert(const QString &outfile);
+1
View File
@@ -11,6 +11,7 @@
const int THUMB_SIZE = 128;
const int THUMB_SIZE_BORDER = 138;
const int THUMB_SIZE_BORDER_Y = 158;
class Peak
{
+3 -2
View File
@@ -17,11 +17,12 @@
<file>translations/tenmon_sk.qm</file>
<file>about/filter.png</file>
<file>about/stretch-panel.png</file>
<file>translations/tenmon_fr.qm</file>
</qresource>
<qresource lang="en" prefix="/">
<qresource prefix="/" lang="en">
<file alias="help">about/help_en</file>
</qresource>
<qresource lang="sk" prefix="/">
<qresource prefix="/" lang="sk">
<file alias="help">about/help_sk</file>
</qresource>
<qresource prefix="/help"/>
+1 -1
View File
@@ -13,7 +13,7 @@ void main(void)
vec2 pos = qt_Vertex * 0.5;
pos.y *= -1.0;
pos = pos * imageSize_num.xy + 69;
ivec2 off = ivec2(imageSize_num.z % viewport_row.z, imageSize_num.z / viewport_row.z) * 138;
ivec2 off = ivec2(imageSize_num.z % viewport_row.z, imageSize_num.z / viewport_row.z) * ivec2(138, 158);
gl_Position = mvp * vec4(pos - offset + off, 0.0, 1.0);
qt_TexCoord0 = vec3(qt_MultiTexCoord0, imageSize_num.z + 0.1);
Binary file not shown.
+39
View File
@@ -30,6 +30,37 @@
<translation>File name</translation>
</message>
</context>
<context>
<name>Filetree</name>
<message>
<source>Open</source>
<translation>Open</translation>
</message>
<message>
<source>Copy marked files</source>
<translation>Copy marked files</translation>
</message>
<message>
<source>Move marked files</source>
<translation>Move marked files</translation>
</message>
<message>
<source>Index directory</source>
<translation>Index directory</translation>
</message>
<message>
<source>Set as root</source>
<translation>Set as root directory</translation>
</message>
<message>
<source>Reset root</source>
<translation>Reset root directory</translation>
</message>
<message>
<source>Go up</source>
<translation>Go up</translation>
</message>
</context>
<context>
<name>HelpDialog</name>
<message>
@@ -256,6 +287,14 @@
<source>FITS/XISF files database</source>
<translation>FITS/XISF files database</translation>
</message>
<message>
<source>File tree</source>
<translation>File tree</translation>
</message>
<message>
<source>Star finder</source>
<translation>Star finder</translation>
</message>
</context>
<context>
<name>MarkedFiles</name>
Binary file not shown.
+423
View File
@@ -0,0 +1,423 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fr_FR" sourcelanguage="en">
<context>
<name>About</name>
<message>
<source>About Tenmon</source>
<translation>A propos de Tenmon</translation>
</message>
</context>
<context>
<name>DataBaseView</name>
<message>
<source>Select columns</source>
<translation>Choix des colonnes</translation>
</message>
<message>
<source>Text to search, you can % as wildcard</source>
<translation>Texte à chercher, utilisez % comme caractère générique</translation>
</message>
<message>
<source>Filter</source>
<translation>Filtre</translation>
</message>
</context>
<context>
<name>FITSFileModel</name>
<message>
<source>File name</source>
<translation>Nom de fichier</translation>
</message>
</context>
<context>
<name>Filetree</name>
<message>
<source>Open</source>
<translation type="unfinished">Ouvrir</translation>
</message>
<message>
<source>Copy marked files</source>
<translation type="unfinished">Copier les fichiers marqués</translation>
</message>
<message>
<source>Move marked files</source>
<translation type="unfinished">Déplace les fichiers marqués</translation>
</message>
<message>
<source>Index directory</source>
<translation type="unfinished">Indexation du répertoire</translation>
</message>
<message>
<source>Set as root</source>
<translation type="unfinished">Définir comme répertoire racine</translation>
</message>
<message>
<source>Reset root</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Go up</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>HelpDialog</name>
<message>
<source>Help</source>
<translation>Aide</translation>
</message>
</context>
<context>
<name>ImageInfo</name>
<message>
<source>Property</source>
<translation>Propriété</translation>
</message>
<message>
<source>Value</source>
<translation>Valeur</translation>
</message>
<message>
<source>Comment</source>
<translation>Commentaire</translation>
</message>
<message>
<source>FITS Header</source>
<translation>En-tête FITS</translation>
</message>
<message>
<source>Image info</source>
<translation>Informations sur l&apos;image</translation>
</message>
</context>
<context>
<name>ImageRingList</name>
<message>
<source>Name</source>
<translation>Nom</translation>
</message>
</context>
<context>
<name>ImageWidget</name>
<message>
<source>OpenGL error</source>
<translation>Erreur OpenGL</translation>
</message>
<message>
<source>Could not initialize OpenGL 3.3 context. Ensure that proper GPU driver is installed.</source>
<translation>Impossible d&apos;initialiser le contexte OpenGL 3.3. Assurez-vous que le pilote GPU approprié est installé.</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
<source>Image info</source>
<translation>Information de l&apos;image</translation>
</message>
<message>
<source>Can&apos;t open DB</source>
<translation>Ne peut ouvrir la base de donnée</translation>
</message>
<message>
<source>Can&apos;t open SQLITE database</source>
<translation>Ne peut ouvrir la base de donnée SQLITE</translation>
</message>
<message>
<source>Filesystem</source>
<translation>Système de fichier</translation>
</message>
<message>
<source>FITS files database</source>
<translation type="vanished">FITS files database</translation>
</message>
<message>
<source>Tenmon</source>
<translation>Tenmon</translation>
</message>
<message>
<source>File</source>
<translation>Fichier</translation>
</message>
<message>
<source>Open</source>
<translation>Ouvrir</translation>
</message>
<message>
<source>Copy marked files</source>
<translation>Copier les fichiers marqués</translation>
</message>
<message>
<source>Save as</source>
<translation>Enregistrer sous</translation>
</message>
<message>
<source>Live mode</source>
<translation>Mode temps réel</translation>
</message>
<message>
<source>Exit</source>
<translation>Sortir</translation>
</message>
<message>
<source>View</source>
<translation>Voir</translation>
</message>
<message>
<source>Zoom In</source>
<translation>Zoom avant</translation>
</message>
<message>
<source>Zoom Out</source>
<translation>Zoom arrière</translation>
</message>
<message>
<source>Best Fit</source>
<translation>Meilleur ajustement</translation>
</message>
<message>
<source>100%</source>
<translation>100%</translation>
</message>
<message>
<source>Fullscreen</source>
<translation>Plein écran</translation>
</message>
<message>
<source>Select</source>
<translation>Choisir</translation>
</message>
<message>
<source>Mark</source>
<translation>Marquer</translation>
</message>
<message>
<source>Unmark</source>
<translation>Décocher</translation>
</message>
<message>
<source>Mark and next</source>
<translation>Marquer et suivant</translation>
</message>
<message>
<source>Unmark and next</source>
<translation>Décocher et suivant</translation>
</message>
<message>
<source>Analyze</source>
<translation>Analyse</translation>
</message>
<message>
<source>Image statistics</source>
<translation>Statistiques de l&apos;image</translation>
</message>
<message>
<source>Peak finder</source>
<translation>Détecteur de pic</translation>
</message>
<message>
<source>Docks</source>
<translation>Encrage</translation>
</message>
<message>
<source>Open file</source>
<translation>Ouvrir le ficher</translation>
</message>
<message>
<source>Select destination</source>
<translation>Choisir la destination</translation>
</message>
<message>
<source>Copying</source>
<translation>Copier</translation>
</message>
<message>
<source>Cancel</source>
<translation>Abandon</translation>
</message>
<message>
<source>Move marked files</source>
<translation>Déplace les fichiers marqués</translation>
</message>
<message>
<source>Index directory</source>
<translation>Indexation du répertoire</translation>
</message>
<message>
<source>Thumbnails</source>
<translation>Vignettes</translation>
</message>
<message>
<source>Show marked</source>
<translation>Afficher marqué</translation>
</message>
<message>
<source>Help</source>
<translation>Aide</translation>
</message>
<message>
<source>About Tenmon</source>
<translation>A propos de Tenmon</translation>
</message>
<message>
<source>About Qt</source>
<translation>A propos de Qt</translation>
</message>
<message>
<source>Moving</source>
<translation>Déplacement</translation>
</message>
<message>
<source>Images (*.jpg *.jpeg *.png *.cr2 *.fit *.fits *.xisf *.JPG *.JPEG *.PNG *.CR2 *.FIT *.FITS *.XISF)</source>
<translation>Images (*.jpg *.jpeg *.png *.cr2 *.fit *.fits *.xisf *.JPG *.JPEG *.PNG *.CR2 *.FIT *.FITS *.XISF)</translation>
</message>
<message>
<source>Indexing FITS files</source>
<translation>Indexation des fichiers FITS</translation>
</message>
<message>
<source>JPEG (*.jpg *.JPG);; PNG (*.png *.PNG);;FITS (*.fits *.FITS);;XISF (*.xisf *.XISF)</source>
<translation>JPEG (*.jpg *.JPG);; PNG (*.png *.PNG);;FITS (*.fits *.FITS);;XISF (*.xisf *.XISF)</translation>
</message>
<message>
<source>Reindex files</source>
<translation>-indexer les fichiers</translation>
</message>
<message>
<source>FITS/XISF files database</source>
<translation>Base de donnée FITS/XISF</translation>
</message>
<message>
<source>File tree</source>
<translation>Arborescence de fichiers</translation>
</message>
<message>
<source>Star finder</source>
<translation>Chercheur d&apos;étoiles</translation>
</message>
</context>
<context>
<name>MarkedFiles</name>
<message>
<source>Marked files</source>
<translation>Fichiers marqués</translation>
</message>
<message>
<source>Filename</source>
<translation>Nom de fichier</translation>
</message>
<message>
<source>Clear selected</source>
<translation>Effacer la sélection</translation>
</message>
<message>
<source>Clear all</source>
<translation>Effacer tout</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>ISO</source>
<translation>ISO</translation>
</message>
<message>
<source>Shutter speed</source>
<translation>Vitesse d&apos;obturation</translation>
</message>
<message>
<source>Width</source>
<translation>Largeur</translation>
</message>
<message>
<source>Height</source>
<translation>Hauteur</translation>
</message>
<message>
<source>Error</source>
<translation>Erreur</translation>
</message>
<message>
<source>Filename</source>
<translation>Nom de fichier</translation>
</message>
<message>
<source>Mean</source>
<translation>Moyenne</translation>
</message>
<message>
<source>Standart deviation</source>
<translation>Écart-type</translation>
</message>
<message>
<source>Median</source>
<translation>Médiane</translation>
</message>
<message>
<source>Minimum</source>
<translation>Minimum</translation>
</message>
<message>
<source>Maximum</source>
<translation>Maximum</translation>
</message>
<message>
<source>MAD</source>
<translation>MAD</translation>
</message>
<message>
<source>Peaks</source>
<translation>Pics</translation>
</message>
<message>
<source>Peaks draw</source>
<translation>Dessin des pic</translation>
</message>
<message>
<source>FWHM X</source>
<translation>FWHM X</translation>
</message>
<message>
<source>FWHM Y</source>
<translation>FWHM Y</translation>
</message>
<message>
<source>Unsupported sample format</source>
<translation>Format non pris en charge</translation>
</message>
</context>
<context>
<name>SelectColumnsDialog</name>
<message>
<source>Select columns</source>
<translation>Choix des colonnes</translation>
</message>
</context>
<context>
<name>StretchToolbar</name>
<message>
<source>Stretch toolbar</source>
<translation>Barre d&apos;outils étirer</translation>
</message>
<message>
<source>Auto Stretch F12</source>
<translation>Étirement automatique F12</translation>
</message>
<message>
<source>Reset Screen Transfer Function F11</source>
<translation>Réinitialiser la fonction de transfert d&apos;écran F11</translation>
</message>
<message>
<source>Invert colors</source>
<translation>Inverser les couleurs</translation>
</message>
<message>
<source>Superpixel CFA draw 2x2 pixel as one</source>
<translation>Superpixel CFA dessine 2x2 pixels comme un seul</translation>
</message>
<message>
<source>Apply auto stretch on load</source>
<translation>Appliquer l&apos;étirement automatiquement au chargement</translation>
</message>
</context>
</TS>
Binary file not shown.
+39
View File
@@ -31,6 +31,37 @@
<translation>Meno súboru</translation>
</message>
</context>
<context>
<name>Filetree</name>
<message>
<source>Open</source>
<translation>Otvoriť</translation>
</message>
<message>
<source>Copy marked files</source>
<translation>Skopírovať označené súbory</translation>
</message>
<message>
<source>Move marked files</source>
<translation>Presunúť označené súbory</translation>
</message>
<message>
<source>Index directory</source>
<translation>Indexovať adresár</translation>
</message>
<message>
<source>Set as root</source>
<translation>Nastav koreňový adresár</translation>
</message>
<message>
<source>Reset root</source>
<translation>Resetuj koreňový adresár</translation>
</message>
<message>
<source>Go up</source>
<translation>O úroveň vyššie</translation>
</message>
</context>
<context>
<name>HelpDialog</name>
<message>
@@ -269,6 +300,14 @@
<source>FITS/XISF files database</source>
<translation>Databáza FITS/XISF súborov</translation>
</message>
<message>
<source>File tree</source>
<translation>Strom súborov</translation>
</message>
<message>
<source>Star finder</source>
<translation>Vyhľadávač hviezd</translation>
</message>
</context>
<context>
<name>MarkedFiles</name>