Mercurial > hg > svgui
changeset 304:4b7e8da8f069
* More work on image layer display &c
author | Chris Cannam |
---|---|
date | Fri, 05 Oct 2007 13:27:21 +0000 |
parents | 46faec7aae12 |
children | 013a37723c0a |
files | layer/ImageLayer.cpp layer/ImageLayer.h widgets/ImageDialog.cpp widgets/ImageDialog.h |
diffstat | 4 files changed, 220 insertions(+), 93 deletions(-) [+] |
line wrap: on
line diff
--- a/layer/ImageLayer.cpp Thu Oct 04 16:34:11 2007 +0000 +++ b/layer/ImageLayer.cpp Fri Oct 05 13:27:21 2007 +0000 @@ -110,8 +110,7 @@ bool ImageLayer::isLayerScrollable(const View *v) const { - QPoint discard; - return !v->shouldIlluminateLocalFeatures(this, discard); + return true; } @@ -120,31 +119,43 @@ { if (!m_model) return ImageModel::PointList(); - std::cerr << "ImageLayer::getLocalPoints(" << x << "," << y << "):"; - - long frame0 = v->getFrameForX(-150); - long frame1 = v->getFrameForX(v->width() + 150); - - ImageModel::PointList points(m_model->getPoints(frame0, frame1)); +// std::cerr << "ImageLayer::getLocalPoints(" << x << "," << y << "):"; + const ImageModel::PointList &points(m_model->getPoints()); ImageModel::PointList rv; - //!!! need to store drawn size as well as original size for each - //image, but for now: - - for (ImageModel::PointList::iterator i = points.begin(); - i != points.end(); ++i) { + for (ImageModel::PointList::const_iterator i = points.begin(); + i != points.end(); ) { const ImageModel::Point &p(*i); + int px = v->getXForFrame(p.frame); + if (px > x) break; - int px = v->getXForFrame(p.frame); + ++i; + if (i != points.end()) { + int nx = v->getXForFrame((*i).frame); + if (nx < x) { + // as we aim not to overlap the images, if the following + // image begins to the left of a point then the current + // one may be assumed to end to the left of it as well. + continue; + } + } - if (x >= px && x < px + 100) { + // this image is a candidate, test it properly + + 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; + } + + if (x >= px && x < px + width) { rv.insert(p); } } - std::cerr << rv.size() << " point(s)" << std::endl; +// std::cerr << rv.size() << " point(s)" << std::endl; return rv; } @@ -270,31 +281,32 @@ // Profiler profiler("ImageLayer::paint", true); - int x0 = rect.left(), x1 = rect.right(); +// int x0 = rect.left(), x1 = rect.right(); + int x0 = 0, x1 = v->width(); + long frame0 = v->getFrameForX(x0); long frame1 = v->getFrameForX(x1); ImageModel::PointList points(m_model->getPoints(frame0, frame1)); if (points.empty()) return; + paint.save(); + paint.setClipRect(rect.x(), 0, rect.width(), v->height()); + QColor penColour; penColour = v->getForeground(); -// std::cerr << "ImageLayer::paint: resolution is " -// << m_model->getResolution() << " frames" << std::endl; + QColor brushColour; + brushColour = v->getBackground(); - QPoint localPos; - long illuminateFrame = -1; + int h, s, val; + brushColour.getHsv(&h, &s, &val); + brushColour.setHsv(h, s, 255, 240); - if (v->shouldIlluminateLocalFeatures(this, localPos)) { - ImageModel::PointList localPoints = getLocalPoints(v, localPos.x(), - localPos.y()); - if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame; - } + paint.setPen(penColour); + paint.setBrush(brushColour); + paint.setRenderHint(QPainter::Antialiasing, true); - paint.save(); - paint.setClipRect(rect.x(), 0, rect.width(), v->height()); - for (ImageModel::PointList::const_iterator i = points.begin(); i != points.end(); ++i) { @@ -309,67 +321,154 @@ int jx = v->getXForFrame(j->frame); if (jx < nx) nx = jx; } -/* - if (illuminateFrame == p.frame) { - paint.setBrush(penColour); - paint.setPen(v->getBackground()); - } else { - paint.setPen(penColour); - paint.setBrush(brushColour); - } -*/ - QString label = p.label; - QString imageName = p.image; - int nw = nx - x; - if (nw < 10) nw = 20; + drawImage(v, paint, p, x, nx); + } - int top = 10; - if (v->height() < 50) top = 5; - - int bottom = top; + paint.setRenderHint(QPainter::Antialiasing, false); + paint.restore(); +} - QRect labelRect; - if (label != "") { - float aspect = getImageAspect(imageName); - int iw = lrintf((v->height() - v->height()/4 - top - bottom) - * aspect); - labelRect = paint.fontMetrics().boundingRect - (QRect(0, 0, iw, v->height()/4), - Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, label); - bottom += labelRect.height() + 5; +void +ImageLayer::drawImage(View *v, QPainter &paint, const ImageModel::Point &p, + int x, int nx) const +{ + QString label = p.label; + QString imageName = p.image; + + QImage image; + QString additionalText; + + QSize imageSize; + if (!getImageOriginalSize(imageName, imageSize)) { + image = QImage(":icons/emptypage.png"); + imageSize = image.size(); + additionalText = imageName; + } + + int topMargin = 10; + int bottomMargin = 10; + int spacing = 5; + + if (v->height() < 100) { + topMargin = 5; + bottomMargin = 5; + } + + int maxBoxHeight = v->height() - topMargin - bottomMargin; + + int availableWidth = nx - x - 3; + if (availableWidth < 20) availableWidth = 20; + + QRect labelRect; + + if (label != "") { + + int likelyHeight = v->height() / 4; + + int likelyWidth = // available height times image aspect + ((maxBoxHeight - likelyHeight) * imageSize.width()) + / imageSize.height(); + + if (likelyWidth > imageSize.width()) { + likelyWidth = imageSize.width(); } - QImage image = getImage(v, - imageName, - QSize(nw, v->height() - top - bottom)); - - if (image.isNull()) { - image = QImage(":icons/emptypage.png"); + if (likelyWidth > availableWidth) { + likelyWidth = availableWidth; } - paint.setRenderHint(QPainter::Antialiasing, false); - - int boxWidth = image.width(); - - if (label != "") { - boxWidth = std::max(boxWidth, labelRect.width()); + int singleWidth = paint.fontMetrics().width(label); + if (singleWidth < availableWidth && singleWidth < likelyWidth * 2) { + likelyWidth = singleWidth + 4; } - paint.drawRect(x-1, top-1, boxWidth+1, v->height() - 2 * top +1); + labelRect = paint.fontMetrics().boundingRect + (QRect(0, 0, likelyWidth, likelyHeight), + Qt::AlignCenter | Qt::TextWordWrap, label); - paint.setRenderHint(QPainter::Antialiasing, true); - - paint.drawImage(x + (boxWidth - image.width())/2, top, image); - - paint.drawText(QRect(x, v->height() - bottom + 5, - boxWidth, labelRect.height()), - Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, - label); + labelRect.setWidth(labelRect.width() + 6); } - paint.restore(); - paint.setRenderHint(QPainter::Antialiasing, false); + if (image.isNull()) { + image = getImage(v, imageName, + QSize(availableWidth, + maxBoxHeight - labelRect.height())); + } + + int boxWidth = image.width(); + if (boxWidth < labelRect.width()) { + boxWidth = labelRect.width(); + } + + int boxHeight = image.height(); + if (label != "") { + boxHeight += labelRect.height() + spacing; + } + + int division = image.height(); + + if (additionalText != "") { + + paint.save(); + + QFont font(paint.font()); + font.setItalic(true); + paint.setFont(font); + + int tw = paint.fontMetrics().width(additionalText); + if (tw > availableWidth) { + tw = availableWidth; + } + if (boxWidth < tw) { + boxWidth = tw; + } + boxHeight += paint.fontMetrics().height(); + division += paint.fontMetrics().height(); + } + + bottomMargin = v->height() - topMargin - boxHeight; + if (bottomMargin > topMargin + v->height()/7) { + topMargin += v->height()/8; + bottomMargin -= v->height()/8; + } + + paint.drawRect(x - 1, + topMargin - 1, + boxWidth + 2, + boxHeight + 2); + + int imageY; + if (label != "") { + imageY = topMargin + labelRect.height() + spacing; + } else { + imageY = topMargin; + } + + paint.drawImage(x + (boxWidth - image.width())/2, + imageY, + image); + + if (additionalText != "") { + paint.drawText(x, + imageY + image.height() + paint.fontMetrics().ascent(), + additionalText); + paint.restore(); + } + + if (label != "") { + paint.drawLine(x, + topMargin + labelRect.height() + spacing, + x + boxWidth, + topMargin + labelRect.height() + spacing); + + paint.drawText(QRect(x, + topMargin, + boxWidth, + labelRect.height()), + Qt::AlignCenter | Qt::TextWordWrap, + label); + } } void @@ -389,14 +488,18 @@ //!!! how to reap no-longer-used images? -float -ImageLayer::getImageAspect(QString name) const +bool +ImageLayer::getImageOriginalSize(QString name, QSize &size) const { if (m_images.find(name) == m_images.end()) { m_images[name] = QImage(name); } - if (m_images[name].isNull()) return 1.f; - return float(m_images[name].width()) / float(m_images[name].height()); + if (m_images[name].isNull()) { + return false; + } else { + size = m_images[name].size(); + return true; + } } QImage @@ -404,13 +507,15 @@ { 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())) { -// std::cerr << "cache hit" << 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; return m_scaled[v][name]; } @@ -419,8 +524,11 @@ } 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()) { + m_scaled[v][name] = m_images[name]; } else { m_scaled[v][name] = m_images[name].scaled(maxSize,
--- a/layer/ImageLayer.h Thu Oct 04 16:34:11 2007 +0000 +++ b/layer/ImageLayer.h Fri Oct 05 13:27:21 2007 +0000 @@ -96,14 +96,19 @@ protected: ImageModel::PointList getLocalPoints(View *v, int x, int y) const; - float getImageAspect(QString name) const; + bool getImageOriginalSize(QString name, QSize &size) const; QImage getImage(View *v, QString name, QSize maxSize) const; + void drawImage(View *v, QPainter &paint, const ImageModel::Point &p, + int x, int nx) const; + //!!! how to reap no-longer-used images? typedef std::map<QString, QImage> ImageMap; typedef std::map<const View *, ImageMap> ViewImageMap; + + static ImageMap m_images; mutable ViewImageMap m_scaled;
--- a/widgets/ImageDialog.cpp Thu Oct 04 16:34:11 2007 +0000 +++ b/widgets/ImageDialog.cpp Fri Oct 05 13:27:21 2007 +0000 @@ -21,6 +21,8 @@ #include <QDialogButtonBox> #include <QPushButton> #include <QGroupBox> +#include <QDesktopWidget> +#include <QApplication> #include "data/fileio/FileFinder.h" @@ -53,8 +55,9 @@ subgrid->addWidget(new QLabel(tr("File:")), row, 0); m_imageEdit = new QLineEdit; - m_imageEdit->setReadOnly(true); subgrid->addWidget(m_imageEdit, row, 1, 1, 1); + connect(m_imageEdit, SIGNAL(textEdited(const QString &)), + this, SLOT(imageEditEdited(const QString &))); QPushButton *browse = new QPushButton(tr("Browse...")); connect(browse, SIGNAL(clicked()), this, SLOT(browseClicked())); @@ -73,6 +76,10 @@ m_imagePreview->setMinimumSize(QSize(100, 100)); + QDesktopWidget *desktop = QApplication::desktop(); + m_imagePreview->setMaximumSize(QSize((desktop->width() * 2) / 3, + (desktop->height() * 2) / 3)); + grid->addWidget(databox, 0, 0); grid->addWidget(previewbox, 1, 0); @@ -133,12 +140,20 @@ } void +ImageDialog::imageEditEdited(const QString &) +{ + updatePreview(); +} + +void ImageDialog::updatePreview() { if (!m_imagePreview) return; QString img = m_imageEdit->text(); + m_okButton->setEnabled(img != ""); + if (img != m_loadedImageFile) { m_loadedImage = QPixmap(img); m_loadedImageFile = img; @@ -150,13 +165,11 @@ if (m_loadedImage.isNull()) { m_imagePreview->setPixmap(QPixmap()); - m_okButton->setEnabled(false); } else { m_imagePreview->setPixmap(m_loadedImage.scaled (sz, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - m_okButton->setEnabled(true); } }