Fixed signal/slot loop: on property changes model emits signals that are collected by the MainWindow and sent back to the PaintGui/MappingGui (this fixes OSC changes of model objects).

This commit is contained in:
Tats
2016-03-03 22:25:00 -05:00
parent 5fe89ab9ac
commit e87de3d3e9
10 changed files with 213 additions and 74 deletions
+25
View File
@@ -39,3 +39,28 @@ Element::Element(uid id, UidAllocator* allocator) : _name(""), _isLocked(false),
Element::~Element() {
_allocator->free(_id);
}
void Element::setLocked(bool locked)
{
if (locked != _isLocked)
{
_isLocked = locked;
_emitPropertyChanged("locked");
}
}
void Element::setOpacity(float opacity)
{
opacity = qBound(opacity, 0.0f, 1.0f);
if (opacity != _opacity)
{
_opacity = opacity;
_emitPropertyChanged("opacity");
}
}
void Element::_emitPropertyChanged(const QString& propertyName)
{
emit propertyChanged(getId(), propertyName, property(propertyName.toAscii()));
}
+10 -6
View File
@@ -27,6 +27,7 @@
#include "Serializable.h"
#include "UidAllocator.h"
#include <QEvent>
Q_DECLARE_METATYPE(uid)
class Element : public Serializable
@@ -36,7 +37,7 @@ class Element : public Serializable
Q_PROPERTY(uid id READ getId)
Q_PROPERTY(QString name READ getName WRITE setName RESET unsetName)
Q_PROPERTY(bool locked READ isLocked WRITE setLocked)
Q_PROPERTY(float opacity READ getOpacity WRITE setOpacity)
Q_PROPERTY(float opacity READ getOpacity WRITE setOpacity NOTIFY propertyChanged)
Q_PROPERTY(QIcon icon READ getIcon)
public:
@@ -52,22 +53,25 @@ public:
virtual void unsetName() { _name = _id; }
float getOpacity() const { return _opacity; }
void setOpacity(float opacity) {
_opacity = qBound(opacity, 0.0f, 1.0f);
}
void setOpacity(float opacity);
bool isLocked() const { return _isLocked; }
void setLocked(bool locked) { _isLocked = locked; }
void toggleLocked() { _isLocked = !_isLocked; }
void setLocked(bool locked);
void toggleLocked() { setLocked(!isLocked()); }
virtual void build() {}
virtual QIcon getIcon() const { return QIcon(); }
signals:
void propertyChanged(uid id, QString propertyName, QVariant value);
protected:
virtual QList<QString> _propertiesAttributes() const
{ return Serializable::_propertiesAttributes() << "name" << "locked"; }
void _emitPropertyChanged(const QString& propertyName);
private:
uid _id;
QString _name;
+38 -3
View File
@@ -272,6 +272,30 @@ void MainWindow::handlePaintChanged(Paint::ptr paint) {
setCurrentMapping(curMappingId);
}
void MainWindow::mappingPropertyChanged(uid id, QString propertyName, QVariant value)
{
// Retrieve mapping.
Mapping::ptr mapping = mappingManager->getMappingById(id);
Q_CHECK_PTR(mapping);
MappingGui::ptr mappingGui = getMappingGuiByMappingId(id);
Q_CHECK_PTR(mappingGui);
mappingGui->setValue(propertyName, value);
}
void MainWindow::paintPropertyChanged(uid id, QString propertyName, QVariant value)
{
// Retrieve paint.
Paint::ptr paint = mappingManager->getPaintById(id);
Q_CHECK_PTR(paint);
PaintGui::ptr paintGui = getPaintGuiByPaintId(id);
Q_CHECK_PTR(paintGui);
paintGui->setValue(propertyName, value);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
// Stop video playback to avoid lags. XXX Hack
@@ -2315,6 +2339,13 @@ void MainWindow::addPaintItem(uid paintId, const QIcon& icon, const QString& nam
connect(paintGui.data(), SIGNAL(valueChanged(Paint::ptr)),
this, SLOT(handlePaintChanged(Paint::ptr)));
connect(paint.data(), SIGNAL(propertyChanged(uid, QString, QVariant)),
this, SLOT(paintPropertyChanged(uid, QString, QVariant)));
// TODO: attention: if mapping is invisible canvases will be updated for no reason
connect(paint.data(), SIGNAL(propertyChanged(uid, QString, QVariant)),
this, SLOT(updateCanvases()));
// Add paint item to paintList widget.
QListWidgetItem* item = new QListWidgetItem(icon, name);
setItemId(*item, paintId); // TODO: could possibly be replaced by a Paint pointer
@@ -2414,15 +2445,19 @@ void MainWindow::addMappingItem(uid mappingId)
mappingPropertyPanel->setEnabled(true);
// When mapper value is changed, update canvases.
connect(mapper.data(), SIGNAL(valueChanged()),
this, SLOT(updateCanvases()));
connect(sourceCanvas, SIGNAL(shapeChanged(MShape*)),
mapper.data(), SLOT(updateShape(MShape*)));
connect(destinationCanvas, SIGNAL(shapeChanged(MShape*)),
mapper.data(), SLOT(updateShape(MShape*)));
connect(mapping.data(), SIGNAL(propertyChanged(uid, QString, QVariant)),
this, SLOT(mappingPropertyChanged(uid, QString, QVariant)));
// TODO: attention: if mapping is invisible canvases will be updated for no reason
connect(mapping.data(), SIGNAL(propertyChanged(uid, QString, QVariant)),
this, SLOT(updateCanvases()));
// Switch to mapping tab.
contentTab->setCurrentWidget(mappingSplitter);
+6
View File
@@ -117,6 +117,9 @@ private slots:
void handleItemSelected(QListWidgetItem* item);
void handlePaintChanged(Paint::ptr paint);
void mappingPropertyChanged(uid id, QString propertyName, QVariant value);
void paintPropertyChanged(uid id, QString propertyName, QVariant value);
void addMesh();
void addTriangle();
void addEllipse();
@@ -442,7 +445,10 @@ private:
public:
// Accessor/mutators for the view. ///////////////////////////////////////////////////////////////////
MappingManager& getMappingManager() const { return *mappingManager; }
MappingGui::ptr getMappingGuiByMappingId(uint id) const { return mappers[id]; }
PaintGui::ptr getPaintGuiByPaintId(uint id) const { return paintGuis[id]; }
uid getCurrentPaintId() const { return currentPaintId; }
uid getCurrentMappingId() const { return currentMappingId; }
Mapping::ptr getCurrentMapping() const { return mappingManager->getMappingById(currentMappingId); }
+6
View File
@@ -92,6 +92,12 @@ void MappingGui::setValue(QtProperty* property, const QVariant& value)
}
}
void MappingGui::setValue(QString propertyName, QVariant value)
{
if (propertyName == "opacity")
_opacityItem->setValue(value.toDouble() * 100);
}
void MappingGui::updateShape(MShape* shape)
{
if (shape == _mapping->getShape().data())
+1
View File
@@ -87,6 +87,7 @@ public:
public slots:
virtual void setValue(QtProperty* property, const QVariant& value);
virtual void setValue(QString propertyName, QVariant value);
virtual void updateShape(MShape* shape);
signals:
+71 -47
View File
@@ -35,27 +35,31 @@ Paint::~Paint()
bool Image::setUri(const QString &uri)
{
this->uri = uri;
build();
return !image.isNull();
if (uri != _uri)
{
_uri = uri;
build();
_emitPropertyChanged("uri");
}
return !_image.isNull();
}
/* Implementation of the Video class */
Video::Video(int id) : Texture(id),
uri(""),
impl(NULL)
_uri(""),
_impl(NULL)
{
impl = new VideoImpl("", false);
_impl = new VideoImpl("", false);
setRate(1);
setVolume(1);
}
Video::Video(const QString uri_, bool live, double rate, uid id):
Texture(id),
uri(uri_),
impl(NULL)
_uri(uri_),
_impl(NULL)
{
impl = new VideoImpl("", live);
_impl = new VideoImpl("", live);
setRate(rate);
setVolume(1);
setUri(uri_);
@@ -65,81 +69,89 @@ Video::Video(const QString uri_, bool live, double rate, uid id):
Video::~Video()
{
delete impl;
delete _impl;
}
void Video::build()
{
this->impl->build();
this->_impl->build();
}
int Video::getWidth() const
{
while (!this->impl->videoIsConnected());
return this->impl->getWidth();
while (!this->_impl->videoIsConnected());
return this->_impl->getWidth();
}
int Video::getHeight() const
{
while (!this->impl->videoIsConnected());
return this->impl->getHeight();
while (!this->_impl->videoIsConnected());
return this->_impl->getHeight();
}
void Video::update() {
impl->update();
_impl->update();
}
void Video::play()
{
impl->setPlayState(true);
_impl->setPlayState(true);
}
void Video::pause()
{
impl->setPlayState(false);
_impl->setPlayState(false);
}
void Video::rewind()
{
impl->resetMovie();
_impl->resetMovie();
}
void Video::lockMutex() {
impl->lockMutex();
_impl->lockMutex();
}
void Video::unlockMutex() {
impl->unlockMutex();
_impl->unlockMutex();
}
const uchar* Video::getBits()
{
return this->impl->getBits();
return this->_impl->getBits();
}
bool Video::bitsHaveChanged() const
{
return this->impl->bitsHaveChanged();
return this->_impl->bitsHaveChanged();
}
void Video::setRate(double rate)
{
impl->setRate(rate);
if (rate != _impl->getRate())
{
_impl->setRate(rate);
_emitPropertyChanged("rate");
}
}
double Video::getRate() const
{
return impl->getRate();
return _impl->getRate();
}
void Video::setVolume(double rate)
void Video::setVolume(double volume)
{
impl->setVolume(rate);
if (volume != _impl->getVolume())
{
_impl->setVolume(volume);
_emitPropertyChanged("volume");
}
}
double Video::getVolume() const
{
return impl->getVolume();
return _impl->getVolume();
}
bool Video::hasVideoSupport()
@@ -149,40 +161,54 @@ bool Video::hasVideoSupport()
bool Video::setUri(const QString &uri)
{
static QFileIconProvider provider;
// Try to load movie.
if (!impl->loadMovie(uri))
// Check if we're actually changing the uri.
if (uri != _uri)
{
qDebug() << "Cannot load movie " << uri << "." << endl;
return false;
// Try to load movie.
if (!_impl->loadMovie(uri))
{
qDebug() << "Cannot load movie " << uri << "." << endl;
return false;
}
// Set uri.
_uri = uri;
// Try to get thumbnail.
if (!_generateThumbnail())
qDebug() << "Could not generate thumbnail for " << uri << ": using generic icon." << endl;
_emitPropertyChanged("uri");
}
// Set uri.
this->uri = uri;
// Return success.
return true;
}
bool Video::_generateThumbnail()
{
static QFileIconProvider provider;
// Default (in case seeking and loading don't work).
icon = provider.icon(QFileInfo(uri));
// Try to get thumbnail.
_icon = provider.icon(QFileInfo(_uri));
// Wait for the first samples to be available to make sure we are ready.
if (!impl->waitForNextBits(1000))
if (_impl->waitForNextBits(1000))
{
return false;
}
// Try seeking to the middle of the movie.
if (!impl->seekTo(0.5))
if (!_impl->seekTo(0.5))
{
impl->resetMovie();
_impl->resetMovie();
return false;
}
// Try to get a sample from the current position.
// NOTE: There is no guarantee the sample has yet been acquired.
const uchar* bits;
if (!impl->waitForNextBits(ICON_TIMEOUT, &bits))
if (!_impl->waitForNextBits(ICON_TIMEOUT, &bits))
{
qDebug() << "Second waiting wrong..." << endl;
return false;
@@ -203,12 +229,10 @@ bool Video::setUri(const QString &uri)
}
// Generate icon.
icon = QIcon(QPixmap::fromImage(thumbnail));
_icon = QIcon(QPixmap::fromImage(thumbnail));
// Reset movie.
impl->resetMovie();
_impl->resetMovie();
// Return success.
return true;
}
+17 -13
View File
@@ -182,8 +182,8 @@ class Image : public Texture
Q_PROPERTY(QString uri READ getUri WRITE setUri)
protected:
QString uri;
QImage image;
QString _uri;
QImage _image;
public:
Q_INVOKABLE Image(int id=NULL_UID) : Texture(id) {}
@@ -196,26 +196,26 @@ public:
virtual ~Image() {}
virtual void build() {
image = QGLWidget::convertToGLFormat(QImage(uri)).mirrored(true, false).transformed(QTransform().rotate(180));
_image = QGLWidget::convertToGLFormat(QImage(_uri)).mirrored(true, false).transformed(QTransform().rotate(180));
bitsChanged = true;
}
const QString getUri() const { return uri; }
const QString getUri() const { return _uri; }
bool setUri(const QString &uri);
virtual QString getType() const { return "image"; }
virtual int getWidth() const { return image.width(); }
virtual int getHeight() const { return image.height(); }
virtual int getWidth() const { return _image.width(); }
virtual int getHeight() const { return _image.height(); }
virtual const uchar* getBits() {
bitsChanged = false;
return image.bits();
return _image.bits();
}
virtual bool bitsHaveChanged() const { return bitsChanged; }
virtual QIcon getIcon() const { return QIcon(QPixmap::fromImage(image)); }
virtual QIcon getIcon() const { return QIcon(QPixmap::fromImage(_image)); }
};
class VideoImpl; // forward declaration
@@ -242,7 +242,7 @@ public:
virtual ~Video();
const QString getUri() const
{
return uri;
return _uri;
}
bool setUri(const QString &uri);
virtual void build();
@@ -289,17 +289,21 @@ public:
*/
static bool hasVideoSupport();
virtual QIcon getIcon() const { return icon; }
virtual QIcon getIcon() const { return _icon; }
protected:
QString uri;
QIcon icon;
// Try to generate a thumbnail from currently loaded movie.
bool _generateThumbnail();
QString _uri;
QIcon _icon;
/**
* Private implementation, so that GStreamer headers don't need
* to be included from every file in the project.
*/
VideoImpl *impl;
VideoImpl *_impl;
};
#endif /* PAINT_H_ */
+35 -2
View File
@@ -69,6 +69,11 @@ void PaintGui::setValue(QtProperty* property, const QVariant& value)
}
}
void PaintGui::setValue(QString propertyName, QVariant value)
{
if (propertyName == "opacity")
_opacityItem->setValue(value.toDouble() * 100);
}
ColorGui::ColorGui(Paint::ptr paint)
: PaintGui(paint)
@@ -93,6 +98,14 @@ void ColorGui::setValue(QtProperty* property, const QVariant& value) {
PaintGui::setValue(property, value);
}
void ColorGui::setValue(QString propertyName, QVariant value)
{
if (propertyName == "color")
setValue(_colorItem, value);
else
PaintGui::setValue(propertyName, value);
}
TextureGui::TextureGui(Paint::ptr paint) : PaintGui(paint) {
}
@@ -117,7 +130,15 @@ void ImageGui::setValue(QtProperty* property, const QVariant& value) {
emit valueChanged(_paint);
}
else
PaintGui::setValue(property, value);
TextureGui::setValue(property, value);
}
void ImageGui::setValue(QString propertyName, QVariant value)
{
if (propertyName == "uri")
_imageFileItem->setValue(value);
else
TextureGui::setValue(propertyName, value);
}
VideoGui::VideoGui(Paint::ptr paint)
@@ -182,5 +203,17 @@ void VideoGui::setValue(QtProperty* property, const QVariant& value)
emit valueChanged(_paint);
}
else
PaintGui::setValue(property, value);
TextureGui::setValue(property, value);
}
void VideoGui::setValue(QString propertyName, QVariant value)
{
if (propertyName == "uri")
_mediaFileItem->setValue(value);
if (propertyName == "rate")
_mediaRateItem->setValue(value.toDouble()*100);
if (propertyName == "volume")
_mediaVolumeItem->setValue(value.toDouble()*100);
else
TextureGui::setValue(propertyName, value);
}
+4 -3
View File
@@ -66,6 +66,7 @@ public:
public slots:
virtual void setValue(QtProperty* property, const QVariant& value);
virtual void setValue(QString propertyName, QVariant value);
signals:
void valueChanged(Paint::ptr);
@@ -88,6 +89,7 @@ public:
public slots:
virtual void setValue(QtProperty* property, const QVariant& value);
virtual void setValue(QString propertyName, QVariant value);
protected:
QSharedPointer<Color> color;
@@ -100,9 +102,6 @@ class TextureGui : public PaintGui {
public:
TextureGui(Paint::ptr paint);
virtual ~TextureGui() {}
public slots:
virtual void setValue(QtProperty* property, const QVariant& value) = 0;
};
class ImageGui : public TextureGui {
@@ -114,6 +113,7 @@ public:
public slots:
virtual void setValue(QtProperty* property, const QVariant& value);
virtual void setValue(QString propertyName, QVariant value);
protected:
QSharedPointer<Image> image;
@@ -129,6 +129,7 @@ public:
public slots:
virtual void setValue(QtProperty* property, const QVariant& value);
virtual void setValue(QString propertyName, QVariant value);
protected:
QSharedPointer<Video> media;