diff --git a/CMakeLists.txt b/CMakeLists.txt index 24f8b2a..6da84af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ set(TENMON_SRC src/database.cpp src/database.h src/databaseview.cpp src/databaseview.h src/delete.cpp + src/filemanager.h src/filemanager.cpp src/filemanager.ui src/filesystemwidget.cpp src/filesystemwidget.h src/histogram.cpp src/histogram.h src/httpdownloader.h src/httpdownloader.cpp @@ -77,7 +78,7 @@ endif() qt_add_executable(tenmon WIN32 MACOSX_BUNDLE ${tenmon_ICON} ${TENMON_SRC}) find_path(FITS_INCLUDE fitsio2.h PATH_SUFFIXES cfitsio REQUIRED) -target_include_directories(tenmon PRIVATE ${FITS_INCLUDE} ${CMAKE_BINARY_DIR} ${libXISF_SOURCE_DIR}) +target_include_directories(tenmon PRIVATE ${FITS_INCLUDE} ${CMAKE_BINARY_DIR} ${libXISF_SOURCE_DIR} "src") option(COLOR_MANAGMENT "Enable sRGB framebuffer support for gamma correct images and color profiles support" ON) if(COLOR_MANAGMENT) diff --git a/src/filemanager.cpp b/src/filemanager.cpp new file mode 100644 index 0000000..2e19c93 --- /dev/null +++ b/src/filemanager.cpp @@ -0,0 +1,178 @@ +#include "filemanager.h" +#include "ui_filemanager.h" + +#include +#include +#include +#include "loadimage.h" + +FileManager::FileManager(const QSet &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()); + ui->leftTab->header()->restoreState(settings.value("filemanager/leftTabHeader").toByteArray()); + ui->rightTab->setDir(settings.value("filemanager/rightTabPath", picturesPath).toString()); + ui->rightTab->header()->restoreState(settings.value("filemanager/rightTabHeader").toByteArray()); + restoreGeometry(settings.value("filemanager/geometry").toByteArray()); + + setAttribute(Qt::WA_DeleteOnClose); +} + +FileManager::~FileManager() +{ + QSettings settings; + settings.setValue("filemanager/leftTabPath", ui->leftTab->dir()); + settings.setValue("filemanager/leftTabHeader", ui->leftTab->header()->saveState()); + settings.setValue("filemanager/rightTabPath", ui->rightTab->dir()); + settings.setValue("filemanager/rightTabHeader", ui->leftTab->header()->saveState()); + settings.setValue("filemanager/geometry", saveGeometry()); + delete ui; +} + +QCache* DirFileSystemModel::getCacheInstance() +{ + static bool init = true; + static QCache cache; + if(!init) + { + cache.setMaxCost(10000); + init = false; + } + return &cache; +} + +DirFileSystemModel::DirFileSystemModel(QObject *parent) : QFileSystemModel(parent) +{ + _cache = getCacheInstance(); + setFilter(QDir::AllEntries | QDir::NoDot); +} + +void DirFileSystemModel::setDir(const QString &path) +{ + _dir = index(path); +} + +QString DirFileSystemModel::dir() const +{ + return fileInfo(_dir).canonicalFilePath(); +} + +Qt::ItemFlags DirFileSystemModel::flags(const QModelIndex &index) const +{ + return QFileSystemModel::flags(index) & ~Qt::ItemIsEditable; +} + +int DirFileSystemModel::columnCount(const QModelIndex &parent) const +{ + return QFileSystemModel::columnCount(parent) + 1; +} + +QVariant DirFileSystemModel::data(const QModelIndex &index, int role) const +{ + if(index.column() >= QFileSystemModel::columnCount() && role == Qt::DisplayRole) + { + QFileInfo info = fileInfo(index); + QString path = info.canonicalFilePath(); + QString suffix = info.suffix(); + ImageInfoData *infoData; + if(_cache->contains(path)) + { + infoData = _cache->object(path); + } + else + { + infoData = new ImageInfoData; + if(isFITS(suffix)) + readFITSHeader(path, *infoData); + else if(isXISF(suffix)) + readXISFHeader(path, *infoData); + _cache->insert(path, infoData); + } + for(auto &record : infoData->fitsHeader) + if(record.key == "OBJECT") + return record.value; + + return ""; + } + return QFileSystemModel::data(index, role); +} + +QVariant DirFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= QFileSystemModel::columnCount()) + return "FITS"; + + return QFileSystemModel::headerData(section, orientation, role); +} + +bool DirFileSystemModel::hasChildren(const QModelIndex &parent) const +{ + if(parent.parent() == _dir)return false; + + return QFileSystemModel::hasChildren(parent); +} + +DirView::DirView(QWidget *parent) : QTreeView(parent) +{ + _dirFileSystemModel = new DirFileSystemModel(this); +#ifdef Q_OS_LINUX + _dirFileSystemModel->setRootPath("/"); +#elif defined(Q_OS_WIN64) + _dirFileSystemModel->setRootPath("C:/"); +#endif + _dirFileSystemModel->setReadOnly(false); + setDragEnabled(true); + setAcceptDrops(true); + + setModel(_dirFileSystemModel); + setSelectionMode(QAbstractItemView::ExtendedSelection); + + connect(this, &QTreeView::doubleClicked, [this](const QModelIndex &index){ + QFileInfo info = _dirFileSystemModel->fileInfo(index); + if(_dirFileSystemModel->isDir(index)) + { + setDir(info.canonicalFilePath()); + } + else if(info.isFile()) + { + if(_openFilter.contains(info.suffix())) + emit openFile(info.absoluteFilePath()); + else + QDesktopServices::openUrl(QUrl::fromLocalFile(info.absoluteFilePath())); + } + }); +} + +void DirView::setDir(const QString &path) +{ + _dirFileSystemModel->setDir(path); + setRootIndex(_dirFileSystemModel->index(path, 0)); + clearSelection(); + emit dirChanged(path); +} + +QString DirView::dir() const +{ + return _dirFileSystemModel->dir(); +} + +void DirView::setOpenFilter(const QSet &openFilter) +{ + _openFilter = openFilter; +} diff --git a/src/filemanager.h b/src/filemanager.h new file mode 100644 index 0000000..709132b --- /dev/null +++ b/src/filemanager.h @@ -0,0 +1,57 @@ +#ifndef FILEMANAGER_H +#define FILEMANAGER_H + +#include +#include +#include +#include +#include "imageinfodata.h" + +namespace Ui { +class FileManager; +} + +class FileManager : public QMainWindow +{ + Q_OBJECT +public: + explicit FileManager(const QSet &openFilter, QWidget *parent = nullptr); + ~FileManager(); +signals: + void openFile(const QString &path); +private: + Ui::FileManager *ui; +}; + +class DirFileSystemModel : public QFileSystemModel +{ + mutable QCache *_cache = nullptr; + static QCache* getCacheInstance(); + QModelIndex _dir; +public: + explicit DirFileSystemModel(QObject *parent = nullptr); + void setDir(const QString &path); + QString dir() 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; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + bool hasChildren(const QModelIndex &parent) const override; +}; + +class DirView : public QTreeView +{ + Q_OBJECT + DirFileSystemModel *_dirFileSystemModel = nullptr; + QSet _openFilter; +public: + explicit DirView(QWidget *parent = nullptr); + void setDir(const QString &path); + QString dir() const; + void setOpenFilter(const QSet &openFilter); +signals: + void dirChanged(const QString &path); + void openFile(const QString &path); +}; + +#endif // FILEMANAGER_H diff --git a/src/filemanager.ui b/src/filemanager.ui new file mode 100644 index 0000000..137be0a --- /dev/null +++ b/src/filemanager.ui @@ -0,0 +1,68 @@ + + + FileManager + + + + 0 + 0 + 1282 + 858 + + + + File Manager + + + + + + + + + true + + + + + + + + + + + + + + true + + + + + + + + + + + + + + 0 + 0 + 1282 + 23 + + + + + + + DirView + QTreeView +
filemanager.h
+
+
+ + +
diff --git a/src/filesystemwidget.cpp b/src/filesystemwidget.cpp index c97b7bd..c7f2b33 100644 --- a/src/filesystemwidget.cpp +++ b/src/filesystemwidget.cpp @@ -5,6 +5,7 @@ #include #include #include +#include FilesystemWidget::FilesystemWidget(QAbstractItemModel *model, QWidget *parent) : QWidget(parent) , m_model(model) @@ -117,6 +118,7 @@ void Filetree::contextMenuEvent(QContextMenuEvent *event) { setRootIndex(index); m_rootDir = m_fileSystemModel->filePath(index); + m_fileSystemModel->setRootPath(m_rootDir); } else if(a == resetRoot) { @@ -127,6 +129,7 @@ void Filetree::contextMenuEvent(QContextMenuEvent *event) { setRootIndex(rootIndex().parent()); m_rootDir = m_fileSystemModel->filePath(rootIndex().parent()); + m_fileSystemModel->setRootPath(m_rootDir); } else if(a == copy) { diff --git a/src/filesystemwidget.h b/src/filesystemwidget.h index 6483407..0cdab94 100644 --- a/src/filesystemwidget.h +++ b/src/filesystemwidget.h @@ -3,6 +3,7 @@ #include #include +#include #include #include diff --git a/src/loadimage.cpp b/src/loadimage.cpp index d489753..3ddfacc 100644 --- a/src/loadimage.cpp +++ b/src/loadimage.cpp @@ -409,18 +409,19 @@ bool loadImage(const QString &path, ImageInfoData &info, std::shared_ptr &rawImage, int index, bool planar = false); +bool isFITS(const QString &suffix); +bool isXISF(const QString &suffix); #endif // LOADIMAGE_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0b1caed..0cc9a34 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -29,6 +29,7 @@ #include "settingsdialog.h" #include "histogram.h" #include "batchprocessing.h" +#include "filemanager.h" #ifdef __linux__ #include @@ -66,6 +67,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) _openFilter.append(tr(";;All files (*)")); nameFilter.append({"fit", "fits", "fts", "fz", "xisf", "cr2", "cr3", "nef", "dng"}); QImageReader::setAllocationLimit(0); + _openSuffix = {nameFilter.constBegin(), nameFilter.constEnd()}; m_info = new ImageInfo(this); QDockWidget *infoDock = new QDockWidget(tr("Image info"), this); @@ -176,6 +178,7 @@ 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(); + fileMenu->addAction(tr("File manager"), this, &MainWindow::openFileManager); 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); @@ -808,6 +811,13 @@ void MainWindow::checkNewVersion() }); } +void MainWindow::openFileManager() +{ + FileManager *filemanager = new FileManager(_openSuffix); + connect(filemanager, &FileManager::openFile, this, static_cast(&MainWindow::loadFile)); + filemanager->show(); +} + void MainWindow::updateWindowTitle() { ImagePtr ptr = m_ringList->currentImage(); diff --git a/src/mainwindow.h b/src/mainwindow.h index d091c16..feb565d 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -30,6 +30,7 @@ class MainWindow : public QMainWindow bool _maximized; QString _openFilter; QString _saveFilter; + QSet _openSuffix; public: MainWindow(QWidget *parent = 0); ~MainWindow() override; @@ -67,6 +68,7 @@ public slots: void showSettingsDialog(); void exportCSV(); void checkNewVersion(); + void openFileManager(); }; #endif // MAINWINDOW_H diff --git a/src/scriptengine.cpp b/src/scriptengine.cpp index 878116a..61be4a9 100644 --- a/src/scriptengine.cpp +++ b/src/scriptengine.cpp @@ -455,11 +455,11 @@ void File::loadFitsKeywords() { _fitsKeywordsLoaded = true; ImageInfoData info; - if(suffix().toLower() == "xisf") + if(isXISF(suffix())) { readXISFHeader(_path, info); } - else if(suffix().toLower() == "fits" || suffix().toLower() == "fit" || suffix().toLower() == "fz") + else if(isFITS(suffix())) { readFITSHeader(_path, info); }