Compare commits

...

3 Commits

Author SHA1 Message Date
nou cbc779090f Prioritize M number then IC for object name 2025-07-27 15:36:19 +02:00
nou d826744f26 Add tabs to file manager 2025-07-27 15:35:25 +02:00
nou 3bdfb12d4f Disable use of QFileSystemModel on ARM platform 2025-07-27 10:06:38 +02:00
8 changed files with 299 additions and 33 deletions
+1
View File
@@ -36,6 +36,7 @@ set(TENMON_SRC
src/delete.cpp
src/filemanager.h src/filemanager.cpp src/filemanager.ui
src/filesystemwidget.cpp src/filesystemwidget.h
src/fitskeyword.ui
src/histogram.cpp src/histogram.h
src/httpdownloader.h src/httpdownloader.cpp
src/imageinfo.cpp src/imageinfo.h
+19 -4
View File
@@ -271,15 +271,30 @@ QVector<SkyObject> Database::getObjects(double minRa, double maxRa, double minDe
while(m_getNgc.next())
{
QString name;
QString name2;
QString m = m_getNgc.value("M").toString();
QString ic = m_getNgc.value("IC").toString();
if(!m.isEmpty())name = "M" + m + " ";
if(!ic.isEmpty())name += "IC" + ic + " ";
name += m_getNgc.value("Name").toString();
if(!m.isEmpty())
{
name = "M" + m;
m.clear();
}
else if(!ic.isEmpty())
{
name = "IC" + ic;
ic.clear();
}
else
{
name = m_getNgc.value("Name").toString();
}
if(!ic.isEmpty())name2 += "IC" + ic + " ";
name2 += m_getNgc.value("Common names").toString();
objects.append({
name,
m_getNgc.value("Common names").toString(),
name2,
{m_getNgc.value("RA_deg").toDouble(), m_getNgc.value("DEC_deg").toDouble()},
m_getNgc.value("MajAx").toDouble(),
m_getNgc.value("MinAx").toDouble(),
+214 -18
View File
@@ -1,50 +1,213 @@
#include "filemanager.h"
#include "ui_filemanager.h"
#include "ui_fitskeyword.h"
#include <QSettings>
#include <QStandardPaths>
#include <QDesktopServices>
#include "loadimage.h"
PathTabBar::PathTabBar(const QStringList &tabs) :
_tabs(tabs)
{
setTabsClosable(true);
setExpanding(false);
for(auto &t : tabs)
{
QDir dir(t);
int i = addTab(dir.dirName());
setTabToolTip(i, t);
}
connect(this, &QTabBar::currentChanged, [this](int index){
QString path = _tabs.at(index);
emit pathChanged(path);
});
connect(this, &QTabBar::tabCloseRequested, [this](int index){
if(_tabs.size() >= 2)
{
_tabs.remove(index);
removeTab(index);
}
});
connect(this, &QTabBar::currentChanged, [this](int index){
emit tabChanged(_tabs[index]);
});
}
QHBoxLayout *PathTabBar::createLayout()
{
QHBoxLayout *hlayout = new QHBoxLayout();
hlayout->addWidget(this);
hlayout->addStretch(2);
QPushButton *addButton = new QPushButton("+");
connect(addButton, &QPushButton::clicked, [this](){
QString path = _tabs[currentIndex()];
QDir dir(path);
_tabs.append(path);
int i = addTab(dir.dirName());
setTabToolTip(i, path);
});
hlayout->addWidget(addButton);
return hlayout;
}
const QStringList &PathTabBar::tabPaths() const
{
return _tabs;
}
QString PathTabBar::currentTabPath() const
{
int index = std::clamp(currentIndex(), 0, (int)_tabs.size());
return _tabs[index];
}
void PathTabBar::pathChanged(const QString &path)
{
QDir dir(path);
int index = currentIndex();
setTabText(index, dir.dirName());
setTabToolTip(index, path);
_tabs[index] = path;
}
FITSSelection::FITSSelection(const QStringList &keywords, QWidget *parent) : QDialog(parent)
,ui(new Ui::FITSKeyword)
{
ui->setupUi(this);
connect(ui->addButton, &QPushButton::clicked, [this](){
auto item = ui->keywordList->findItems(ui->keyword->text(), Qt::MatchFixedString | Qt::MatchCaseSensitive);
if(item.size())return;
ui->keywordList->addItem(ui->keyword->text());
});
connect(ui->removeButton, &QPushButton::clicked, [this](){
auto items = ui->keywordList->selectedItems();
for(auto item : items)
delete item;
});
ui->keywordList->addItems(keywords);
}
FITSSelection::~FITSSelection()
{
delete ui;
}
QStringList FITSSelection::FITSKeywords() const
{
QStringList keywords;
for(int i = 0; i < ui->keywordList->count(); i++)
keywords.append(ui->keywordList->item(i)->text());
return keywords;
}
FileManager::FileManager(const QSet<QString> &openFilter, QWidget *parent) : QMainWindow(parent)
,ui(new Ui::FileManager)
{
ui->setupUi(this);
ui->leftTab->setOpenFilter(openFilter);
ui->rightTab->setOpenFilter(openFilter);
connect(ui->leftTab, &DirView::dirChanged, ui->leftPath, &QLineEdit::setText);
connect(ui->rightTab, &DirView::dirChanged, ui->rightPath, &QLineEdit::setText);
connect(ui->leftTab, &DirView::openFile, this, &FileManager::openFile);
connect(ui->rightTab, &DirView::openFile, this, &FileManager::openFile);
QStringList standardLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
QString picturesPath;
if(standardLocations.size())
picturesPath = standardLocations.first();
QSettings settings;
ui->leftTab->setDir(settings.value("filemanager/leftTabPath", picturesPath).toString());
QStringList leftTabs = settings.value("filemanager/leftTabPaths", picturesPath).toStringList();
QStringList rightTabs = settings.value("filemanager/rightTabPaths", picturesPath).toStringList();
if(leftTabs.empty())leftTabs.append(picturesPath);
if(rightTabs.empty())rightTabs.append(picturesPath);
ui->leftTab->setOpenFilter(openFilter);
ui->rightTab->setOpenFilter(openFilter);
_rightTabBar = new PathTabBar(rightTabs);
ui->rightLayout->insertLayout(0, _rightTabBar->createLayout());
connect(_rightTabBar, &PathTabBar::tabChanged, ui->rightTab, &DirView::setDir);
_leftTabBar = new PathTabBar(leftTabs);
ui->leftLayout->insertLayout(0, _leftTabBar->createLayout());
connect(_leftTabBar, &PathTabBar::tabChanged, ui->leftTab, &DirView::setDir);
connect(ui->leftTab, &DirView::dirChanged, ui->leftPath, &QLineEdit::setText);
connect(ui->leftTab, &DirView::dirChanged, _leftTabBar, &PathTabBar::pathChanged);
connect(ui->rightTab, &DirView::dirChanged, ui->rightPath, &QLineEdit::setText);
connect(ui->rightTab, &DirView::dirChanged, _rightTabBar, &PathTabBar::pathChanged);
connect(ui->leftTab, &DirView::openFile, this, &FileManager::openFile);
connect(ui->rightTab, &DirView::openFile, this, &FileManager::openFile);
connect(ui->actionLoad_FITS_keywordsLeft, &QAction::toggled, ui->leftTab, &DirView::loadFitsKeywords);
connect(ui->actionLoad_FITS_keywordsRight, &QAction::toggled, ui->rightTab, &DirView::loadFitsKeywords);
ui->leftTab->setDir(_leftTabBar->currentTabPath());
ui->leftTab->setFITSKeywords(settings.value("filemanager/leftFitsKeywords", QStringList("OBJECT")).toStringList());
ui->leftTab->header()->restoreState(settings.value("filemanager/leftTabHeader").toByteArray());
ui->rightTab->setDir(settings.value("filemanager/rightTabPath", picturesPath).toString());
ui->rightTab->setDir(_rightTabBar->currentTabPath());
ui->rightTab->setFITSKeywords(settings.value("filemanager/rightFitsKeywords", QStringList("OBJECT")).toStringList());
ui->rightTab->header()->restoreState(settings.value("filemanager/rightTabHeader").toByteArray());
ui->actionLoad_FITS_keywordsLeft->setChecked(settings.value("filemanager/leftLoadFitsKeywords", true).toBool());
ui->actionLoad_FITS_keywordsRight->setChecked(settings.value("filemanager/rightLoadFitsKeywords", true).toBool());
restoreGeometry(settings.value("filemanager/geometry").toByteArray());
setAttribute(Qt::WA_DeleteOnClose);
connect(ui->actionSelect_columnsLeft, &QAction::triggered, this, &FileManager::selectFITSKeywords);
connect(ui->actionSelect_columnsRight, &QAction::triggered, this, &FileManager::selectFITSKeywords);
QFileInfoList drives = QDir::drives();
for(auto &drive : drives)
{
QString path = drive.absoluteFilePath();
ui->menuLeft_Tab->addAction(drive.absoluteFilePath(), [path, this](){ ui->leftTab->setDir(path); });
ui->menuRight_Tab->addAction(drive.absoluteFilePath(), [path, this](){ ui->rightTab->setDir(path); });
}
}
FileManager::~FileManager()
{
QSettings settings;
settings.setValue("filemanager/leftTabPath", ui->leftTab->dir());
settings.setValue("filemanager/leftFitsKeywords", ui->leftTab->FITSKeywords());
settings.setValue("filemanager/leftTabPaths", _leftTabBar->tabPaths());
settings.setValue("filemanager/leftTabHeader", ui->leftTab->header()->saveState());
settings.setValue("filemanager/rightTabPath", ui->rightTab->dir());
settings.setValue("filemanager/rightFitsKeywords", ui->rightTab->FITSKeywords());
settings.setValue("filemanager/rightTabPaths", _rightTabBar->tabPaths());
settings.setValue("filemanager/rightTabHeader", ui->rightTab->header()->saveState());
settings.setValue("filemanager/leftLoadFitsKeywords", ui->actionLoad_FITS_keywordsLeft->isChecked());
settings.setValue("filemanager/rightLoadFitsKeywords", ui->actionLoad_FITS_keywordsRight->isChecked());
settings.setValue("filemanager/geometry", saveGeometry());
delete ui;
}
void FileManager::selectFITSKeywords()
{
QStringList columns;
if(sender() == ui->actionSelect_columnsLeft)
columns = ui->leftTab->FITSKeywords();
if(sender() == ui->actionSelect_columnsRight)
columns = ui->rightTab->FITSKeywords();
FITSSelection selection(columns, this);
int ret = selection.exec();
if(ret == QDialog::Accepted)
{
if(sender() == ui->actionSelect_columnsLeft)
ui->leftTab->setFITSKeywords(selection.FITSKeywords());
if(sender() == ui->actionSelect_columnsRight)
ui->rightTab->setFITSKeywords(selection.FITSKeywords());
}
}
void FileManager::addTab()
{
}
QCache<QString, ImageInfoData>* DirFileSystemModel::getCacheInstance()
{
static bool init = true;
@@ -61,7 +224,7 @@ DirFileSystemModel::DirFileSystemModel(QObject *parent) : QFileSystemModel(paren
{
_cache = getCacheInstance();
setFilter(QDir::AllEntries | QDir::NoDot);
_fitsKeywords = {"OBJECT", "RA", "DEC"};
_fitsKeywords = {"OBJECT"};
}
void DirFileSystemModel::setDir(const QString &path)
@@ -74,6 +237,18 @@ QString DirFileSystemModel::dir() const
return fileInfo(_dir).canonicalFilePath();
}
void DirFileSystemModel::setFITSKeywords(const QStringList &keywords)
{
beginResetModel();
_fitsKeywords = keywords;
endResetModel();
}
const QStringList &DirFileSystemModel::FITSKeywords() const
{
return _fitsKeywords;
}
Qt::ItemFlags DirFileSystemModel::flags(const QModelIndex &index) const
{
return QFileSystemModel::flags(index) & ~Qt::ItemIsEditable;
@@ -91,23 +266,25 @@ QVariant DirFileSystemModel::data(const QModelIndex &index, int role) const
QFileInfo info = fileInfo(index);
QString path = info.canonicalFilePath();
QString suffix = info.suffix();
ImageInfoData *infoData;
ImageInfoData *infoData = nullptr;
if(_cache->contains(path))
{
infoData = _cache->object(path);
}
else
{
infoData = new ImageInfoData;
if(_loadFitsKeywords)
{
infoData = new ImageInfoData;
if(isFITS(suffix))
readFITSHeader(path, *infoData);
else if(isXISF(suffix))
readXISFHeader(path, *infoData);
}
_cache->insert(path, infoData);
}
}
if(infoData)
{
int column = index.column() - QFileSystemModel::columnCount();
if(column < _fitsKeywords.size())
{
@@ -116,6 +293,7 @@ QVariant DirFileSystemModel::data(const QModelIndex &index, int role) const
if(record.key == key)
return record.value;
}
}
return "";
}
return QFileSystemModel::data(index, role);
@@ -164,7 +342,7 @@ DirView::DirView(QWidget *parent) : QTreeView(parent)
}
else if(info.isFile())
{
if(_openFilter.contains(info.suffix()))
if(_openFilter.contains(info.suffix().toLower()))
emit openFile(info.absoluteFilePath());
else
QDesktopServices::openUrl(QUrl::fromLocalFile(info.absoluteFilePath()));
@@ -177,10 +355,11 @@ DirView::DirView(QWidget *parent) : QTreeView(parent)
void DirView::setDir(const QString &path)
{
QString oldPath = _dirFileSystemModel->dir();
_dirFileSystemModel->setDir(path);
setRootIndex(_dirFileSystemModel->index(path, 0));
clearSelection();
emit dirChanged(path);
if(oldPath != path)emit dirChanged(path);
}
QString DirView::dir() const
@@ -193,6 +372,18 @@ void DirView::setOpenFilter(const QSet<QString> &openFilter)
_openFilter = openFilter;
}
void DirView::setFITSKeywords(const QStringList &keywords)
{
QString d = dir();
_dirFileSystemModel->setFITSKeywords(keywords);
setDir(d);
}
const QStringList &DirView::FITSKeywords() const
{
return _dirFileSystemModel->FITSKeywords();
}
void DirView::headerContextMenu(const QPoint &pos)
{
QHeaderView *head = header();
@@ -213,3 +404,8 @@ void DirView::headerContextMenu(const QPoint &pos)
else head->hideSection(a->data().toInt());
}
}
void DirView::loadFitsKeywords(bool enable)
{
_dirFileSystemModel->loadFitsKeywords(enable);
}
+42
View File
@@ -5,22 +5,59 @@
#include <QCache>
#include <QFileSystemModel>
#include <QTreeView>
#include <QDialog>
#include <QTabBar>
#include <QHBoxLayout>
#include "imageinfodata.h"
namespace Ui {
class FileManager;
class FITSKeyword;
}
class PathTabBar : public QTabBar
{
Q_OBJECT
public:
explicit PathTabBar(const QStringList &tabs);
QHBoxLayout* createLayout();
const QStringList& tabPaths() const;
QString currentTabPath() const;
public slots:
void pathChanged(const QString &path);
signals:
void tabChanged(const QString &path);
private:
QStringList _tabs;
};
class FITSSelection : public QDialog
{
Q_OBJECT
public:
FITSSelection(const QStringList &keywords, QWidget *parent = nullptr);
~FITSSelection();
QStringList FITSKeywords() const;
private:
Ui::FITSKeyword *ui;
};
class FileManager : public QMainWindow
{
Q_OBJECT
public:
explicit FileManager(const QSet<QString> &openFilter, QWidget *parent = nullptr);
~FileManager();
public slots:
void selectFITSKeywords();
protected slots:
void addTab();
signals:
void openFile(const QString &path);
private:
Ui::FileManager *ui;
PathTabBar *_leftTabBar;
PathTabBar *_rightTabBar;
};
class DirFileSystemModel : public QFileSystemModel
@@ -35,6 +72,8 @@ public:
explicit DirFileSystemModel(QObject *parent = nullptr);
void setDir(const QString &path);
QString dir() const;
void setFITSKeywords(const QStringList &keywords);
const QStringList& FITSKeywords() const;
Qt::ItemFlags flags(const QModelIndex &index) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
@@ -54,8 +93,11 @@ public:
void setDir(const QString &path);
QString dir() const;
void setOpenFilter(const QSet<QString> &openFilter);
void setFITSKeywords(const QStringList &keywords);
const QStringList& FITSKeywords() const;
public slots:
void headerContextMenu(const QPoint &pos);
void loadFitsKeywords(bool enable);
signals:
void dirChanged(const QString &path);
void openFile(const QString &path);
+4 -2
View File
@@ -16,7 +16,7 @@
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="leftLayout">
<item>
<widget class="QLineEdit" name="leftPath">
<property name="readOnly">
@@ -30,7 +30,7 @@
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="rightLayout">
<item>
<widget class="QLineEdit" name="rightPath">
<property name="readOnly">
@@ -60,6 +60,7 @@
</property>
<addaction name="actionLoad_FITS_keywordsLeft"/>
<addaction name="actionSelect_columnsLeft"/>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="menuRight_Tab">
<property name="title">
@@ -67,6 +68,7 @@
</property>
<addaction name="actionLoad_FITS_keywordsRight"/>
<addaction name="actionSelect_columnsRight"/>
<addaction name="separator"/>
</widget>
<addaction name="menuLeft_Tab"/>
<addaction name="menuRight_Tab"/>
+11 -1
View File
@@ -102,11 +102,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
connect(m_filesystem, &FilesystemWidget::sortChanged, m_ringList, &ImageRingList::setSort);
connect(m_filesystem, &FilesystemWidget::reverseSort, m_ringList, &ImageRingList::reverseSort);
m_filetree = nullptr;
#if !defined(FLATPAK) || !defined(__aarch64__)//bug with QTreeView and QFileSystemModel on ARM64 under flatpak
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));
#endif
m_databaseView = new DataBaseView(m_database, this);
connect(m_databaseView, &DataBaseView::loadFile, this, static_cast<void (MainWindow::*)(const QString &)>(&MainWindow::loadFile));
@@ -145,11 +148,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
databaseViewDock->hide();
addDockWidget(Qt::BottomDockWidgetArea, databaseViewDock);
#if !defined(FLATPAK) || !defined(__aarch64__)
QDockWidget *filetreeDock = new QDockWidget(tr("File tree"), this);
filetreeDock->setWidget(m_filetree);
filetreeDock->setObjectName("filetreeDock");
databaseViewDock->hide();
addDockWidget(Qt::LeftDockWidgetArea, filetreeDock);
#endif
Histogram *histogram = new Histogram(this);
QDockWidget *histogramDock = new QDockWidget(tr("Histogram"), this);
@@ -178,7 +183,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
fileMenu->addAction(tr("Open directory recursively"), this, &MainWindow::loadDir);
QAction *saveAs = fileMenu->addAction(tr("Save as"), QKeySequence::Save, this, &MainWindow::saveAs);
fileMenu->addSeparator();
#if !defined(FLATPAK) || !defined(__aarch64__)
fileMenu->addAction(tr("File manager"), this, &MainWindow::openFileManager);
#endif
fileMenu->addAction(tr("Copy marked files"), Qt::Key_F5, this, &MainWindow::copyMarked);
fileMenu->addAction(tr("Move marked files"), Qt::Key_F6, this, &MainWindow::moveMarked);
fileMenu->addAction(tr("Move marked files to trash"), QKeySequence::Delete, this, &MainWindow::deleteMarked);
@@ -194,7 +201,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
fileMenu->addSeparator();
QAction *liveModeAction = fileMenu->addAction(tr("Live mode"), this, &MainWindow::liveMode);
liveModeAction->setCheckable(true);
QAction *exitAction = fileMenu->addAction(tr("Exit"), this, &MainWindow::close);
QAction *exitAction = fileMenu->addAction(tr("Exit"), QCoreApplication::instance(), &QCoreApplication::quit, Qt::QueuedConnection);
exitAction->setShortcut(QKeySequence::Quit);
menuBar()->addMenu(fileMenu);
@@ -367,6 +374,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
filesystemDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
databaseViewDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
filetreeDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
if(_plateSolving)_plateSolving->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
m_stretchPanel->setFloatable(false);
}
}
@@ -813,9 +821,11 @@ void MainWindow::checkNewVersion()
void MainWindow::openFileManager()
{
#if !defined(FLATPAK) || !defined(__aarch64__)
FileManager *filemanager = new FileManager(_openSuffix);
connect(filemanager, &FileManager::openFile, this, static_cast<void (MainWindow::*)(const QString&)>(&MainWindow::loadFile));
filemanager->show();
#endif
}
void MainWindow::updateWindowTitle()
+1 -1
View File
@@ -23,7 +23,7 @@ class MainWindow : public QMainWindow
FilesystemWidget *m_filesystem;
Filetree *m_filetree;
DataBaseView *m_databaseView;
PlateSolving *_plateSolving;
PlateSolving *_plateSolving = nullptr;
static int socketPair[2];
QSocketNotifier *socketNotifier;
QString _lastDir;
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef PLATESOLVING_H
#define PLATESOLVING_H
#include "qelapsedtimer.h"
#include <QElapsedTimer>
#include <QDockWidget>
class Solver;