changeset 377:0bcb449d15f4

* Fix #1628781 changes to layer visibility and mute should use a command * Also use a command for changes to layer playback pan, gain, plugin settings * Refactor PlayParameterRepository to remove dependency on audioio from base * Fix failure to save play parameters for main model in session file
author Chris Cannam
date Thu, 13 Mar 2008 14:06:03 +0000
parents e1a9e478b7f2
children 22b72f0f6a4e
files widgets/CommandHistory.cpp widgets/PropertyBox.cpp widgets/PropertyBox.h widgets/PropertyStack.cpp
diffstat 4 files changed, 144 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/widgets/CommandHistory.cpp	Wed Mar 12 17:42:56 2008 +0000
+++ b/widgets/CommandHistory.cpp	Thu Mar 13 14:06:03 2008 +0000
@@ -35,6 +35,8 @@
 
 #include <iostream>
 
+//#define DEBUG_COMMAND_HISTORY 1
+
 CommandHistory *CommandHistory::m_instance = 0;
 
 CommandHistory::CommandHistory() :
@@ -95,7 +97,9 @@
 void
 CommandHistory::clear()
 {
-//    std::cerr << "CommandHistory::clear()" << std::endl;
+#ifdef DEBUG_COMMAND_HISTORY
+    std::cerr << "CommandHistory::clear()" << std::endl;
+#endif
     closeBundle();
     m_savedAt = -1;
     clearStack(m_undoStack);
@@ -147,10 +151,14 @@
 	closeBundle();
     }
 
-//    std::cerr << "CommandHistory::addCommand: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl;
+#ifdef DEBUG_COMMAND_HISTORY
+    std::cerr << "CommandHistory::addCommand: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl;
+    if (!m_redoStack.empty()) {
+        std::cerr << "CommandHistory::clearing redo stack" << std::endl;
+    }
+#endif
 
     // We can't redo after adding a command
-//    std::cerr << "CommandHistory::clearing redo stack" << std::endl;
     clearStack(m_redoStack);
 
     // can we reach savedAt?
@@ -176,6 +184,11 @@
 {
     if (m_currentBundle) {
 	if (!command || (command->getName() != m_currentBundleName)) {
+#ifdef DEBUG_COMMAND_HISTORY
+            std::cerr << "CommandHistory::addToBundle: "
+                      << command->getName().toStdString()
+                      << ": closing current bundle" << std::endl;
+#endif
 	    closeBundle();
 	}
     }
@@ -183,6 +196,13 @@
     if (!command) return;
 
     if (!m_currentBundle) {
+
+#ifdef DEBUG_COMMAND_HISTORY
+        std::cerr << "CommandHistory::addToBundle: "
+                  << command->getName().toStdString()
+                  << ": creating new bundle" << std::endl;
+#endif
+
 	// need to addCommand before setting m_currentBundle, as addCommand
 	// with bundle false will reset m_currentBundle to 0
 	MacroCommand *mc = new MacroCommand(command->getName());
@@ -191,9 +211,22 @@
 	m_currentBundleName = command->getName();
     }
 
+#ifdef DEBUG_COMMAND_HISTORY
+    std::cerr << "CommandHistory::addToBundle: "
+              << command->getName().toStdString()
+              << ": adding to bundle" << std::endl;
+#endif
+
     if (execute) command->execute();
     m_currentBundle->addCommand(command);
 
+    // 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();
+
     delete m_bundleTimer;
     m_bundleTimer = new QTimer(this);
     connect(m_bundleTimer, SIGNAL(timeout()), this, SLOT(bundleTimerTimeout()));
@@ -203,6 +236,10 @@
 void
 CommandHistory::closeBundle()
 {
+#ifdef DEBUG_COMMAND_HISTORY
+    std::cerr << "CommandHistory::closeBundle" << std::endl;
+#endif
+
     m_currentBundle = 0;
     m_currentBundleName = "";
 }
@@ -210,13 +247,19 @@
 void
 CommandHistory::bundleTimerTimeout()
 {
+#ifdef DEBUG_COMMAND_HISTORY
+    std::cerr << "CommandHistory::bundleTimerTimeout: bundle is " << m_currentBundle << std::endl;
+#endif
+
     closeBundle();
 }
 
 void
 CommandHistory::addToCompound(Command *command, bool execute)
 {
-//    std::cerr << "CommandHistory::addToCompound: " << command->getName().toLocal8Bit().data() << std::endl;
+#ifdef DEBUG_COMMAND_HISTORY
+    std::cerr << "CommandHistory::addToCompound: " << command->getName().toLocal8Bit().data() << std::endl;
+#endif
     if (!m_currentCompound) {
 	std::cerr << "CommandHistory::addToCompound: ERROR: no compound operation in progress!" << std::endl;
         return;
@@ -278,6 +321,10 @@
 {
     if (m_undoStack.empty()) return;
 
+#ifdef DEBUG_COMMAND_HISTORY
+    std::cerr << "CommandHistory::undo()" << std::endl;
+#endif
+
     closeBundle();
 
     Command *command = m_undoStack.top();
@@ -299,6 +346,10 @@
 {
     if (m_redoStack.empty()) return;
 
+#ifdef DEBUG_COMMAND_HISTORY
+    std::cerr << "CommandHistory::redo()" << std::endl;
+#endif
+
     closeBundle();
 
     Command *command = m_redoStack.top();
@@ -374,8 +425,10 @@
 	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;
+#ifdef DEBUG_COMMAND_HISTORY
+	    Command *command = stack.top();
+	    std::cerr << "CommandHistory::clipStack: Saving recent command: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl;
+#endif
 	    tempStack.push(stack.top());
 	    stack.pop();
 	}
@@ -395,7 +448,9 @@
     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;
+#ifdef DEBUG_COMMAND_HISTORY
+	std::cerr << "CommandHistory::clearStack: About to delete command " << command << std::endl;
+#endif
 	delete command;
 	stack.pop();
     }
--- a/widgets/PropertyBox.cpp	Wed Mar 12 17:42:56 2008 +0000
+++ b/widgets/PropertyBox.cpp	Thu Mar 13 14:06:03 2008 +0000
@@ -18,6 +18,7 @@
 
 #include "base/PropertyContainer.h"
 #include "base/PlayParameters.h"
+#include "base/PlayParameterRepository.h"
 #include "layer/Layer.h"
 #include "layer/ColourDatabase.h"
 #include "base/UnitDatabase.h"
@@ -176,13 +177,13 @@
         m_playButton->setState(!params->isPlayMuted());
 	layout->addWidget(m_playButton);
 	connect(m_playButton, SIGNAL(stateChanged(bool)),
-		params, SLOT(setPlayAudible(bool)));
+		this, SLOT(playAudibleButtonChanged(bool)));
         connect(m_playButton, SIGNAL(mouseEntered()),
                 this, SLOT(mouseEnteredWidget()));
         connect(m_playButton, SIGNAL(mouseLeft()),
                 this, SLOT(mouseLeftWidget()));
 	connect(params, SIGNAL(playAudibleChanged(bool)),
-		m_playButton, SLOT(setState(bool)));
+		this, SLOT(playAudibleChanged(bool)));
 	layout->setAlignment(m_playButton, Qt::AlignVCenter);
 
 	layout->insertStretch(-1, 10);
@@ -214,14 +215,13 @@
 		this, SLOT(playGainDialChanged(int)));
 	connect(params, SIGNAL(playGainChanged(float)),
 		this, SLOT(playGainChanged(float)));
-	connect(this, SIGNAL(changePlayGain(float)),
-		params, SLOT(setPlayGain(float)));
 	connect(this, SIGNAL(changePlayGainDial(int)),
 		gainDial, SLOT(setValue(int)));
         connect(gainDial, SIGNAL(mouseEntered()),
                 this, SLOT(mouseEnteredWidget()));
         connect(gainDial, SIGNAL(mouseLeft()),
                 this, SLOT(mouseLeftWidget()));
+        playGainChanged(params->getPlayGain());
 	layout->setAlignment(gainDial, Qt::AlignVCenter);
 
 	AudioDial *panDial = new AudioDial;
@@ -241,14 +241,13 @@
 		this, SLOT(playPanDialChanged(int)));
 	connect(params, SIGNAL(playPanChanged(float)),
 		this, SLOT(playPanChanged(float)));
-	connect(this, SIGNAL(changePlayPan(float)),
-		params, SLOT(setPlayPan(float)));
 	connect(this, SIGNAL(changePlayPanDial(int)),
 		panDial, SLOT(setValue(int)));
         connect(panDial, SIGNAL(mouseEntered()),
                 this, SLOT(mouseEnteredWidget()));
         connect(panDial, SIGNAL(mouseLeft()),
                 this, SLOT(mouseLeftWidget()));
+        playPanChanged(params->getPlayPan());
 	layout->setAlignment(panDial, Qt::AlignVCenter);
 
     } else {
@@ -656,6 +655,26 @@
         db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
     }
 }
+
+void
+PropertyBox::playAudibleChanged(bool audible)
+{
+    m_playButton->setState(audible);
+}
+
+void
+PropertyBox::playAudibleButtonChanged(bool audible)
+{
+    PlayParameters *params = m_container->getPlayParameters();
+    if (!params) return;
+
+    if (params->isPlayAudible() != audible) {
+        PlayParameterRepository::EditCommand *command =
+            new PlayParameterRepository::EditCommand(params);
+        command->setPlayAudible(audible);
+        CommandHistory::getInstance()->addCommand(command, true, true);
+    }
+}
     
 void
 PropertyBox::playGainChanged(float gain)
@@ -670,8 +689,19 @@
 PropertyBox::playGainDialChanged(int dialValue)
 {
     QObject *obj = sender();
+
+    PlayParameters *params = m_container->getPlayParameters();
+    if (!params) return;
+
     float gain = pow(10, float(dialValue) / 20.0);
-    emit changePlayGain(gain);
+
+    if (params->getPlayGain() != gain) {
+        PlayParameterRepository::EditCommand *command =
+            new PlayParameterRepository::EditCommand(params);
+        command->setPlayGain(gain);
+        CommandHistory::getInstance()->addCommand(command, true, true);
+    }
+
     updateContextHelp(obj);
 }
     
@@ -688,10 +718,21 @@
 PropertyBox::playPanDialChanged(int dialValue)
 {
     QObject *obj = sender();
+
+    PlayParameters *params = m_container->getPlayParameters();
+    if (!params) return;
+
     float pan = float(dialValue) / 50.0;
     if (pan < -1.0) pan = -1.0;
     if (pan >  1.0) pan =  1.0;
-    emit changePlayPan(pan);
+
+    if (params->getPlayPan() != pan) {
+        PlayParameterRepository::EditCommand *command =
+            new PlayParameterRepository::EditCommand(params);
+        command->setPlayPan(pan);
+        CommandHistory::getInstance()->addCommand(command, true, true);
+    }
+
     updateContextHelp(obj);
 }
 
@@ -705,6 +746,9 @@
 
     QString pluginId = params->getPlayPluginId();
     QString configurationXml = params->getPlayPluginConfiguration();
+
+    PlayParameterRepository::EditCommand *command = 
+        new PlayParameterRepository::EditCommand(params);
     
     RealTimePluginFactory *factory =
 	RealTimePluginFactory::instanceFor(pluginId);
@@ -721,8 +765,11 @@
             this, SLOT(pluginConfigurationChanged(QString)));
 
     if (dialog->exec() == QDialog::Accepted) {
-        params->setPlayPluginConfiguration(PluginXml(instance).toXmlString());
+        QString newConfiguration = PluginXml(instance).toXmlString();
+        command->setPlayPluginConfiguration(newConfiguration);
+        CommandHistory::getInstance()->addCommand(command, true);
     } else {
+        delete command;
         // restore in case we mucked about with the configuration
         // as a consequence of signals from the dialog
         params->setPlayPluginConfiguration(configurationXml);
--- a/widgets/PropertyBox.h	Wed Mar 12 17:42:56 2008 +0000
+++ b/widgets/PropertyBox.h	Thu Mar 13 14:06:03 2008 +0000
@@ -39,9 +39,7 @@
     PropertyContainer *getContainer() { return m_container; }
 
 signals:
-    void changePlayGain(float);
     void changePlayGainDial(int);
-    void changePlayPan(float);
     void changePlayPanDial(int);
     void showLayer(bool);
     void contextHelpChanged(const QString &);
@@ -56,6 +54,8 @@
     void propertyControllerChanged(int);
     void propertyControllerChanged(bool);
 
+    void playAudibleChanged(bool);
+    void playAudibleButtonChanged(bool);
     void playGainChanged(float);
     void playGainDialChanged(int);
     void playPanChanged(float);
--- a/widgets/PropertyStack.cpp	Wed Mar 12 17:42:56 2008 +0000
+++ b/widgets/PropertyStack.cpp	Thu Mar 13 14:06:03 2008 +0000
@@ -21,6 +21,8 @@
 #include "layer/LayerFactory.h"
 #include "widgets/NotifyingTabBar.h"
 #include "widgets/IconLoader.h"
+#include "base/Command.h"
+#include "widgets/CommandHistory.h"
 
 #include <QIcon>
 #include <QTabWidget>
@@ -198,6 +200,26 @@
     repopulate();
 }
 
+class ShowLayerCommand : public QObject, public Command
+{
+public:
+    ShowLayerCommand(View *view, Layer *layer, bool show) :
+        m_view(view), m_layer(layer), m_show(show) { }
+    void execute() {
+        m_layer->showLayer(m_view, m_show);
+    }
+    void unexecute() {
+        m_layer->showLayer(m_view, !m_show);
+    }
+    QString getName() const {
+        return tr("Change Layer Visibility");
+    }
+protected:
+    View *m_view;
+    Layer *m_layer;
+    bool m_show;
+};
+
 void
 PropertyStack::showLayer(bool show)
 {
@@ -207,7 +229,8 @@
 	if (obj == m_boxes[i]) {
 	    Layer *layer = dynamic_cast<Layer *>(m_boxes[i]->getContainer());
 	    if (layer) {
-		layer->showLayer(m_client, show);
+                CommandHistory::getInstance()->addCommand
+                    (new ShowLayerCommand(m_client, layer, show));
 		return;
 	    }
 	}