tenmon/imageringlist.cpp

316 lines
6.9 KiB
C++

#include "imageringlist.h"
#include <QThreadPool>
#include <QDir>
#include "loadrunable.h"
#include "rawimage.h"
using namespace std;
const int DEFAULT_WIDTH = 2;
Image::Image(const QString name, ImageRingList *ringList) :
m_loading(false),
m_released(true),
m_current(false),
m_name(name),
m_ringList(ringList)
{
}
void Image::load()
{
if(!m_rawImage && !m_loading)
{
m_loading = true;
m_released = false;
QThreadPool::globalInstance()->start(new LoadRunable(m_name, this, m_ringList->analyzeLevel()));
}
if(!m_loading && m_rawImage)
emit pixmapLoaded(this);
}
void Image::release()
{
m_rawImage.reset();
m_released = true;
m_loading = false;
}
QString Image::name() const
{
return m_name;
}
RawImage *Image::rawImage()
{
return m_rawImage.get();
}
ImageInfoData Image::info() const
{
return m_info;
}
bool Image::isCurrent() const
{
return !m_released;
}
void Image::imageLoaded(void *rawImage, ImageInfoData info)
{
m_loading = false;
if(!m_released)
{
m_rawImage.reset(static_cast<RawImage*>(rawImage));
m_info = info;
emit pixmapLoaded(this);
}
else
{
delete static_cast<RawImage*>(rawImage);
}
}
ImageRingList::ImageRingList(QObject *parent) : QAbstractItemModel(parent)
, m_liveMode(false)
, m_analyzeLevel(None)
{
connect(&m_fileSystemWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString)));
}
ImageRingList::~ImageRingList()
{
QThreadPool::globalInstance()->clear();
QThreadPool::globalInstance()->waitForDone();
}
bool ImageRingList::setDir(const QString path, const QString &currentFile)
{
QDir dir(path);
if(dir.exists())
{
QStringList nameFilter;
nameFilter << "*.jpg" << "*.jpeg" << "*.png" << "*.cr2" << "*.fit" << "*.fits";
QStringList list = dir.entryList(nameFilter, QDir::Files | QDir::Readable, m_liveMode ? QDir::Time : QDir::Name);
QStringList absolutePaths;
foreach(const QString &file, list)
{
absolutePaths.append(dir.absoluteFilePath(file));
}
setFiles(absolutePaths, m_liveMode ? list.first() : currentFile);
m_fileSystemWatcher.removePaths(m_fileSystemWatcher.directories());
m_fileSystemWatcher.addPath(path);
return true;
}
return false;
}
void ImageRingList::setFile(const QString &file)
{
QFileInfo info(file);
if(info.isDir())
setDir(file);
else
setDir(info.absolutePath(), file);
}
ImagePtr ImageRingList::currentImage()
{
if(m_images.size())
return *m_currImage;
else
return 0;
}
void ImageRingList::increment()
{
if(m_images.size())
{
(*m_firstImage)->release();
m_firstImage = increment(m_firstImage);
m_currImage = increment(m_currImage);
(*m_currImage)->load();
m_lastImage = increment(m_lastImage);
(*m_lastImage)->load();
}
}
void ImageRingList::decrement()
{
if(m_images.size())
{
(*m_lastImage)->release();
m_firstImage = decrement(m_firstImage);
m_currImage = decrement(m_currImage);
(*m_currImage)->load();
m_lastImage = decrement(m_lastImage);
(*m_firstImage)->load();
}
}
void ImageRingList::setLiveMode(bool live)
{
m_liveMode = live;
}
void ImageRingList::setCalculateStats(bool stats)
{
m_analyzeLevel = stats ? Statistics : None;
}
void ImageRingList::setFindPeaks(bool findPeaks)
{
m_analyzeLevel = findPeaks ? Peaks : None;
}
void ImageRingList::setFindStars(bool findStars)
{
m_analyzeLevel = findStars ? Stars : None;
}
AnalyzeLevel ImageRingList::analyzeLevel() const
{
return m_analyzeLevel;
}
void ImageRingList::loadFile(int row)
{
if(row < m_images.size())
{
m_firstImage = m_currImage = m_lastImage = m_images.begin()+row;
if(m_images.empty())
return;
(*m_currImage)->load();
m_width = DEFAULT_WIDTH<m_images.size()/2 ? DEFAULT_WIDTH : m_images.size()/2;
if(m_liveMode)
m_width = 0;
for(int i=0; i<m_width; i++)
{
m_firstImage = decrement(m_firstImage);
(*m_firstImage)->load();
m_lastImage = increment(m_lastImage);
(*m_lastImage)->load();
}
if(m_lastImage != m_firstImage)
{
QList<ImagePtr>::iterator iter = increment(m_lastImage);
while(m_firstImage != iter)
{
(*iter)->release();
iter = increment(iter);
}
}
}
}
QModelIndex ImageRingList::index(int row, int column, const QModelIndex &parent) const
{
return createIndex(row, column, m_images.at(row).get());
}
QModelIndex ImageRingList::parent(const QModelIndex &child) const
{
return QModelIndex();
}
int ImageRingList::rowCount(const QModelIndex &parent) const
{
if(parent == QModelIndex())
return m_images.size();
else
return 0;
}
int ImageRingList::columnCount(const QModelIndex &parent) const
{
return 1;
}
QVariant ImageRingList::data(const QModelIndex &index, int role) const
{
switch(role)
{
case Qt::DisplayRole:
{
QFileInfo info(m_images.at(index.row())->name());
return info.fileName();
}
default:
return QVariant();
}
}
QVariant ImageRingList::headerData(int section, Qt::Orientation orientation, int role) const
{
if(section==0 && orientation==Qt::Horizontal && role==Qt::DisplayRole)
{
return tr("Name");
}
return QVariant();
}
void ImageRingList::setFiles(const QStringList files, const QString &currentFile)
{
QThreadPool::globalInstance()->clear();
QThreadPool::globalInstance()->waitForDone();
beginResetModel();
m_images.clear();
foreach(const QString &file, files)
{
ImagePtr ptr = make_shared<Image>(file, this);
connect(ptr.get(), SIGNAL(pixmapLoaded(Image*)), this, SLOT(imageLoaded(Image*)));
m_images.append(ptr);
}
int index = files.indexOf(currentFile);
if(index < 0)
index = 0;
endResetModel();
loadFile(index);
}
QList<ImagePtr>::iterator ImageRingList::increment(QList<ImagePtr>::iterator iter)
{
iter++;
if(iter == m_images.end())
iter = m_images.begin();
return iter;
}
QList<ImagePtr>::iterator ImageRingList::decrement(QList<ImagePtr>::iterator iter)
{
if(iter == m_images.begin())
iter = m_images.end();
iter--;
return iter;
}
void ImageRingList::imageLoaded(Image *image)
{
if(image->name() == (*m_currImage)->name())
{
emit pixmapLoaded(image);
emit infoLoaded(image->info());
emit currentImageChanged(m_currImage-m_images.begin());
}
}
void ImageRingList::dirChanged(QString dir)
{
QString currentFile;
if(m_images.size())
currentFile = (*m_currImage)->name();
setDir(dir, currentFile);
if(m_images.size())
emit currentImageChanged(m_currImage-m_images.begin());
}