changeset 55:128ebfeeebee

* Add Insert Instant function in main window * Ensure selections and window geometry are saved in session file * Add wait cursor on session file save * Various improvements to display of texts in pane (clearer readability) * Use commands for setting properties on layers and panes (still need to batch up multiple sets on the same property) * Fix failure of spectrogram to refresh when initial part became visible * Some fixes & paint optimisations in View &c * Make curve mode for time value layers work properly when resolution == 1 * Some vague improvements for time value layer vertical scale
author Chris Cannam
date Thu, 16 Mar 2006 18:46:00 +0000
parents 8dae7f6732c1
children fedaf3ffe80a
files layer/SpectrogramLayer.cpp layer/TimeRulerLayer.cpp layer/TimeValueLayer.cpp widgets/Pane.cpp widgets/PropertyBox.cpp
diffstat 5 files changed, 151 insertions(+), 130 deletions(-) [+]
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp	Wed Mar 15 18:21:17 2006 +0000
+++ b/layer/SpectrogramLayer.cpp	Thu Mar 16 18:46:00 2006 +0000
@@ -174,13 +174,13 @@
 
 int
 SpectrogramLayer::getPropertyRangeAndValue(const PropertyName &name,
-					    int *min, int *max) const
+					   int *min, int *max) const
 {
     int deft = 0;
 
-    int throwaway;
-    if (!min) min = &throwaway;
-    if (!max) max = &throwaway;
+    int garbage0, garbage1;
+    if (!min) min = &garbage0;
+    if (!max) max = &garbage1;
 
     if (name == tr("Gain")) {
 
@@ -412,7 +412,6 @@
     } else if (name == tr("Colour Rotation")) {
 	setColourRotation(value);
     } else if (name == tr("Colour")) {
-//!!!	if (v) v->setLightBackground(value == 2);
 	switch (value) {
 	default:
 	case 0:	setColourScheme(DefaultColours); break;
@@ -582,6 +581,9 @@
 void
 SpectrogramLayer::setGain(float gain)
 {
+    std::cerr << "SpectrogramLayer::setGain(" << gain << ") (my gain is now "
+	      << m_gain << ")" << std::endl;
+
     if (m_gain == gain) return;
 
     m_mutex.lock();
@@ -874,8 +876,8 @@
 #ifdef DEBUG_SPECTROGRAM_REPAINT
 		std::cerr << "complete!" << std::endl;
 #endif
+		m_pixmapCacheInvalid = true;
 		emit modelChanged();
-		m_pixmapCacheInvalid = true;
 		delete m_updateTimer;
 		m_updateTimer = 0;
 		m_lastFillExtent = 0;
@@ -884,8 +886,8 @@
 		std::cerr << "SpectrogramLayer: emitting modelChanged("
 			  << m_lastFillExtent << "," << fillExtent << ")" << std::endl;
 #endif
+		m_pixmapCacheInvalid = true;
 		emit modelChanged(m_lastFillExtent, fillExtent);
-		m_pixmapCacheInvalid = true;
 		m_lastFillExtent = fillExtent;
 	    }
 	} else {
@@ -896,8 +898,8 @@
 		std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged("
 			  << sf << "," << m_model->getEndFrame() << ")" << std::endl;
 #endif
+		m_pixmapCacheInvalid = true;
 		emit modelChanged(sf, m_model->getEndFrame());
-		m_pixmapCacheInvalid = true;
 //	    }
 	    m_lastFillExtent = fillExtent;
 	}
@@ -1206,7 +1208,7 @@
 void
 SpectrogramLayer::Cache::resize(size_t width, size_t height)
 {
-    std::cerr << "SpectrogramLayer::Cache[" << this << "]::resize(" << width << "x" << height << ")" << std::endl;
+    std::cerr << "SpectrogramLayer::Cache[" << this << "]::resize(" << width << "x" << height << " = " << width*height << ")" << std::endl;
     
     if (m_width == width && m_height == height) return;
 
@@ -1698,6 +1700,12 @@
 void
 SpectrogramLayer::paint(View *v, QPainter &paint, QRect rect) const
 {
+    if (m_colourScheme == BlackOnWhite) {
+	v->setLightBackground(true);
+    } else {
+	v->setLightBackground(false);
+    }
+
 //    Profiler profiler("SpectrogramLayer::paint", true);
 #ifdef DEBUG_SPECTROGRAM_REPAINT
     std::cerr << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << ", pixmap cache invalid " << m_pixmapCacheInvalid << std::endl;
--- a/layer/TimeRulerLayer.cpp	Wed Mar 15 18:21:17 2006 +0000
+++ b/layer/TimeRulerLayer.cpp	Thu Mar 16 18:46:00 2006 +0000
@@ -137,8 +137,8 @@
 
     long rectStart = startFrame + (rect.x() - 100) * zoomLevel;
     long rectEnd = startFrame + (rect.x() + rect.width() + 100) * zoomLevel;
-    if (rectStart < startFrame) rectStart = startFrame;
-    if (rectEnd > endFrame) rectEnd = endFrame;
+//    if (rectStart < startFrame) rectStart = startFrame;
+//    if (rectEnd > endFrame) rectEnd = endFrame;
 
 //    std::cerr << "TimeRulerLayer::paint: calling paint.save()" << std::endl;
     paint.save();
@@ -197,6 +197,7 @@
     QRect newClipRect(oldClipRect.x() - 25, oldClipRect.y(),
 		      oldClipRect.width() + 50, oldClipRect.height());
     paint.setClipRect(newClipRect);
+    paint.setClipRect(rect);
 
     QColor greyColour(m_colour);
     if (m_colour == Qt::black) {
@@ -241,22 +242,13 @@
 
 	int tw = metrics.width(text);
 
-	paint.setPen(v->palette().background().color());
+	if (v->getLayer(0) == this) {
+	    // backmost layer, don't worry about outlining the text
+	    paint.drawText(x+2 - tw/2, y, text);
+	} else {
+	    v->drawVisibleText(paint, x+2 - tw/2, y, text, View::OutlinedText);
+	}
 
-	//!!! simple drawing function for this please
-	//!!! and need getContrastingColour() in widget, or use the
-	//palette properly -- get the base class able to draw text
-	//using the proper colour (or this technique) automatically
-	for (int dx = -1; dx <= 1; ++dx) {
-	    for (int dy = -1; dy <= 1; ++dy) {
-		if ((dx && dy) || !(dx || dy)) continue;
-		paint.drawText(x + 2 - tw / 2 + dx, y + dy, text);
-	    }
-	}
-	
-	paint.setPen(m_colour);
-	paint.drawText(x + 2 - tw / 2, y, text);
-		
 	paint.setPen(greyColour);
 
 	for (int i = 1; i < ticks; ++i) {
--- a/layer/TimeValueLayer.cpp	Wed Mar 15 18:21:17 2006 +0000
+++ b/layer/TimeValueLayer.cpp	Thu Mar 16 18:46:00 2006 +0000
@@ -406,12 +406,8 @@
 
     paint.save();
 
-    if (w > 1 &&
-	(m_plotStyle == PlotLines ||
-	 m_plotStyle == PlotCurve)) {
-	paint.setRenderHint(QPainter::Antialiasing, true);
-    }
     QPainterPath path;
+    int pointCount = 0;
     
     for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
 	 i != points.end(); ++i) {
@@ -504,14 +500,27 @@
 
 		} else {
 
-		    if (path.isEmpty()) {
-			path.moveTo(x + w/2, y);
+		    float x0 = x + float(w)/2;
+		    float x1 = nx + float(w)/2;
+		    
+		    float y0 = y;
+		    float y1 = ny;
+
+		    if (pointCount == 0) {
+			path.moveTo((x0 + x1) / 2, (y0 + y1) / 2);
 		    }
+		    ++pointCount;
 
 		    if (nx - x > 5) {
-			path.cubicTo(x + w, y, nx, ny, nx + w/2, ny);
+			path.cubicTo(x0, y0,
+				     x0, y0,
+				     (x0 + x1) / 2, (y0 + y1) / 2);
+
+			// // or
+			// path.quadTo(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
+
 		    } else {
-			path.lineTo(nx + w/2, ny);
+			path.lineTo((x0 + x1) / 2, (y0 + y1) / 2);
 		    }
 		}
 	    }
@@ -529,12 +538,13 @@
 	    paint.drawRect(x, -1, nx - x, v->height() + 1);
 	}
 
-///	if (p.label != "") {
-///	    paint.drawText(x + 5, y - paint.fontMetrics().height() + paint.fontMetrics().ascent(), p.label);
-///	}
+	if (p.label != "") {
+	    paint.drawText(x + 5, y - paint.fontMetrics().height() + paint.fontMetrics().ascent(), p.label);
+	}
     }
 
     if (m_plotStyle == PlotCurve && !path.isEmpty()) {
+	paint.setRenderHint(QPainter::Antialiasing, pointCount <= v->width());
 	paint.drawPath(path);
     }
 
@@ -547,23 +557,31 @@
 int
 TimeValueLayer::getVerticalScaleWidth(View *v, QPainter &paint) const
 {
-    return 100; //!!!
+    if (m_plotStyle == PlotSegmentation) return 0;
+    return paint.fontMetrics().width("+0.000e+00") + 15;
 }
 
 void
 TimeValueLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const
 {
     if (!m_model) return;
+    if (m_plotStyle == PlotSegmentation) return;
 
     float val = m_model->getValueMinimum();
     float inc = (m_model->getValueMaximum() - val) / 10;
 
+    char buffer[40];
+
+    int w = getVerticalScaleWidth(v, paint);
+
     while (val < m_model->getValueMaximum()) {
 	int y = getYForValue(v, val);
-	QString label = QString("%1").arg(val);
-	paint.drawLine(100 - 10, y, 100, y);
-	paint.drawText(100 - 15 - paint.fontMetrics().width(label),
-		       y - paint.fontMetrics().height() /2 + paint.fontMetrics().ascent(),
+//	QString label = QString("%1").arg(val);
+	sprintf(buffer, "%+.3e", val);
+	QString label = QString(buffer);
+	paint.drawLine(w - 5, y, w, y);//  100 - 10, y, 100, y);
+	paint.drawText(5, // 100 - 15 - paint.fontMetrics().width(label),
+		       y - paint.fontMetrics().height() + paint.fontMetrics().ascent(),
 		       label);
 	val += inc;
     }
--- a/widgets/Pane.cpp	Wed Mar 15 18:21:17 2006 +0000
+++ b/widgets/Pane.cpp	Thu Mar 16 18:46:00 2006 +0000
@@ -135,6 +135,9 @@
     const Model *waveformModel = 0; // just for reporting purposes
     int verticalScaleWidth = 0;
     
+    int fontHeight = paint.fontMetrics().height();
+    int fontAscent = paint.fontMetrics().ascent();
+
     for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
 	--vi;
 
@@ -217,6 +220,9 @@
 	break;
     }
     
+    int sampleRate = getModelsSampleRate();
+    paint.setBrush(Qt::NoBrush);
+
     if (m_centreLineVisible) {
 
 	if (hasLightBackground()) {
@@ -224,16 +230,12 @@
 	} else {
 	    paint.setPen(QColor(200, 200, 200));
 	}	
-	paint.setBrush(Qt::NoBrush);
 	paint.drawLine(width() / 2, 0, width() / 2, height() - 1);
-	
-//    QFont font(paint.font());
-//    font.setBold(true);
-//    paint.setFont(font);
 
-	int sampleRate = getModelsSampleRate();
-	int y = height() - paint.fontMetrics().height()
-	    + paint.fontMetrics().ascent() - 6;
+	paint.setPen(QColor(50, 50, 50));
+
+	int y = height() - fontHeight
+	    + fontAscent - 6;
 	
 	LayerList::iterator vi = m_layers.end();
 	
@@ -242,12 +244,12 @@
 	    switch ((*--vi)->getPreferredFrameCountPosition()) {
 		
 	    case Layer::PositionTop:
-		y = paint.fontMetrics().ascent() + 6;
+		y = fontAscent + 6;
 		break;
 		
 	    case Layer::PositionMiddle:
-		y = (height() - paint.fontMetrics().height()) / 2
-		    + paint.fontMetrics().ascent();
+		y = (height() - fontHeight) / 2
+		    + fontAscent;
 		break;
 
 	    case Layer::PositionBottom:
@@ -265,73 +267,56 @@
 	    int tw = paint.fontMetrics().width(text);
 	    int x = width()/2 - 4 - tw;
 
-	    if (hasLightBackground()) {
-		paint.setPen(palette().background().color());
-		for (int dx = -1; dx <= 1; ++dx) {
-		    for (int dy = -1; dy <= 1; ++dy) {
-			if ((dx && dy) || !(dx || dy)) continue;
-			paint.drawText(x + dx, y + dy, text);
-		    }
-		}
-		paint.setPen(QColor(50, 50, 50));
-	    } else {
-		paint.setPen(QColor(200, 200, 200));
-	    }
-
-	    paint.drawText(x, y, text);
+	    drawVisibleText(paint, x, y, text, OutlinedText);
 	}
 
 	QString text = QString("%1").arg(m_centreFrame);
 
 	int tw = paint.fontMetrics().width(text);
 	int x = width()/2 + 4;
-    
-	if (hasLightBackground()) {
-	    paint.setPen(palette().background().color());
-	    for (int dx = -1; dx <= 1; ++dx) {
-		for (int dy = -1; dy <= 1; ++dy) {
-		    if ((dx && dy) || !(dx || dy)) continue;
-		    paint.drawText(x + dx, y + dy, text);
-		}
-	    }
-	    paint.setPen(QColor(50, 50, 50));
+
+	drawVisibleText(paint, x, y, text, OutlinedText);
+
+    } else {
+
+	paint.setPen(QColor(50, 50, 50));
+    }
+
+    if (waveformModel &&
+	r.y() + r.height() >= height() - fontHeight - 6) {
+
+	size_t mainModelRate = m_manager->getMainModelSampleRate();
+	size_t playbackRate = m_manager->getPlaybackSampleRate();
+	    
+	QString srNote = "";
+
+	// Show (R) for waveform models that will be resampled on
+	// playback, and (X) for waveform models that will be played
+	// at the wrong rate because their rate differs from that of
+	// the main model.
+
+	if (sampleRate == mainModelRate) {
+	    if (sampleRate != playbackRate) srNote = " " + tr("(R)");
 	} else {
-	    paint.setPen(QColor(200, 200, 200));
+	    std::cerr << "Sample rate = " << sampleRate << ", main model rate = " << mainModelRate << std::endl;
+	    srNote = " " + tr("(X)");
 	}
-	paint.drawText(x, y, text);
 
-	if (waveformModel) {
+	QString desc = tr("%1 / %2Hz%3")
+	    .arg(RealTime::frame2RealTime(waveformModel->getEndFrame(),
+					  sampleRate)
+		 .toText(false).c_str())
+	    .arg(sampleRate)
+	    .arg(srNote);
 
-	    size_t mainModelRate = m_manager->getMainModelSampleRate();
-	    size_t playbackRate = m_manager->getPlaybackSampleRate();
-	    
-	    QString srNote = "";
+	if (r.x() < verticalScaleWidth + 5 + paint.fontMetrics().width(desc)) {
+	    drawVisibleText(paint, verticalScaleWidth + 5,
+			    height() - fontHeight + fontAscent - 6,
+			    desc, OutlinedText);
+	}
+    }
 
-	    // Show (R) for waveform models that will be resampled on
-	    // playback, and (X) for waveform models that will be
-	    // played at the wrong rate because their rate differs
-	    // from that of the main model.
-
-	    if (sampleRate == mainModelRate) {
-		if (sampleRate != playbackRate) srNote = " " + tr("(R)");
-	    } else {
-		std::cerr << "Sample rate = " << sampleRate << ", main model rate = " << mainModelRate << std::endl;
-		srNote = " " + tr("(X)");
-	    }
-
-	    QString desc = tr("%1 / %2Hz%3")
-		.arg(RealTime::frame2RealTime(waveformModel->getEndFrame(),
-					      sampleRate)
-		     .toText(false).c_str())
-		.arg(sampleRate)
-		.arg(srNote);
-
-	    paint.drawText(verticalScaleWidth + 5,
-			   //width() - paint.fontMetrics().width(desc) - 5,
-			   height() - paint.fontMetrics().height() +
-			   paint.fontMetrics().ascent() - 6,
-			   desc);
-	}
+    if (r.y() + r.height() >= height() - m_layers.size() * fontHeight - 6) {
 
 	std::vector<QString> texts;
 	int maxTextWidth = 0;
@@ -348,30 +333,28 @@
 	    } else {
 		text = layerName;
 	    }
-	    
+	
 	    texts.push_back(text);
 	    int tw = paint.fontMetrics().width(text);
 	    if (tw > maxTextWidth) maxTextWidth = tw;
 	}
-
+    
 	int lly = height() - 6;
 
-	for (int i = 0; i < texts.size(); ++i) {
+	if (r.x() + r.width() >= width() - maxTextWidth - 5) {
+	    
+	    for (int i = 0; i < texts.size(); ++i) {
 
-	    if (i == texts.size() - 1) {
-		if (m_lightBackground) {
+		if (i == texts.size() - 1) {
 		    paint.setPen(Qt::black);
-		} else {
-		    paint.setPen(Qt::white);
 		}
+		
+		drawVisibleText(paint, width() - maxTextWidth - 5,
+				lly - fontHeight + fontAscent,
+				texts[i], OutlinedText);
+		
+		lly -= fontHeight;
 	    }
-
-	    paint.drawText(width() - maxTextWidth - 5,
-			   lly - paint.fontMetrics().height() +
-			   paint.fontMetrics().ascent(),
-			   texts[i]);
-	    
-	    lly -= paint.fontMetrics().height();
 	}
     }
 
@@ -663,6 +646,8 @@
 
 //!!!	if (mode != ViewManager::DrawMode) {
 
+	if (getSelectedLayer()) {
+
 	    bool previouslyIdentifying = m_identifyFeatures;
 	    m_identifyFeatures = true;
 	    
@@ -670,6 +655,8 @@
 		m_identifyPoint != prevPoint) {
 		update();
 	    }
+	}
+
 //	}
 
 	return;
@@ -986,8 +973,8 @@
 {
     return View::toXmlString
 	(indent,
-	 QString("type=\"pane\" centreLineVisible=\"%1\" %2")
-	 .arg(m_centreLineVisible).arg(extraAttributes));
+	 QString("type=\"pane\" centreLineVisible=\"%1\" height=\"%2\" %3")
+	 .arg(m_centreLineVisible).arg(height()).arg(extraAttributes));
 }
 
 
--- a/widgets/PropertyBox.cpp	Wed Mar 15 18:21:17 2006 +0000
+++ b/widgets/PropertyBox.cpp	Thu Mar 16 18:46:00 2006 +0000
@@ -264,7 +264,11 @@
 	    m_propertyControllers[name] = cb;
 	}
 
-	if (cb->isChecked() != (value > 0)) cb->setChecked(value > 0);
+	if (cb->isChecked() != (value > 0)) {
+	    cb->blockSignals(true);
+	    cb->setChecked(value > 0);
+	    cb->blockSignals(false);
+	}
 	break;
     }
 
@@ -308,7 +312,11 @@
 	    m_propertyControllers[name] = dial;
 	}
 
-	if (dial->value() != value) dial->setValue(value);
+	if (dial->value() != value) {
+	    dial->blockSignals(true);
+	    dial->setValue(value);
+	    dial->blockSignals(false);
+	}
 	break;
     }
 
@@ -340,7 +348,11 @@
 	    m_propertyControllers[name] = cb;
 	}
 
-	if (cb->currentIndex() != value) cb->setCurrentIndex(value);
+	if (cb->currentIndex() != value) {
+	    cb->blockSignals(true);
+	    cb->setCurrentIndex(value);
+	    cb->blockSignals(false);
+	}
 
 #ifdef Q_WS_MAC
 	// Crashes on startup without this, for some reason
@@ -360,6 +372,10 @@
 {
     if (pc != m_container) return;
     
+#ifdef DEBUG_PROPERTY_BOX
+    std::cerr << "PropertyBox::propertyContainerPropertyChanged" << std::endl;
+#endif
+
     PropertyContainer::PropertyList properties = m_container->getProperties();
     size_t i;
 
@@ -386,7 +402,7 @@
     PropertyContainer::PropertyType type = m_container->getPropertyType(name);
     
     if (type != PropertyContainer::InvalidProperty) {
-	m_container->setProperty(name, value);
+	m_container->setPropertyWithCommand(name, value);
     }
 
     if (type == PropertyContainer::RangeProperty) {