mirror of
https://github.com/mapmapteam/mapmap.git
synced 2026-06-16 12:33:19 +02:00
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:
+25
@@ -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()));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user