From e87de3d3e95cc3962fa9cbc0079eb469141ec375 Mon Sep 17 00:00:00 2001 From: Tats Date: Thu, 3 Mar 2016 22:25:00 -0500 Subject: [PATCH] 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). --- Element.cpp | 25 +++++++++++ Element.h | 16 ++++--- MainWindow.cpp | 41 +++++++++++++++-- MainWindow.h | 6 +++ MappingGui.cpp | 6 +++ MappingGui.h | 1 + Paint.cpp | 118 +++++++++++++++++++++++++++++-------------------- Paint.h | 30 +++++++------ PaintGui.cpp | 37 +++++++++++++++- PaintGui.h | 7 +-- 10 files changed, 213 insertions(+), 74 deletions(-) diff --git a/Element.cpp b/Element.cpp index f0ba070..815b785 100644 --- a/Element.cpp +++ b/Element.cpp @@ -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())); +} + diff --git a/Element.h b/Element.h index 8c3240b..2081390 100644 --- a/Element.h +++ b/Element.h @@ -27,6 +27,7 @@ #include "Serializable.h" #include "UidAllocator.h" +#include 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 _propertiesAttributes() const { return Serializable::_propertiesAttributes() << "name" << "locked"; } + void _emitPropertyChanged(const QString& propertyName); + private: uid _id; QString _name; diff --git a/MainWindow.cpp b/MainWindow.cpp index 790fb78..fd076f9 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -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); diff --git a/MainWindow.h b/MainWindow.h index 7dbda87..a455036 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -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); } diff --git a/MappingGui.cpp b/MappingGui.cpp index 1e5c9d6..eeeb214 100644 --- a/MappingGui.cpp +++ b/MappingGui.cpp @@ -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()) diff --git a/MappingGui.h b/MappingGui.h index ea8da6e..a68e903 100644 --- a/MappingGui.h +++ b/MappingGui.h @@ -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: diff --git a/Paint.cpp b/Paint.cpp index afd5b6e..bfaa578 100644 --- a/Paint.cpp +++ b/Paint.cpp @@ -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; } - diff --git a/Paint.h b/Paint.h index 908baae..ce6132b 100644 --- a/Paint.h +++ b/Paint.h @@ -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_ */ diff --git a/PaintGui.cpp b/PaintGui.cpp index 305bb92..7d4e5b7 100644 --- a/PaintGui.cpp +++ b/PaintGui.cpp @@ -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); } diff --git a/PaintGui.h b/PaintGui.h index 00ccc4b..873e9d8 100644 --- a/PaintGui.h +++ b/PaintGui.h @@ -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; @@ -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; @@ -129,6 +129,7 @@ public: public slots: virtual void setValue(QtProperty* property, const QVariant& value); + virtual void setValue(QString propertyName, QVariant value); protected: QSharedPointer