Mercurial > hg > svgui
diff layer/ImageLayer.cpp @ 305:013a37723c0a
* Add support for remote files to image layer
author | Chris Cannam |
---|---|
date | Fri, 05 Oct 2007 15:52:52 +0000 |
parents | 4b7e8da8f069 |
children | 90b9cfb5b0bb |
line wrap: on
line diff
--- a/layer/ImageLayer.cpp Fri Oct 05 13:27:21 2007 +0000 +++ b/layer/ImageLayer.cpp Fri Oct 05 15:52:52 2007 +0000 @@ -21,12 +21,14 @@ #include "view/View.h" #include "data/model/ImageModel.h" +#include "data/fileio/RemoteFile.h" #include "widgets/ImageDialog.h" #include <QPainter> #include <QMouseEvent> #include <QInputDialog> +#include <QMutexLocker> #include <iostream> #include <cmath> @@ -34,6 +36,9 @@ ImageLayer::ImageMap ImageLayer::m_images; +QMutex +ImageLayer::m_imageMapMutex; + ImageLayer::ImageLayer() : Layer(), m_model(0), @@ -42,7 +47,14 @@ m_editingPoint(0, "", ""), m_editingCommand(0) { - +} + +ImageLayer::~ImageLayer() +{ + for (RemoteFileMap::iterator i = m_remoteFiles.begin(); + i != m_remoteFiles.end(); ++i) { + delete i->second; + } } void @@ -51,15 +63,21 @@ if (m_model == model) return; m_model = model; - connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged())); + connect(m_model, SIGNAL(modelChanged()), + this, SIGNAL(modelChanged())); connect(m_model, SIGNAL(modelChanged(size_t, size_t)), this, SIGNAL(modelChanged(size_t, size_t))); connect(m_model, SIGNAL(completionChanged()), this, SIGNAL(modelCompletionChanged())); +// connect(m_model, SIGNAL(modelChanged()), +// this, SLOT(checkAddRemotes())); + // std::cerr << "ImageLayer::setModel(" << model << ")" << std::endl; +// checkAddRemotes(); + emit modelReplaced(); } @@ -147,7 +165,7 @@ int width = 32; if (m_scaled[v].find(p.image) != m_scaled[v].end()) { width = m_scaled[v][p.image].width(); - std::cerr << "scaled width = " << width << std::endl; +// std::cerr << "scaled width = " << width << std::endl; } if (x >= px && x < px + width) { @@ -478,6 +496,7 @@ // Delete the images named in the view's scaled map from the // general image map as well. They can always be re-loaded // if it turns out another view still needs them. + QMutexLocker locker(&m_imageMapMutex); for (ImageMap::iterator i = m_scaled[v].begin(); i != m_scaled[v].end(); ++i) { m_images.erase(i->first); @@ -491,10 +510,15 @@ bool ImageLayer::getImageOriginalSize(QString name, QSize &size) const { +// std::cerr << "getImageOriginalSize: \"" << name.toStdString() << "\"" << std::endl; + + QMutexLocker locker(&m_imageMapMutex); if (m_images.find(name) == m_images.end()) { - m_images[name] = QImage(name); +// std::cerr << "don't have, trying to open local" << std::endl; + m_images[name] = QImage(getLocalFilename(name)); } if (m_images[name].isNull()) { +// std::cerr << "null image" << std::endl; return false; } else { size = m_images[name].size(); @@ -507,24 +531,26 @@ { bool need = false; - std::cerr << "ImageLayer::getImage(" << v << ", " << name.toStdString() << ", (" - << maxSize.width() << "x" << maxSize.height() << "))" << std::endl; +// std::cerr << "ImageLayer::getImage(" << v << ", " << name.toStdString() << ", (" +// << maxSize.width() << "x" << maxSize.height() << "))" << std::endl; if (!m_scaled[v][name].isNull() && ((m_scaled[v][name].width() == maxSize.width() && m_scaled[v][name].height() <= maxSize.height()) || (m_scaled[v][name].width() <= maxSize.width() && m_scaled[v][name].height() == maxSize.height()))) { - std::cerr << "cache hit" << std::endl; +// std::cerr << "cache hit" << std::endl; return m_scaled[v][name]; } + QMutexLocker locker(&m_imageMapMutex); + if (m_images.find(name) == m_images.end()) { - m_images[name] = QImage(name); + m_images[name] = QImage(getLocalFilename(name)); } if (m_images[name].isNull()) { - std::cerr << "null image" << std::endl; +// std::cerr << "null image" << std::endl; m_scaled[v][name] = QImage(); } else if (m_images[name].width() <= maxSize.width() && m_images[name].height() <= maxSize.height()) { @@ -588,7 +614,11 @@ bool ok = false; ImageDialog dialog(tr("Select image"), "", tr("<no label>")); + if (dialog.exec() == QDialog::Accepted) { + + checkAddRemote(dialog.getImage()); + ImageModel::ChangeImageCommand *command = new ImageModel::ChangeImageCommand (m_model, m_editingPoint, dialog.getImage(), dialog.getLabel()); @@ -672,9 +702,13 @@ label); if (dialog.exec() == QDialog::Accepted) { + + checkAddRemote(dialog.getImage()); + ImageModel::ChangeImageCommand *command = new ImageModel::ChangeImageCommand (m_model, *points.begin(), dialog.getImage(), dialog.getLabel()); + CommandHistory::getInstance()->addCommand(command); } @@ -815,6 +849,77 @@ } QString +ImageLayer::getLocalFilename(QString img) const +{ + if (m_remoteFiles.find(img) == m_remoteFiles.end()) { + checkAddRemote(img); + return img; + } + return m_remoteFiles[img]->getLocalFilename(); +} + +void +ImageLayer::checkAddRemote(QString img) const +{ + if (RemoteFile::isRemote(img)) { + + if (m_remoteFiles.find(img) != m_remoteFiles.end()) { + return; + } + + QUrl url(img); + if (RemoteFile::canHandleScheme(url)) { + RemoteFile *rf = new RemoteFile(url); + if (rf->isOK()) { + m_remoteFiles[img] = rf; + connect(rf, SIGNAL(ready()), this, SLOT(remoteFileReady())); + } else { + delete rf; + } + } + } +} + +void +ImageLayer::checkAddRemotes() +{ + const ImageModel::PointList &points(m_model->getPoints()); + + for (ImageModel::PointList::const_iterator i = points.begin(); + i != points.end(); ++i) { + + checkAddRemote((*i).image); + } +} + +void +ImageLayer::remoteFileReady() +{ +// std::cerr << "ImageLayer::remoteFileReady" << std::endl; + + RemoteFile *rf = dynamic_cast<RemoteFile *>(sender()); + if (!rf) return; + + QString img; + for (RemoteFileMap::const_iterator i = m_remoteFiles.begin(); + i != m_remoteFiles.end(); ++i) { + if (i->second == rf) { + img = i->first; +// std::cerr << "it's image \"" << img.toStdString() << "\"" << std::endl; + break; + } + } + if (img == "") return; + + QMutexLocker locker(&m_imageMapMutex); + m_images.erase(img); + for (ViewImageMap::iterator i = m_scaled.begin(); i != m_scaled.end(); ++i) { + i->second.erase(img); + const_cast<View *>(i->first)->update(); + } +} + +QString ImageLayer::toXmlString(QString indent, QString extraAttributes) const { return Layer::toXmlString(indent, extraAttributes);