diff view/View.h @ 127:89c625dda204

* Reorganising code base. This revision will not compile.
author Chris Cannam
date Mon, 31 Jul 2006 11:44:37 +0000
parents
children 33929e0c3c6b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/view/View.h	Mon Jul 31 11:44:37 2006 +0000
@@ -0,0 +1,362 @@
+/* -*- 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 _CANVAS_H_
+#define _CANVAS_H_
+
+#include <QFrame>
+#include <QProgressBar>
+
+#include "base/ZoomConstraint.h"
+#include "base/PropertyContainer.h"
+#include "base/ViewManager.h"
+#include "base/XmlExportable.h"
+
+// #define DEBUG_VIEW_WIDGET_PAINT 1
+
+class Layer;
+class ViewPropertyContainer;
+
+#include <map>
+
+/**
+ * View is the base class of widgets that display one or more
+ * overlaid views of data against a horizontal time scale. 
+ *
+ * A View may have any number of attached Layers, each of which
+ * is expected to have one data Model (although multiple views may
+ * share the same model).
+ *
+ * A View may be panned in time and zoomed, although the
+ * mechanisms for doing so (as well as any other operations and
+ * properties available) depend on the subclass.
+ */
+
+class View : public QFrame,
+	     public XmlExportable
+{
+    Q_OBJECT
+
+public:
+    /**
+     * Deleting a View does not delete any of its layers.  They should
+     * be managed elsewhere (e.g. by the Document).
+     */
+    virtual ~View();
+
+    /**
+     * Retrieve the first visible sample frame on the widget.
+     * This is a calculated value based on the centre-frame, widget
+     * width and zoom level.  The result may be negative.
+     */
+    virtual long getStartFrame() const;
+
+    /**
+     * Set the widget pan based on the given first visible frame.  The
+     * frame value may be negative.
+     */
+    virtual void setStartFrame(long);
+
+    /**
+     * Return the centre frame of the visible widget.  This is an
+     * exact value that does not depend on the zoom block size.  Other
+     * frame values (start, end) are calculated from this based on the
+     * zoom and other factors.
+     */
+    virtual size_t getCentreFrame() const { return m_centreFrame; }
+
+    /**
+     * Set the centre frame of the visible widget.
+     */
+    virtual void setCentreFrame(size_t f) { setCentreFrame(f, true); }
+
+    /**
+     * Retrieve the last visible sample frame on the widget.
+     * This is a calculated value based on the centre-frame, widget
+     * width and zoom level.
+     */
+    virtual size_t getEndFrame() const;
+
+    /**
+     * Return the pixel x-coordinate corresponding to a given sample
+     * frame (which may be negative).
+     */
+    int getXForFrame(long frame) const;
+
+    /**
+     * Return the closest frame to the given pixel x-coordinate.
+     */
+    long getFrameForX(int x) const;
+
+    /**
+     * Return the pixel y-coordinate corresponding to a given
+     * frequency, if the frequency range is as specified.  This does
+     * not imply any policy about layer frequency ranges, but it might
+     * be useful for layers to match theirs up if desired.
+     *
+     * Not thread-safe in logarithmic mode.  Call only from GUI thread.
+     */
+    float getYForFrequency(float frequency, float minFreq, float maxFreq, 
+			   bool logarithmic) const;
+
+    /**
+     * Return the closest frequency to the given pixel y-coordinate,
+     * if the frequency range is as specified.
+     *
+     * Not thread-safe in logarithmic mode.  Call only from GUI thread.
+     */
+    float getFrequencyForY(int y, float minFreq, float maxFreq,
+			   bool logarithmic) const;
+
+    /**
+     * Return the zoom level, i.e. the number of frames per pixel
+     */
+    int getZoomLevel() const;
+
+    /**
+     * Set the zoom level, i.e. the number of frames per pixel.  The
+     * centre frame will be unchanged; the start and end frames will
+     * change.
+     */
+    virtual void setZoomLevel(size_t z);
+
+    /**
+     * Zoom in or out.
+     */
+    virtual void zoom(bool in);
+
+    /**
+     * Scroll left or right by a smallish or largish amount.
+     */
+    virtual void scroll(bool right, bool lots);
+
+    virtual void addLayer(Layer *v);
+    virtual void removeLayer(Layer *v); // does not delete the layer
+    virtual int getLayerCount() const { return m_layers.size(); }
+
+    /**
+     * Return a layer, counted in stacking order.  That is, layer 0 is
+     * the bottom layer and layer "getLayerCount()-1" is the top one.
+     */
+    virtual Layer *getLayer(int n) { return m_layers[n]; }
+
+    /**
+     * Return the layer last selected by the user.  This is normally
+     * the top layer, the same as getLayer(getLayerCount()-1).
+     * However, if the user has selected the pane itself more recently
+     * than any of the layers on it, this function will return 0.  It
+     * will also return 0 if there are no layers.
+     */
+    virtual Layer *getSelectedLayer();
+    virtual const Layer *getSelectedLayer() const;
+
+    virtual void setViewManager(ViewManager *m);
+    virtual ViewManager *getViewManager() const { return m_manager; }
+
+    virtual void setFollowGlobalPan(bool f);
+    virtual bool getFollowGlobalPan() const { return m_followPan; }
+
+    virtual void setFollowGlobalZoom(bool f);
+    virtual bool getFollowGlobalZoom() const { return m_followZoom; }
+
+    virtual void setLightBackground(bool lb) { m_lightBackground = lb; }
+    virtual bool hasLightBackground() const { return m_lightBackground; }
+
+    enum TextStyle {
+	BoxedText,
+	OutlinedText
+    };
+
+    virtual void drawVisibleText(QPainter &p, int x, int y,
+				 QString text, TextStyle style);
+
+    virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const {
+	return false;
+    }
+    virtual bool shouldIlluminateLocalSelection(QPoint &, bool &, bool &) const {
+	return false;
+    }
+
+    enum PlaybackFollowMode {
+	PlaybackScrollContinuous,
+	PlaybackScrollPage,
+	PlaybackIgnore
+    };
+    virtual void setPlaybackFollow(PlaybackFollowMode m);
+    virtual PlaybackFollowMode getPlaybackFollow() const { return m_followPlay; }
+
+    typedef PropertyContainer::PropertyName PropertyName;
+
+    // We implement the PropertyContainer API, although we don't
+    // actually subclass PropertyContainer.  We have our own
+    // PropertyContainer that we can return on request that just
+    // delegates back to us.
+    virtual PropertyContainer::PropertyList getProperties() const;
+    virtual QString getPropertyLabel(const PropertyName &) const;
+    virtual PropertyContainer::PropertyType getPropertyType(const PropertyName &) const;
+    virtual int getPropertyRangeAndValue(const PropertyName &,
+					 int *min, int *max) const;
+    virtual QString getPropertyValueLabel(const PropertyName &,
+					  int value) const;
+    virtual void setProperty(const PropertyName &, int value);
+    virtual QString getPropertyContainerName() const {
+	return objectName();
+    }
+    virtual QString getPropertyContainerIconName() const = 0;
+
+    virtual size_t getPropertyContainerCount() const;
+
+    virtual const PropertyContainer *getPropertyContainer(size_t i) const;
+    virtual PropertyContainer *getPropertyContainer(size_t i);
+
+    virtual int getTextLabelHeight(const Layer *layer, QPainter &) const;
+
+    virtual bool getValueExtents(QString unit, float &min, float &max,
+                                 bool &log) const;
+
+    virtual QString toXmlString(QString indent = "",
+				QString extraAttributes = "") const;
+
+    size_t getModelsStartFrame() const;
+    size_t getModelsEndFrame() const;
+
+signals:
+    void propertyContainerAdded(PropertyContainer *pc);
+    void propertyContainerRemoved(PropertyContainer *pc);
+    void propertyContainerPropertyChanged(PropertyContainer *pc);
+    void propertyContainerNameChanged(PropertyContainer *pc);
+    void propertyChanged(PropertyContainer::PropertyName);
+
+    void centreFrameChanged(void *, unsigned long, bool);
+    void zoomLevelChanged(void *, unsigned long, bool);
+
+public slots:
+    virtual void modelChanged();
+    virtual void modelChanged(size_t startFrame, size_t endFrame);
+    virtual void modelCompletionChanged();
+    virtual void modelReplaced();
+    virtual void layerParametersChanged();
+    virtual void layerNameChanged();
+
+    virtual void viewManagerCentreFrameChanged(void *, unsigned long, bool);
+    virtual void viewManagerPlaybackFrameChanged(unsigned long);
+    virtual void viewManagerZoomLevelChanged(void *, unsigned long, bool);
+
+    virtual void propertyContainerSelected(View *, PropertyContainer *pc);
+
+    virtual void selectionChanged();
+    virtual void toolModeChanged();
+
+protected:
+    View(QWidget *, bool showProgress);
+    virtual void paintEvent(QPaintEvent *e);
+    virtual void drawSelections(QPainter &);
+    virtual bool shouldLabelSelections() const { return true; }
+
+    typedef std::vector<Layer *> LayerList;
+
+    int getModelsSampleRate() const;
+    bool areLayersScrollable() const;
+    LayerList getScrollableBackLayers(bool testChanged, bool &changed) const;
+    LayerList getNonScrollableFrontLayers(bool testChanged, bool &changed) const;
+    size_t getZoomConstraintBlockSize(size_t blockSize,
+				      ZoomConstraint::RoundingDirection dir =
+				      ZoomConstraint::RoundNearest) const;
+
+    bool setCentreFrame(size_t f, bool doEmit);
+
+    void checkProgress(void *object);
+
+    size_t              m_centreFrame;
+    int                 m_zoomLevel;
+    bool                m_followPan;
+    bool                m_followZoom;
+    PlaybackFollowMode  m_followPlay;
+    size_t              m_playPointerFrame;
+    bool                m_lightBackground;
+    bool                m_showProgress;
+
+    QPixmap            *m_cache;
+    size_t              m_cacheCentreFrame;
+    int                 m_cacheZoomLevel;
+    bool                m_selectionCached;
+
+    bool                m_deleting;
+
+    LayerList           m_layers; // I don't own these, but see dtor note above
+    bool                m_haveSelectedLayer;
+
+    // caches for use in getScrollableBackLayers, getNonScrollableFrontLayers
+    mutable LayerList m_lastScrollableBackLayers;
+    mutable LayerList m_lastNonScrollableBackLayers;
+
+    class LayerProgressBar : public QProgressBar {
+    public:
+	LayerProgressBar(QWidget *parent);
+	virtual QString text() const { return m_text; }
+	virtual void setText(QString text) { m_text = text; }
+    protected:
+	QString m_text;
+    };
+
+    typedef std::map<Layer *, LayerProgressBar *> ProgressMap;
+    ProgressMap m_progressBars; // I own the ProgressBars
+
+    ViewManager *m_manager; // I don't own this
+    ViewPropertyContainer *m_propertyContainer; // I own this
+};
+
+
+// Use this for delegation, because we can't subclass from
+// PropertyContainer (which is a QObject) ourselves because of
+// ambiguity with QFrame parent
+
+class ViewPropertyContainer : public PropertyContainer
+{
+    Q_OBJECT
+
+public:
+    ViewPropertyContainer(View *v);
+    PropertyList getProperties() const { return m_v->getProperties(); }
+    QString getPropertyLabel(const PropertyName &n) const {
+        return m_v->getPropertyLabel(n);
+    }
+    PropertyType getPropertyType(const PropertyName &n) const {
+	return m_v->getPropertyType(n);
+    }
+    int getPropertyRangeAndValue(const PropertyName &n, int *min, int *max) const {
+	return m_v->getPropertyRangeAndValue(n, min, max);
+    }
+    QString getPropertyValueLabel(const PropertyName &n, int value) const {
+	return m_v->getPropertyValueLabel(n, value);
+    }
+    QString getPropertyContainerName() const {
+	return m_v->getPropertyContainerName();
+    }
+    QString getPropertyContainerIconName() const {
+	return m_v->getPropertyContainerIconName();
+    }
+
+public slots:
+    virtual void setProperty(const PropertyName &n, int value) {
+	m_v->setProperty(n, value);
+    }
+
+protected:
+    View *m_v;
+};
+
+#endif
+