# HG changeset patch # User Chris Cannam # Date 1142534760 0 # Node ID 5364a9d338a2690b9997017a5a0969f5e2f6af34 # Parent b11edc8b8ea0c789cde7bf162b6390abb6affc9a * Add Insert Instant function in main window * Ensure selections and window geometry are saved in session file * Add wait cursor on session file save * Various improvements to display of texts in pane (clearer readability) * Use commands for setting properties on layers and panes (still need to batch up multiple sets on the same property) * Fix failure of spectrogram to refresh when initial part became visible * Some fixes & paint optimisations in View &c * Make curve mode for time value layers work properly when resolution == 1 * Some vague improvements for time value layer vertical scale diff -r b11edc8b8ea0 -r 5364a9d338a2 base/CommandHistory.cpp --- a/base/CommandHistory.cpp Wed Mar 15 18:11:23 2006 +0000 +++ b/base/CommandHistory.cpp Thu Mar 16 18:46:00 2006 +0000 @@ -33,6 +33,7 @@ CommandHistory::CommandHistory() : m_undoLimit(50), m_redoLimit(50), + m_menuLimit(15), m_savedAt(0), m_currentMacro(0), m_executeMacro(false) @@ -112,7 +113,7 @@ return; } - std::cerr << "MVCH::addCommand: " << command->getName().toLocal8Bit().data() << std::endl; + std::cerr << "MVCH::addCommand: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl; // We can't redo after adding a command clearStack(m_redoStack); @@ -241,6 +242,13 @@ } void +CommandHistory::setMenuLimit(int limit) +{ + m_menuLimit = limit; + updateActions(); +} + +void CommandHistory::documentSaved() { m_savedAt = m_undoStack.size(); @@ -287,7 +295,8 @@ { while (!stack.empty()) { Command *command = stack.top(); - std::cerr << "MVCH::clearStack: About to delete command: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl; + // Not safe to call getName() on a command about to be deleted + std::cerr << "MVCH::clearStack: About to delete command " << command << std::endl; delete command; stack.pop(); } @@ -353,7 +362,7 @@ CommandStack tempStack; int j = 0; - while (j < 10 && !stack.empty()) { + while (j < m_menuLimit && !stack.empty()) { Command *command = stack.top(); tempStack.push(command); diff -r b11edc8b8ea0 -r 5364a9d338a2 base/CommandHistory.h --- a/base/CommandHistory.h Wed Mar 15 18:11:23 2006 +0000 +++ b/base/CommandHistory.h Thu Mar 16 18:46:00 2006 +0000 @@ -60,17 +60,23 @@ void addCommand(Command *command, bool execute = true); /// Return the maximum number of items in the undo history. - int undoLimit() { return m_undoLimit; } + 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 redoLimit() { return m_redoLimit; } + 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); + /// Start recording commands to batch up into a single compound command. void startCompoundOperation(QString name, bool execute); @@ -148,6 +154,7 @@ int m_undoLimit; int m_redoLimit; + int m_menuLimit; int m_savedAt; MacroCommand *m_currentMacro; diff -r b11edc8b8ea0 -r 5364a9d338a2 base/PropertyContainer.cpp --- a/base/PropertyContainer.cpp Wed Mar 15 18:11:23 2006 +0000 +++ b/base/PropertyContainer.cpp Thu Mar 16 18:46:00 2006 +0000 @@ -8,6 +8,9 @@ */ #include "PropertyContainer.h" +#include "CommandHistory.h" + +#include PropertyContainer::PropertyList PropertyContainer::getProperties() const @@ -42,7 +45,47 @@ } void -PropertyContainer::setProperty(const PropertyName &, int) +PropertyContainer::setProperty(const PropertyName &name, int) +{ + std::cerr << "WARNING: PropertyContainer[" << getPropertyContainerName().toStdString() << "]::setProperty(" << name.toStdString() << "): no implementation in subclass!" << std::endl; +} + +void +PropertyContainer::setPropertyWithCommand(const PropertyName &name, int value) +{ + int currentValue = getPropertyRangeAndValue(name, 0, 0); + if (value == currentValue) return; + + CommandHistory::getInstance()->addCommand + (new SetPropertyCommand(this, name, value)); +} + +PropertyContainer::SetPropertyCommand::SetPropertyCommand(PropertyContainer *pc, + const PropertyName &pn, + int value) : + m_pc(pc), + m_pn(pn), + m_value(value), + m_oldValue(0) { } +void +PropertyContainer::SetPropertyCommand::execute() +{ + m_oldValue = m_pc->getPropertyRangeAndValue(m_pn, 0, 0); + m_pc->setProperty(m_pn, m_value); +} + +void +PropertyContainer::SetPropertyCommand::unexecute() +{ + m_pc->setProperty(m_pn, m_oldValue); +} + +QString +PropertyContainer::SetPropertyCommand::getName() const +{ + return m_pc->tr("Set %1 Property").arg(m_pn); +} + diff -r b11edc8b8ea0 -r 5364a9d338a2 base/PropertyContainer.h --- a/base/PropertyContainer.h Wed Mar 15 18:11:23 2006 +0000 +++ b/base/PropertyContainer.h Thu Mar 16 18:46:00 2006 +0000 @@ -10,6 +10,8 @@ #ifndef _PROPERTY_CONTAINER_H_ #define _PROPERTY_CONTAINER_H_ +#include "Command.h" + #include #include #include @@ -89,6 +91,30 @@ * colours, the integer value should be treated as a qRgb. */ virtual void setProperty(const PropertyName &, int value); + + /** + * Set a property using a command, supporting undo and redo. + */ + virtual void setPropertyWithCommand(const PropertyName &, int value); + +protected: + + class SetPropertyCommand : public Command + { + public: + SetPropertyCommand(PropertyContainer *pc, const PropertyName &pn, int); + virtual ~SetPropertyCommand() { } + + virtual void execute(); + virtual void unexecute(); + virtual QString getName() const; + + protected: + PropertyContainer *m_pc; + PropertyName m_pn; + int m_value; + int m_oldValue; + }; }; #endif diff -r b11edc8b8ea0 -r 5364a9d338a2 base/Selection.cpp --- a/base/Selection.cpp Wed Mar 15 18:11:23 2006 +0000 +++ b/base/Selection.cpp Thu Mar 16 18:46:00 2006 +0000 @@ -186,3 +186,19 @@ return Selection(); } + +QString +MultiSelection::toXmlString(QString indent, + QString extraAttributes) const +{ + QString s; + s += indent + QString("\n").arg(extraAttributes); + for (SelectionList::iterator i = m_selections.begin(); + i != m_selections.end(); ++i) { + s += indent + QString(" \n") + .arg(i->getStartFrame()).arg(i->getEndFrame()); + } + s += indent + "\n"; + return s; +} + diff -r b11edc8b8ea0 -r 5364a9d338a2 base/Selection.h --- a/base/Selection.h Wed Mar 15 18:11:23 2006 +0000 +++ b/base/Selection.h Thu Mar 16 18:46:00 2006 +0000 @@ -13,6 +13,8 @@ #include #include +#include "XmlExportable.h" + class Selection { public: @@ -35,7 +37,7 @@ size_t m_endFrame; }; -class MultiSelection +class MultiSelection : public XmlExportable { public: MultiSelection(); @@ -57,6 +59,9 @@ */ Selection getContainingSelection(size_t frame, bool defaultToFollowing) const; + virtual QString toXmlString(QString indent = "", + QString extraAttributes = "") const; + protected: SelectionList m_selections; }; diff -r b11edc8b8ea0 -r 5364a9d338a2 base/View.cpp --- a/base/View.cpp Wed Mar 15 18:11:23 2006 +0000 +++ b/base/View.cpp Thu Mar 16 18:46:00 2006 +0000 @@ -470,9 +470,40 @@ } void -View::drawVisibleText(int x, int y, QString text, TextStyle style) +View::drawVisibleText(QPainter &paint, int x, int y, QString text, TextStyle style) { - //!!! blah. + if (style == OutlinedText) { + + QColor origPenColour = paint.pen().color(); + QColor penColour = origPenColour; + QColor surroundColour = Qt::white; //palette().background().color(); + + if (!hasLightBackground()) { + int h, s, v; + penColour.getHsv(&h, &s, &v); + penColour = QColor::fromHsv(h, s, 255 - v); + surroundColour = Qt::black; + } + + paint.setPen(surroundColour); + + for (int dx = -1; dx <= 1; ++dx) { + for (int dy = -1; dy <= 1; ++dy) { + if (!(dx || dy)) continue; + paint.drawText(x + dx, y + dy, text); + } + } + + paint.setPen(penColour); + + paint.drawText(x, y, text); + + paint.setPen(origPenColour); + + } else { + + std::cerr << "ERROR: View::drawVisibleText: Boxed style not yet implemented!" << std::endl; + } } void @@ -811,26 +842,18 @@ { changed = false; + // We want a list of all the scrollable layers that are behind the + // backmost non-scrollable layer. + LayerList scrollables; for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) { if ((*i)->isLayerDormant(this)) continue; + if ((*i)->isLayerOpaque()) { + // You can't see anything behind an opaque layer! + scrollables.clear(); + } if ((*i)->isLayerScrollable(this)) scrollables.push_back(*i); - else { - if (testChanged && scrollables != m_lastScrollableBackLayers) { - m_lastScrollableBackLayers = scrollables; - changed = true; - } - return scrollables; - } - } - - if (scrollables.size() == 1 && - dynamic_cast(*scrollables.begin())) { - - // If only the ruler is scrollable, it's not worth the bother - // -- it probably redraws as quickly as it refreshes from - // cache - scrollables.clear(); + else break; } if (testChanged && scrollables != m_lastScrollableBackLayers) { @@ -850,13 +873,18 @@ // Everything in front of the first non-scrollable from the back // should also be considered non-scrollable - size_t count = 0; + bool started = false; + for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) { if ((*i)->isLayerDormant(this)) continue; - if (count < scrollables.size()) { - ++count; + if (!started && (*i)->isLayerScrollable(this)) { continue; } + started = true; + if ((*i)->isLayerOpaque()) { + // You can't see anything behind an opaque layer! + nonScrollables.clear(); + } nonScrollables.push_back(*i); } @@ -1006,7 +1034,7 @@ QRect nonCacheRect(cacheRect); // If not all layers are scrollable, but some of the back layers - // are, we should store only those in the cache + // are, we should store only those in the cache. bool layersChanged = false; LayerList scrollables = getScrollableBackLayers(true, layersChanged); @@ -1015,6 +1043,10 @@ bool haveSelections = m_manager && !m_manager->getSelections().empty(); bool selectionDrawn = false; + // If all the non-scrollable layers are non-opaque, then we draw + // the selection rectangle behind them and cache it. If any are + // opaque, however, we can't cache. + // if (!selectionCacheable) { selectionCacheable = true; for (LayerList::const_iterator i = nonScrollables.begin(); diff -r b11edc8b8ea0 -r 5364a9d338a2 base/View.h --- a/base/View.h Wed Mar 15 18:11:23 2006 +0000 +++ b/base/View.h Thu Mar 16 18:46:00 2006 +0000 @@ -170,7 +170,8 @@ OutlinedText }; - virtual void drawVisibleText(int x, int y, QString text, TextStyle style); + virtual void drawVisibleText(QPainter &p, int x, int y, + QString text, TextStyle style); virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const { return false;