Merge branch 'develop' into statesaving

Conflicts:
	DestinationGLCanvas.cpp
	MainWindow.cpp
	MainWindow.h
	Mapper.h
	MappingManager.cpp
	MappingManager.h
	Paint.h
	Shape.h
	SourceGLCanvas.cpp
	Util.cpp
	libremapping.pro
	main.cpp
This commit is contained in:
Tats
2014-01-05 18:06:41 -05:00
168 changed files with 37421 additions and 573 deletions

View File

@@ -24,9 +24,14 @@
MainWindow::MainWindow()
{
if (!instance)
setInstance(this);
mappingManager = new MappingManager;
currentPaintId = -1;
currentMappingId = -1;
currentPaintId = 0;
currentMappingId = 0;
_hasCurrentPaint = false;
_hasCurrentMapping = false;
createLayout();
@@ -45,8 +50,14 @@ MainWindow::MainWindow()
MainWindow& MainWindow::getInstance()
{
static MainWindow instance;
return instance;
Q_ASSERT(instance);
return *instance;
}
void MainWindow::setInstance(MainWindow* inst)
{
instance = inst;
}
MainWindow::~MainWindow()
@@ -58,42 +69,57 @@ void MainWindow::handleSourceItemSelectionChanged()
{
std::cout << "selection changed" << std::endl;
QListWidgetItem* item = sourceList->currentItem();
int idx = item->data(Qt::UserRole).toInt();
uint idx = item->data(Qt::UserRole).toUInt();
std::cout << "idx=" << idx << std::endl;
setCurrentPaint(idx);
// Reconstruct shape item list.
shapeList->clear();
setCurrentMapping(-1); // de-select current mapping to avoid being stuck with the last selection
// Retrieve all mappings associated to paint.
std::map<int, Mapping::ptr> mappings = getMappingManager().getPaintMappings(idx);
for (std::map<int, Mapping::ptr>::iterator it = mappings.begin(); it != mappings.end(); ++it)
{
addMappingItem(it->first);
}
removeCurrentMapping();
// Update canvases.
sourceCanvas->update();
destinationCanvas->update();
updateAll();
//sourceCanvas->switchImage(idx);
//sourceCanvas->repaint();
//destinationCanvas->repaint();
}
void MainWindow::handleShapeItemSelectionChanged()
void MainWindow::handleLayerItemSelectionChanged()
{
std::cout << "shape selection changed" << std::endl;
QListWidgetItem* item = shapeList->currentItem();
int idx = item->data(Qt::UserRole).toInt();
std::cout << "idx=" << idx << std::endl;
setCurrentMapping(idx);
sourceCanvas->update();
destinationCanvas->update();
QListWidgetItem* item = layerList->currentItem();
uint idx = item->data(Qt::UserRole).toUInt();
Mapping::ptr mapping = mappingManager->getLayerById(idx)->getMapping();
setCurrentPaint(mapping->getPaint()->getId());
setCurrentMapping(mapping->getId());
updateAll();
//sourceCanvas->switchImage(idx);
//sourceCanvas->repaint();
//destinationCanvas->repaint();
}
void MainWindow::handleLayerItemChanged(QListWidgetItem* item)
{
uint layerId = item->data(Qt::UserRole).toUInt();
Layer::ptr layer = mappingManager->getLayerById(layerId);
layer->setVisible(item->checkState() == Qt::Checked);
updateAll();
}
void MainWindow::handleLayerIndexesMoved()
{
qDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1Moved!!!" << endl;
std::vector<uint> newOrder;
for (int row=layerList->count()-1; row>=0; row--)
{
uint layerId = layerList->item(row)->data(Qt::UserRole).toUInt();
newOrder.push_back(layerId);
}
mappingManager->reorderLayers(newOrder);
updateAll();
}
//void MainWindow::handleSourceSelectionChanged(const QItemSelection& selection)
//{
// std::cout << "selection changed" << std::endl;
@@ -169,7 +195,7 @@ void MainWindow::import()
}
}
void MainWindow::addQuad()
void MainWindow::addMesh()
{
// Create default quad.
@@ -181,13 +207,15 @@ void MainWindow::addQuad()
Q_CHECK_PTR(texture);
// Create input and output quads.
Shape::ptr outputQuad = Shape::ptr(Util::createQuadForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
Shape::ptr inputQuad = Shape::ptr(Util::createQuadForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
qDebug() << "adding mesh" << endl;
Shape::ptr outputQuad = Shape::ptr(Util::createMeshForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
Shape::ptr inputQuad = Shape::ptr(Util::createMeshForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
// Create texture mapping.
int mappingId = mappingManager->addMapping(Mapping::ptr(new TextureMapping(paint, outputQuad, inputQuad)));
Mapping::ptr mapping(new TextureMapping(paint, outputQuad, inputQuad));
uint layerId = mappingManager->addLayer(mapping);
addMappingItem(mappingId);
addLayerItem(layerId);
}
void MainWindow::addTriangle()
@@ -206,9 +234,10 @@ void MainWindow::addTriangle()
Shape::ptr inputTriangle = Shape::ptr(Util::createTriangleForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
// Create texture mapping.
int mappingId = mappingManager->addMapping(Mapping::ptr(new TextureMapping(paint, inputTriangle, outputTriangle)));
Mapping::ptr mapping(new TextureMapping(paint, inputTriangle, outputTriangle));
uint layerId = mappingManager->addLayer(mapping);
addMappingItem(mappingId);
addLayerItem(layerId);
}
void MainWindow::about()
@@ -253,16 +282,25 @@ void MainWindow::createLayout()
{
sourceList = new QListWidget;
sourceList->setSelectionMode(QAbstractItemView::SingleSelection);
sourceList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
sourceList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sourceList->setMinimumWidth(SOURCE_LIST_MINIMUM_WIDTH);
shapeList = new QListWidget;
shapeList->setSelectionMode(QAbstractItemView::SingleSelection);
shapeList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
layerList = new QListWidget;
layerList->setSelectionMode(QAbstractItemView::SingleSelection);
layerList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
//layerList->setDragDropMode(QAbstractItemView::DragDrop);
layerList->setDefaultDropAction(Qt::MoveAction);
layerList->setDragDropMode(QAbstractItemView::InternalMove);
layerList->setMinimumWidth(LAYER_LIST_MINIMUM_WIDTH);
propertyPanel = new QStackedWidget;
propertyPanel->setDisabled(true);
propertyPanel->setMinimumWidth(PROPERTY_PANEL_MINIMUM_WIDTH);
sourceCanvas = new SourceGLCanvas;
destinationCanvas = new DestinationGLCanvas(0, sourceCanvas);
connect(sourceCanvas, SIGNAL(quadChanged()),
connect(sourceCanvas, SIGNAL(shapeChanged(Shape*)),
destinationCanvas, SLOT(updateCanvas()));
// connect(destinationCanvas, SIGNAL(imageChanged()),
@@ -277,19 +315,29 @@ void MainWindow::createLayout()
sourceCanvas->setMinimumSize(CANVAS_MINIMUM_WIDTH, CANVAS_MINIMUM_HEIGHT);
destinationCanvas->setMinimumSize(CANVAS_MINIMUM_WIDTH, CANVAS_MINIMUM_HEIGHT);
mainSplitter = new QSplitter(Qt::Horizontal);
mainSplitter = new QSplitter(Qt::Vertical);
resourceSplitter = new QSplitter(Qt::Horizontal);
resourceSplitter->addWidget(sourceList);
resourceSplitter->addWidget(layerList);
resourceSplitter->addWidget(propertyPanel);
canvasSplitter = new QSplitter(Qt::Horizontal);
canvasSplitter->addWidget(sourceCanvas);
canvasSplitter->addWidget(destinationCanvas);
sourceSplitter = new QSplitter(Qt::Vertical);
sourceSplitter->addWidget(sourceList);
sourceSplitter->addWidget(shapeList);
mainSplitter->addWidget(sourceSplitter);
mainSplitter->addWidget(canvasSplitter);
mainSplitter->setStretchFactor(1, 1); // Upon resizing window, give the extra stretch expansion to canvasSplitter.
mainSplitter->addWidget(resourceSplitter);
// Initialize size to 2:1 proportions.
QSize sz = mainSplitter->size();
QList<int> sizes;
sizes.append(sz.height() * 2 / 3);
sizes.append(sz.height() - sizes.at(0));
mainSplitter->setSizes(sizes);
// Upon resizing window, give some extra stretch expansion to canvasSplitter.
//mainSplitter->setStretchFactor(0, 1);
setWindowTitle(tr("Libremapping"));
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
@@ -312,9 +360,17 @@ void MainWindow::createLayout()
connect(sourceList, SIGNAL(itemSelectionChanged()),
this, SLOT(handleSourceItemSelectionChanged()));
connect(shapeList, SIGNAL(itemSelectionChanged()),
this, SLOT(handleShapeItemSelectionChanged()));
// sourceList->setModel(sourcesModel);
connect(layerList, SIGNAL(itemSelectionChanged()),
this, SLOT(handleLayerItemSelectionChanged()));
connect(layerList, SIGNAL(itemChanged(QListWidgetItem*)),
this, SLOT(handleLayerItemChanged(QListWidgetItem*)));
connect(layerList->model(), SIGNAL(layoutChanged()),
this, SLOT(handleLayerIndexesMoved()));
// sourceList->setModel(sourcesModel);
//
// connect(sourceList->selectionModel(),
// SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
@@ -348,12 +404,12 @@ void MainWindow::createActions()
importAction = new QAction(tr("&Import media source..."), this);
importAction->setIcon(QIcon(":/images/document-import-2.png"));
importAction->setShortcut(QKeySequence::Italic); // ctrl-I
importAction->setShortcut(QKeySequence::Open);
importAction->setStatusTip(tr("Import a media source file"));
connect(importAction, SIGNAL(triggered()), this, SLOT(import()));
exitAction = new QAction(tr("E&xit"), this);
exitAction->setShortcut(QKeySequence::Quit);
exitAction->setShortcut(tr("Ctrl+Q"));
exitAction->setStatusTip(tr("Exit the application"));
connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
@@ -387,7 +443,7 @@ void MainWindow::createActions()
addQuadAction = new QAction(tr("&Add quad"), this);
addQuadAction->setIcon(QIcon(":/images/draw-rectangle-2.png"));
addQuadAction->setStatusTip(tr("Add quad"));
connect(addQuadAction, SIGNAL(triggered()), this, SLOT(addQuad()));
connect(addQuadAction, SIGNAL(triggered()), this, SLOT(addMesh()));
addTriangleAction = new QAction(tr("&Add triangle"), this);
addTriangleAction->setIcon(QIcon(":/images/draw-triangle.png"));
@@ -447,7 +503,6 @@ void MainWindow::createContextMenu()
void MainWindow::createToolBars()
{
fileToolBar = addToolBar(tr("&File"));
fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
fileToolBar->addAction(importAction);
fileToolBar->addAction(newAction);
fileToolBar->addAction(openAction);
@@ -490,9 +545,8 @@ void MainWindow::readSettings()
restoreGeometry(settings.value("geometry").toByteArray());
mainSplitter->restoreState(settings.value("mainSplitter").toByteArray());
sourceSplitter->restoreState(settings.value("sourceSplitter").toByteArray());
resourceSplitter->restoreState(settings.value("resourceSplitter").toByteArray());
canvasSplitter->restoreState(settings.value("canvasSplitter").toByteArray());
config_osc_receive_port = settings.value("osc_receive_port", 12345).toInt();
}
void MainWindow::writeSettings()
@@ -501,9 +555,8 @@ void MainWindow::writeSettings()
settings.setValue("geometry", saveGeometry());
settings.setValue("mainSplitter", mainSplitter->saveState());
settings.setValue("sourceSplitter", sourceSplitter->saveState());
settings.setValue("resourceSplitter", resourceSplitter->saveState());
settings.setValue("canvasSplitter", canvasSplitter->saveState());
settings.setValue("osc_receive_port", config_osc_receive_port);
}
bool MainWindow::okToContinue()
@@ -528,55 +581,30 @@ bool MainWindow::okToContinue()
bool MainWindow::loadFile(const QString &fileName)
{
QFile file(fileName);
// TODO: Try to read file.
// if (!spreadsheet->readFile(fileName))
// {
// statusBar()->showMessage(tr("Loading canceled"), 2000);
// return false;
// }
if (! file.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::warning(this, tr("Error reading mapping project file"),
tr("Cannot read file %1:\n%2.")
.arg(fileName)
.arg(file.errorString()));
return false;
}
mappingManager->clearProject(); // FIXME: clearProject is not implemented!
ProjectReader reader(mappingManager);
if (! reader.readFile(&file))
{
QMessageBox::warning(this, tr("Error reading mapping project file"),
tr("Parse error in file %1:\n\n%2")
.arg(fileName)
.arg(reader.errorString()));
}
else
{
statusBar()->showMessage(tr("File loaded"), 2000);
setCurrentFile(fileName);
}
setCurrentFile(fileName);
statusBar()->showMessage(tr("File loaded"), 2000);
return true;
}
bool MainWindow::saveFile(const QString &fileName)
{
QFile file(fileName);
if (! file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::warning(this, tr("Error saving mapping project"),
tr("Cannot write file %1:\n%2.")
.arg(fileName)
.arg(file.errorString()));
return false;
}
// TODO: Try to write file.
// if (!spreadsheet->writeFile(fileName))
// {
// statusBar()->showMessage(tr("Saving canceled"), 2000);
// return false;
// }
ProjectWriter writer(mappingManager);
if (writer.writeFile(&file))
{
setCurrentFile(fileName);
statusBar()->showMessage(tr("File saved"), 2000);
return true;
}
else
return false;
setCurrentFile(fileName);
statusBar()->showMessage(tr("File saved"), 2000);
return true;
}
void MainWindow::setCurrentFile(const QString &fileName)
@@ -593,12 +621,7 @@ void MainWindow::setCurrentFile(const QString &fileName)
setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("LibreMapping Project")));
}
// TODO
// bool MainWindow::updateMediaFile(const QString &source_name, const QString &fileName)
// {
// }
bool MainWindow::importMediaFile(const QString &fileName)
bool MainWindow::importFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
@@ -612,7 +635,7 @@ bool MainWindow::importMediaFile(const QString &fileName)
QApplication::setOverrideCursor(Qt::WaitCursor);
// Add image to model.
int imageId = mappingManager->addImage(fileName, sourceCanvas->width(), sourceCanvas->height());
uint imageId = mappingManager->addImage(fileName, sourceCanvas->width(), sourceCanvas->height());
// Add image to sourceList widget.
QListWidgetItem* item = new QListWidgetItem(strippedName(fileName));
@@ -630,24 +653,39 @@ bool MainWindow::importMediaFile(const QString &fileName)
return true;
}
void MainWindow::addMappingItem(int mappingId)
void MainWindow::addLayerItem(uint layerId)
{
Mapping::ptr mapping = mappingManager->getMapping(mappingId);
Q_CHECK_PTR(mapping);
Layer::ptr layer = mappingManager->getLayerById(layerId);
Q_CHECK_PTR(layer);
Mapping::ptr mapping = layer->getMapping();
uint mappingId = mapping->getId();
QString label;
QIcon icon;
// Add mapper.
// XXX hardcoded for textures
std::tr1::shared_ptr<TextureMapping> textureMapping = std::tr1::static_pointer_cast<TextureMapping>(mapping);
Q_CHECK_PTR(textureMapping);
Mapper::ptr mapper;
// XXX Branching on nVertices() is crap
// Triangle
if (mapping->getShape()->nVertices() == 3)
{
label = QString("Triangle %1").arg(mappingId);
icon = QIcon(":/images/draw-triangle.png");
mapper = Mapper::ptr(new TriangleTextureMapper(textureMapping));
}
// Mesh
else if (mapping->getShape()->nVertices() == 4)
{
label = QString("Quad %1").arg(mappingId);
icon = QIcon(":/images/draw-rectangle-2.png");
mapper = Mapper::ptr(new MeshTextureMapper(textureMapping));
}
else
{
@@ -655,13 +693,32 @@ void MainWindow::addMappingItem(int mappingId)
icon = QIcon(":/images/draw-polygon-2.png");
}
// Add image to sourceList widget.
// Add to list of mappers.
mappers[mappingId] = mapper;
QWidget* mapperEditor = mapper->getPropertiesEditor();
propertyPanel->addWidget(mapperEditor);
propertyPanel->setCurrentWidget(mapperEditor);
propertyPanel->setEnabled(true);
// When mapper value is changed, update canvases.
connect(mapper.get(), SIGNAL(valueChanged()),
this, SLOT(updateAll()));
connect(sourceCanvas, SIGNAL(shapeChanged(Shape*)),
mapper.get(), SLOT(updateShape(Shape*)));
connect(destinationCanvas, SIGNAL(shapeChanged(Shape*)),
mapper.get(), SLOT(updateShape(Shape*)));
// Add item to layerList widget.
QListWidgetItem* item = new QListWidgetItem(label);
item->setData(Qt::UserRole, mappingId); // TODO: could possibly be replaced by a Paint pointer
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Checked);
item->setData(Qt::UserRole, layerId); // TODO: could possibly be replaced by a Paint pointer
item->setIcon(icon);
item->setSizeHint(QSize(item->sizeHint().width(), MainWindow::SHAPE_LIST_ITEM_HEIGHT));
shapeList->addItem(item);
shapeList->setCurrentItem(item);
layerList->insertItem(0, item);
layerList->setCurrentItem(item);
}
void MainWindow::clearWindow()
@@ -669,86 +726,13 @@ void MainWindow::clearWindow()
// TODO: implement clearWindow()
}
void MainWindow::updateAll()
{
sourceCanvas->update();
destinationCanvas->update();
}
QString MainWindow::strippedName(const QString &fullFileName)
{
return QFileInfo(fullFileName).fileName();
}
void MainWindow::startOscReceiver()
{
#ifdef HAVE_OSC
int port = config_osc_receive_port;
std::ostringstream os;
os << port;
osc_interface.reset(new OscInterface(this, os.str()));
if (port != 0)
{
osc_interface->start();
}
osc_timer = new QTimer(this); // FIXME: memleak?
connect(osc_timer, SIGNAL(timeout()), this, SLOT(pollOscInterface()));
osc_timer->start();
#endif
}
void MainWindow::pollOscInterface()
{
#ifdef HAVE_OSC
osc_interface->consume_commands();
#endif
}
void MainWindow::applyOscCommand(QVariantList & command)
{
bool VERBOSE = true;
if (VERBOSE)
{
std::cout << "Receive OSC: ";
for (int i = 0; i < command.size(); ++i)
{
if (command.at(i).type() == QVariant::Int)
{
std::cout << command.at(i).toInt() << " ";
}
else if (command.at(i).type() == QVariant::Double)
{
std::cout << command.at(i).toDouble() << " ";
}
else if (command.at(i).type() == QVariant::String)
{
std::cout << command.at(i).toString().toStdString() << " ";
}
else
{
std::cout << "??? ";
}
}
std::cout << std::endl;
std::cout.flush();
}
if (command.size() < 2)
return;
if (command.at(0).type() != QVariant::String)
return;
if (command.at(1).type() != QVariant::String)
return;
std::string path = command.at(0).toString().toStdString();
std::string typetags = command.at(1).toString().toStdString();
// Handle all OSC messages here
if (path == "/image/uri" && typetags == "s")
{
std::string image_uri = command.at(2).toString().toStdString();
std::cout << "TODO load /image/uri " << image_uri << std::endl;
}
else if (path == "/add/quad")
addQuad();
else if (path == "/add/triangle")
addTriangle();
else if (path == "/project/save")
save();
else if (path == "/project/open")
open();
}