# HG changeset patch # User Chris Cannam # Date 1394559199 0 # Node ID a352fb986e7bc499d04f0637c8874b41826e2d2c # Parent e5f4385615ac87c8cc9d93fd453b0f91add6a486# Parent 56ba2b03508ecc2f5952a8db978360503845e711 Merge from branch tonioni diff -r e5f4385615ac -r a352fb986e7b layer/Colour3DPlotLayer.cpp --- a/layer/Colour3DPlotLayer.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/layer/Colour3DPlotLayer.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -51,6 +51,7 @@ m_binScale(LinearBinScale), m_normalizeColumns(false), m_normalizeVisibleArea(false), + m_normalizeHybrid(false), m_invertVertical(false), m_opaque(false), m_smooth(false), @@ -430,6 +431,21 @@ } void +Colour3DPlotLayer::setNormalizeHybrid(bool n) +{ + if (m_normalizeHybrid == n) return; + m_normalizeHybrid = n; + cacheInvalid(); + emit layerParametersChanged(); +} + +bool +Colour3DPlotLayer::getNormalizeHybrid() const +{ + return m_normalizeHybrid; +} + +void Colour3DPlotLayer::setNormalizeVisibleArea(bool n) { if (m_normalizeVisibleArea == n) return; @@ -882,7 +898,7 @@ { DenseThreeDimensionalModel::Column values = m_model->getColumn(col); while (values.size() < m_model->getHeight()) values.push_back(0.f); - if (!m_normalizeColumns) return values; + if (!m_normalizeColumns && !m_normalizeHybrid) return values; float colMax = 0.f, colMin = 0.f; float min = 0.f, max = 0.f; @@ -905,6 +921,13 @@ if (value != newvalue) values[y] = newvalue; } + if (m_normalizeHybrid && (colMax > 0.0)) { + float logmax = log10(colMax); + for (size_t y = 0; y < values.size(); ++y) { + values[y] *= logmax; + } + } + return values; } diff -r e5f4385615ac -r a352fb986e7b layer/Colour3DPlotLayer.h --- a/layer/Colour3DPlotLayer.h Tue Jan 28 15:02:09 2014 +0000 +++ b/layer/Colour3DPlotLayer.h Tue Mar 11 17:33:19 2014 +0000 @@ -116,12 +116,26 @@ void setBinScale(BinScale); BinScale getBinScale() const; + /** + * Normalize each column to its maximum value, independent of its + * neighbours. + */ void setNormalizeColumns(bool n); bool getNormalizeColumns() const; + /** + * Normalize each value against the maximum in the visible region. + */ void setNormalizeVisibleArea(bool n); bool getNormalizeVisibleArea() const; + /** + * Normalize each column to its maximum value, and then scale by + * the log of the (absolute) maximum value. + */ + void setNormalizeHybrid(bool n); + bool getNormalizeHybrid() const; + void setInvertVertical(bool i); bool getInvertVertical() const; @@ -168,6 +182,7 @@ BinScale m_binScale; bool m_normalizeColumns; bool m_normalizeVisibleArea; + bool m_normalizeHybrid; bool m_invertVertical; bool m_opaque; bool m_smooth; diff -r e5f4385615ac -r a352fb986e7b layer/Layer.h --- a/layer/Layer.h Tue Jan 28 15:02:09 2014 +0000 +++ b/layer/Layer.h Tue Mar 11 17:33:19 2014 +0000 @@ -131,7 +131,7 @@ virtual int getVerticalScaleWidth(View *, bool detailed, QPainter &) const = 0; - virtual void paintVerticalScale(View *, bool detailed, + virtual void paintVerticalScale(View *, bool /* detailed */, QPainter &, QRect) const { } virtual bool getCrosshairExtents(View *, QPainter &, QPoint /* cursorPos */, @@ -150,7 +150,7 @@ return ""; } - virtual QString getLabelPreceding(size_t frame) const { + virtual QString getLabelPreceding(size_t /* frame */) const { return ""; } @@ -231,7 +231,7 @@ virtual void splitStart(View *, QMouseEvent *) { } virtual void splitEnd(View *, QMouseEvent *) { } - virtual void addNote(View *v, QMouseEvent *e) { }; + virtual void addNote(View *, QMouseEvent *) { }; // Measurement rectangle (or equivalent). Unlike draw and edit, // the base Layer class can provide working implementations of diff -r e5f4385615ac -r a352fb986e7b layer/ShowLayerCommand.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/ShowLayerCommand.h Tue Mar 11 17:33:19 2014 +0000 @@ -0,0 +1,42 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _SHOW_LAYER_COMMAND_H_ +#define _SHOW_LAYER_COMMAND_H_ + +#include "base/Command.h" + +class ShowLayerCommand : public Command +{ +public: + ShowLayerCommand(View *view, Layer *layer, bool show, QString commandName) : + m_view(view), m_layer(layer), m_show(show), m_name(commandName) { } + void execute() { + m_layer->showLayer(m_view, m_show); + } + void unexecute() { + m_layer->showLayer(m_view, !m_show); + } + QString getName() const { + return m_name; + } +protected: + View *m_view; + Layer *m_layer; + bool m_show; + QString m_name; +}; + +#endif diff -r e5f4385615ac -r a352fb986e7b layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/layer/SpectrogramLayer.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -75,6 +75,7 @@ m_binDisplay(AllBins), m_normalizeColumns(false), m_normalizeVisibleArea(false), + m_normalizeHybrid(false), m_lastEmittedZoomStep(-1), m_synchronous(false), m_haveDetailedScale(false), @@ -951,6 +952,24 @@ } void +SpectrogramLayer::setNormalizeHybrid(bool n) +{ + if (m_normalizeHybrid == n) return; + + invalidateImageCaches(); + invalidateMagnitudes(); + m_normalizeHybrid = n; + + emit layerParametersChanged(); +} + +bool +SpectrogramLayer::getNormalizeHybrid() const +{ + return m_normalizeHybrid; +} + +void SpectrogramLayer::setNormalizeVisibleArea(bool n) { SVDEBUG << "SpectrogramLayer::setNormalizeVisibleArea(" << n @@ -1245,50 +1264,6 @@ } float -SpectrogramLayer::getInputForDisplayValue(unsigned char uc) const -{ - //!!! unused - - int value = uc; - float input; - - //!!! incorrect for normalizing visible area (and also out of date) - - switch (m_colourScale) { - - default: - case LinearColourScale: - input = float(value - 1) / 255.0 / (m_normalizeColumns ? 1 : 50); - break; - - case MeterColourScale: - input = AudioLevel::preview_to_multiplier(value - 1, 255) - / (m_normalizeColumns ? 1.0 : 50.0); - break; - - case dBSquaredColourScale: - input = float(value - 1) / 255.0; - input = (input * 80.0) - 80.0; - input = powf(10.0, input) / 20.0; - value = int(input); - break; - - case dBColourScale: - input = float(value - 1) / 255.0; - input = (input * 80.0) - 80.0; - input = powf(10.0, input) / 20.0; - value = int(input); - break; - - case PhaseColourScale: - input = float(value - 128) * M_PI / 127.0; - break; - } - - return input; -} - -float SpectrogramLayer::getEffectiveMinFrequency() const { int sr = m_model->getSampleRate(); @@ -2556,6 +2531,14 @@ fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1); } else if (m_normalizeColumns) { fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); + } else if (m_normalizeHybrid) { + fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); + float max = fft->getMaximumMagnitudeAt(sx); + if (max > 0.f) { + for (int i = minbin; i <= maxbin; ++i) { + values[i - minbin] *= log10(max); + } + } } else { fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); } @@ -2574,7 +2557,7 @@ float value = values[bin - minbin]; if (m_colourScale != PhaseColourScale) { - if (!m_normalizeColumns) { + if (!m_normalizeColumns && !m_normalizeHybrid) { value /= (m_fftSize/2.f); } mag.sample(value); @@ -2715,6 +2698,14 @@ fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); } else if (m_normalizeColumns) { fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); + } else if (m_normalizeHybrid) { + fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); + float max = fft->getMaximumMagnitudeAt(sx); + for (int i = minbin; i <= maxbin; ++i) { + if (max > 0.f) { + autoarray[i - minbin] *= log10(max); + } + } } else { fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); } @@ -2723,7 +2714,7 @@ SVDEBUG << "Retrieving column " << sx << " from peaks cache" << endl; #endif c = sourceModel->getColumn(sx); - if (m_normalizeColumns) { + if (m_normalizeColumns || m_normalizeHybrid) { for (int y = 0; y < h; ++y) { if (c[y] > columnMax) columnMax = c[y]; } @@ -2823,9 +2814,12 @@ float peak = peaks[y]; if (m_colourScale != PhaseColourScale && - m_normalizeColumns && + (m_normalizeColumns || m_normalizeHybrid) && columnMax > 0.f) { peak /= columnMax; + if (m_normalizeHybrid) { + peak *= log10(columnMax); + } } unsigned char peakpix = getDisplayValue(v, peak); diff -r e5f4385615ac -r a352fb986e7b layer/SpectrogramLayer.h --- a/layer/SpectrogramLayer.h Tue Jan 28 15:02:09 2014 +0000 +++ b/layer/SpectrogramLayer.h Tue Mar 11 17:33:19 2014 +0000 @@ -170,13 +170,27 @@ */ void setBinDisplay(BinDisplay); BinDisplay getBinDisplay() const; - + + /** + * Normalize each column to its maximum value, independent of its + * neighbours. + */ void setNormalizeColumns(bool n); bool getNormalizeColumns() const; + /** + * Normalize each value against the maximum in the visible region. + */ void setNormalizeVisibleArea(bool n); bool getNormalizeVisibleArea() const; + /** + * Normalize each column to its maximum value, and then scale by + * the log of the (absolute) maximum value. + */ + void setNormalizeHybrid(bool n); + bool getNormalizeHybrid() const; + void setColourMap(int map); int getColourMap() const; @@ -260,6 +274,7 @@ BinDisplay m_binDisplay; bool m_normalizeColumns; bool m_normalizeVisibleArea; + bool m_normalizeHybrid; int m_lastEmittedZoomStep; bool m_synchronous; @@ -320,7 +335,6 @@ void rotatePalette(int distance); unsigned char getDisplayValue(View *v, float input) const; - float getInputForDisplayValue(unsigned char uc) const; int getColourScaleWidth(QPainter &) const; diff -r e5f4385615ac -r a352fb986e7b layer/TimeValueLayer.cpp --- a/layer/TimeValueLayer.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/layer/TimeValueLayer.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -972,7 +972,7 @@ i != points.end(); ++i) { if (m_derivative && i == points.begin()) continue; - + const SparseTimeValueModel::Point &p(*i); float value = p.value; @@ -987,6 +987,10 @@ bool gap = false; if (m_plotStyle == PlotDiscreteCurves) { + if (value == 0.0) { + // Treat zeros as gaps + continue; + } gap = (p.frame > prevFrame && (p.frame - prevFrame >= m_model->getResolution() * 2)); } @@ -1000,6 +1004,7 @@ } bool haveNext = false; + float nvalue = 0.f; int nf = v->getModelsEndFrame(); int nx = v->getXForFrame(nf); int ny = y; @@ -1009,7 +1014,7 @@ if (j != points.end()) { const SparseTimeValueModel::Point &q(*j); - float nvalue = q.value; + nvalue = q.value; if (m_derivative) nvalue -= p.value; nf = q.frame; nx = v->getXForFrame(nf); @@ -1116,7 +1121,9 @@ float y1 = ny; if (m_plotStyle == PlotDiscreteCurves) { - bool nextGap = nf - p.frame >= m_model->getResolution() * 2; + bool nextGap = + (nvalue == 0.0) || + (nf - p.frame >= m_model->getResolution() * 2); if (nextGap) { x1 = x0; y1 = y0; @@ -1163,31 +1170,37 @@ paint.drawRect(x, -1, nx - x, v->height() + 1); } - QString label = p.label; - bool italic = false; + if (v->shouldShowFeatureLabels()) { - if (label == "" && - (m_plotStyle == PlotPoints || - m_plotStyle == PlotSegmentation || - m_plotStyle == PlotConnectedPoints)) { - char lc[20]; - snprintf(lc, 20, "%.3g", p.value); - label = lc; - italic = true; + QString label = p.label; + bool italic = false; + + if (label == "" && + (m_plotStyle == PlotPoints || + m_plotStyle == PlotSegmentation || + m_plotStyle == PlotConnectedPoints)) { + char lc[20]; + snprintf(lc, 20, "%.3g", p.value); + label = lc; + italic = true; + } + + if (label != "") { + // Quick test for 20px before we do the slower test using metrics + bool haveRoom = (nx > x + 20); + haveRoom = (haveRoom && + (nx > x + 6 + paint.fontMetrics().width(label))); + if (haveRoom || + (!haveNext && + (pointCount == 0 || !italic))) { + v->drawVisibleText(paint, x + 5, textY, label, + italic ? + View::OutlinedItalicText : + View::OutlinedText); + } + } } - if (label != "") { - bool haveRoom = nx > x + 6 + paint.fontMetrics().width(label); - if (haveRoom || - (!haveNext && - (pointCount == 0 || !italic))) { - v->drawVisibleText(paint, x + 5, textY, label, - italic ? - View::OutlinedItalicText : - View::OutlinedText); - } - } - prevFrame = p.frame; ++pointCount; } diff -r e5f4385615ac -r a352fb986e7b svgui.pro --- a/svgui.pro Tue Jan 28 15:02:09 2014 +0000 +++ b/svgui.pro Tue Mar 11 17:33:19 2014 +0000 @@ -5,6 +5,10 @@ include(config.pri) } !exists(config.pri) { + + CONFIG += release + DEFINES += NDEBUG BUILD_RELEASE NO_TIMING + win32-g++ { INCLUDEPATH += ../sv-dependency-builds/win32-mingw/include LIBS += -L../sv-dependency-builds/win32-mingw/lib diff -r e5f4385615ac -r a352fb986e7b view/Pane.cpp --- a/view/Pane.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/view/Pane.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -90,8 +90,10 @@ updateHeadsUpDisplay(); - -// SVDEBUG << "Pane::Pane(" << this << ") returning" << endl; + connect(this, SIGNAL(regionOutlined(QRect)), + this, SLOT(zoomToRegion(QRect))); + + cerr << "Pane::Pane(" << this << ") returning" << endl; } void @@ -357,10 +359,10 @@ bool &closeToRight) const { if (m_identifyFeatures && - m_manager && - m_manager->getToolModeFor(this) == ViewManager::EditMode && - !m_manager->getSelections().empty() && - !selectionIsBeingEdited()) { + m_manager && + m_manager->getToolModeFor(this) == ViewManager::EditMode && + !m_manager->getSelections().empty() && + !selectionIsBeingEdited()) { Selection s(getSelectionAt(m_identifyPoint.x(), closeToLeft, closeToRight)); @@ -1440,7 +1442,7 @@ int y0 = std::min(m_clickPos.y(), m_mousePos.y()); int y1 = std::max(m_clickPos.y(), m_mousePos.y()); - zoomToRegion(x0, y0, x1, y1); + emit regionOutlined(QRect(x0, y0, x1 - x0, y1 - y0)); } } else if (mode == ViewManager::SelectMode) { @@ -1452,6 +1454,7 @@ if (m_manager && m_manager->haveInProgressSelection()) { + //cerr << "JTEST: release with selection" << endl; bool exclusive; Selection selection = m_manager->getInProgressSelection(exclusive); @@ -1467,6 +1470,16 @@ m_manager->addSelection(selection); } } + else if (m_manager && !m_manager->haveInProgressSelection()) { + + //cerr << "JTEST: release without selection" << endl; + // Get frame location of mouse + int mouseFrame = getFrameForX(e->x()); + //cerr << "JTEST: frame location of click is " << mouseFrame << endl; + // Move play head to that frame location + int playbackFrame = fmax(0,mouseFrame); + m_manager->setPlaybackFrame(playbackFrame); + } update(); @@ -1792,8 +1805,13 @@ } void -Pane::zoomToRegion(int x0, int y0, int x1, int y1) +Pane::zoomToRegion(QRect r) { + int x0 = r.x(); + int y0 = r.y(); + int x1 = r.x() + r.width(); + int y1 = r.y() + r.height(); + int w = x1 - x0; long newStartFrame = getFrameForX(x0); diff -r e5f4385615ac -r a352fb986e7b view/Pane.h --- a/view/Pane.h Tue Jan 28 15:02:09 2014 +0000 +++ b/view/Pane.h Tue Mar 11 17:33:19 2014 +0000 @@ -68,6 +68,7 @@ void dropAccepted(QStringList uriList); void dropAccepted(QString text); void doubleClickSelectInvoked(size_t frame); + void regionOutlined(QRect rect); public slots: virtual void toolModeChanged(); @@ -85,6 +86,8 @@ virtual void propertyContainerSelected(View *, PropertyContainer *pc); + void zoomToRegion(QRect r); + void mouseEnteredWidget(); void mouseLeftWidget(); @@ -130,7 +133,6 @@ void dragTopLayer(QMouseEvent *e); void dragExtendSelection(QMouseEvent *e); - void zoomToRegion(int x0, int y0, int x1, int y1); void updateContextHelp(const QPoint *pos); void edgeScrollMaybe(int x); diff -r e5f4385615ac -r a352fb986e7b view/PaneStack.cpp --- a/view/PaneStack.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/view/PaneStack.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -247,11 +247,16 @@ void PaneStack::deletePane(Pane *pane) { + cerr << "PaneStack::deletePane(" << pane << ")" << endl; + std::vector::iterator i; bool found = false; + QWidget *stack = 0; + for (i = m_panes.begin(); i != m_panes.end(); ++i) { if (i->pane == pane) { + stack = i->propertyStack; m_panes.erase(i); found = true; break; @@ -262,6 +267,7 @@ for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) { if (i->pane == pane) { + stack = i->propertyStack; m_hiddenPanes.erase(i); found = true; break; @@ -276,6 +282,18 @@ emit paneAboutToBeDeleted(pane); + cerr << "PaneStack::deletePane: about to delete parent " << pane->parent() << " of pane " << pane << endl; + + // The property stack associated with the parent was initially + // created with the same parent as it, so it would be deleted when + // we delete the pane's parent in a moment -- but it may have been + // reparented depending on the layout. We'd better delete it + // separately first. (This fixes a crash on opening a new layer + // with a new unit type in it, when a long-defunct property box + // could be signalled from the unit database to tell it that a new + // unit had appeared.) + delete stack; + delete pane->parent(); if (m_currentPane == pane) { diff -r e5f4385615ac -r a352fb986e7b view/View.cpp --- a/view/View.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/view/View.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -64,12 +64,12 @@ m_manager(0), m_propertyContainer(new ViewPropertyContainer(this)) { - SVDEBUG << "View::View(" << this << ")" << endl; +// cerr << "View::View(" << this << ")" << endl; } View::~View() { -// SVDEBUG << "View::~View(" << this << ")" << endl; +// cerr << "View::~View(" << this << ")" << endl; m_deleting = true; delete m_propertyContainer; @@ -626,7 +626,15 @@ View::getSelectedLayer() { if (m_haveSelectedLayer && !m_layers.empty()) { - return getLayer(getLayerCount() - 1); + int n = getLayerCount(); + while (n > 0) { + --n; + Layer *layer = getLayer(n); + if (!(layer->isLayerDormant(this))) { + return layer; + } + } + return 0; } else { return 0; } @@ -2407,7 +2415,11 @@ ViewPropertyContainer::ViewPropertyContainer(View *v) : m_v(v) { +// cerr << "ViewPropertyContainer: " << this << " is owned by View " << v << endl; connect(m_v, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), this, SIGNAL(propertyChanged(PropertyContainer::PropertyName))); } +ViewPropertyContainer::~ViewPropertyContainer() +{ +} diff -r e5f4385615ac -r a352fb986e7b view/View.h --- a/view/View.h Tue Jan 28 15:02:09 2014 +0000 +++ b/view/View.h Tue Mar 11 17:33:19 2014 +0000 @@ -200,6 +200,9 @@ virtual void drawMeasurementRect(QPainter &p, const Layer *, QRect rect, bool focus) const; + virtual bool shouldShowFeatureLabels() const { + return m_manager && m_manager->shouldShowFeatureLabels(); + } virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const { return false; } @@ -401,6 +404,8 @@ public: ViewPropertyContainer(View *v); + virtual ~ViewPropertyContainer(); + PropertyList getProperties() const { return m_v->getProperties(); } QString getPropertyLabel(const PropertyName &n) const { return m_v->getPropertyLabel(n); diff -r e5f4385615ac -r a352fb986e7b view/ViewManager.cpp --- a/view/ViewManager.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/view/ViewManager.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -43,7 +43,7 @@ m_playSelectionMode(false), m_playSoloMode(false), m_alignMode(false), - m_overlayMode(MinimalOverlays), + m_overlayMode(StandardOverlays), m_zoomWheelsEnabled(true), m_showCentreLine(true), m_illuminateLocalFeatures(true), @@ -57,9 +57,9 @@ (settings.value("overlay-mode", int(m_overlayMode)).toInt()); if (m_overlayMode != NoOverlays && - m_overlayMode != MinimalOverlays && + m_overlayMode != StandardOverlays && m_overlayMode != AllOverlays) { - m_overlayMode = MinimalOverlays; + m_overlayMode = StandardOverlays; } m_zoomWheelsEnabled = @@ -279,6 +279,7 @@ if (m_selections.getSelections() == ms.getSelections()) return; SetSelectionCommand *command = new SetSelectionCommand(this, ms); CommandHistory::getInstance()->addCommand(command); + emit selectionChangedByUser(); } size_t @@ -669,11 +670,13 @@ m_lightPalette = QApplication::palette(); } +#ifndef Q_OS_MAC if (dark) { QApplication::setPalette(m_darkPalette); } else { QApplication::setPalette(m_lightPalette); } +#endif } bool diff -r e5f4385615ac -r a352fb986e7b view/ViewManager.h --- a/view/ViewManager.h Tue Jan 28 15:02:09 2014 +0000 +++ b/view/ViewManager.h Tue Mar 11 17:33:19 2014 +0000 @@ -155,7 +155,8 @@ enum OverlayMode { NoOverlays, - MinimalOverlays, + GlobalOverlays, + StandardOverlays, AllOverlays }; void setOverlayMode(OverlayMode mode); @@ -177,7 +178,7 @@ return m_overlayMode == AllOverlays; } bool shouldShowSelectionExtents() const { - return m_overlayMode != NoOverlays; + return m_overlayMode != NoOverlays && m_overlayMode != GlobalOverlays; } bool shouldShowLayerNames() const { return m_overlayMode == AllOverlays; @@ -191,6 +192,9 @@ bool shouldIlluminateLocalFeatures() const { return m_illuminateLocalFeatures; } + bool shouldShowFeatureLabels() const { + return m_overlayMode != NoOverlays && m_overlayMode != GlobalOverlays; + } void setZoomWheelsEnabled(bool enable); bool getZoomWheelsEnabled() const { return m_zoomWheelsEnabled; } @@ -214,9 +218,14 @@ /** Emitted when the output levels change. Values in range 0.0 -> 1.0. */ void outputLevelsChanged(float left, float right); - /** Emitted when the selection has changed. */ + /** Emitted whenever the selection has changed. */ void selectionChanged(); + /** Emitted when the selection has been changed through an + * explicit selection-editing action. *Not* emitted when the + * selection has been changed through undo or redo. */ + void selectionChangedByUser(); + /** Emitted when the in-progress (rubberbanding) selection has changed. */ void inProgressSelectionChanged(); diff -r e5f4385615ac -r a352fb986e7b widgets/AudioDial.cpp --- a/widgets/AudioDial.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/widgets/AudioDial.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -231,31 +231,31 @@ c = c.light(110); } - // Scale shadow... + // Scale shadow, omitting the bottom part... shadowAngle = 2160; - c = palette().dark().color(); - for (int arc = 120; arc < 2880; arc += 240) { + c = palette().shadow().color(); + for (int i = 0; i < 5; ++i) { pen.setColor(c); paint.setPen(pen); + int arc = i * 240 + 120; paint.drawArc(scale/2, scale/2, width-scale, width-scale, shadowAngle + arc, 240); + c = c.light(110); + } + c = palette().shadow().color(); + for (int i = 0; i < 12; ++i) { + pen.setColor(c); + paint.setPen(pen); + int arc = i * 240 + 120; paint.drawArc(scale/2, scale/2, width-scale, width-scale, shadowAngle - arc, 240); - c = c.light(108); + c = c.light(110); } - // Undraw the bottom part... - - pen.setColor(palette().background().color()); - pen.setWidth(scale * 4); - paint.setPen(pen); - paint.drawArc(scale/2, scale/2, - width-scale, width-scale, -45 * 16, -92 * 16); - // Scale ends... - pen.setColor(palette().dark().color()); + pen.setColor(palette().shadow().color()); pen.setWidth(scale); paint.setPen(pen); for (int i = 0; i < numTicks; ++i) { diff -r e5f4385615ac -r a352fb986e7b widgets/KeyReference.cpp --- a/widgets/KeyReference.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/widgets/KeyReference.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -49,7 +49,7 @@ QString name = action->text(); if (overrideName != "") name = overrideName; - QString shortcut = action->shortcut().toString(); + QString shortcut = action->shortcut().toString(QKeySequence::NativeText); QString tip = action->statusTip(); registerShortcut(name, shortcut, tip); @@ -87,6 +87,13 @@ } void +KeyReference::registerAlternativeShortcut(QAction *action, QKeySequence shortcut) +{ + QString name = action->text(); + registerAlternativeShortcut(name, shortcut.toString(QKeySequence::NativeText)); +} + +void KeyReference::registerAlternativeShortcut(QString name, QString alternative) { name.replace(tr("&"), ""); @@ -102,6 +109,12 @@ } void +KeyReference::registerAlternativeShortcut(QString name, QKeySequence shortcut) +{ + registerAlternativeShortcut(name, shortcut.toString(QKeySequence::NativeText)); +} + +void KeyReference::show() { if (m_dialog) { @@ -147,7 +160,7 @@ altdesc = tr(" (%1)").arg(altdesc); } - text += QString(" %1%2 %3%4\n") + text += QString(" %1%2 %3%4\n") .arg(shortcut).arg(altdesc).arg(actionName).arg(tip); } } diff -r e5f4385615ac -r a352fb986e7b widgets/KeyReference.h --- a/widgets/KeyReference.h Tue Jan 28 15:02:09 2014 +0000 +++ b/widgets/KeyReference.h Tue Mar 11 17:33:19 2014 +0000 @@ -20,6 +20,7 @@ #include #include #include +#include class QAction; class QTextEdit; @@ -38,9 +39,11 @@ void registerShortcut(QAction *, QString overrideName = ""); void registerAlternativeShortcut(QAction *, QString alternative); + void registerAlternativeShortcut(QAction *, QKeySequence alternative); void registerShortcut(QString actionName, QString shortcut, QString tipText); void registerAlternativeShortcut(QString actionName, QString alternative); + void registerAlternativeShortcut(QString actionName, QKeySequence alternative); void show(); void hide(); diff -r e5f4385615ac -r a352fb986e7b widgets/PropertyBox.cpp --- a/widgets/PropertyBox.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/widgets/PropertyBox.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -117,7 +117,7 @@ PropertyBox::populateViewPlayFrame() { #ifdef DEBUG_PROPERTY_BOX - cerr << "PropertyBox(" << m_container << ")::populateViewPlayFrame" << endl; + cerr << "PropertyBox[" << this << ":" << m_container << "]::populateViewPlayFrame" << endl; #endif if (m_viewPlayFrame) { @@ -563,7 +563,9 @@ void PropertyBox::unitDatabaseChanged() { +#ifdef DEBUG_PROPERTY_BOX cerr << "PropertyBox[" << this << "]: unitDatabaseChanged" << endl; +#endif blockSignals(true); // cerr << "my container is " << m_container << endl; diff -r e5f4385615ac -r a352fb986e7b widgets/PropertyStack.cpp --- a/widgets/PropertyStack.cpp Tue Jan 28 15:02:09 2014 +0000 +++ b/widgets/PropertyStack.cpp Tue Mar 11 17:33:19 2014 +0000 @@ -23,6 +23,7 @@ #include "widgets/IconLoader.h" #include "base/Command.h" #include "widgets/CommandHistory.h" +#include "layer/ShowLayerCommand.h" #include #include @@ -74,6 +75,10 @@ m_client, SLOT(propertyContainerSelected(View *, PropertyContainer *))); } +PropertyStack::~PropertyStack() +{ +} + void PropertyStack::repopulate() { @@ -153,9 +158,19 @@ int PropertyStack::getContainerIndex(PropertyContainer *pc) const { - for (size_t i = 0; i < m_client->getPropertyContainerCount(); ++i) { - PropertyContainer *container = m_client->getPropertyContainer(i); - if (pc == container) return i; + // This is used to obtain an index to be passed to setCurrentIndex + // -- which is the index of the property container's box in our + // stack of boxes. That is not the same thing as the index of the + // container (i.e. the layer) in the view: the view reorders its + // containers whenever one is raised to the top, while our boxes + // remain in the same order. So we must find this container in the + // box list, not in the view. + + for (size_t i = 0; i < m_boxes.size(); ++i) { + PropertyContainer *container = m_boxes[i]->getContainer(); + if (pc == container) { + return i; + } } return false; @@ -207,27 +222,6 @@ repopulate(); } -class ShowLayerCommand : public QObject, public Command -{ -public: - ShowLayerCommand(View *view, Layer *layer, bool show, QString name) : - m_view(view), m_layer(layer), m_show(show), m_name(name) { } - void execute() { - m_layer->showLayer(m_view, m_show); - } - void unexecute() { - m_layer->showLayer(m_view, !m_show); - } - QString getName() const { - return m_name; - } -protected: - View *m_view; - Layer *m_layer; - bool m_show; - QString m_name; -}; - void PropertyStack::showLayer(bool show) { diff -r e5f4385615ac -r a352fb986e7b widgets/PropertyStack.h --- a/widgets/PropertyStack.h Tue Jan 28 15:02:09 2014 +0000 +++ b/widgets/PropertyStack.h Tue Mar 11 17:33:19 2014 +0000 @@ -31,6 +31,7 @@ public: PropertyStack(QWidget *parent, View *client); + virtual ~PropertyStack(); View *getClient() { return m_client; } bool containsContainer(PropertyContainer *container) const;