changeset 387:7aa1de571880

* juggle some files around in order to free audioio, base, and system libraries from dependency on QtGui
author Chris Cannam
date Wed, 12 Mar 2008 17:42:56 +0000
parents e6d11871e4c9
children 370aa9714ef5
files base/ColourDatabase.cpp base/ColourDatabase.h base/ColourMapper.cpp base/ColourMapper.h base/CommandHistory.cpp base/CommandHistory.h base/Exceptions.cpp base/Exceptions.h base/Preferences.cpp base/PropertyContainer.cpp base/PropertyContainer.h base/TextAbbrev.cpp base/TextAbbrev.h base/XmlExportable.cpp base/XmlExportable.h base/base.pro data/fft/FFTDataServer.cpp data/fileio/MatrixFile.cpp data/model/EditableDenseThreeDimensionalModel.cpp data/model/FFTModel.h data/model/SparseModel.h data/model/SparseOneDimensionalModel.h plugin/transform/FeatureExtractionModelTransformer.cpp plugin/transform/TransformFactory.h system/Init.cpp system/system.pro
diffstat 26 files changed, 80 insertions(+), 1798 deletions(-) [+]
line wrap: on
line diff
--- a/base/ColourDatabase.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/* -*- 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 2007 QMUL.
-    
-    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.
-*/
-
-#include "ColourDatabase.h"
-#include "XmlExportable.h"
-
-#include <QPainter>
-
-ColourDatabase
-ColourDatabase::m_instance;
-
-ColourDatabase *
-ColourDatabase::getInstance()
-{
-    return &m_instance;
-}
-
-ColourDatabase::ColourDatabase()
-{
-}
-
-int
-ColourDatabase::getColourCount() const
-{
-    return m_colours.size();
-}
-
-QString
-ColourDatabase::getColourName(int c) const
-{
-    if (c < 0 || size_t(c) >= m_colours.size()) return "";
-    return m_colours[c].name;
-}
-
-QColor
-ColourDatabase::getColour(int c) const
-{
-    if (c < 0 || size_t(c) >= m_colours.size()) return Qt::black;
-    return m_colours[c].colour;
-}
-
-QColor
-ColourDatabase::getColour(QString name) const
-{
-    for (ColourList::const_iterator i = m_colours.begin();
-         i != m_colours.end(); ++i) {
-        if (i->name == name) return i->colour;
-    }
-
-    return Qt::black;
-}
-
-int
-ColourDatabase::getColourIndex(QString name) const
-{
-    int index = 0;
-    for (ColourList::const_iterator i = m_colours.begin();
-         i != m_colours.end(); ++i) {
-        if (i->name == name) return index;
-        ++index;
-    }
-
-    return -1;
-}
-
-int
-ColourDatabase::getColourIndex(QColor c) const
-{
-    int index = 0;
-    for (ColourList::const_iterator i = m_colours.begin();
-         i != m_colours.end(); ++i) {
-        if (i->colour == c) return index;
-        ++index;
-    }
-
-    return -1;
-}
-
-bool
-ColourDatabase::useDarkBackground(int c) const
-{
-    if (c < 0 || size_t(c) >= m_colours.size()) return false;
-    return m_colours[c].darkbg;
-}
-
-void
-ColourDatabase::setUseDarkBackground(int c, bool dark)
-{
-    if (c < 0 || size_t(c) >= m_colours.size()) return;
-    if (m_colours[c].darkbg != dark) {
-        m_colours[c].darkbg = dark;
-        emit colourDatabaseChanged();
-    }
-}
-
-int
-ColourDatabase::addColour(QColor c, QString name)
-{
-    int index = 0;
-    for (ColourList::iterator i = m_colours.begin();
-         i != m_colours.end(); ++i) {
-        if (i->name == name) {
-            i->colour = c;
-            return index;
-        }
-        ++index;
-    }
-
-    ColourRec rec;
-    rec.colour = c;
-    rec.name = name;
-    rec.darkbg = false;
-    m_colours.push_back(rec);
-    emit colourDatabaseChanged();
-    return index;
-}
-
-void
-ColourDatabase::removeColour(QString name)
-{
-    for (ColourList::iterator i = m_colours.begin();
-         i != m_colours.end(); ++i) {
-        if (i->name == name) {
-            m_colours.erase(i);
-            return;
-        }
-    }
-}
-
-void
-ColourDatabase::getStringValues(int index,
-                                QString &colourName,
-                                QString &colourSpec,
-                                QString &darkbg) const
-{
-    colourName = "";
-    colourSpec = "";
-    if (index < 0 || size_t(index) >= m_colours.size()) return;
-
-    colourName = getColourName(index);
-    colourSpec = XmlExportable::encodeColour(getColour(index));
-    darkbg = useDarkBackground(index) ? "true" : "false";
-}
-
-int
-ColourDatabase::putStringValues(QString colourName,
-                                QString colourSpec,
-                                QString darkbg)
-{
-    int index = -1;
-    if (colourSpec != "") {
-	QColor colour(colourSpec);
-        index = getColourIndex(colour);
-        if (index < 0) {
-            index = addColour(colour,
-                              colourName == "" ? colourSpec : colourName);
-        }
-    } else if (colourName != "") {
-        index = getColourIndex(colourName);
-    }
-    if (index >= 0) {
-        setUseDarkBackground(index, darkbg == "true");
-    }
-    return index;
-}
-
-void
-ColourDatabase::getColourPropertyRange(int *min, int *max) const
-{
-    ColourDatabase *db = getInstance();
-    if (min) *min = 0;
-    if (max) {
-        *max = 0;
-        if (db->getColourCount() > 0) *max = db->getColourCount()-1;
-    }
-}
-
-QPixmap
-ColourDatabase::getExamplePixmap(int index, QSize size) const
-{
-    QPixmap pmap(size);
-    pmap.fill(useDarkBackground(index) ? Qt::black : Qt::white);
-    QPainter paint(&pmap);
-    QColor colour(getColour(index));
-    paint.setPen(colour);
-    paint.setBrush(colour);
-    int margin = 2;
-    if (size.width() < 4 || size.height() < 4) margin = 0;
-    else if (size.width() < 8 || size.height() < 8) margin = 1;
-    paint.drawRect(margin, margin,
-                   size.width() - margin*2 - 1, size.height() - margin*2 - 1);
-    return pmap;
-}
-
--- a/base/ColourDatabase.h	Sat Mar 01 16:17:44 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/* -*- 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 2007 QMUL.
-    
-    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 _COLOUR_DATABASE_H_
-#define _COLOUR_DATABASE_H_
-
-#include <QObject>
-#include <QString>
-#include <QColor>
-#include <QSize>
-#include <QPixmap>
-#include <vector>
-
-class ColourDatabase : public QObject
-{
-    Q_OBJECT
-
-public:
-    static ColourDatabase *getInstance();
-
-    int getColourCount() const;
-    QString getColourName(int c) const;
-    QColor getColour(int c) const;
-    QColor getColour(QString name) const;
-    int getColourIndex(QString name) const; // -1 -> not found
-    int getColourIndex(QColor c) const; // returns first index of possibly many
-    bool haveColour(QColor c) const;
-
-    bool useDarkBackground(int c) const;
-    void setUseDarkBackground(int c, bool dark);
-
-    int addColour(QColor, QString); // returns index
-    void removeColour(QString);
-
-    // returned colour is not necessarily in database
-    QColor getContrastingColour(int c) const;
-
-    // for use in XML export
-    void getStringValues(int index,
-                         QString &colourName,
-                         QString &colourSpec,
-                         QString &darkbg) const;
-
-    // for use in XML import
-    int putStringValues(QString colourName,
-                        QString colourSpec,
-                        QString darkbg);
-
-    // for use by PropertyContainer getPropertyRangeAndValue methods
-    void getColourPropertyRange(int *min, int *max) const;
-
-    QPixmap getExamplePixmap(int index, QSize size) const;
-    
-signals:
-    void colourDatabaseChanged();
-
-protected:
-    ColourDatabase();
-
-    struct ColourRec {
-        QColor colour;
-        QString name;
-        bool darkbg;
-    };
-    
-    typedef std::vector<ColourRec> ColourList;
-    ColourList m_colours;
-
-    static ColourDatabase m_instance;
-};
-
-#endif
--- a/base/ColourMapper.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,254 +0,0 @@
-/* -*- 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-2007 Chris Cannam and QMUL.
-    
-    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.
-*/
-
-#include "ColourMapper.h"
-
-#include <iostream>
-
-#include <cmath>
-
-ColourMapper::ColourMapper(int map, float min, float max) :
-    QObject(),
-    m_map(map),
-    m_min(min),
-    m_max(max)
-{
-    if (m_min == m_max) {
-        std::cerr << "WARNING: ColourMapper: min == max (== " << m_min
-                  << "), adjusting" << std::endl;
-        m_max = m_min + 1;
-    }
-}
-
-ColourMapper::~ColourMapper()
-{
-}
-
-int
-ColourMapper::getColourMapCount()
-{
-    return 11;
-}
-
-QString
-ColourMapper::getColourMapName(int n)
-{
-    if (n >= getColourMapCount()) return tr("<unknown>");
-    StandardMap map = (StandardMap)n;
-
-    switch (map) {
-    case DefaultColours:   return tr("Default");
-    case WhiteOnBlack:     return tr("White on Black");
-    case BlackOnWhite:     return tr("Black on White");
-    case RedOnBlue:        return tr("Red on Blue");
-    case YellowOnBlack:    return tr("Yellow on Black");
-    case BlueOnBlack:      return tr("Blue on Black");
-    case Sunset:           return tr("Sunset");
-    case FruitSalad:       return tr("Fruit Salad");
-    case Banded:           return tr("Banded");
-    case Highlight:        return tr("Highlight");
-    case Printer:          return tr("Printer");
-    }
-
-    return tr("<unknown>");
-}
-
-QColor
-ColourMapper::map(float value) const
-{
-    float norm = (value - m_min) / (m_max - m_min);
-    if (norm < 0.f) norm = 0.f;
-    if (norm > 1.f) norm = 1.f;
-    
-    float h = 0.f, s = 0.f, v = 0.f, r = 0.f, g = 0.f, b = 0.f;
-    bool hsv = true;
-
-//    float red = 0.f, green = 0.3333f;
-    float blue = 0.6666f, pieslice = 0.3333f;
-
-    if (m_map >= getColourMapCount()) return Qt::black;
-    StandardMap map = (StandardMap)m_map;
-
-    switch (map) {
-
-    case DefaultColours:
-        h = blue - norm * 2.f * pieslice;
-        s = 0.5f + norm/2.f;
-        v = norm;
-        break;
-
-    case WhiteOnBlack:
-        r = g = b = norm;
-        hsv = false;
-        break;
-
-    case BlackOnWhite:
-        r = g = b = 1.f - norm;
-        hsv = false;
-        break;
-
-    case RedOnBlue:
-        h = blue - pieslice/4.f + norm * (pieslice + pieslice/4.f);
-        s = 1.f;
-        v = norm;
-        break;
-
-    case YellowOnBlack:
-        h = 0.15f;
-        s = 1.f;
-        v = norm;
-        break;
-
-    case BlueOnBlack:
-        h = blue;
-        s = 1.f;
-        v = norm * 2.f;
-        if (v > 1.f) {
-            v = 1.f;
-            s = 1.f - (sqrtf(norm) - 0.707f) * 3.413f;
-            if (s < 0.f) s = 0.f;
-            if (s > 1.f) s = 1.f;
-        }
-        break;
-
-    case Sunset:
-        r = (norm - 0.24f) * 2.38f;
-        if (r > 1.f) r = 1.f;
-        if (r < 0.f) r = 0.f;
-        g = (norm - 0.64f) * 2.777f;
-        if (g > 1.f) g = 1.f;
-        if (g < 0.f) g = 0.f;
-        b = (3.6f * norm);
-        if (norm > 0.277f) b = 2.f - b;
-        if (b > 1.f) b = 1.f;
-        if (b < 0.f) b = 0.f;
-        hsv = false;
-        break;
-
-    case FruitSalad:
-        h = blue + (pieslice/6.f) - norm;
-        if (h < 0.f) h += 1.f;
-        s = 1.f;
-        v = 1.f;
-        break;
-
-    case Banded:
-        if      (norm < 0.125) return Qt::darkGreen;
-        else if (norm < 0.25)  return Qt::green;
-        else if (norm < 0.375) return Qt::darkBlue;
-        else if (norm < 0.5)   return Qt::blue;
-        else if (norm < 0.625) return Qt::darkYellow;
-        else if (norm < 0.75)  return Qt::yellow;
-        else if (norm < 0.875) return Qt::darkRed;
-        else                   return Qt::red;
-        break;
-
-    case Highlight:
-        if (norm > 0.99) return Qt::white;
-        else return Qt::darkBlue;
-
-    case Printer:
-        if (norm > 0.8) {
-            r = 1.f;
-        } else if (norm > 0.7) {
-            r = 0.9f;
-        } else if (norm > 0.6) {
-            r = 0.8f;
-        } else if (norm > 0.5) {
-            r = 0.7f;
-        } else if (norm > 0.4) {
-            r = 0.6f;
-        } else if (norm > 0.3) {
-            r = 0.5f;
-        } else if (norm > 0.2) {
-            r = 0.4f;
-        } else {
-            r = 0.f;
-        }
-        r = g = b = 1.f - r;
-        hsv = false;
-        break;
-    }
-
-    if (hsv) {
-        return QColor::fromHsvF(h, s, v);
-    } else {
-        return QColor::fromRgbF(r, g, b);
-    }
-}
-
-QColor
-ColourMapper::getContrastingColour() const
-{
-    if (m_map >= getColourMapCount()) return Qt::white;
-    StandardMap map = (StandardMap)m_map;
-
-    switch (map) {
-
-    case DefaultColours:
-        return QColor(255, 150, 50);
-
-    case WhiteOnBlack:
-        return Qt::red;
-
-    case BlackOnWhite:
-        return Qt::darkGreen;
-
-    case RedOnBlue:
-        return Qt::green;
-
-    case YellowOnBlack:
-        return QColor::fromHsv(240, 255, 255);
-
-    case BlueOnBlack:
-        return Qt::red;
-
-    case Sunset:
-        return Qt::white;
-
-    case FruitSalad:
-        return Qt::white;
-
-    case Banded:
-        return Qt::cyan;
-
-    case Highlight:
-        return Qt::red;
-
-    case Printer:
-        return Qt::red;
-    }
-
-    return Qt::white;
-}
-
-bool
-ColourMapper::hasLightBackground() const
-{
-    if (m_map >= getColourMapCount()) return false;
-    StandardMap map = (StandardMap)m_map;
-
-    switch (map) {
-
-    case BlackOnWhite:
-    case Printer:
-        return true;
-
-    default:
-        return false;
-    }
-}
-
-
--- a/base/ColourMapper.h	Sat Mar 01 16:17:44 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* -*- 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-2007 Chris Cannam and QMUL.
-    
-    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 _COLOUR_MAPPER_H_
-#define _COLOUR_MAPPER_H_
-
-#include <QObject>
-#include <QColor>
-#include <QString>
-
-/**
- * A class for mapping intensity values onto various colour maps.
- */
-
-class ColourMapper : public QObject
-{
-    Q_OBJECT
-
-public:
-    ColourMapper(int map, float minValue, float maxValue);
-    virtual ~ColourMapper();
-
-    enum StandardMap {
-        DefaultColours,
-        Sunset,
-        WhiteOnBlack,
-        BlackOnWhite,
-        RedOnBlue,
-        YellowOnBlack,
-        BlueOnBlack,
-        FruitSalad,
-        Banded,
-        Highlight,
-        Printer
-    };
-
-    int getMap() const { return m_map; }
-    float getMinValue() const { return m_min; }
-    float getMaxValue() const { return m_max; }
-
-    static int getColourMapCount();
-    static QString getColourMapName(int n);
-
-    QColor map(float value) const;
-
-    QColor getContrastingColour() const; // for cursors etc
-    bool hasLightBackground() const;
-
-protected:
-    int m_map;
-    float m_min;
-    float m_max;
-};
-
-#endif
-
--- a/base/CommandHistory.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,486 +0,0 @@
-/* -*- 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 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.
-*/
-
-/*
-   This is a modified version of a source file from the Rosegarden
-   MIDI and audio sequencer and notation editor, copyright 2000-2006
-   Chris Cannam, distributed under the GNU General Public License.
-
-   This file contains traces of the KCommandHistory class from the KDE
-   project, copyright 2000 Werner Trobin and David Faure and
-   distributed under the GNU Lesser General Public License.
-*/
-
-#include "CommandHistory.h"
-
-#include "Command.h"
-
-#include <QRegExp>
-#include <QMenu>
-#include <QToolBar>
-#include <QString>
-#include <QTimer>
-
-#include <iostream>
-
-CommandHistory *CommandHistory::m_instance = 0;
-
-CommandHistory::CommandHistory() :
-    m_undoLimit(50),
-    m_redoLimit(50),
-    m_menuLimit(15),
-    m_savedAt(0),
-    m_currentCompound(0),
-    m_executeCompound(false),
-    m_currentBundle(0),
-    m_bundleTimer(0),
-    m_bundleTimeout(5000)
-{
-    m_undoAction = new QAction(QIcon(":/icons/undo.png"), tr("&Undo"), this);
-    m_undoAction->setShortcut(tr("Ctrl+Z"));
-    m_undoAction->setStatusTip(tr("Undo the last editing operation"));
-    connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undo()));
-    
-    m_undoMenuAction = new QAction(QIcon(":/icons/undo.png"), tr("&Undo"), this);
-    connect(m_undoMenuAction, SIGNAL(triggered()), this, SLOT(undo()));
-    
-    m_undoMenu = new QMenu(tr("&Undo"));
-    m_undoMenuAction->setMenu(m_undoMenu);
-    connect(m_undoMenu, SIGNAL(triggered(QAction *)),
-	    this, SLOT(undoActivated(QAction*)));
-
-    m_redoAction = new QAction(QIcon(":/icons/redo.png"), tr("Re&do"), this);
-    m_redoAction->setShortcut(tr("Ctrl+Shift+Z"));
-    m_redoAction->setStatusTip(tr("Redo the last operation that was undone"));
-    connect(m_redoAction, SIGNAL(triggered()), this, SLOT(redo()));
-    
-    m_redoMenuAction = new QAction(QIcon(":/icons/redo.png"), tr("Re&do"), this);
-    connect(m_redoMenuAction, SIGNAL(triggered()), this, SLOT(redo()));
-
-    m_redoMenu = new QMenu(tr("Re&do"));
-    m_redoMenuAction->setMenu(m_redoMenu);
-    connect(m_redoMenu, SIGNAL(triggered(QAction *)),
-	    this, SLOT(redoActivated(QAction*)));
-}
-
-CommandHistory::~CommandHistory()
-{
-    m_savedAt = -1;
-    clearStack(m_undoStack);
-    clearStack(m_redoStack);
-
-    delete m_undoMenu;
-    delete m_redoMenu;
-}
-
-CommandHistory *
-CommandHistory::getInstance()
-{
-    if (!m_instance) m_instance = new CommandHistory();
-    return m_instance;
-}
-
-void
-CommandHistory::clear()
-{
-//    std::cerr << "CommandHistory::clear()" << std::endl;
-    closeBundle();
-    m_savedAt = -1;
-    clearStack(m_undoStack);
-    clearStack(m_redoStack);
-    updateActions();
-}
-
-void
-CommandHistory::registerMenu(QMenu *menu)
-{
-    menu->addAction(m_undoAction);
-    menu->addAction(m_redoAction);
-}
-
-void
-CommandHistory::registerToolbar(QToolBar *toolbar)
-{
-    toolbar->addAction(m_undoMenuAction);
-    toolbar->addAction(m_redoMenuAction);
-}
-
-void
-CommandHistory::addCommand(Command *command)
-{
-    if (!command) return;
-
-    if (m_currentCompound) {
-	addToCompound(command, m_executeCompound);
-	return;
-    }
-
-    addCommand(command, true);
-}
-
-void
-CommandHistory::addCommand(Command *command, bool execute, bool bundle)
-{
-    if (!command) return;
-
-    if (m_currentCompound) {
-	addToCompound(command, execute);
-	return;
-    }
-
-    if (bundle) {
-	addToBundle(command, execute);
-	return;
-    } else if (m_currentBundle) {
-	closeBundle();
-    }
-
-//    std::cerr << "CommandHistory::addCommand: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl;
-
-    // We can't redo after adding a command
-//    std::cerr << "CommandHistory::clearing redo stack" << std::endl;
-    clearStack(m_redoStack);
-
-    // can we reach savedAt?
-    if ((int)m_undoStack.size() < m_savedAt) m_savedAt = -1; // nope
-
-    m_undoStack.push(command);
-    clipCommands();
-    
-    if (execute) {
-	command->execute();
-    }
-
-    // Emit even if we aren't executing the command, because
-    // someone must have executed it for this to make any sense
-    emit commandExecuted();
-    emit commandExecuted(command);
-
-    updateActions();
-}
-
-void
-CommandHistory::addToBundle(Command *command, bool execute)
-{
-    if (m_currentBundle) {
-	if (!command || (command->getName() != m_currentBundleName)) {
-	    closeBundle();
-	}
-    }
-
-    if (!command) return;
-
-    if (!m_currentBundle) {
-	// need to addCommand before setting m_currentBundle, as addCommand
-	// with bundle false will reset m_currentBundle to 0
-	MacroCommand *mc = new MacroCommand(command->getName());
-	addCommand(mc, false);
-	m_currentBundle = mc;
-	m_currentBundleName = command->getName();
-    }
-
-    if (execute) command->execute();
-    m_currentBundle->addCommand(command);
-
-    delete m_bundleTimer;
-    m_bundleTimer = new QTimer(this);
-    connect(m_bundleTimer, SIGNAL(timeout()), this, SLOT(bundleTimerTimeout()));
-    m_bundleTimer->start(m_bundleTimeout);
-}
-
-void
-CommandHistory::closeBundle()
-{
-    m_currentBundle = 0;
-    m_currentBundleName = "";
-}
-
-void
-CommandHistory::bundleTimerTimeout()
-{
-    closeBundle();
-}
-
-void
-CommandHistory::addToCompound(Command *command, bool execute)
-{
-//    std::cerr << "CommandHistory::addToCompound: " << command->getName().toLocal8Bit().data() << std::endl;
-    if (!m_currentCompound) {
-	std::cerr << "CommandHistory::addToCompound: ERROR: no compound operation in progress!" << std::endl;
-        return;
-    }
-
-    if (execute) command->execute();
-    m_currentCompound->addCommand(command);
-}
-
-void
-CommandHistory::startCompoundOperation(QString name, bool execute)
-{
-    if (m_currentCompound) {
-	std::cerr << "CommandHistory::startCompoundOperation: ERROR: compound operation already in progress!" << std::endl;
-	std::cerr << "(name is " << m_currentCompound->getName().toLocal8Bit().data() << ")" << std::endl;
-        return;
-    }
- 
-    closeBundle();
-   
-    m_currentCompound = new MacroCommand(name);
-    m_executeCompound = execute;
-}
-
-void
-CommandHistory::endCompoundOperation()
-{
-    if (!m_currentCompound) {
-	std::cerr << "CommandHistory::endCompoundOperation: ERROR: no compound operation in progress!" << std::endl;
-        return;
-    }
-
-    MacroCommand *toAdd = m_currentCompound;
-    m_currentCompound = 0;
-
-    if (toAdd->haveCommands()) {
-
-        // We don't execute the macro command here, because we have
-        // been executing the individual commands as we went along if
-        // m_executeCompound was true.
-        addCommand(toAdd, false);
-    }
-}    
-
-void
-CommandHistory::addExecutedCommand(Command *command)
-{
-    addCommand(command, false);
-}
-
-void
-CommandHistory::addCommandAndExecute(Command *command)
-{
-    addCommand(command, true);
-}
-
-void
-CommandHistory::undo()
-{
-    if (m_undoStack.empty()) return;
-
-    closeBundle();
-
-    Command *command = m_undoStack.top();
-    command->unexecute();
-    emit commandExecuted();
-    emit commandUnexecuted(command);
-
-    m_redoStack.push(command);
-    m_undoStack.pop();
-
-    clipCommands();
-    updateActions();
-
-    if ((int)m_undoStack.size() == m_savedAt) emit documentRestored();
-}
-
-void
-CommandHistory::redo()
-{
-    if (m_redoStack.empty()) return;
-
-    closeBundle();
-
-    Command *command = m_redoStack.top();
-    command->execute();
-    emit commandExecuted();
-    emit commandExecuted(command);
-
-    m_undoStack.push(command);
-    m_redoStack.pop();
-    // no need to clip
-
-    updateActions();
-
-    if ((int)m_undoStack.size() == m_savedAt) emit documentRestored();
-}
-
-void
-CommandHistory::setUndoLimit(int limit)
-{
-    if (limit > 0 && limit != m_undoLimit) {
-        m_undoLimit = limit;
-        clipCommands();
-    }
-}
-
-void
-CommandHistory::setRedoLimit(int limit)
-{
-    if (limit > 0 && limit != m_redoLimit) {
-        m_redoLimit = limit;
-        clipCommands();
-    }
-}
-
-void
-CommandHistory::setMenuLimit(int limit)
-{
-    m_menuLimit = limit;
-    updateActions();
-}
-
-void
-CommandHistory::setBundleTimeout(int ms)
-{
-    m_bundleTimeout = ms;
-}
-
-void
-CommandHistory::documentSaved()
-{
-    closeBundle();
-    m_savedAt = m_undoStack.size();
-}
-
-void
-CommandHistory::clipCommands()
-{
-    if ((int)m_undoStack.size() > m_undoLimit) {
-	m_savedAt -= (m_undoStack.size() - m_undoLimit);
-    }
-
-    clipStack(m_undoStack, m_undoLimit);
-    clipStack(m_redoStack, m_redoLimit);
-}
-
-void
-CommandHistory::clipStack(CommandStack &stack, int limit)
-{
-    int i;
-
-    if ((int)stack.size() > limit) {
-
-	CommandStack tempStack;
-
-	for (i = 0; i < limit; ++i) {
-//	    Command *command = stack.top();
-//	    std::cerr << "CommandHistory::clipStack: Saving recent command: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl;
-	    tempStack.push(stack.top());
-	    stack.pop();
-	}
-
-	clearStack(stack);
-
-	for (i = 0; i < m_undoLimit; ++i) {
-	    stack.push(tempStack.top());
-	    tempStack.pop();
-	}
-    }
-}
-
-void
-CommandHistory::clearStack(CommandStack &stack)
-{
-    while (!stack.empty()) {
-	Command *command = stack.top();
-	// Not safe to call getName() on a command about to be deleted
-//	std::cerr << "CommandHistory::clearStack: About to delete command " << command << std::endl;
-	delete command;
-	stack.pop();
-    }
-}
-
-void
-CommandHistory::undoActivated(QAction *action)
-{
-    int pos = m_actionCounts[action];
-    for (int i = 0; i <= pos; ++i) {
-	undo();
-    }
-}
-
-void
-CommandHistory::redoActivated(QAction *action)
-{
-    int pos = m_actionCounts[action];
-    for (int i = 0; i <= pos; ++i) {
-	redo();
-    }
-}
-
-void
-CommandHistory::updateActions()
-{
-    m_actionCounts.clear();
-
-    for (int undo = 0; undo <= 1; ++undo) {
-
-	QAction *action(undo ? m_undoAction : m_redoAction);
-	QAction *menuAction(undo ? m_undoMenuAction : m_redoMenuAction);
-	QMenu *menu(undo ? m_undoMenu : m_redoMenu);
-	CommandStack &stack(undo ? m_undoStack : m_redoStack);
-
-	if (stack.empty()) {
-
-	    QString text(undo ? tr("Nothing to undo") : tr("Nothing to redo"));
-
-	    action->setEnabled(false);
-	    action->setText(text);
-
-	    menuAction->setEnabled(false);
-	    menuAction->setText(text);
-
-	} else {
-
-	    action->setEnabled(true);
-	    menuAction->setEnabled(true);
-
-	    QString commandName = stack.top()->getName();
-	    commandName.replace(QRegExp("&"), "");
-
-	    QString text = (undo ? tr("&Undo %1") : tr("Re&do %1"))
-		.arg(commandName);
-
-	    action->setText(text);
-	    menuAction->setText(text);
-	}
-
-	menu->clear();
-
-	CommandStack tempStack;
-	int j = 0;
-
-	while (j < m_menuLimit && !stack.empty()) {
-
-	    Command *command = stack.top();
-	    tempStack.push(command);
-	    stack.pop();
-
-	    QString commandName = command->getName();
-	    commandName.replace(QRegExp("&"), "");
-
-	    QString text;
-	    if (undo) text = tr("&Undo %1").arg(commandName);
-	    else      text = tr("Re&do %1").arg(commandName);
-	    
-	    QAction *action = menu->addAction(text);
-	    m_actionCounts[action] = j++;
-	}
-
-	while (!tempStack.empty()) {
-	    stack.push(tempStack.top());
-	    tempStack.pop();
-	}
-    }
-}
-
--- a/base/CommandHistory.h	Sat Mar 01 16:17:44 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/* -*- 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 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.
-*/
-
-/*
-   This is a modified version of a source file from the Rosegarden
-   MIDI and audio sequencer and notation editor, copyright 2000-2006
-   Chris Cannam, distributed under the GNU General Public License.
-
-   This file contains traces of the KCommandHistory class from the KDE
-   project, copyright 2000 Werner Trobin and David Faure and
-   distributed under the GNU Lesser General Public License.
-*/
-
-#ifndef _MULTI_VIEW_COMMAND_HISTORY_H_
-#define _MULTI_VIEW_COMMAND_HISTORY_H_
-
-#include <QObject>
-#include <QString>
-
-#include <stack>
-#include <set>
-#include <map>
-
-class Command;
-class MacroCommand;
-class QAction;
-class QMenu;
-class QToolBar;
-class QTimer;
-
-/**
- * The CommandHistory class stores a list of executed commands and
- * maintains Undo and Redo actions synchronised with those commands.
- *
- * CommandHistory allows you to associate more than one Undo and Redo
- * menu or toolbar with the same command history, and it keeps them
- * all up-to-date at once.  This makes it effective in systems where
- * multiple views may be editing the same data.
- */
-
-class CommandHistory : public QObject
-{
-    Q_OBJECT
-
-public:
-    virtual ~CommandHistory();
-
-    static CommandHistory *getInstance();
-
-    void clear();
-    
-    void registerMenu(QMenu *menu);
-    void registerToolbar(QToolBar *toolbar);
-
-    /**
-     * Add a command to the command history.
-     * 
-     * The command will normally be executed before being added; but
-     * if a compound operation is in use (see startCompoundOperation
-     * below), the execute status of the compound operation will
-     * determine whether the command is executed or not.
-     */
-    void addCommand(Command *command);
-    
-    /**
-     * Add a command to the command history.
-     *
-     * If execute is true, the command will be executed before being
-     * added.  Otherwise it will be assumed to have been already
-     * executed -- a command should not be added to the history unless
-     * its work has actually been done somehow!
-     *
-     * If a compound operation is in use (see startCompoundOperation
-     * below), the execute value passed to this method will override
-     * the execute status of the compound operation.  In this way it's
-     * possible to have a compound operation mixing both to-execute
-     * and pre-executed commands.
-     *
-     * If bundle is true, the command will be a candidate for bundling
-     * with any adjacent bundleable commands that have the same name,
-     * into a single compound command.  This is useful for small
-     * commands that may be executed repeatedly altering the same data
-     * (e.g. type text, set a parameter) whose number and extent is
-     * not known in advance.  The bundle parameter will be ignored if
-     * a compound operation is already in use.
-     */
-    void addCommand(Command *command, bool execute, bool bundle = false);
-    
-    /// Return the maximum number of items in the undo history.
-    int getUndoLimit() const { return m_undoLimit; }
-
-    /// Set the maximum number of items in the undo history.
-    void setUndoLimit(int limit);
-
-    /// Return the maximum number of items in the redo history.
-    int getRedoLimit() const { return m_redoLimit; }
-
-    /// Set the maximum number of items in the redo history.
-    void setRedoLimit(int limit);
-    
-    /// Return the maximum number of items visible in undo and redo menus.
-    int getMenuLimit() const { return m_menuLimit; }
-
-    /// Set the maximum number of items in the menus.
-    void setMenuLimit(int limit);
-
-    /// Return the time after which a bundle will be closed if nothing is added.
-    int getBundleTimeout() const { return m_bundleTimeout; }
-
-    /// Set the time after which a bundle will be closed if nothing is added.
-    void setBundleTimeout(int msec);
-
-    /// Start recording commands to batch up into a single compound command.
-    void startCompoundOperation(QString name, bool execute);
-
-    /// Finish recording commands and store the compound command.
-    void endCompoundOperation();
-
-public slots:
-    /**
-     * Checkpoint function that should be called when the document is
-     * saved.  If the undo/redo stack later returns to the point at
-     * which the document was saved, the documentRestored signal will
-     * be emitted.
-     */
-    virtual void documentSaved();
-
-    /**
-     * Add a command to the history that has already been executed,
-     * without executing it again.  Equivalent to addCommand(command, false).
-     */
-    void addExecutedCommand(Command *);
-
-    /**
-     * Add a command to the history and also execute it.  Equivalent
-     * to addCommand(command, true).
-     */
-    void addCommandAndExecute(Command *);
-
-    void undo();
-    void redo();
-
-protected slots:
-    void undoActivated(QAction *);
-    void redoActivated(QAction *);
-    void bundleTimerTimeout();
-    
-signals:
-    /**
-     * Emitted whenever a command has just been executed or
-     * unexecuted, whether by addCommand, undo, or redo.
-     */
-    void commandExecuted();
-
-    /**
-     * Emitted whenever a command has just been executed, whether by
-     * addCommand or redo.
-     */
-    void commandExecuted(Command *);
-
-    /**
-     * Emitted whenever a command has just been unexecuted, whether by
-     * addCommand or undo.
-     */
-    void commandUnexecuted(Command *);
-
-    /**
-     * Emitted when the undo/redo stack has reached the same state at
-     * which the documentSaved slot was last called.
-     */
-    void documentRestored();
-
-protected:
-    CommandHistory();
-    static CommandHistory *m_instance;
-
-    QAction *m_undoAction;
-    QAction *m_redoAction;
-    QAction *m_undoMenuAction;
-    QAction *m_redoMenuAction;
-    QMenu *m_undoMenu;
-    QMenu *m_redoMenu;
-
-    std::map<QAction *, int> m_actionCounts;
-
-    typedef std::stack<Command *> CommandStack;
-    CommandStack m_undoStack;
-    CommandStack m_redoStack;
-
-    int m_undoLimit;
-    int m_redoLimit;
-    int m_menuLimit;
-    int m_savedAt;
-
-    MacroCommand *m_currentCompound;
-    bool m_executeCompound;
-    void addToCompound(Command *command, bool execute);
-
-    MacroCommand *m_currentBundle;
-    QString m_currentBundleName;
-    QTimer *m_bundleTimer;
-    int m_bundleTimeout;
-    void addToBundle(Command *command, bool execute);
-    void closeBundle();
-    
-    void updateActions();
-
-    void clipCommands();
-
-    void clipStack(CommandStack &stack, int limit);
-    void clearStack(CommandStack &stack);
-};
-
-
-#endif
--- a/base/Exceptions.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/base/Exceptions.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -107,3 +107,18 @@
         .arg(m_directory).arg(m_required).arg(m_available).toLocal8Bit().data();
 }
 
+AllocationFailed::AllocationFailed(QString purpose) throw() :
+    m_purpose(purpose)
+{
+    std::cerr << "ERROR: Allocation failed: " << purpose.toStdString()
+              << std::endl;
+}
+
+const char *
+AllocationFailed::what() const throw()
+{
+    return QString("Allocation failed: %1")
+        .arg(m_purpose).toLocal8Bit().data();
+}
+
+
--- a/base/Exceptions.h	Sat Mar 01 16:17:44 2008 +0000
+++ b/base/Exceptions.h	Wed Mar 12 17:42:56 2008 +0000
@@ -93,4 +93,15 @@
     size_t m_available;
 };
 
+class AllocationFailed : virtual public std::exception
+{
+public:
+    AllocationFailed(QString purpose) throw();
+    virtual ~AllocationFailed() throw() { }
+    virtual const char *what() const throw();
+
+protected:
+    QString m_purpose;
+};
+
 #endif
--- a/base/Preferences.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/base/Preferences.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -23,8 +23,6 @@
 #include <QFileInfo>
 #include <QMutex>
 #include <QSettings>
-#include <QApplication>
-#include <QFont>
 
 Preferences *
 Preferences::m_instance = 0;
@@ -62,9 +60,7 @@
     m_resampleOnLoad = settings.value("resample-on-load", false).toBool();
     m_backgroundMode = BackgroundMode
         (settings.value("background-mode", int(BackgroundFromTheme)).toInt());
-    m_viewFontSize = settings.value
-        ("view-font-size", int(QApplication::font().pointSize() * 0.9))
-        .toInt();
+    m_viewFontSize = settings.value("view-font-size", 10).toInt();
     m_showSplash = settings.value("show-splash", true).toBool();
     settings.endGroup();
 
@@ -222,7 +218,7 @@
     if (name == "View Font Size") {
         if (min) *min = 3;
         if (max) *max = 48;
-        if (deflt) *deflt = int(QApplication::font().pointSize() * 0.9);
+        if (deflt) *deflt = 10;
         return int(m_viewFontSize);
     }
 
--- a/base/PropertyContainer.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/base/PropertyContainer.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -14,12 +14,8 @@
 */
 
 #include "PropertyContainer.h"
-#include "CommandHistory.h"
 #include "RangeMapper.h"
 #include "UnitDatabase.h"
-#include "ColourDatabase.h"
-
-#include <QColor>
 
 #include <iostream>
 
@@ -60,13 +56,6 @@
 QString
 PropertyContainer::getPropertyValueLabel(const PropertyName &name, int value) const
 {
-    if (getPropertyType(name) == ColourProperty) {
-        ColourDatabase *db = ColourDatabase::getInstance();
-        if (value >= 0 && size_t(value) < db->getColourCount()) {
-            return db->getColourName(value);
-        }
-    }
-
     return QString();
 }
 
@@ -82,14 +71,12 @@
     std::cerr << "WARNING: PropertyContainer[" << getPropertyContainerName().toStdString() << "]::setProperty(" << name.toStdString() << "): no implementation in subclass!" << std::endl;
 }
 
-void
-PropertyContainer::setPropertyWithCommand(const PropertyName &name, int value)
+Command *
+PropertyContainer::getSetPropertyCommand(const PropertyName &name, int value)
 {
     int currentValue = getPropertyRangeAndValue(name, 0, 0, 0);
-    if (value == currentValue) return;
-
-    CommandHistory::getInstance()->addCommand
-	(new SetPropertyCommand(this, name, value), true, true); // bundled
+    if (value == currentValue) return 0;
+    return new SetPropertyCommand(this, name, value);
 }
  
 void
@@ -107,19 +94,19 @@
     setProperty(name, value);
 }
  
-void
-PropertyContainer::setPropertyWithCommand(QString nameString, QString valueString)
+Command *
+PropertyContainer::getSetPropertyCommand(QString nameString, QString valueString)
 {
     PropertyName name;
     int value;
     if (!convertPropertyStrings(nameString, valueString, name, value)) {
-        std::cerr << "WARNING: PropertyContainer::setPropertyWithCommand(\""
+        std::cerr << "WARNING: PropertyContainer::getSetPropertyCommand(\""
                   << nameString.toStdString() << "\", \""
                   << valueString.toStdString()
                   << "\"): Name and value conversion failed" << std::endl;
-        return;
+        return 0;
     }
-    setPropertyWithCommand(name, value);
+    return getSetPropertyCommand(name, value);
 }
 
 bool
@@ -184,6 +171,7 @@
         break;
 
     case ValueProperty:
+    case ColourProperty:
     {
         int min, max;
         getPropertyRangeAndValue(name, &min, &max, 0);
@@ -196,12 +184,6 @@
         }
         break;
     }
-
-    case ColourProperty:
-        value = ColourDatabase::getInstance()->getColourIndex(valueString);
-        if (value >= 0) success = true;
-        else value = 0;
-        break;
         
     case UnitsProperty:
         value = UnitDatabase::getInstance()->getUnitId(valueString, false);
--- a/base/PropertyContainer.h	Sat Mar 01 16:17:44 2008 +0000
+++ b/base/PropertyContainer.h	Wed Mar 12 17:42:56 2008 +0000
@@ -118,10 +118,11 @@
     virtual void setProperty(const PropertyName &, int value);
 
     /**
-     * Set a property using a command, supporting undo and redo.
-     * The default implementation should work for most subclasses.
+     * Obtain a command that sets the given property, which can be
+     * added to the command history for undo/redo.  Returns NULL
+     * if the property is already set to the given value.
      */
-    virtual void setPropertyWithCommand(const PropertyName &, int value);
+    virtual Command *getSetPropertyCommand(const PropertyName &, int value);
 
     /**
      * Set a property using a fuzzy match.  Compare nameString with
@@ -141,9 +142,9 @@
     virtual void setProperty(QString nameString, QString valueString);
 
     /**
-     * As above, but using a command.
+     * As above, but returning a command.
      */
-    virtual void setPropertyWithCommand(QString nameString, QString valueString);
+    virtual Command *getSetPropertyCommand(QString nameString, QString valueString);
 
 protected:
 
--- a/base/TextAbbrev.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/* -*- 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-2007 Chris Cannam and QMUL.
-    
-    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.
-*/
-
-#include "TextAbbrev.h"
-
-#include <QFontMetrics>
-#include <QApplication>
-
-#include <iostream>
-
-QString
-TextAbbrev::getDefaultEllipsis()
-{
-    return "...";
-}
-
-int
-TextAbbrev::getFuzzLength(QString ellipsis)
-{
-    int len = ellipsis.length();
-    if (len < 3) return len + 3;
-    else if (len > 5) return len + 5;
-    else return len * 2;
-}
-
-int
-TextAbbrev::getFuzzWidth(const QFontMetrics &metrics, QString ellipsis)
-{
-    int width = metrics.width(ellipsis);
-    return width * 2;
-}
-
-QString
-TextAbbrev::abbreviateTo(QString text, int characters, Policy policy,
-                         QString ellipsis)
-{
-    switch (policy) {
-
-    case ElideEnd:
-    case ElideEndAndCommonPrefixes:
-        text = text.left(characters) + ellipsis;
-        break;
-        
-    case ElideStart:
-        text = ellipsis + text.right(characters);
-        break;
-
-    case ElideMiddle:
-        if (characters > 2) {
-            text = text.left(characters/2 + 1) + ellipsis
-                + text.right(characters - (characters/2 + 1));
-        } else {
-            text = text.left(characters) + ellipsis;
-        }
-        break;
-    }
-
-    return text;
-}
-
-QString
-TextAbbrev::abbreviate(QString text, int maxLength, Policy policy, bool fuzzy,
-                       QString ellipsis)
-{
-    if (ellipsis == "") ellipsis = getDefaultEllipsis();
-    int fl = (fuzzy ? getFuzzLength(ellipsis) : 0);
-    if (maxLength <= ellipsis.length()) maxLength = ellipsis.length() + 1;
-    if (text.length() <= maxLength + fl) return text;
-
-    int truncated = maxLength - ellipsis.length();
-    return abbreviateTo(text, truncated, policy, ellipsis);
-}
-
-QString
-TextAbbrev::abbreviate(QString text,
-                       const QFontMetrics &metrics, int &maxWidth,
-                       Policy policy, QString ellipsis)
-{
-    if (ellipsis == "") ellipsis = getDefaultEllipsis();
-
-    int tw = metrics.width(text);
-
-    if (tw <= maxWidth) {
-        maxWidth = tw;
-        return text;
-    }
-
-    int truncated = text.length();
-    QString original = text;
-
-    while (tw > maxWidth && truncated > 1) {
-
-        truncated--;
-
-        if (truncated > ellipsis.length()) {
-            text = abbreviateTo(original, truncated, policy, ellipsis);
-        } else {
-            break;
-        }
-
-        tw = metrics.width(text);
-    }
-
-    maxWidth = tw;
-    return text;
-}
-
-QStringList
-TextAbbrev::abbreviate(const QStringList &texts, int maxLength,
-                       Policy policy, bool fuzzy, QString ellipsis)
-{
-    if (policy == ElideEndAndCommonPrefixes &&
-        texts.size() > 1) {
-
-        if (ellipsis == "") ellipsis = getDefaultEllipsis();
-        int fl = (fuzzy ? getFuzzLength(ellipsis) : 0);
-        if (maxLength <= ellipsis.length()) maxLength = ellipsis.length() + 1;
-
-        int maxOrigLength = 0;
-        for (int i = 0; i < texts.size(); ++i) {
-            int len = texts[i].length();
-            if (len > maxOrigLength) maxOrigLength = len;
-        }
-        if (maxOrigLength <= maxLength + fl) return texts;
-
-        return abbreviate(elidePrefixes
-                          (texts, maxOrigLength - maxLength, ellipsis),
-                          maxLength, ElideEnd, fuzzy, ellipsis);
-    }
-
-    QStringList results;
-    for (int i = 0; i < texts.size(); ++i) {
-        results.push_back
-            (abbreviate(texts[i], maxLength, policy, fuzzy, ellipsis));
-    }
-    return results;
-}
-
-QStringList
-TextAbbrev::abbreviate(const QStringList &texts, const QFontMetrics &metrics,
-                       int &maxWidth, Policy policy, QString ellipsis)
-{
-    if (policy == ElideEndAndCommonPrefixes &&
-        texts.size() > 1) {
-
-        if (ellipsis == "") ellipsis = getDefaultEllipsis();
-
-        int maxOrigWidth = 0;
-        for (int i = 0; i < texts.size(); ++i) {
-            int w = metrics.width(texts[i]);
-            if (w > maxOrigWidth) maxOrigWidth = w;
-        }
-
-        return abbreviate(elidePrefixes(texts, metrics,
-                                        maxOrigWidth - maxWidth, ellipsis),
-                          metrics, maxWidth, ElideEnd, ellipsis);
-    }
-
-    QStringList results;
-    int maxAbbrWidth = 0;
-    for (int i = 0; i < texts.size(); ++i) {
-        int width = maxWidth;
-        QString abbr = abbreviate(texts[i], metrics, width, policy, ellipsis);
-        if (width > maxAbbrWidth) maxAbbrWidth = width;
-        results.push_back(abbr);
-    }
-    maxWidth = maxAbbrWidth;
-    return results;
-}
-
-QStringList
-TextAbbrev::elidePrefixes(const QStringList &texts,
-                          int targetReduction,
-                          QString ellipsis)
-{
-    if (texts.empty()) return texts;
-    int plen = getPrefixLength(texts);
-    int fl = getFuzzLength(ellipsis);
-    if (plen < fl) return texts;
-
-    QString prefix = texts[0].left(plen);
-    int truncated = plen;
-    if (plen >= targetReduction + fl) {
-        truncated = plen - targetReduction;
-    } else {
-        truncated = fl;
-    }
-    prefix = abbreviate(prefix, truncated, ElideEnd, false, ellipsis);
-
-    QStringList results;
-    for (int i = 0; i < texts.size(); ++i) {
-        results.push_back
-            (prefix + texts[i].right(texts[i].length() - plen));
-    }
-    return results;
-}
-
-QStringList
-TextAbbrev::elidePrefixes(const QStringList &texts,
-                          const QFontMetrics &metrics,
-                          int targetWidthReduction,
-                          QString ellipsis)
-{
-    if (texts.empty()) return texts;
-    int plen = getPrefixLength(texts);
-    int fl = getFuzzLength(ellipsis);
-    if (plen < fl) return texts;
-
-    QString prefix = texts[0].left(plen);
-    int pwid = metrics.width(prefix);
-    int twid = pwid - targetWidthReduction;
-    if (twid < metrics.width(ellipsis) * 2) twid = metrics.width(ellipsis) * 2;
-    prefix = abbreviate(prefix, metrics, twid, ElideEnd, ellipsis);
-
-    QStringList results;
-    for (int i = 0; i < texts.size(); ++i) {
-        results.push_back
-            (prefix + texts[i].right(texts[i].length() - plen));
-    }
-    return results;
-}
-
-static bool
-havePrefix(QString prefix, const QStringList &texts)
-{
-    for (int i = 1; i < texts.size(); ++i) {
-        if (!texts[i].startsWith(prefix)) return false;
-    }
-    return true;
-}
-
-int
-TextAbbrev::getPrefixLength(const QStringList &texts)
-{
-    QString reference = texts[0];
-
-    if (reference == "" || havePrefix(reference, texts)) {
-        return reference.length();
-    }
-
-    int candidate = reference.length();
-    QString splitChars(";:,./#-!()$_+=[]{}\\");
-
-    while (--candidate > 1) {
-        if (splitChars.contains(reference[candidate])) {
-            if (havePrefix(reference.left(candidate), texts)) {
-                break;
-            }
-        }
-    }
-
-//    std::cerr << "TextAbbrev::getPrefixLength: prefix length is " << candidate << std::endl;
-//    for (int i = 0; i < texts.size(); ++i) {
-//        std::cerr << texts[i].left(candidate).toStdString() << "|" << texts[i].right(texts[i].length() - candidate).toStdString() << std::endl;
-//    }
-
-    return candidate;
-}
-
--- a/base/TextAbbrev.h	Sat Mar 01 16:17:44 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/* -*- 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-2007 Chris Cannam and QMUL.
-    
-    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 _TEXT_ABBREV_H_
-#define _TEXT_ABBREV_H_
-
-#include <QString>
-#include <QStringList>
-
-class QFontMetrics;
-
-class TextAbbrev 
-{
-public:
-    enum Policy {
-        ElideEnd,
-        ElideEndAndCommonPrefixes,
-        ElideStart,
-        ElideMiddle
-    };
-
-    /**
-     * Abbreviate the given text to the given maximum length
-     * (including ellipsis), using the given abbreviation policy.  If
-     * fuzzy is true, the text will be left alone if it is "not much
-     * more than" the maximum length.
-     * 
-     * If ellipsis is non-empty, it will be used to show elisions in
-     * preference to the default (which is "...").
-     */
-    static QString abbreviate(QString text, int maxLength,
-                              Policy policy = ElideEnd,
-                              bool fuzzy = true,
-                              QString ellipsis = "");
-
-    /**
-     * Abbreviate the given text to the given maximum painted width,
-     * using the given abbreviation policy.  maxWidth is also modified
-     * so as to return the painted width of the abbreviated text.
-     *
-     * If ellipsis is non-empty, it will be used to show elisions in
-     * preference to the default (which is tr("...")).
-     */
-    static QString abbreviate(QString text,
-                              const QFontMetrics &metrics,
-                              int &maxWidth,
-                              Policy policy = ElideEnd,
-                              QString ellipsis = "");
-    
-    /**
-     * Abbreviate all of the given texts to the given maximum length,
-     * using the given abbreviation policy.  If fuzzy is true, texts
-     * that are "not much more than" the maximum length will be left
-     * alone.
-     *
-     * If ellipsis is non-empty, it will be used to show elisions in
-     * preference to the default (which is tr("...")).
-     */
-    static QStringList abbreviate(const QStringList &texts, int maxLength,
-                                  Policy policy = ElideEndAndCommonPrefixes,
-                                  bool fuzzy = true,
-                                  QString ellipsis = "");
-
-    /**
-     * Abbreviate all of the given texts to the given maximum painted
-     * width, using the given abbreviation policy.  maxWidth is also
-     * modified so as to return the maximum painted width of the
-     * abbreviated texts.
-     *
-     * If ellipsis is non-empty, it will be used to show elisions in
-     * preference to the default (which is tr("...")).
-     */
-    static QStringList abbreviate(const QStringList &texts,
-                                  const QFontMetrics &metrics,
-                                  int &maxWidth,
-                                  Policy policy = ElideEndAndCommonPrefixes,
-                                  QString ellipsis = "");
-
-protected:
-    static QString getDefaultEllipsis();
-    static int getFuzzLength(QString ellipsis);
-    static int getFuzzWidth(const QFontMetrics &metrics, QString ellipsis);
-    static QString abbreviateTo(QString text, int characters,
-                                Policy policy, QString ellipsis);
-    static QStringList elidePrefixes(const QStringList &texts,
-                                     int targetReduction,
-                                     QString ellipsis);
-    static QStringList elidePrefixes(const QStringList &texts,
-                                     const QFontMetrics &metrics,
-                                     int targetWidthReduction,
-                                     QString ellipsis);
-    static int getPrefixLength(const QStringList &texts);
-};
-
-#endif
-
--- a/base/XmlExportable.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/base/XmlExportable.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -51,18 +51,18 @@
 }
 
 QString
-XmlExportable::encodeColour(QColor c)
+XmlExportable::encodeColour(int ri, int gi, int bi)
 {
     QString r, g, b;
 
-    r.setNum(c.red(), 16);
-    if (c.red() < 16) r = "0" + r;
+    r.setNum(ri, 16);
+    if (ri < 16) r = "0" + r;
 
-    g.setNum(c.green(), 16);
-    if (c.green() < 16) g = "0" + g;
+    g.setNum(gi, 16);
+    if (gi < 16) g = "0" + g;
 
-    b.setNum(c.blue(), 16);
-    if (c.blue() < 16) b = "0" + b;
+    b.setNum(bi, 16);
+    if (bi < 16) b = "0" + b;
 
     return "#" + r + g + b;
 }
--- a/base/XmlExportable.h	Sat Mar 01 16:17:44 2008 +0000
+++ b/base/XmlExportable.h	Wed Mar 12 17:42:56 2008 +0000
@@ -17,7 +17,6 @@
 #define _XML_EXPORTABLE_H_
 
 #include <QString>
-#include <QColor>
 
 class QTextStream;
 
@@ -43,7 +42,7 @@
 
     static QString encodeEntities(QString);
 
-    static QString encodeColour(QColor); 
+    static QString encodeColour(int r, int g, int b); 
 
     static int getObjectExportId(const void *); // thread-safe
 };
--- a/base/base.pro	Sat Mar 01 16:17:44 2008 +0000
+++ b/base/base.pro	Wed Mar 12 17:42:56 2008 +0000
@@ -4,6 +4,7 @@
 load(../sv.prf)
 
 CONFIG += sv staticlib qt thread warn_on stl rtti exceptions
+QT -= gui
 
 TARGET = svbase
 
@@ -16,10 +17,7 @@
 HEADERS += AudioLevel.h \
            AudioPlaySource.h \
            Clipboard.h \
-	   ColourDatabase.h \
-	   ColourMapper.h \
            Command.h \
-           CommandHistory.h \
            Exceptions.h \
            LogRange.h \
            Pitch.h \
@@ -39,18 +37,15 @@
            Serialiser.h \
            StorageAdviser.h \
            TempDirectory.h \
-           TextAbbrev.h \
            Thread.h \
            UnitDatabase.h \
+           ViewManagerBase.h \
            Window.h \
            XmlExportable.h \
            ZoomConstraint.h
 SOURCES += AudioLevel.cpp \
            Clipboard.cpp \
-	   ColourDatabase.cpp \
-	   ColourMapper.cpp \
            Command.cpp \
-           CommandHistory.cpp \
            Exceptions.cpp \
            LogRange.cpp \
            Pitch.cpp \
@@ -67,7 +62,6 @@
            Serialiser.cpp \
            StorageAdviser.cpp \
            TempDirectory.cpp \
-           TextAbbrev.cpp \
            Thread.cpp \
            UnitDatabase.cpp \
            XmlExportable.cpp
--- a/data/fft/FFTDataServer.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/data/fft/FFTDataServer.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -27,9 +27,6 @@
 #include "base/Profiler.h"
 #include "base/Thread.h" // for debug mutex locker
 
-#include <QMessageBox>
-#include <QApplication>
-
 //#define DEBUG_FFT_SERVER 1
 //#define DEBUG_FFT_SERVER_FILL 1
 
@@ -851,19 +848,14 @@
             }
         }
 
-        if (cache) {
+        if (!cache) {
             std::cerr << "ERROR: Memory allocation failed when resizing"
                       << " FFT file cache no. " << c << " to " << width
                       << "x" << m_height << " (of total width " << m_width
                       << "): abandoning this cache" << std::endl;
+
+            throw AllocationFailed("Failed to create or resize an FFT model slice");
         }
-
-        //!!! Shouldn't be using QtGui here.  Need a better way to report this.
-        QMessageBox::critical
-            (0, QApplication::tr("FFT cache resize failed"),
-             QApplication::tr
-             ("Failed to create or resize an FFT model slice.\n"
-              "There may be insufficient memory or disc space to continue."));
     }
 
     m_caches[c] = cache;
--- a/data/fileio/MatrixFile.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/data/fileio/MatrixFile.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -32,8 +32,8 @@
 #include <QFileInfo>
 #include <QDir>
 
-//#define DEBUG_MATRIX_FILE 1
-//#define DEBUG_MATRIX_FILE_READ_SET 1
+#define DEBUG_MATRIX_FILE 1
+#define DEBUG_MATRIX_FILE_READ_SET 1
 
 #ifdef DEBUG_MATRIX_FILE_READ_SET
 #ifndef DEBUG_MATRIX_FILE
--- a/data/model/EditableDenseThreeDimensionalModel.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/data/model/EditableDenseThreeDimensionalModel.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -17,6 +17,8 @@
 
 #include <QTextStream>
 
+#include <QStringList>
+
 #include <iostream>
 
 #include <cmath>
--- a/data/model/FFTModel.h	Sat Mar 01 16:17:44 2008 +0000
+++ b/data/model/FFTModel.h	Wed Mar 12 17:42:56 2008 +0000
@@ -24,8 +24,10 @@
 
 /**
  * An implementation of DenseThreeDimensionalModel that makes FFT data
- * derived from a DenseTimeValueModel available as a generic data grid.
- * The FFT data is acquired using FFTDataServer.
+ * derived from a DenseTimeValueModel available as a generic data
+ * grid.  The FFT data is acquired using FFTDataServer.  Note that any
+ * of the accessor functions may throw AllocationFailed if a cache
+ * resize fails.
  */
 
 class FFTModel : public DenseThreeDimensionalModel
--- a/data/model/SparseModel.h	Sat Mar 01 16:17:44 2008 +0000
+++ b/data/model/SparseModel.h	Wed Mar 12 17:42:56 2008 +0000
@@ -18,7 +18,6 @@
 
 #include "Model.h"
 #include "base/Command.h"
-#include "base/CommandHistory.h"
 
 #include <iostream>
 
@@ -215,10 +214,11 @@
 	virtual void addCommand(Command *command) { addCommand(command, true); }
 
 	/**
-	 * If any points have been added or deleted, add this command
-	 * to the command history.  Otherwise delete the command.
+	 * If any points have been added or deleted, return this
+	 * command (so the caller can add it to the command history).
+	 * Otherwise delete the command.
 	 */
-	virtual void finish();
+	virtual Command *finish();
 
     protected:
 	virtual void addCommand(Command *command, bool executeFirst);
@@ -600,11 +600,11 @@
 }
 
 template <typename PointType>
-void
+Command *
 SparseModel<PointType>::EditCommand::finish()
 {
     if (!m_commands.empty()) {
-	CommandHistory::getInstance()->addCommand(this, false);
+        return this;
     } else {
         delete this;
     }
--- a/data/model/SparseOneDimensionalModel.h	Sat Mar 01 16:17:44 2008 +0000
+++ b/data/model/SparseOneDimensionalModel.h	Wed Mar 12 17:42:56 2008 +0000
@@ -20,6 +20,8 @@
 #include "base/PlayParameterRepository.h"
 #include "base/RealTime.h"
 
+#include <QStringList>
+
 struct OneDimensionalPoint
 {
 public:
--- a/plugin/transform/FeatureExtractionModelTransformer.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/plugin/transform/FeatureExtractionModelTransformer.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -21,6 +21,7 @@
 
 #include "data/model/Model.h"
 #include "base/Window.h"
+#include "base/Exceptions.h"
 #include "data/model/SparseOneDimensionalModel.h"
 #include "data/model/SparseTimeValueModel.h"
 #include "data/model/EditableDenseThreeDimensionalModel.h"
@@ -31,8 +32,6 @@
 
 #include "TransformFactory.h"
 
-#include <QMessageBox>
-
 #include <iostream>
 
 FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in,
@@ -338,13 +337,10 @@
                                    false,
                                    StorageAdviser::PrecisionCritical);
             if (!model->isOK()) {
-                QMessageBox::critical
-                    (0, tr("FFT cache failed"),
-                     tr("Failed to create the FFT model for this transform.\n"
-                        "There may be insufficient memory or disc space to continue."));
                 delete model;
                 setCompletion(100);
-                return;
+                //!!! need a better way to handle this -- previously we were using a QMessageBox but that isn't an appropriate thing to do here either
+                throw AllocationFailed("Failed to create the FFT model for this feature extraction model transformer");
             }
             model->resume();
             fftModels.push_back(model);
--- a/plugin/transform/TransformFactory.h	Sat Mar 01 16:17:44 2008 +0000
+++ b/plugin/transform/TransformFactory.h	Wed Mar 12 17:42:56 2008 +0000
@@ -20,6 +20,8 @@
 
 #include <vamp-sdk/Plugin.h>
 
+#include <QObject>
+
 #include <map>
 #include <set>
 
--- a/system/Init.cpp	Sat Mar 01 16:17:44 2008 +0000
+++ b/system/Init.cpp	Wed Mar 12 17:42:56 2008 +0000
@@ -13,9 +13,6 @@
     COPYING included with this distribution for more information.
 */
 
-#include <QApplication>
-#include <QFont>
-
 #include <iostream>
 
 #ifdef Q_WS_X11
@@ -79,15 +76,7 @@
 
 #ifdef Q_WS_WIN32
     redirectStderr();
-//    QFont fn = qApp->font();
-//    fn.setFamily("Tahoma");
-//    qApp->setFont(fn);
 #else
-#ifdef Q_WS_X11
-//    QFont fn = qApp->font();
-//    fn.setPointSize(fn.pointSize() + 2);
-//    qApp->setFont(fn);
-#endif
 #endif
 }
 
--- a/system/system.pro	Sat Mar 01 16:17:44 2008 +0000
+++ b/system/system.pro	Wed Mar 12 17:42:56 2008 +0000
@@ -5,6 +5,8 @@
 
 CONFIG += sv staticlib qt thread warn_on stl rtti exceptions
 
+QT -= gui
+
 TARGET = svsystem
 
 DEPENDPATH += .