From 093fb3cd9d427ca72c3d9cbf7fb6f47cd1368bb6 Mon Sep 17 00:00:00 2001 From: baydam Date: Tue, 5 Jan 2016 12:10:54 +0000 Subject: [PATCH 01/46] Fix: #179 Paints and mappings renamings are now saved in file --- MainWindow.cpp | 52 +++++++++++++++++++++++++++++++++++------------ MainWindow.h | 10 +++++---- Mapping.h | 7 +++++++ OscInterface.cpp | 4 ++-- ProjectReader.cpp | 10 +++++++++ ProjectWriter.cpp | 3 ++- 6 files changed, 66 insertions(+), 20 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index aa5d3f4..ba9f8ab 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -718,11 +718,11 @@ void MainWindow::deleteItem() } } -void MainWindow::cloneItem() +void MainWindow::duplicateMappingItem() { if (currentSelectedItem) { - cloneMappingItem(getItemId(*mappingList->currentItem())); + duplicateMapping(getItemId(*mappingList->currentItem())); } else { @@ -747,17 +747,27 @@ void MainWindow::renameMappingItem() // Set current item editable and rename it QListWidgetItem* item = mappingList->currentItem(); item->setFlags(item->flags() | Qt::ItemIsEditable); + // Used by context menu mappingList->editItem(item); + // Switch to mapping tab. contentTab->setCurrentWidget(mappingSplitter); } -void MainWindow::renameMappingItem(uid mappingId, QString name) +void MainWindow::renameMapping(uid mappingId, QString name) { - if (mappingList->count() > 0) { - mappingList->item(mappingId)->setText(name); + Mapping::ptr mapping = mappingManager->getMappingById(mappingId); + if (!mapping.isNull()) { + getItemFromId(*mappingList, mappingId)->setText(name); + mapping->setName(name); } } +void MainWindow::mappingListEditEnd(QWidget *editor) +{ + QString name = reinterpret_cast(editor)->text(); + renameMapping(getItemId(*mappingList->currentItem()), name); +} + void MainWindow::deletePaintItem() { if(currentSelectedItem) @@ -775,17 +785,27 @@ void MainWindow::renamePaintItem() // Set current item editable and rename it QListWidgetItem* item = paintList->currentItem(); item->setFlags(item->flags() | Qt::ItemIsEditable); + // Used by context menu paintList->editItem(item); + // Switch to paint tab contentTab->setCurrentWidget(paintSplitter); } -void MainWindow::renamePaintItem(uid paintId, QString name) +void MainWindow::renamePaint(uid paintId, QString name) { - if (paintList->count() > 0) { - paintList->item(paintId)->setText(name); + Paint::ptr paint = mappingManager->getPaintById(paintId); + if (!paint.isNull()) { + getItemFromId(*paintList, paintId)->setText(name); + paint->setName(name); } } +void MainWindow::paintListEditEnd(QWidget *editor) +{ + QString name = reinterpret_cast(editor)->text(); + renamePaint(getItemId(*paintList->currentItem()), name); +} + void MainWindow::openRecentFile() { QAction *action = qobject_cast(sender()); @@ -1123,7 +1143,7 @@ void MainWindow::deleteMapping(uid mappingId) } } -void MainWindow::cloneMappingItem(uid mappingId) +void MainWindow::duplicateMapping(uid mappingId) { // Current Mapping Mapping::ptr mappingPtr = mappingManager->getMappingById(mappingId); @@ -1430,7 +1450,7 @@ void MainWindow::createActions() cloneAction->setShortcut(tr("Ctrl+D")); cloneAction->setStatusTip(tr("Duplicate item")); cloneAction->setIconVisibleInMenu(false); - connect(cloneAction, SIGNAL(triggered()), this, SLOT(cloneItem())); + connect(cloneAction, SIGNAL(triggered()), this, SLOT(duplicateMappingItem())); // Delete mapping. deleteMappingAction = new QAction(tr("Delete"), this); @@ -2462,6 +2482,12 @@ void MainWindow::connectProjectWidgets() connect(paintList, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(handleItemSelected(QListWidgetItem*))); + // Rename Paint with double click + connect(paintList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), + this, SLOT(renamePaintItem())); + // When finish to edit mapping item + connect(paintList->itemDelegate(), SIGNAL(commitData(QWidget*)), + this, SLOT(paintListEditEnd(QWidget*))); connect(mappingList, SIGNAL(itemSelectionChanged()), this, SLOT(handleMappingItemSelectionChanged())); @@ -2483,9 +2509,9 @@ void MainWindow::connectProjectWidgets() // Rename mapping with double click connect(mappingList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(renameMappingItem())); - // Rename Paint with double click - connect(paintList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), - this, SLOT(renamePaintItem())); + // When finish to edit mapping item + connect(mappingList->itemDelegate(), SIGNAL(commitData(QWidget*)), + this, SLOT(mappingListEditEnd(QWidget*))); } void MainWindow::disconnectProjectWidgets() diff --git a/MainWindow.h b/MainWindow.h index ab563d4..6397118 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -93,12 +93,14 @@ private slots: // Edit menu. void deleteItem(); // Context menu for mappings. - void cloneItem(); + void duplicateMappingItem(); void deleteMappingItem(); void renameMappingItem(); + void mappingListEditEnd(QWidget* editor); // Context menu for paints void deletePaintItem(); void renamePaintItem(); + void paintListEditEnd(QWidget* editor); // Widget callbacks. void handlePaintItemSelectionChanged(); @@ -179,7 +181,7 @@ public slots: void deleteMapping(uid mappingId); /// Clone/duplicate a mapping - void cloneMappingItem(uid mappingId); + void duplicateMapping(uid mappingId); /// Deletes/removes a paint and all associated mappigns. void deletePaint(uid paintId, bool replace); @@ -240,8 +242,8 @@ public: void addPaintItem(uid paintId, const QIcon& icon, const QString& name); void updatePaintItem(uid paintId, const QIcon& icon, const QString& name); void removePaintItem(uid paintId); - void renameMappingItem(uid mappingId, QString name); - void renamePaintItem(uid paintId, QString name); + void renameMapping(uid mappingId, QString name); + void renamePaint(uid paintId, QString name); void clearWindow(); // Check if the file exists bool fileExists(const QString file); diff --git a/Mapping.h b/Mapping.h index 7a6d568..49351f1 100644 --- a/Mapping.h +++ b/Mapping.h @@ -59,6 +59,9 @@ private: float _opacity; int _depth; // depth of the layer + // Mapping name + QString _name; + protected: /// Constructor. Mapping(Paint::ptr paint, MShape::ptr shape, uid id=NULL_UID); @@ -118,6 +121,10 @@ public: float getOpacity() const { return _opacity * _paint->getOpacity(); } void setPaint(Paint::ptr p) { _paint = p; } + // Set mapping name + void setName(const QString& name) { _name = name; } + // Get mapping name + QString getName() const { return _name; } }; /** diff --git a/OscInterface.cpp b/OscInterface.cpp index 5d1c278..bfad63d 100644 --- a/OscInterface.cpp +++ b/OscInterface.cpp @@ -211,13 +211,13 @@ void OscInterface::applyOscCommand(MainWindow &main_window, QVariantList & comma { int mappingId = command.at(2).toInt(); QString mappingName = command.at(3).toString(); - main_window.renameMappingItem(mappingId, mappingName); + main_window.renameMapping(mappingId, mappingName); } else if (path == "/mapmap/paint/media/rename" && typetags == "is") { int paintId = command.at(2).toInt(); QString paintName = command.at(3).toString(); - main_window.renamePaintItem(paintId, paintName); + main_window.renamePaint(paintId, paintName); } else if (path == "/mapmap/quit") { diff --git a/ProjectReader.cpp b/ProjectReader.cpp index 18809de..704023b 100644 --- a/ProjectReader.cpp +++ b/ProjectReader.cpp @@ -100,6 +100,10 @@ void ProjectReader::parsePaint(const QDomElement& paint) uid id = _window->createMediaPaint(paintAttrId.toInt(), uri, x.toFloat(), y.toFloat(), paintAttrType == "image", false, rate.toDouble()); if (id == NULL_UID) _xml.raiseError(QObject::tr("Cannot create media with uri %1.").arg(uri)); + + // Restore Paint name + if (!paintAttrName.isEmpty()) + _window->renamePaint(id, paintAttrName); } else if (paintAttrType == "color") { @@ -110,6 +114,9 @@ void ProjectReader::parsePaint(const QDomElement& paint) if (id == NULL_UID) _xml.raiseError(QObject::tr("Cannot create color with RGB hex code %1.").arg(rgb)); + // Restore Paint name + if (!paintAttrName.isEmpty()) + _window->renamePaint(id, paintAttrName); } else _xml.raiseError(QObject::tr("Unsupported paint type: %1.").arg(paintAttrType)); @@ -120,6 +127,7 @@ void ProjectReader::parseMapping(const QDomElement& mapping) { uid id = NULL_UID; QString mappingAttrId = mapping.attribute("id", QString::number(NULL_UID)); + QString mappingAttrName = mapping.attribute("name", ""); QString mappingAttrPaintId = mapping.attribute("paint_id", QString::number(NULL_UID)); QString mappingAttrType = mapping.attribute("type", ""); @@ -218,6 +226,8 @@ void ProjectReader::parseMapping(const QDomElement& mapping) _window->setMappingVisible(id, isVisible); _window->setMappingSolo (id, isSolo); _window->setMappingLocked (id, isLocked); + if (!mappingAttrName.isEmpty()) + _window->renameMapping(id, mappingAttrName); } } diff --git a/ProjectWriter.cpp b/ProjectWriter.cpp index 851e372..6afb942 100644 --- a/ProjectWriter.cpp +++ b/ProjectWriter.cpp @@ -54,7 +54,7 @@ void ProjectWriter::writeItem(Paint *item) { _xml.writeStartElement("paint"); _xml.writeAttribute("id", QString::number(item->getId())); - //_xml.writeAttribute("name", item->getName()); + _xml.writeAttribute("name", item->getName()); _xml.writeAttribute("type", item->getType()); if (item->getType() == "media") @@ -142,6 +142,7 @@ void ProjectWriter::writeItem(Mapping *item) _xml.writeStartElement("mapping"); qDebug() << "ID: " << item->getId() << endl; _xml.writeAttribute("id", QString::number(item->getId())); + _xml.writeAttribute("name", item->getName()); _xml.writeAttribute("paint_id", QString::number(item->getPaint()->getId())); _xml.writeAttribute("type", item->getType()); From f03be893a3b0b2d26736fb8f26ca92ef63a031d7 Mon Sep 17 00:00:00 2001 From: baydam Date: Tue, 5 Jan 2016 18:45:54 +0000 Subject: [PATCH 02/46] Fix: #159 Handle corrupted files --- MainWindow.cpp | 28 +++++++++++++++++++++++++--- MainWindow.h | 8 +++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index e1c7cb8..a35da83 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -753,7 +753,7 @@ void MainWindow::renameMappingItem() contentTab->setCurrentWidget(mappingSplitter); } -void MainWindow::renameMapping(uid mappingId, QString name) +void MainWindow::renameMapping(uid mappingId, const QString &name) { Mapping::ptr mapping = mappingManager->getMappingById(mappingId); if (!mapping.isNull()) { @@ -791,7 +791,7 @@ void MainWindow::renamePaintItem() contentTab->setCurrentWidget(paintSplitter); } -void MainWindow::renamePaint(uid paintId, QString name) +void MainWindow::renamePaint(uid paintId, const QString &name) { Paint::ptr paint = mappingManager->getPaintById(paintId); if (!paint.isNull()) { @@ -2045,6 +2045,9 @@ bool MainWindow::importMediaFile(const QString &fileName, bool isImage) QFile file(fileName); QDir currentDir; + if (!fileSupported(fileName, isImage)) + return false; + bool live = false; if (!file.open(QIODevice::ReadOnly)) { if (file.isSequential()) @@ -2357,7 +2360,7 @@ void MainWindow::clearWindow() clearProject(); } -bool MainWindow::fileExists(const QString file) +bool MainWindow::fileExists(const QString &file) { QFileInfo checkFile(file); @@ -2367,6 +2370,25 @@ bool MainWindow::fileExists(const QString file) return false; } +bool MainWindow::fileSupported(const QString &file, bool isImage) +{ + QFileInfo fileInfo(file); + QString fileExtension = fileInfo.suffix(); + + if (isImage) { + if (MM::IMAGE_FILES_FILTER.contains(fileExtension, Qt::CaseInsensitive)) + return true; + } else { + if (MM::VIDEO_FILES_FILTER.contains(fileExtension, Qt::CaseInsensitive)) + return true; + } + + QMessageBox::warning(this, tr("Warning"), + tr("The following file is not supported: %1") + .arg(fileInfo.fileName())); + return false; +} + QString MainWindow::locateMediaFile(const QString &uri, bool isImage) { // Get more info about url diff --git a/MainWindow.h b/MainWindow.h index 6397118..ea5683a 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -242,11 +242,13 @@ public: void addPaintItem(uid paintId, const QIcon& icon, const QString& name); void updatePaintItem(uid paintId, const QIcon& icon, const QString& name); void removePaintItem(uid paintId); - void renameMapping(uid mappingId, QString name); - void renamePaint(uid paintId, QString name); + void renameMapping(uid mappingId, const QString& name); + void renamePaint(uid paintId, const QString& name); void clearWindow(); // Check if the file exists - bool fileExists(const QString file); + bool fileExists(const QString& file); + // Check if the file is supported + bool fileSupported(const QString& file, bool isImage); // Locate the file not found QString locateMediaFile(const QString& uri, bool isImage); From 82faf0e3c8dd28dba01ae0ed4f3dbca1a7902761 Mon Sep 17 00:00:00 2001 From: Tats Date: Thu, 7 Jan 2016 11:44:26 -0500 Subject: [PATCH 03/46] Added exclusions for moc_ qrc_ and .txt files. --- Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doxyfile b/Doxyfile index 6d760d4..df9e333 100644 --- a/Doxyfile +++ b/Doxyfile @@ -558,7 +558,7 @@ EXCLUDE_SYMLINKS = NO # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* -EXCLUDE_PATTERNS = *old/* *test/* +EXCLUDE_PATTERNS = *old/* *test/* moc_* qrc_* *.txt # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the From 5afc6b3cb5dfc1a507144b87ce9f6b37faa8dc05 Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 7 Jan 2016 18:42:26 +0000 Subject: [PATCH 04/46] Fix: #181 Image glitch when undo stack not displayed --- MainWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index a35da83..426fffe 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -1259,9 +1259,6 @@ void MainWindow::createLayout() mappingPropertyPanel->setDisabled(true); mappingPropertyPanel->setMinimumHeight(MAPPING_PROPERTY_PANEL_MINIMUM_HEIGHT); - // Create undo view. - undoView = new QUndoView(getUndoStack(), this); - // Create canvases. sourceCanvas = new SourceGLCanvas(this); sourceCanvas->setFocusPolicy(Qt::ClickFocus); @@ -2458,6 +2455,9 @@ void MainWindow::displayUndoStack(bool display) { _displayUndoStack = display; + // Create undo view. + undoView = new QUndoView(getUndoStack(), this); + if (display) { contentTab->addTab(undoView, tr("Undo stack")); } else { From b29207ccd79c5f8cca8d4976a5946a66608f9544 Mon Sep 17 00:00:00 2001 From: baydam Date: Tue, 12 Jan 2016 18:28:24 +0000 Subject: [PATCH 05/46] Fix bug when display undo stack is unchecked --- MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 426fffe..080d470 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -2461,7 +2461,7 @@ void MainWindow::displayUndoStack(bool display) if (display) { contentTab->addTab(undoView, tr("Undo stack")); } else { - contentTab->removeTab(contentTab->indexOf(undoView)); + contentTab->removeTab(2); } } From 4e3ccf45d4b5b1de4b30bc26d8aaa43cdfead472 Mon Sep 17 00:00:00 2001 From: baydam Date: Wed, 13 Jan 2016 20:38:43 +0000 Subject: [PATCH 06/46] Add "zoom in/out/reset and fit to content" buttons --- MainWindow.cpp | 46 ++++++--- MainWindow.h | 1 + MapperGLCanvas.cpp | 215 ++++++++++++++++++++++++++++++++------- MapperGLCanvas.h | 36 ++++++- OutputGLCanvas.cpp | 1 + mapmap.qrc | 84 ++++++--------- resources/qss/mapmap.qss | 28 +++++ 7 files changed, 308 insertions(+), 103 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 426fffe..ace6336 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -131,23 +131,25 @@ void MainWindow::handlePaintItemSelectionChanged() void MainWindow::handleMappingItemSelectionChanged() { - if (mappingList->selectedItems().empty()) - { - removeCurrentMapping(); - } - else - { - QListWidgetItem* item = mappingList->currentItem(); - currentSelectedItem = item; - - // Set current paint and mappings. - uid mappingId = getItemId(*item); - Mapping::ptr mapping = mappingManager->getMappingById(mappingId); - uid paintId = mapping->getPaint()->getId(); - setCurrentMapping(mappingId); - setCurrentPaint(paintId); - } + if (mappingList->selectedItems().empty()) + { + removeCurrentMapping(); + } + else + { + QListWidgetItem* item = mappingList->currentItem(); + currentSelectedItem = item; + // Set current paint and mappings. + uid mappingId = getItemId(*item); + Mapping::ptr mapping = mappingManager->getMappingById(mappingId); + uid paintId = mapping->getPaint()->getId(); + setCurrentMapping(mappingId); + setCurrentPaint(paintId); + // Enable or not zoom tool buttons + sourceCanvas->enableZoomToolButtons(item ? true : false); + destinationCanvas->enableZoomToolButtons(item ? true : false); + } // Update canvases. updateCanvases(); @@ -1605,6 +1607,14 @@ void MainWindow::createActions() displayUndoStackAction->setChecked(_displayUndoStack); // Manage show/hide of Undo Stack connect(displayUndoStackAction, SIGNAL(toggled(bool)), this, SLOT(displayUndoStack(bool))); + + // Toggle display of zoom tool buttons + displayZoomToolAction = new QAction(tr("Display &Zoom Toolbar"), this); + displayZoomToolAction->setShortcut(tr("Alt+Z")); + displayZoomToolAction->setCheckable(true); + displayZoomToolAction->setChecked(true); + connect(displayZoomToolAction, SIGNAL(toggled(bool)), sourceCanvas, SLOT(showZoomToolBar(bool))); + connect(displayZoomToolAction, SIGNAL(toggled(bool)), destinationCanvas, SLOT(showZoomToolBar(bool))); } void MainWindow::startFullScreen() @@ -1673,6 +1683,7 @@ void MainWindow::createMenus() viewMenu->addAction(displayTestSignalAction); viewMenu->addSeparator(); viewMenu->addAction(displayUndoStackAction); + viewMenu->addAction(displayZoomToolAction); // Run. runMenu = menuBar->addMenu(tr("&Run")); @@ -1831,6 +1842,8 @@ void MainWindow::readSettings() // new in 0.3.2 if (settings.contains("displayUndoStack")) displayUndoStackAction->setChecked(settings.value("displayUndoStack").toBool()); + if (settings.contains("zoomToolBar")) + displayZoomToolAction->setChecked(settings.value("zoomToolBar").toBool()); } void MainWindow::writeSettings() @@ -1848,6 +1861,7 @@ void MainWindow::writeSettings() settings.setValue("displayTestSignal", displayTestSignalAction->isChecked()); settings.setValue("osc_receive_port", config_osc_receive_port); settings.setValue("displayUndoStack", displayUndoStackAction->isChecked()); + settings.setValue("zoomToolBar", displayZoomToolAction->isChecked()); } bool MainWindow::okToContinue() diff --git a/MainWindow.h b/MainWindow.h index ea5683a..7e2fbdb 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -325,6 +325,7 @@ private: QAction *displayTestSignalAction; QAction *stickyVerticesAction; QAction *displayUndoStackAction; + QAction *displayZoomToolAction; enum { MaxRecentFiles = 10 }; enum { MaxRecentVideo = 5 }; diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index b72f899..e2658f2 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -30,7 +30,8 @@ MapperGLCanvas::MapperGLCanvas(MainWindow* mainWindow, QWidget* parent, const QG _activeVertex(NO_VERTEX), _shapeGrabbed(false), // comment out? _shapeFirstGrab(false), // comment out? - _zoomLevel(0) + _zoomLevel(0), + _shapeIsAdapted(false) { // For now clicking on the window doesn't do anything. setDragMode(QGraphicsView::NoDrag); @@ -59,6 +60,11 @@ MapperGLCanvas::MapperGLCanvas(MainWindow* mainWindow, QWidget* parent, const QG // Black background. this->scene()->setBackgroundBrush(Qt::black); + + // Create zoom tool buttons + createZoomToolButtons(); + // Disable zoom tool buttons + enableZoomToolButtons(false); } MShape::ptr MapperGLCanvas::getCurrentShape() @@ -98,6 +104,73 @@ void MapperGLCanvas::currentShapeWasChanged() emit shapeChanged(getCurrentShape().data()); } +void MapperGLCanvas::applyZoomToView() +{ + // Re-bound zoom (for consistency). + qreal zoomFactor = getZoomFactor(); + // Get first of the list of all the views + QGraphicsView* view = this->scene()->views().first(); + // Resets the view transformation matrix + view->resetMatrix(); + // Scale the current view + view->scale(zoomFactor, zoomFactor); + // And update + view->update(); +} + +void MapperGLCanvas::createZoomToolButtons() +{ + // Create zoom tool bar + _zoomToolBox = new QWidget(this); + _zoomToolBox->setWindowFlags(Qt::WindowStaysOnTopHint); + _zoomToolBox->setObjectName("zoom-toolbox"); + + // Create vertical layout for buttons + QVBoxLayout* buttonsLayout = new QVBoxLayout; + buttonsLayout->setMargin(0); + // Create buttons + // Zoom In button + _zoomInButton = new QPushButton; + _zoomInButton->setIcon(QIcon(":/zoom-in")); + _zoomInButton->setIconSize(QSize(22, 22)); + _zoomInButton->setToolTip(tr("Enlarge the shape")); + _zoomInButton->setFixedSize(32, 32); + _zoomInButton->setObjectName("zoom-in"); + connect(_zoomInButton, SIGNAL(clicked()), this, SLOT(increaseZoomLevel())); + // Zoom Out button + _zoomOutButton = new QPushButton; + _zoomOutButton->setIcon(QIcon(":/zoom-out")); + _zoomOutButton->setIconSize(QSize(22, 22)); + _zoomOutButton->setToolTip(tr("Shrink the shape")); + _zoomOutButton->setFixedSize(32, 32); + _zoomOutButton->setObjectName("zoom-out"); + connect(_zoomOutButton, SIGNAL(clicked()), this, SLOT(decreaseZoomLevel())); + // Reset to normal size button. + _resetZoomButton = new QPushButton; + _resetZoomButton->setIcon(QIcon(":/reset-zoom")); + _resetZoomButton->setIconSize(QSize(22, 22)); + _resetZoomButton->setToolTip(tr("Reset the shape to the normal size")); + _resetZoomButton->setFixedSize(32, 32); + _resetZoomButton->setObjectName("reset-zoom"); + connect(_resetZoomButton, SIGNAL(clicked()), this, SLOT(resetZoomLevel())); + // Fit to view button + _fitToViewButton = new QPushButton; + _fitToViewButton->setIcon(QIcon(":/zoom-fit")); + _fitToViewButton->setIconSize(QSize(22, 22)); + _fitToViewButton->setToolTip(tr("Fit the shape to content view")); + _fitToViewButton->setFixedSize(32, 32); + _fitToViewButton->setObjectName("zoom-fit"); + connect(_fitToViewButton, SIGNAL(clicked()), this, SLOT(fitShapeInView())); + + // Add buttons into layout + buttonsLayout->addWidget(_zoomInButton); + buttonsLayout->addWidget(_zoomOutButton); + buttonsLayout->addWidget(_resetZoomButton); + buttonsLayout->addWidget(_fitToViewButton); + // Insert layout in widget + _zoomToolBox->setLayout(buttonsLayout); +} + // void MapperGLCanvas::mousePressEvent(QMouseEvent* event) @@ -311,14 +384,12 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) // Checks if the key has been handled by this function or needs to be deferred to superclass. bool handledKey = false; - // Active vertex selected. if (hasActiveVertex()) { MShape::ptr shape = getCurrentShape(); QPoint pos = mapFromScene(shape->getVertex(_activeVertex)); handledKey = true; - switch (event->key()) { // TODO: key tab should switch to next vertex: not working because somehow caught at a higher level // to switch between frames of the layout @@ -342,12 +413,6 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) pos.rx()--; break; default: - if (event->matches(QKeySequence::Undo)) - undoStack->undo(); - - else if (event->matches(QKeySequence::Redo)) - undoStack->redo(); - else handledKey = false; break; } @@ -358,6 +423,22 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) // TODO: this will always be called even if no arrow key has been pressed (small performance issue). // Enable to Undo and Redo when arrow keys move the position of vertices undoStack->push(new MoveVertexCommand(this, TransformShapeCommand::STEP, _activeVertex, scenePos)); + } else { + handledKey = true; + if (event->matches(QKeySequence::Undo)) + undoStack->undo(); + else if (event->matches(QKeySequence::Redo)) + undoStack->redo(); + else if (event->matches(QKeySequence::ZoomIn)) + increaseZoomLevel(); + else if (event->matches(QKeySequence::ZoomOut)) + decreaseZoomLevel(); + else if (event->modifiers() == Qt::CTRL) { + if(event->key() == Qt::Key_0) + resetZoomLevel(); + } + else + handledKey = false; } // Defer unhandled keys to parent. @@ -466,38 +547,20 @@ void MapperGLCanvas::deselectAll() void MapperGLCanvas::wheelEvent(QWheelEvent *event) { - int deltaLevel = event->delta() / 120; - qreal zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); - if (deltaLevel > 0) + // [-120]-----[-1]|[1]++++++[120] + _deltaLevel = event->delta() / 120; + + if (_deltaLevel > 0) { - // First check if we're already at max. - while (deltaLevel && zoomFactor < MM::ZOOM_MAX) { - _zoomLevel++; - deltaLevel--; - zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); - } - zoomFactor = qMin(zoomFactor, MM::ZOOM_MAX); + // Increase zoom level + increaseZoomLevel(); } else { - // First check if we're already at min. - while (deltaLevel && zoomFactor > MM::ZOOM_MIN) { - _zoomLevel--; - deltaLevel++; - zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); - } - zoomFactor = qMax(zoomFactor, MM::ZOOM_MIN); + // Decrease zoom level + decreaseZoomLevel(); } - // Re-bound zoom (for consistency). - zoomFactor = getZoomFactor(); - - // Apply zoom to view. - QGraphicsView* view = scene()->views().first(); - view->resetMatrix(); - view->scale(zoomFactor, zoomFactor); - view->update(); - // Accept wheel scrolling event. event->accept(); } @@ -517,6 +580,88 @@ bool MapperGLCanvas::eventFilter(QObject *target, QEvent *event) } } +void MapperGLCanvas::increaseZoomLevel() +{ + qreal zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); + + if (zoomFactor < MM::ZOOM_MAX) { + _zoomLevel++; + if (_deltaLevel) + _deltaLevel--; + zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); + } + zoomFactor = qMin(zoomFactor, MM::ZOOM_MAX); + + // Reset adaptation + _shapeIsAdapted = false; + + // Apply to view + applyZoomToView(); +} + +void MapperGLCanvas::decreaseZoomLevel() +{ + qreal zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); + + if (zoomFactor > MM::ZOOM_MIN) { + _zoomLevel--; + if (_deltaLevel) + _deltaLevel++; + zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); + } + zoomFactor = qMax(zoomFactor, MM::ZOOM_MIN); + + // Reset adaptation + _shapeIsAdapted = false; + + // Apply to view + applyZoomToView(); +} + +void MapperGLCanvas::resetZoomLevel() +{ + // Reset zoom level to zero + _zoomLevel = 0; + + // Reset adaptation + _shapeIsAdapted = false; + + // Apply to view + applyZoomToView(); +} + +void MapperGLCanvas::fitShapeInView() +{ + // Reset zoom level before fit it + //resetZoomLevel(); + // Get first of the list of all the views + QGraphicsView* view = scene()->views().first(); + // Scales the view matrix + view->fitInView(this->scene()->itemsBoundingRect(), Qt::KeepAspectRatio); + // Get the horizontal scaling factor + _scalingFactor = view->matrix().m11(); + + // Adapt shape + _shapeIsAdapted = true; +} + +void MapperGLCanvas::showZoomToolBar(bool visible) +{ + if (visible) + _zoomToolBox->show(); + else + _zoomToolBox->hide(); +} + +void MapperGLCanvas::enableZoomToolButtons(bool enabled) +{ + // Enable/Disable all button + _zoomInButton->setEnabled(enabled); + _zoomOutButton->setEnabled(enabled); + _resetZoomButton->setEnabled(enabled); + _fitToViewButton->setEnabled(enabled); +} + void MapperGLCanvas::_glueVertex(QPointF* p) { diff --git a/MapperGLCanvas.h b/MapperGLCanvas.h index 0124686..28a155d 100644 --- a/MapperGLCanvas.h +++ b/MapperGLCanvas.h @@ -86,11 +86,17 @@ public: bool shapeGrabbed() const { return _shapeGrabbed; } bool vertexGrabbed() const { return _vertexGrabbed; } - qreal getZoomFactor() const { return qBound(qPow(MM::ZOOM_FACTOR, _zoomLevel), MM::ZOOM_MIN, MM::ZOOM_MAX); } + //qreal getZoomFactor() const { return qBound(qPow(MM::ZOOM_FACTOR, _zoomLevel), MM::ZOOM_MIN, MM::ZOOM_MAX); } + qreal getZoomFactor() const { return _shapeIsAdapted + ? _scalingFactor + : qBound(MM::ZOOM_MIN, qPow(MM::ZOOM_FACTOR, _zoomLevel), MM::ZOOM_MAX); } /// This function needs to be called after a shape inside the canvas has been changed for appropriate signals to be activated. void currentShapeWasChanged(); + // Apply zoom to view + void applyZoomToView(); + protected: // void initializeGL(); // void resizeGL(int width, int height); @@ -147,9 +153,27 @@ private: // The zoom level (in number of steps). int _zoomLevel; + // The scaling factor + qreal _scalingFactor; + + bool _shapeIsAdapted; + + // The delta level + int _deltaLevel; + // Pointer to MainWindow UndoStack QUndoStack *undoStack; + // Buttons for toolbox layout + QWidget* _zoomToolBox; + QPushButton* _zoomInButton; + QPushButton* _zoomOutButton; + QPushButton* _resetZoomButton; + QPushButton* _fitToViewButton; + + // Create zoom tool buttons + void createZoomToolButtons(); + signals: void shapeChanged(MShape*); void imageChanged(); @@ -168,6 +192,16 @@ public slots: // Event Filter bool eventFilter(QObject *target, QEvent *event); + // Zoom + void increaseZoomLevel(); + void decreaseZoomLevel(); + void resetZoomLevel(); + void fitShapeInView(); + + // Show/Hide zoom tool buttons + void showZoomToolBar(bool visible); + void enableZoomToolButtons(bool enabled); + protected: // TODO: Perhaps the sticky-sensitivity should be configurable through GUI void _glueVertex(QPointF* p); diff --git a/OutputGLCanvas.cpp b/OutputGLCanvas.cpp index d03fd50..8bd8236 100644 --- a/OutputGLCanvas.cpp +++ b/OutputGLCanvas.cpp @@ -30,6 +30,7 @@ OutputGLCanvas::OutputGLCanvas(MainWindow* mainWindow, QWidget* parent, const QG // Disable scrollbars. setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + showZoomToolBar(false); } void OutputGLCanvas::drawForeground(QPainter *painter , const QRectF &rect) diff --git a/mapmap.qrc b/mapmap.qrc index 561c045..699af80 100644 --- a/mapmap.qrc +++ b/mapmap.qrc @@ -1,53 +1,35 @@ - - resources/images/icons/newdoc_w.png - resources/images/icons/open_w.png - resources/images/icons/save_w.png - resources/images/icons/save_w.png - - resources/images/icons/fullscreen_w.png - resources/images/icons/nofullscreen_w.png - resources/images/icons/ctrl2_w.png - - resources/images/icons/add_movie_w.png - resources/images/icons/add_img_w.png - resources/images/icons/add_paint_w.png - - resources/images/shapes/add_quad.png - resources/images/shapes/add_triangle.png - resources/images/shapes/add_circle.png - - - - resources/images/icons/play_w.png - resources/images/icons/pause_w.png - resources/images/icons/rewind_w.png - - resources/images/shapes/add_quad.png - resources/images/shapes/add_triangle.png - resources/images/shapes/add_circle.png - - resources/images/shapes/add_circle.png - - resources/images/logo/logomapmap.png - resources/images/logo/logo_m_big_mapmap.png - resources/images/logo/splash.png - - resources/fonts/HelveticaNeueLTPro-Bd.otf - - resources/fonts/HelveticaNeueLTPro-Bd.otf - - resources/images/test-signal/test-signal.svg - - resources/qss/mapmap.qss - + + resources/images/icons/newdoc_w.png + resources/images/icons/open_w.png + resources/images/icons/save_w.png + resources/images/icons/save_w.png + resources/images/icons/fullscreen_w.png + resources/images/icons/nofullscreen_w.png + resources/images/icons/ctrl2_w.png + resources/images/icons/add_movie_w.png + resources/images/icons/add_img_w.png + resources/images/icons/add_paint_w.png + resources/images/shapes/add_quad.png + resources/images/shapes/add_triangle.png + resources/images/shapes/add_circle.png + resources/images/icons/play_w.png + resources/images/icons/pause_w.png + resources/images/icons/rewind_w.png + resources/images/shapes/add_quad.png + resources/images/shapes/add_triangle.png + resources/images/shapes/add_circle.png + resources/images/shapes/add_circle.png + resources/images/logo/logomapmap.png + resources/images/logo/logo_m_big_mapmap.png + resources/images/logo/splash.png + resources/fonts/HelveticaNeueLTPro-Bd.otf + resources/fonts/HelveticaNeueLTPro-Bd.otf + resources/images/test-signal/test-signal.svg + resources/qss/mapmap.qss + resources/images/icons/zoom_reset_w.png + resources/images/icons/zoom_in_w.png + resources/images/icons/zoom_out_w.png + resources/images/icons/zoom_fit_w.png + - diff --git a/resources/qss/mapmap.qss b/resources/qss/mapmap.qss index 2bcb487..91ddaa7 100644 --- a/resources/qss/mapmap.qss +++ b/resources/qss/mapmap.qss @@ -58,6 +58,34 @@ QGraphicsView { border-style: none; } +QPushButton#zoom-in, +QPushButton#zoom-out, +QPushButton#reset-zoom, +QPushButton#zoom-fit { + background-color: rgba(0, 0, 0, 0%); +} + +QPushButton:hover#zoom-in, QPushButton:checked#zoom-in, +QPushButton:hover#zoom-out, QPushButton:checked#zoom-out, +QPushButton:hover#reset-zoom, QPushButton:checked#reset-zoom, +QPushButton:hover#zoom-fit, QPushButton:checked#zoom-fit { + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, + stop: 0 #0c0927, stop: 1 #191C28); + border-radius: 2px; + border: none; +} + +QPushButton:pressed#zoom-in, +QPushButton:pressed#zoom-out, +QPushButton:pressed#reset-zoom, +QPushButton:pressed#zoom-fit { + border: none; +} + +QWidget#zoom-toolbox { + background-color: #272a36; +} + /* QListView::item:selected:!active { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, From ffd9d8aaddb5bce78e8667bb45f8e29b227c696a Mon Sep 17 00:00:00 2001 From: baydam Date: Fri, 15 Jan 2016 16:03:13 +0000 Subject: [PATCH 07/46] Add dropdown menu to show or set zoom level --- MainWindow.cpp | 4 +-- MapperGLCanvas.cpp | 90 ++++++++++++++++++++++++++++++++++++---------- MapperGLCanvas.h | 12 +++++-- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index ace6336..ac54797 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -147,8 +147,8 @@ void MainWindow::handleMappingItemSelectionChanged() setCurrentMapping(mappingId); setCurrentPaint(paintId); // Enable or not zoom tool buttons - sourceCanvas->enableZoomToolButtons(item ? true : false); - destinationCanvas->enableZoomToolButtons(item ? true : false); + sourceCanvas->enableZoomToolBar(item ? true : false); + destinationCanvas->enableZoomToolBar(item ? true : false); } // Update canvases. diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index e2658f2..46f2979 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -55,16 +55,16 @@ MapperGLCanvas::MapperGLCanvas(MainWindow* mainWindow, QWidget* parent, const QG setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers), this, shareWidget)); setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + // Create zoom tools layout + createZoomToolsLayout(); + // Disable zoom tool buttons + enableZoomToolBar(false); + // TODO: do we need to delete scene (or call new QGraphicsScene(this)?) setScene(scene ? scene : new QGraphicsScene); // Black background. this->scene()->setBackgroundBrush(Qt::black); - - // Create zoom tool buttons - createZoomToolButtons(); - // Disable zoom tool buttons - enableZoomToolButtons(false); } MShape::ptr MapperGLCanvas::getCurrentShape() @@ -116,17 +116,18 @@ void MapperGLCanvas::applyZoomToView() view->scale(zoomFactor, zoomFactor); // And update view->update(); + // Update dropdown menu + updateDropdownMenu(); } -void MapperGLCanvas::createZoomToolButtons() +void MapperGLCanvas::createZoomToolsLayout() { // Create zoom tool bar - _zoomToolBox = new QWidget(this); - _zoomToolBox->setWindowFlags(Qt::WindowStaysOnTopHint); - _zoomToolBox->setObjectName("zoom-toolbox"); + _zoomToolBar = new QWidget(this); + _zoomToolBar->setObjectName("zoom-toolbox"); - // Create vertical layout for buttons - QVBoxLayout* buttonsLayout = new QVBoxLayout; + // Create vertical layout for widgets + QHBoxLayout* buttonsLayout = new QHBoxLayout; buttonsLayout->setMargin(0); // Create buttons // Zoom In button @@ -162,13 +163,31 @@ void MapperGLCanvas::createZoomToolButtons() _fitToViewButton->setObjectName("zoom-fit"); connect(_fitToViewButton, SIGNAL(clicked()), this, SLOT(fitShapeInView())); - // Add buttons into layout + // Create separator + QFrame *separator = new QFrame(_zoomToolBar); + separator->setFixedSize(5, 30); + separator->setFrameShape(QFrame::VLine); + + // Create the dropdowm menu + _dropdownMenu = new QComboBox; + // make some settings + _dropdownMenu->setObjectName("dropdown-menu"); + // Create if empty or update list + updateDropdownMenu(); + // And listen + connect(_dropdownMenu, SIGNAL(activated(QString)), this, SLOT(setZoomFromMenu(QString))); + + // Add widgets into layout buttonsLayout->addWidget(_zoomInButton); buttonsLayout->addWidget(_zoomOutButton); buttonsLayout->addWidget(_resetZoomButton); buttonsLayout->addWidget(_fitToViewButton); + buttonsLayout->addWidget(separator); + buttonsLayout->addWidget(_dropdownMenu); + buttonsLayout->addSpacing(5); + // Insert layout in widget - _zoomToolBox->setLayout(buttonsLayout); + _zoomToolBar->setLayout(buttonsLayout); } @@ -632,8 +651,6 @@ void MapperGLCanvas::resetZoomLevel() void MapperGLCanvas::fitShapeInView() { - // Reset zoom level before fit it - //resetZoomLevel(); // Get first of the list of all the views QGraphicsView* view = scene()->views().first(); // Scales the view matrix @@ -643,23 +660,60 @@ void MapperGLCanvas::fitShapeInView() // Adapt shape _shapeIsAdapted = true; + + // Update zoom menu list + updateDropdownMenu(); } void MapperGLCanvas::showZoomToolBar(bool visible) { if (visible) - _zoomToolBox->show(); + _zoomToolBar->show(); else - _zoomToolBox->hide(); + _zoomToolBar->hide(); } -void MapperGLCanvas::enableZoomToolButtons(bool enabled) +void MapperGLCanvas::enableZoomToolBar(bool enabled) { // Enable/Disable all button _zoomInButton->setEnabled(enabled); _zoomOutButton->setEnabled(enabled); _resetZoomButton->setEnabled(enabled); _fitToViewButton->setEnabled(enabled); + _dropdownMenu->setEnabled(enabled); +} + +void MapperGLCanvas::setZoomFromMenu(const QString &text) +{ + // Get text choosen by user and convert it to double + qreal zoomFactor = text.mid(0, text.length() - 1).toDouble(); + // Set zoom factor + _scalingFactor = zoomFactor / 100; + + // Adapt shape + _shapeIsAdapted = true; + + // Apply to view + applyZoomToView(); +} + +void MapperGLCanvas::updateDropdownMenu() +{ + // Get current zoom factor percentage + QString zoomFactor = QString::number(int(getZoomFactor() * 100)).append(QChar('%')); + //Create list + QStringList zoomFactorList; + zoomFactorList << "400%" << "300%" << "200%" << "150%" << "125%" << + "100%" << "75%" << "50%" << "25%" << "12.5%"; + // Avoid duplicate + if (!zoomFactorList.contains(zoomFactor)) + zoomFactorList.append(zoomFactor); + // Clear if is not empty + _dropdownMenu->clear(); + // Add list item + _dropdownMenu->addItems(zoomFactorList); + // Select 100% by default + _dropdownMenu->setCurrentText(zoomFactor); } diff --git a/MapperGLCanvas.h b/MapperGLCanvas.h index 28a155d..9e72064 100644 --- a/MapperGLCanvas.h +++ b/MapperGLCanvas.h @@ -165,14 +165,16 @@ private: QUndoStack *undoStack; // Buttons for toolbox layout - QWidget* _zoomToolBox; + QWidget* _zoomToolBar; QPushButton* _zoomInButton; QPushButton* _zoomOutButton; QPushButton* _resetZoomButton; QPushButton* _fitToViewButton; + // Dropdown menu + QComboBox* _dropdownMenu; // Create zoom tool buttons - void createZoomToolButtons(); + void createZoomToolsLayout(); signals: void shapeChanged(MShape*); @@ -200,7 +202,11 @@ public slots: // Show/Hide zoom tool buttons void showZoomToolBar(bool visible); - void enableZoomToolButtons(bool enabled); + void enableZoomToolBar(bool enabled); + // Set zoom factor with drowmenu data + void setZoomFromMenu(const QString& text); + // Update and feedback zoom level + void updateDropdownMenu(); protected: // TODO: Perhaps the sticky-sensitivity should be configurable through GUI From e53ca4581fa32183b61a5f58de26b46bcce2d652 Mon Sep 17 00:00:00 2001 From: baydam Date: Mon, 18 Jan 2016 15:02:50 +0000 Subject: [PATCH 08/46] zoom toolbar margin enhancements --- MapperGLCanvas.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index 46f2979..f6c8b75 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -128,7 +128,7 @@ void MapperGLCanvas::createZoomToolsLayout() // Create vertical layout for widgets QHBoxLayout* buttonsLayout = new QHBoxLayout; - buttonsLayout->setMargin(0); + buttonsLayout->setContentsMargins(0, 0, 5, 0); // Create buttons // Zoom In button _zoomInButton = new QPushButton; @@ -184,7 +184,6 @@ void MapperGLCanvas::createZoomToolsLayout() buttonsLayout->addWidget(_fitToViewButton); buttonsLayout->addWidget(separator); buttonsLayout->addWidget(_dropdownMenu); - buttonsLayout->addSpacing(5); // Insert layout in widget _zoomToolBar->setLayout(buttonsLayout); From a7a56e6e922a8e94b5a48bf8700c92acd52ec249 Mon Sep 17 00:00:00 2001 From: baydam Date: Wed, 20 Jan 2016 16:35:36 +0000 Subject: [PATCH 09/46] Improvements of the menu elements --- MainWindow.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MainWindow.h b/MainWindow.h index 7e2fbdb..f680476 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -283,6 +283,9 @@ private: QMenu *recentVideoMenu; QMenu *mappingContextMenu; QMenu *paintContextMenu; + // Some menus when need to be separated + QMenu *sourceMenu; + QMenu *destinationMenu; // Toolbar. QToolBar *mainToolBar; @@ -300,7 +303,7 @@ private: QAction *exitAction; QAction *undoAction; QAction *redoAction; - QAction *cloneAction; + QAction *cloneMappingAction; QAction *deleteMappingAction; QAction *renameMappingAction; QAction *deletePaintAction; From efe5c8f02a340cc708a563fac22b4e93fe44eff7 Mon Sep 17 00:00:00 2001 From: baydam Date: Wed, 20 Jan 2016 18:56:39 +0000 Subject: [PATCH 10/46] Improvements of the menu elements --- MainWindow.cpp | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 0f83945..dd774d3 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -134,6 +134,12 @@ void MainWindow::handleMappingItemSelectionChanged() if (mappingList->selectedItems().empty()) { removeCurrentMapping(); + /* Disable some menus and buttons when + * no mapping was selected */ + sourceCanvas->enableZoomToolBar(false); + sourceMenu->setEnabled(false); + destinationCanvas->enableZoomToolBar(false); + destinationMenu->setEnabled(false); } else { @@ -146,9 +152,11 @@ void MainWindow::handleMappingItemSelectionChanged() uid paintId = mapping->getPaint()->getId(); setCurrentMapping(mappingId); setCurrentPaint(paintId); - // Enable or not zoom tool buttons - sourceCanvas->enableZoomToolBar(item ? true : false); - destinationCanvas->enableZoomToolBar(item ? true : false); + // Enable some menus and buttons + sourceCanvas->enableZoomToolBar(true); + sourceMenu->setEnabled(true); + destinationCanvas->enableZoomToolBar(true); + destinationMenu->setEnabled(true); } // Update canvases. @@ -1445,11 +1453,11 @@ void MainWindow::createActions() connect(aboutAction, SIGNAL(triggered()), this, SLOT(about())); // Duplicate. - cloneAction = new QAction(tr("Duplicate"), this); - cloneAction->setShortcut(tr("Ctrl+D")); - cloneAction->setStatusTip(tr("Duplicate item")); - cloneAction->setIconVisibleInMenu(false); - connect(cloneAction, SIGNAL(triggered()), this, SLOT(duplicateMappingItem())); + cloneMappingAction = new QAction(tr("Duplicate"), this); + cloneMappingAction->setShortcut(tr("Ctrl+D")); + cloneMappingAction->setStatusTip(tr("Duplicate item")); + cloneMappingAction->setIconVisibleInMenu(false); + connect(cloneMappingAction, SIGNAL(triggered()), this, SLOT(duplicateMappingItem())); // Delete mapping. deleteMappingAction = new QAction(tr("Delete"), this); @@ -1669,9 +1677,23 @@ void MainWindow::createMenus() // Edit. editMenu = menuBar->addMenu(tr("&Edit")); + // Undo & Redo menu editMenu->addAction(undoAction); editMenu->addAction(redoAction); - editMenu->addAction(deleteMappingAction); + editMenu->addSeparator(); + // Source canvas menu + sourceMenu = editMenu->addMenu(tr("Source")); + sourceMenu->setEnabled(false); + sourceMenu->addAction(deletePaintAction); + sourceMenu->addAction(renamePaintAction); + // Destination canvas menu + destinationMenu = editMenu->addMenu(tr("Destination")); + destinationMenu->setEnabled(false); + destinationMenu->addAction(cloneMappingAction); + destinationMenu->addAction(deleteMappingAction); + destinationMenu->addAction(renameMappingAction); + editMenu->addSeparator(); + // Preferences editMenu->addAction(preferencesAction); // View. @@ -1704,7 +1726,7 @@ void MainWindow::createMappingContextMenu() mappingContextMenu = new QMenu(this); // Add different Action - mappingContextMenu->addAction(cloneAction); + mappingContextMenu->addAction(cloneMappingAction); mappingContextMenu->addAction(deleteMappingAction); mappingContextMenu->addAction(renameMappingAction); From 156e74acd5fb0c484fe28dc23e60524ed4f0d427 Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 21 Jan 2016 21:54:34 +0000 Subject: [PATCH 11/46] Fix:#183 "Display logging output in a console and able to show and hide" --- ConsoleWindow.cpp | 132 +++++++++++++++++++++++++++++++++++++++ ConsoleWindow.h | 77 +++++++++++++++++++++++ MainWindow.cpp | 20 +++++- MainWindow.h | 3 + OscInterface.cpp | 11 +--- Util.cpp | 2 +- main.cpp | 9 +++ mapmap.pro | 2 + resources/qss/mapmap.qss | 3 +- 9 files changed, 246 insertions(+), 13 deletions(-) create mode 100644 ConsoleWindow.cpp create mode 100644 ConsoleWindow.h diff --git a/ConsoleWindow.cpp b/ConsoleWindow.cpp new file mode 100644 index 0000000..7929862 --- /dev/null +++ b/ConsoleWindow.cpp @@ -0,0 +1,132 @@ +/* + * ConsoleWindow.cpp + * + * (c) 2016 Dame Diongue -- baydamd(@)gmail(.)com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ConsoleWindow.h" +#include + +ConsoleWindow* ConsoleWindow::_singleton = NULL; + +ConsoleWindow::ConsoleWindow(QWidget *parent) : QMainWindow(parent) +{ + // Set Fixed size + resize(CONSOLE_WINDOW_DEFAULT_WIDTH, CONSOLE_WINDOW_DEFAULT_HEIGHT); + setMinimumSize(CONSOLE_WINDOW_DEFAULT_WIDTH, CONSOLE_WINDOW_DEFAULT_HEIGHT); + // Create console + _console = new QPlainTextEdit(this); + // Make read-only but allow copy of text + _console->setReadOnly(true); + // Create and customize font + QFont font(QFont(":/base-font", 10, QFont::Medium)); + font.setStyleHint(QFont::Monospace, QFont::PreferAntialias); + _console->setFont(font); + // Set color scheme + QPalette scheme = palette(); + scheme.setColor(QPalette::Base, Qt::black); + scheme.setColor(QPalette::Text, Qt::white); + _console->setPalette(scheme); + + // Create view elements + createActions(); + createMenu(); + + // Set window title + setWindowTitle(tr("Message Log Output - Mapmap")); + // Set main widget + setCentralWidget(_console); +} + +ConsoleWindow *ConsoleWindow::getInstance() +{ + if (!_singleton) + _singleton = new ConsoleWindow; + + return _singleton; +} + +void ConsoleWindow::createActions() +{ + // Quit + quitAction = new QAction(tr("&Close"), this); + quitAction->setShortcut(QKeySequence::Close); + quitAction->setStatusTip(tr("Close the console")); + connect(quitAction, SIGNAL(triggered(bool)), this, SLOT(close())); +} + +void ConsoleWindow::createMenu() +{ + // File menu + fileMenu = menuBar()->addMenu(tr("&File")); + fileMenu->addSeparator(); + fileMenu->addAction(quitAction); +} + +void ConsoleWindow::messageLog(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + // Message + QByteArray message = msg.toLocal8Bit(); + // Context + QString contexts(QStringLiteral("%1:%2").arg(context.file).arg(context.line)); + // Date and time + QString time(QDateTime::currentDateTime().toString(tr("MMM dd yy HH:mm"))); + // Output + QString output; + + switch (type) { + case QtDebugMsg: + output = time + " | Debug: " + QString(message.constData()) + " - " + contexts; + break; + case QtInfoMsg: + output = time + " | Info: " + QString(message.constData()) + " - " + contexts; + break; + case QtWarningMsg: + output = time + " | Warning: " + QString(message.constData()) + " - " + contexts; + break; + case QtCriticalMsg: + output = time + " | Critical: " + QString(message.constData()) + " - " + contexts; + break; + case QtFatalMsg: + output = time + " | Fatal: " + QString(message.constData()) + " - " + contexts; + abort(); + } + // Print in console + _console->appendPlainText(output); +} + +void ConsoleWindow::closeEvent(QCloseEvent *event) +{ + // Send signal if the window is closed + emit windowClosed(); + event->accept(); +} + +void ConsoleWindow::kill() +{ + if (_singleton) { + delete _singleton; + _singleton = NULL; + } +} + +ConsoleWindow::~ConsoleWindow() +{ + kill(); +} + + + diff --git a/ConsoleWindow.h b/ConsoleWindow.h new file mode 100644 index 0000000..edfda7b --- /dev/null +++ b/ConsoleWindow.h @@ -0,0 +1,77 @@ +/* + * ConsoleWindow.h + * + * (c) 2016 Dame Diongue -- baydamd(@)gmail(.)com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#include +#include +#include + +class QAction; +class QMenu; +class QMenuBar; + +class ConsoleWindow : public QMainWindow +{ + Q_OBJECT + +private: + // Private constructor + ConsoleWindow(QWidget *parent = 0); + +public: + // Using a singleton instance + static ConsoleWindow *getInstance(); + // Console log message handler + void messageLog(QtMsgType type, const QMessageLogContext &context, const QString &msg); + // Destructor + ~ConsoleWindow(); + // This instance killer + static void kill(); + +signals: + void windowClosed(); + +protected: + void closeEvent(QCloseEvent *event); + +private: + // This instance + static ConsoleWindow *_singleton; + + // Console logger + QPlainTextEdit *_console; + + // Create view elements + void createActions(); + void createMenu(); + + // Actions + QAction *quitAction; + + // Menus + QMenu *fileMenu; + + // Constants + static const int CONSOLE_WINDOW_DEFAULT_WIDTH = 640; + static const int CONSOLE_WINDOW_DEFAULT_HEIGHT = 480; +}; + +#endif // CONSOLE_H diff --git a/MainWindow.cpp b/MainWindow.cpp index dd774d3..f041363 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -29,9 +29,9 @@ MainWindow::MainWindow() { // Create model. if (Media::hasVideoSupport()) - std::cout << "Video support: yes" << std::endl; + QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: yes"; else - std::cout << "Video support: no" << std::endl; + QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: no"; mappingManager = new MappingManager; @@ -1298,6 +1298,10 @@ void MainWindow::createLayout() // connect(outputWindow->getCanvas()->scene(), SIGNAL(changed(const QList&)), // destinationCanvas, SLOT(updateCanvas())); + // Create console logging output + consoleWindow = ConsoleWindow::getInstance(); + consoleWindow->setVisible(false); + // Create layout. paintSplitter = new QSplitter(Qt::Vertical); paintSplitter->addWidget(paintList); @@ -1616,6 +1620,15 @@ void MainWindow::createActions() // Manage show/hide of Undo Stack connect(displayUndoStackAction, SIGNAL(toggled(bool)), this, SLOT(displayUndoStack(bool))); + // Toggle display of Console output + displayConsoleAction = new QAction(tr("Disp&lay Console"), this); + displayConsoleAction->setShortcut(tr("Alt+L")); + displayConsoleAction->setCheckable(true); + displayConsoleAction->setChecked(false); + connect(displayConsoleAction, SIGNAL(toggled(bool)), consoleWindow, SLOT(setVisible(bool))); + // uncheck action when window is closed + connect(consoleWindow, SIGNAL(windowClosed()), displayConsoleAction, SLOT(toggle())); + // Toggle display of zoom tool buttons displayZoomToolAction = new QAction(tr("Display &Zoom Toolbar"), this); displayZoomToolAction->setShortcut(tr("Alt+Z")); @@ -1706,6 +1719,7 @@ void MainWindow::createMenus() viewMenu->addSeparator(); viewMenu->addAction(displayUndoStackAction); viewMenu->addAction(displayZoomToolAction); + viewMenu->addAction(displayConsoleAction); // Run. runMenu = menuBar->addMenu(tr("&Run")); @@ -2690,7 +2704,7 @@ void MainWindow::startOscReceiver() int port = config_osc_receive_port; std::ostringstream os; os << port; - std::cout << "OSC port: " << port << std::endl; + QMessageLogger(__FILE__, __LINE__, 0).info() << "OSC port: " << port ; osc_interface.reset(new OscInterface(os.str())); if (port != 0) { diff --git a/MainWindow.h b/MainWindow.h index f680476..7ae5825 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -39,6 +39,7 @@ #include "OutputGLWindow.h" #include "PreferencesDialog.h" +#include "ConsoleWindow.h" #include "MappingManager.h" @@ -329,6 +330,7 @@ private: QAction *stickyVerticesAction; QAction *displayUndoStackAction; QAction *displayZoomToolAction; + QAction *displayConsoleAction; enum { MaxRecentFiles = 10 }; enum { MaxRecentVideo = 5 }; @@ -351,6 +353,7 @@ private: SourceGLCanvas* sourceCanvas; DestinationGLCanvas* destinationCanvas; OutputGLWindow* outputWindow; + ConsoleWindow* consoleWindow; QSplitter* mainSplitter; QSplitter* canvasSplitter; diff --git a/OscInterface.cpp b/OscInterface.cpp index bfad63d..a41a603 100644 --- a/OscInterface.cpp +++ b/OscInterface.cpp @@ -34,7 +34,7 @@ OscInterface::OscInterface( //if (listen_port != OSC_PORT_NONE) receiving_enabled_ = true; if (receiving_enabled_) { - std::cout << "Listening osc.udp://localhost:" << listen_port << std::endl; + QMessageLogger(__FILE__, __LINE__, 0).debug() << "Listening osc.udp://localhost:" << listen_port.c_str(); // receiver_.addHandler("/ping", "", ping_cb, this); // receiver_.addHandler("/pong", "", pong_cb, this); //receiver_.addHandler("/image/path", "ss", image_path_cb, this); @@ -53,7 +53,7 @@ int OscInterface::pong_cb(const char *path, const char * /*types*/, lo_arg ** /*argv*/, int /*argc*/, void * /*data*/, void *user_data) { OscInterface* context = static_cast(user_data); if (context->is_verbose()) - std::cout << "Got " << path << std::endl; + QMessageLogger(__FILE__, __LINE__, 0).debug() << "Got " << path; return 0; } @@ -64,7 +64,7 @@ int OscInterface::ping_cb(const char *path, const char * /*types*/, lo_arg ** /*argv*/, int /*argc*/, void * /*data*/, void *user_data) { OscInterface* context = static_cast(user_data); if (context->is_verbose()) - std::cout << "Got " << path << std::endl; + QMessageLogger(__FILE__, __LINE__, 0).debug() << "Got " << path; return 0; } @@ -171,35 +171,30 @@ void OscInterface::applyOscCommand(MainWindow &main_window, QVariantList & comma { int paint_id = command.at(2).toInt(); std::string image_uri = command.at(3).toString().toStdString(); - //std::cout << "load /mapmap/paint/media/load " << paint_id << " " << image_uri << std::endl; main_window.setTextureUri(paint_id, image_uri); } else if (path == "/mapmap/paint/media/rate" && typetags == "if") { int paint_id = command.at(2).toInt(); float rate = command.at(3).toDouble(); - //std::cout << "load /mapmap/paint/media/load " << paint_id << " " << image_uri << std::endl; main_window.setTextureRate(paint_id, rate); } else if (path == "/mapmap/paint/media/volume" && typetags == "if") { int paint_id = command.at(2).toInt(); float volume = command.at(3).toDouble(); - //std::cout << "set /mapmap/paint/media/volume " << paint_id << " " << image_uri << std::endl; main_window.setTextureVolume(paint_id, volume); } else if (path == "/mapmap/paint/media/played" && typetags == "ii") { int paint_id = command.at(2).toInt(); int played = command.at(3).toInt(); - //std::cout << "set /mapmap/paint/media/played " << paint_id << " " << image_uri << std::endl; main_window.setTexturePlayState(paint_id, played ? true : false); } else if (path == "/mapmap/mapping/visible" && typetags == "ii") { int mappingId = command.at(2).toInt(); int visible = command.at(3).toInt(); - //std::cout << "Visibility of MappingId " << mappingId << " set to " << visible << std::endl; main_window.setMappingVisible(mappingId, visible ? true : false); } else if (path == "/mapmap/output/fullscreen" && typetags == "i") diff --git a/Util.cpp b/Util.cpp index 6b4145c..516157d 100644 --- a/Util.cpp +++ b/Util.cpp @@ -276,7 +276,7 @@ bool eraseSettings() } else { - std::cout << "Erase MapMap settings." << std::endl; + QMessageLogger(__FILE__, __LINE__, 0).debug() << "Erase MapMap settings."; settingsFile.close(); return settingsFile.remove(); } diff --git a/main.cpp b/main.cpp index fe8eeef..09a8a43 100644 --- a/main.cpp +++ b/main.cpp @@ -42,8 +42,17 @@ public: } }; +// Intercept all logging message and display it in the console +void logMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + ConsoleWindow::getInstance()->messageLog(type, context, msg); +} + int main(int argc, char *argv[]) { + // Install message handler + qInstallMessageHandler(logMessageHandler); + set_env_vars_if_needed(); MainApplication app(argc, argv); diff --git a/mapmap.pro b/mapmap.pro index 3264353..c545273 100644 --- a/mapmap.pro +++ b/mapmap.pro @@ -8,6 +8,7 @@ DEFINES += UNICODE QT_THREAD_SUPPORT QT_CORE_LIB QT_GUI_LIB HEADERS = \ Commands.h \ + ConsoleWindow.h \ DestinationGLCanvas.h \ MM.h \ MainApplication.h \ @@ -36,6 +37,7 @@ HEADERS = \ SOURCES = \ Commands.cpp \ + ConsoleWindow.cpp \ DestinationGLCanvas.cpp \ MM.cpp \ MainApplication.cpp \ diff --git a/resources/qss/mapmap.qss b/resources/qss/mapmap.qss index 91ddaa7..bfef9e9 100644 --- a/resources/qss/mapmap.qss +++ b/resources/qss/mapmap.qss @@ -54,7 +54,8 @@ QListView::item:selected { background: #272a36; } -QGraphicsView { +QGraphicsView, +QPlainTextEdit { border-style: none; } From a892efa860f84caf076e780af144fa4122f1a24f Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 21 Jan 2016 22:21:33 +0000 Subject: [PATCH 12/46] Adding zoom images to the develop branch --- .gitignore | 2 ++ resources/images/icons/zoom_fit.png | Bin 0 -> 1499 bytes resources/images/icons/zoom_fit_w.png | Bin 0 -> 1451 bytes resources/images/icons/zoom_in.png | Bin 0 -> 1373 bytes resources/images/icons/zoom_in_w.png | Bin 0 -> 1321 bytes resources/images/icons/zoom_out.png | Bin 0 -> 1187 bytes resources/images/icons/zoom_out_w.png | Bin 0 -> 1129 bytes resources/images/icons/zoom_reset.png | Bin 0 -> 1234 bytes resources/images/icons/zoom_reset_w.png | Bin 0 -> 1192 bytes 9 files changed, 2 insertions(+) create mode 100644 resources/images/icons/zoom_fit.png create mode 100644 resources/images/icons/zoom_fit_w.png create mode 100644 resources/images/icons/zoom_in.png create mode 100644 resources/images/icons/zoom_in_w.png create mode 100644 resources/images/icons/zoom_out.png create mode 100644 resources/images/icons/zoom_out_w.png create mode 100644 resources/images/icons/zoom_reset.png create mode 100644 resources/images/icons/zoom_reset_w.png diff --git a/.gitignore b/.gitignore index de902b5..2fd7c2c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,8 @@ Release/ *.mov *.ogg *.png +# except resources files +!resources/images/icons/*.png *.tar *.rar *.qm diff --git a/resources/images/icons/zoom_fit.png b/resources/images/icons/zoom_fit.png new file mode 100644 index 0000000000000000000000000000000000000000..65e6d8efbff5f521c1b92cecb0bfd61d6e26eac7 GIT binary patch literal 1499 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 literal 0 HcmV?d00001 diff --git a/resources/images/icons/zoom_in.png b/resources/images/icons/zoom_in.png new file mode 100644 index 0000000000000000000000000000000000000000..a42c5ece5b054dd0b35b05714a2a0e2e3e95aa96 GIT binary patch literal 1373 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 PVvWJm)z4*}Q$iB}(T7BG literal 0 HcmV?d00001 diff --git a/resources/images/icons/zoom_out.png b/resources/images/icons/zoom_out.png new file mode 100644 index 0000000000000000000000000000000000000000..1b446cb8270869f4aa73a0070efdec18a26e7cfa GIT binary patch literal 1187 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEX7WqAsj$Z!;#Vf4nJ z=y-!L<5JscD}jQNC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NC6E}@N{tu zshIQjj$wv$x=hck*Ese7-DSbKX z>=rq0)^@**(=SN~NzKu_zHq`qJu}Un1&gQp%DyYH*fb@|ZI}MH-~Y^%fBtEIKhbZW zf6VIJZ;e)|_$_Y?O<QzD_?U;vlr#yn#32<(^B*7G-?NVC_Eo9ti}tDCJ^1|3={HtS zrLMmUcKEvfUNeJp@|8`e=l1)&)U~p|u)mr5h>p%Qd>hD{cb@p|6!`6nw5fa%9 zYrma2Wb#2K{&x6f##@3<*Ub};KQFRDDlqTmtYuR>itO*3oOPcP|IEO5v*1(nN}tOy zE&Gox)p>WH+rW^|VGgsvbA}_9429${_ZpsSj@|vuEPUCzp3f7mJ$HT1>Ob#~?Y75T zZy9qhzOP%=5num%X6u)^g|g?^ei;Am=D+v9BIo#LO}y6jmKwjXsr&PA`2}T`uQ#91 zXZid4AoGu3tMi@v1wvjh)NtW-@xkv*`+onMeL>lSTh8IdS%FeJ){bI^M=}i->s@S>%Ytj%Rc@P!KMhiR_vlXI5eF26Ay|A7D!ZaaX&L)>T~i>JSgLO z!10Bq&WvV`8=SVSteY=qo!9YUKHs?V!sUp?Ru0yuy5C6L;I-{F%`*ok(tD*1XBRAv z;F!&@HgEeLdl#YQ-y4@s5ROd#_DLzaZTfnab?j2dW`(aWm34?q;cr~4@Hk@fwpCl% z{NA(HFupOj?l;YtU(}oZHN9b;ir@1F_XD%fo=xTbAs%t2`^{4C|I5pmSF7J)nrCJ* z!}nhBgRuXP4o`Ud0GQO7yML4vNWKZ)_eq|=s^Gu`6vJP8IN1ny@;3zEKnFcUHx3vIVCg! E04c@|H~;_u literal 0 HcmV?d00001 diff --git a/resources/images/icons/zoom_out_w.png b/resources/images/icons/zoom_out_w.png new file mode 100644 index 0000000000000000000000000000000000000000..f41233e3972cbac0185a1d23b02d4035e6c980ef GIT binary patch literal 1129 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEX7WqAsj$Z!;#Vf4nJ z=y-!L<5JscD}jQNC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NHH)lKl5~P z45^s&_Kv;BltP)~AGh=KRwcWzc$u;AZgr7h6VrVukSJi1wqvW?THdv8*|Vo43yAo> z6jD`b-Fij9B&9+`urKbm=^vYmum2PuFW#U3^XHyp*0p~Qy+3PPe*XQ(s#jmFWLGdG zAJ8!1_`=M5;GZ8~T5dGsv_`EBEN7VX8?Kh|U%8yd@c4jA0ppA8@BNYCR~sx7q$;-E zj=z=5aQJ|T!KI5C({9@oNJrdw$zIO2fXRko-Bjc0sbz~lEEWBya%XY0L(`)tr z-7B83W!uzVelzwD4D&yK-!yrNY25aYA_hErPTEdvwK#ms{YdY6hG4_Z5e;9r=CK&` z>3`CYR9ySBieYl$=7Kw=Yvl z$HTmM#z&uchsiJy*WL7{hxJz z^*&Fywq*PI>5JX_rzq=dna6`xyoeAwF%ZT{Y^UqRQV z;l){jQUc0@_N$(W7rtKm|I76wH~$~U?=I}FMHLl2;Ppj7ENv;nw8hIe7@TGe=$&`y zPzZN|W)&Cr<`9O>7lR{a+?-dnH;%E6vG(HSh%nO!4vcG2LOmPMy`p2bgm9iR@uG)6xT!*|6=$hM%Ggm(&}t zA6R+DIa02B$@G6wj~kycFt9b0A6QsZ9LZ+ipg2qK@Ag}~F>HEF_lAuvJUg?eq( wjr%7LuF2J2VqOw@sqCN5ho&v-FHf_7vS#PX-OP6v0gD9&Pgg&ebxsLQ0C1V))c^nh literal 0 HcmV?d00001 diff --git a/resources/images/icons/zoom_reset.png b/resources/images/icons/zoom_reset.png new file mode 100644 index 0000000000000000000000000000000000000000..ec5a42b32b59142d8b709b1c65bac7c5be689e28 GIT binary patch literal 1234 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEX7WqAsj$Z!;#Vf4nJ z=y-!L<5JscD}jQNC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NC6G<_jGX# zshIQj&UtT{beZEHzwB-_(S{`pmQH`6I7Ng@ZnX#h+np6}?Gx%{ zm~AUQ+-bTrx$1@f!iAlhttS;HIO}?Osm)#dI=6a8so}0=eg)4@{`$EmZ`11EteSmKRSyoI2{@45Bj`u|)%v&^ulQ|ajYcfs!Y`bS6icdTPr{nqqdN1yFWGrQ;U zDc3cw?^s;SmGOV|_vnU&YwF(1{p+sy!m&XlLt=G&`dZ}|F%Lhx%E?ZCYx-V>QH+T% zIZ=nf#I5akd&BY{xAx6aGY|@V_p0*aR~{x~!Kc&KWzOo;`2N}Va)e8zaeL-2slaMgWs7ZS*-o?=gZseKR!NxUuDuOC(npmId(&c5RLipo_)pPJAZVFKW|=myh8IQ z2WIFX`Sw?y{(}XT2b$j`zA)Tnl_A#x4BTTUKK$74AX6p4y{Mz%?uFn8gWZA~#H+Zt z)AX6joct3HzHvF=_Cixk4yt=)26 z%3`PF7tIZ^?`^^s=bkcs_o9Z)V#<-18U^ANOZV+u!}gy+xN@Rx@yq{5$_jpSnl~Od zNh6`QQADmof0E7FKabFyuYh+dSQO@~27visDkT)Bi5@ zVwCZERKhWXaap6`11*ED_d2V*9V?a3%RMdo$F||#z3VHV*c(W_^!*j{U?H&lVeoYI Kb6Mw<&;$S^xh#$V literal 0 HcmV?d00001 diff --git a/resources/images/icons/zoom_reset_w.png b/resources/images/icons/zoom_reset_w.png new file mode 100644 index 0000000000000000000000000000000000000000..d1f708c7afbd6dd8ad5d27d205db695705824e4d GIT binary patch literal 1192 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEX7WqAsj$Z!;#Vf4nJ z=y-!L<5JscD}jQNC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NC6E}^>lFz zshIQj&e`mcaG7Ht-^c7aaVE%xi*p(G!PX{^tu7t6^nApY`Z!(}-K4Q&i~j$H=)$+l zcs!>u9=tI1gw(WdwQ918?QQD-R2Y(j5 zKVv(6<&(;Dj8_^86L=)p*cufdoN)X%Q*;~K8YbTa))~xl46j}P2QE!uC{1A6!4%TH zZ|2lhtY?^c6Uz42Z@JIl)^Pj4i$=H2H^ds|Hy+&^w6PuL|NwB-XHDf4G-PAw$1K_30#G@#c0eOPpTPR=UUZHx?i_H z{MYY4Uk>XoQ%m=%pMRx>Mc_HZ5le|4_L zEBZd`hK(Bof0(nLn`<3>$>i_(<#>&pUZelu?5(1O*Y*E@ow8mpUOQ9D){Y6o-PnCY zis+6f`}qY9UwOh4JlS~V@gEvLIk1Hf+{9mb`UwlH4y?Sa9^8NNsza&5SB}=uPd4@J zGM=^_svD;5?^NuabVstl7 zke%Ug({t3Ef6aD%7SkZVBu^8C81@YN4+0XtW_?GuFvPUHW$a<-5Asb3jAal@{2g~d z$zX1ZOn2ri{%-!;{R{&8IBi($`fa8h-RNTRW&17u5;g_{78^FZUi0a$AM^|6^?Col zyRA9AaeZUBVB02(IKgXQ>VMl=-{t?%5^y@G(>YScyJc(5rMD;V=5b^SofH3;aAW^6 z&g>nJ+wRAevutg6-LjsSd++SiUfUcZHowmKdEmP5cK*iQE1884i0&!>urX6m@4Z>W z&A3p)lFz?yvqqokA@*HriPrUe6%IG9Yd*1mp}DhmuKlGDV5!33 M>FVdQ&MBb@0HpT Date: Fri, 22 Jan 2016 09:26:44 +0000 Subject: [PATCH 13/46] Insert header may fix compilation error --- ConsoleWindow.h | 4 ++-- MainWindow.h | 1 + OscInterface.h | 1 + mapmap.pro | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ConsoleWindow.h b/ConsoleWindow.h index edfda7b..01caf59 100644 --- a/ConsoleWindow.h +++ b/ConsoleWindow.h @@ -22,11 +22,11 @@ #include #include -#include +#include +#include class QAction; class QMenu; -class QMenuBar; class ConsoleWindow : public QMainWindow { diff --git a/MainWindow.h b/MainWindow.h index 7ae5825..31461cd 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "MM.h" diff --git a/OscInterface.h b/OscInterface.h index f68d81f..257a0c9 100644 --- a/OscInterface.h +++ b/OscInterface.h @@ -27,6 +27,7 @@ #ifdef HAVE_OSC #include +#include #include "concurrentqueue.h" #include "OscReceiver.h" diff --git a/mapmap.pro b/mapmap.pro index c545273..1143d4e 100644 --- a/mapmap.pro +++ b/mapmap.pro @@ -3,7 +3,7 @@ TEMPLATE = app VERSION = 0.3.2 TARGET = mapmap QT += gui opengl xml -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets core DEFINES += UNICODE QT_THREAD_SUPPORT QT_CORE_LIB QT_GUI_LIB HEADERS = \ From 990250ed1394d9769188a4d4f0754efe17cafb1b Mon Sep 17 00:00:00 2001 From: Tats Date: Sat, 23 Jan 2016 14:51:32 -0500 Subject: [PATCH 14/46] Cosmetic change. --- MainWindow.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index f041363..9cab4a4 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -28,10 +28,7 @@ MainWindow::MainWindow() { // Create model. - if (Media::hasVideoSupport()) - QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: yes"; - else - QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: no"; + QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no") << endl; mappingManager = new MappingManager; From fe848a635516ee5c551b9275bbedb03e61ffedaa Mon Sep 17 00:00:00 2001 From: Tats Date: Sat, 23 Jan 2016 14:52:40 -0500 Subject: [PATCH 15/46] Added actions directly to the MainWindow to allow top-level use of hot keys (closes #40). --- MainWindow.cpp | 62 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 9cab4a4..fcef39c 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -1351,6 +1351,7 @@ void MainWindow::createActions() newAction->setShortcut(QKeySequence::New); newAction->setStatusTip(tr("Create a new project")); newAction->setIconVisibleInMenu(false); + addAction(newAction); connect(newAction, SIGNAL(triggered()), this, SLOT(newFile())); // Open. @@ -1359,6 +1360,7 @@ void MainWindow::createActions() openAction->setShortcut(QKeySequence::Open); openAction->setStatusTip(tr("Open an existing project")); openAction->setIconVisibleInMenu(false); + addAction(openAction); connect(openAction, SIGNAL(triggered()), this, SLOT(open())); // Save. @@ -1367,14 +1369,16 @@ void MainWindow::createActions() saveAction->setShortcut(QKeySequence::Save); saveAction->setStatusTip(tr("Save the project")); saveAction->setIconVisibleInMenu(false); + addAction(saveAction); connect(saveAction, SIGNAL(triggered()), this, SLOT(save())); // Save as. saveAsAction = new QAction(tr("Save &As..."), this); saveAsAction->setIcon(QIcon(":/save-as")); - saveAsAction->setShortcut(tr("Ctrl+Shift+S")); + saveAsAction->setShortcut(QKeySequence::SaveAs); saveAsAction->setStatusTip(tr("Save the project as...")); saveAsAction->setIconVisibleInMenu(false); + addAction(saveAsAction); connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs())); // Recents file @@ -1410,6 +1414,7 @@ void MainWindow::createActions() importVideoAction->setIcon(QIcon(":/add-video")); importVideoAction->setStatusTip(tr("Import a video source file...")); importVideoAction->setIconVisibleInMenu(false); + addAction(importVideoAction); connect(importVideoAction, SIGNAL(triggered()), this, SLOT(importVideo())); // Import imiage. @@ -1418,6 +1423,7 @@ void MainWindow::createActions() importImageAction->setIcon(QIcon(":/add-image")); importImageAction->setStatusTip(tr("Import a image source file...")); importImageAction->setIconVisibleInMenu(false); + addAction(importImageAction); connect(importImageAction, SIGNAL(triggered()), this, SLOT(importImage())); // Add color. @@ -1426,13 +1432,15 @@ void MainWindow::createActions() addColorAction->setIcon(QIcon(":/add-color")); addColorAction->setStatusTip(tr("Add a color paint...")); addColorAction->setIconVisibleInMenu(false); + addAction(addColorAction); connect(addColorAction, SIGNAL(triggered()), this, SLOT(addColor())); // Exit/quit. exitAction = new QAction(tr("E&xit"), this); - exitAction->setShortcut(tr("Ctrl+Q")); + exitAction->setShortcut(QKeySequence::Quit); exitAction->setStatusTip(tr("Exit the application")); exitAction->setIconVisibleInMenu(false); + addAction(exitAction); connect(exitAction, SIGNAL(triggered()), this, SLOT(close())); // Undo action @@ -1440,31 +1448,36 @@ void MainWindow::createActions() undoAction->setShortcut(QKeySequence::Undo); undoAction->setIconVisibleInMenu(false); undoAction->setShortcutContext(Qt::ApplicationShortcut); + addAction(undoAction); //Redo action redoAction = undoStack->createRedoAction(this, tr("&Redo")); redoAction->setShortcut(QKeySequence::Redo); redoAction->setIconVisibleInMenu(false); redoAction->setShortcutContext(Qt::ApplicationShortcut); + addAction(redoAction); // About. aboutAction = new QAction(tr("&About"), this); aboutAction->setStatusTip(tr("Show the application's About box")); aboutAction->setIconVisibleInMenu(false); + addAction(aboutAction); connect(aboutAction, SIGNAL(triggered()), this, SLOT(about())); // Duplicate. cloneMappingAction = new QAction(tr("Duplicate"), this); - cloneMappingAction->setShortcut(tr("Ctrl+D")); + cloneMappingAction->setShortcut(Qt::CTRL + Qt::Key_D); cloneMappingAction->setStatusTip(tr("Duplicate item")); cloneMappingAction->setIconVisibleInMenu(false); + addAction(cloneMappingAction); connect(cloneMappingAction, SIGNAL(triggered()), this, SLOT(duplicateMappingItem())); // Delete mapping. - deleteMappingAction = new QAction(tr("Delete"), this); - deleteMappingAction->setShortcut(tr("CTRL+DEL")); + deleteMappingAction = new QAction(tr("Delete mapping"), this); + deleteMappingAction->setShortcut(QKeySequence::Delete); deleteMappingAction->setStatusTip(tr("Delete item")); deleteMappingAction->setIconVisibleInMenu(false); + addAction(deleteMappingAction); connect(deleteMappingAction, SIGNAL(triggered()), this, SLOT(deleteMappingItem())); // Rename mapping. @@ -1472,10 +1485,11 @@ void MainWindow::createActions() renameMappingAction->setShortcut(Qt::Key_F2); renameMappingAction->setStatusTip(tr("Rename item")); renameMappingAction->setIconVisibleInMenu(false); + addAction(renameMappingAction); connect(renameMappingAction, SIGNAL(triggered()), this, SLOT(renameMappingItem())); // Delete paint. - deletePaintAction = new QAction(tr("Delete"), this); + deletePaintAction = new QAction(tr("Delete paint"), this); //deletePaintAction->setShortcut(tr("CTRL+DEL")); deletePaintAction->setStatusTip(tr("Delete item")); deletePaintAction->setIconVisibleInMenu(false); @@ -1486,14 +1500,16 @@ void MainWindow::createActions() //renamePaintAction->setShortcut(Qt::Key_F2); renamePaintAction->setStatusTip(tr("Rename item")); renamePaintAction->setIconVisibleInMenu(false); + addAction(renamePaintAction); connect(renamePaintAction, SIGNAL(triggered()), this, SLOT(renamePaintItem())); // Preferences... preferencesAction = new QAction(tr("&Preferences..."), this); //preferencesAction->setIcon(QIcon(":/preferences")); - preferencesAction->setShortcut(tr("CTRL+,")); + preferencesAction->setShortcut(Qt::CTRL + Qt::Key_Comma); preferencesAction->setStatusTip(tr("Configure preferences...")); //preferencesAction->setIconVisibleInMenu(false); + addAction(preferencesAction); connect(preferencesAction, SIGNAL(triggered()), this, SLOT(preferences())); // Add quad/mesh. @@ -1502,6 +1518,7 @@ void MainWindow::createActions() addMeshAction->setIcon(QIcon(":/add-mesh")); addMeshAction->setStatusTip(tr("Add quad/mesh")); addMeshAction->setIconVisibleInMenu(false); + addAction(addMeshAction); connect(addMeshAction, SIGNAL(triggered()), this, SLOT(addMesh())); addMeshAction->setEnabled(false); @@ -1511,6 +1528,7 @@ void MainWindow::createActions() addTriangleAction->setIcon(QIcon(":/add-triangle")); addTriangleAction->setStatusTip(tr("Add triangle")); addTriangleAction->setIconVisibleInMenu(false); + addAction(addTriangleAction); connect(addTriangleAction, SIGNAL(triggered()), this, SLOT(addTriangle())); addTriangleAction->setEnabled(false); @@ -1520,6 +1538,7 @@ void MainWindow::createActions() addEllipseAction->setIcon(QIcon(":/add-ellipse")); addEllipseAction->setStatusTip(tr("Add ellipse")); addEllipseAction->setIconVisibleInMenu(false); + addAction(addEllipseAction); connect(addEllipseAction, SIGNAL(triggered()), this, SLOT(addEllipse())); addEllipseAction->setEnabled(false); @@ -1529,6 +1548,7 @@ void MainWindow::createActions() playAction->setIcon(QIcon(":/play")); playAction->setStatusTip(tr("Play")); playAction->setIconVisibleInMenu(false); + addAction(playAction); connect(playAction, SIGNAL(triggered()), this, SLOT(play())); playAction->setVisible(true); @@ -1538,25 +1558,28 @@ void MainWindow::createActions() pauseAction->setIcon(QIcon(":/pause")); pauseAction->setStatusTip(tr("Pause")); pauseAction->setIconVisibleInMenu(false); + addAction(pauseAction); connect(pauseAction, SIGNAL(triggered()), this, SLOT(pause())); pauseAction->setVisible(false); - // Pause. + // Rewind. rewindAction = new QAction(tr("Rewind"), this); rewindAction->setShortcut(tr("CTRL+R")); rewindAction->setIcon(QIcon(":/rewind")); rewindAction->setStatusTip(tr("Rewind")); rewindAction->setIconVisibleInMenu(false); + addAction(rewindAction); connect(rewindAction, SIGNAL(triggered()), this, SLOT(rewind())); // Toggle display of output window. displayOutputWindowAction = new QAction(tr("&Display Output Window"), this); - displayOutputWindowAction->setShortcut(tr("Ctrl+W")); + displayOutputWindowAction->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_W); displayOutputWindowAction->setIcon(QIcon(":/output-window")); displayOutputWindowAction->setStatusTip(tr("Display output window")); displayOutputWindowAction->setIconVisibleInMenu(false); displayOutputWindowAction->setCheckable(true); displayOutputWindowAction->setChecked(true); + addAction(displayOutputWindowAction); // Manage show/hide of GL output window. connect(displayOutputWindowAction, SIGNAL(toggled(bool)), outputWindow, SLOT(setVisible(bool))); // When closing the GL output window, uncheck the action in menu. @@ -1565,11 +1588,12 @@ void MainWindow::createActions() // Toggle display of output window. outputWindowFullScreenAction = new QAction(tr("&Fullscreen"), this); outputWindowFullScreenAction->setIcon(QIcon(":/fullscreen")); - outputWindowFullScreenAction->setShortcut(tr("Ctrl+F")); + outputWindowFullScreenAction->setShortcut(Qt::CTRL + Qt::Key_F); outputWindowFullScreenAction->setStatusTip(tr("Full screen")); outputWindowFullScreenAction->setIconVisibleInMenu(false); outputWindowFullScreenAction->setCheckable(true); outputWindowFullScreenAction->setChecked(false); + addAction(displayOutputWindowAction); // Manage fullscreen mode for output window. connect(outputWindowFullScreenAction, SIGNAL(toggled(bool)), outputWindow, SLOT(setFullScreen(bool))); // When fullscreen is toggled by the output window (eg. when pressing ESC), change the action checkbox. @@ -1579,58 +1603,64 @@ void MainWindow::createActions() // Toggle display of canvas controls. displayControlsAction = new QAction(tr("&Display Canvas Controls"), this); - displayControlsAction->setShortcut(tr("Alt+D")); + displayControlsAction->setShortcut(Qt::ALT + Qt::Key_C); displayControlsAction->setIcon(QIcon(":/control-points")); displayControlsAction->setStatusTip(tr("Display canvas controls")); displayControlsAction->setIconVisibleInMenu(false); displayControlsAction->setCheckable(true); displayControlsAction->setChecked(_displayControls); + addAction(displayControlsAction); // Manage show/hide of canvas controls. connect(displayControlsAction, SIGNAL(toggled(bool)), this, SLOT(enableDisplayControls(bool))); // Toggle sticky vertices stickyVerticesAction = new QAction(tr("&Sticky Vertices"), this); - stickyVerticesAction->setShortcut(tr("Alt+S")); + stickyVerticesAction->setShortcut(Qt::ALT + Qt::Key_S); stickyVerticesAction->setIcon(QIcon(":/control-points")); stickyVerticesAction->setStatusTip(tr("Enable sticky vertices")); stickyVerticesAction->setIconVisibleInMenu(false); stickyVerticesAction->setCheckable(true); stickyVerticesAction->setChecked(_stickyVertices); + addAction(stickyVerticesAction); // Manage sticky vertices connect(stickyVerticesAction, SIGNAL(toggled(bool)), this, SLOT(enableStickyVertices(bool))); displayTestSignalAction = new QAction(tr("&Display Test Signal"), this); - displayTestSignalAction->setShortcut(tr("Alt+T")); + displayTestSignalAction->setShortcut(Qt::ALT + Qt::Key_T); displayTestSignalAction->setIcon(QIcon(":/control-points")); displayTestSignalAction->setStatusTip(tr("Display test signal")); displayTestSignalAction->setIconVisibleInMenu(false); displayTestSignalAction->setCheckable(true); displayTestSignalAction->setChecked(_displayTestSignal); + addAction(displayTestSignalAction); // Manage show/hide of test signal connect(displayTestSignalAction, SIGNAL(toggled(bool)), this, SLOT(enableTestSignal(bool))); // Toggle display of Undo Stack displayUndoStackAction = new QAction(tr("Display &Undo Stack"), this); - displayUndoStackAction->setShortcut(tr("Ctrl+U")); + displayUndoStackAction->setShortcut(Qt::ALT + Qt::Key_U); displayUndoStackAction->setCheckable(true); displayUndoStackAction->setChecked(_displayUndoStack); + addAction(displayUndoStackAction); // Manage show/hide of Undo Stack connect(displayUndoStackAction, SIGNAL(toggled(bool)), this, SLOT(displayUndoStack(bool))); // Toggle display of Console output displayConsoleAction = new QAction(tr("Disp&lay Console"), this); - displayConsoleAction->setShortcut(tr("Alt+L")); + displayConsoleAction->setShortcut(Qt::ALT + Qt::Key_L); displayConsoleAction->setCheckable(true); displayConsoleAction->setChecked(false); + addAction(displayConsoleAction); connect(displayConsoleAction, SIGNAL(toggled(bool)), consoleWindow, SLOT(setVisible(bool))); // uncheck action when window is closed connect(consoleWindow, SIGNAL(windowClosed()), displayConsoleAction, SLOT(toggle())); // Toggle display of zoom tool buttons displayZoomToolAction = new QAction(tr("Display &Zoom Toolbar"), this); - displayZoomToolAction->setShortcut(tr("Alt+Z")); + displayZoomToolAction->setShortcut(Qt::ALT + Qt::Key_Z); displayZoomToolAction->setCheckable(true); displayZoomToolAction->setChecked(true); + addAction(displayZoomToolAction); connect(displayZoomToolAction, SIGNAL(toggled(bool)), sourceCanvas, SLOT(showZoomToolBar(bool))); connect(displayZoomToolAction, SIGNAL(toggled(bool)), destinationCanvas, SLOT(showZoomToolBar(bool))); } From a98193c116c7600964b5e9782eae54b5ccab0d81 Mon Sep 17 00:00:00 2001 From: baydam Date: Mon, 25 Jan 2016 19:53:47 +0000 Subject: [PATCH 16/46] Close all top level window when the main window is closed --- MainWindow.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MainWindow.cpp b/MainWindow.cpp index fcef39c..1816dca 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -275,7 +275,14 @@ void MainWindow::closeEvent(QCloseEvent *event) // Popup dialog allowing the user to save before closing. if (okToContinue()) { + // Save settings writeSettings(); + // Close all top level widgets + foreach (QWidget *widget, QApplication::topLevelWidgets()) { + if (widget != this) { // Avoid recursion + widget->close(); + } + } event->accept(); } else From 6c9ab74b055e7897e0368ce3f517099399991469 Mon Sep 17 00:00:00 2001 From: Bay Dam Date: Tue, 26 Jan 2016 16:35:24 +0000 Subject: [PATCH 17/46] Update NEWS --- NEWS | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 2f34c26..1d63df0 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,22 @@ Release notes for MapMap 2015-??-?? - MapMap 0.3.2 ------------------------- -* (none) +* Added zoom toolbar +* Added console window +* Fix #179: Paints and mappings renamings are now saved in file +* Fix #162: Zooming in the destination canvas changes the size of controls in output window. +* Fix #154: Problem with some video files: shape is size of single point +* Can rename paints and mappings via OSC +* Can rename paints and mappings with double click +* Fix #156 White rectangle around the fullscreen window +* Fix #152: The software frozen when we load a project and the video files are not found +* Abled to locate the video files if is not found when load a project +* Fix #149: Deleting a mapping actually deletes a paint when the paint tab is chosen +* Improved Test signal +* Enhancement #117: Ellipse conical projection +* Performance improvements +* OSC general bug fixes +* OSC support on OSX 2015-10-30 - MapMap 0.3.1 ------------------------- From e52e92910800b3e2e87d7b5e49bdb96d13340353 Mon Sep 17 00:00:00 2001 From: Alexandre Quessy Date: Tue, 26 Jan 2016 23:54:47 -0500 Subject: [PATCH 18/46] Add a macro to check for Qt >= 5.4 --- ConsoleWindow.cpp | 4 ++++ MainWindow.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/ConsoleWindow.cpp b/ConsoleWindow.cpp index 7929862..8a73026 100644 --- a/ConsoleWindow.cpp +++ b/ConsoleWindow.cpp @@ -32,9 +32,11 @@ ConsoleWindow::ConsoleWindow(QWidget *parent) : QMainWindow(parent) // Make read-only but allow copy of text _console->setReadOnly(true); // Create and customize font +#if QT_VERSION >= 0x050400 QFont font(QFont(":/base-font", 10, QFont::Medium)); font.setStyleHint(QFont::Monospace, QFont::PreferAntialias); _console->setFont(font); +#endif // Set color scheme QPalette scheme = palette(); scheme.setColor(QPalette::Base, Qt::black); @@ -91,9 +93,11 @@ void ConsoleWindow::messageLog(QtMsgType type, const QMessageLogContext &context case QtDebugMsg: output = time + " | Debug: " + QString(message.constData()) + " - " + contexts; break; +#if QT_VERSION >= 0x050400 case QtInfoMsg: output = time + " | Info: " + QString(message.constData()) + " - " + contexts; break; +#endif case QtWarningMsg: output = time + " | Warning: " + QString(message.constData()) + " - " + contexts; break; diff --git a/MainWindow.cpp b/MainWindow.cpp index 1816dca..e1888e8 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -28,7 +28,9 @@ MainWindow::MainWindow() { // Create model. +#if QT_VERSION >= 0x050400 QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no") << endl; +#endif mappingManager = new MappingManager; @@ -2738,7 +2740,9 @@ void MainWindow::startOscReceiver() int port = config_osc_receive_port; std::ostringstream os; os << port; +#if QT_VERSION >= 0x050400 QMessageLogger(__FILE__, __LINE__, 0).info() << "OSC port: " << port ; +#endif osc_interface.reset(new OscInterface(os.str())); if (port != 0) { From 9b528e6549bb271c7635f59043200a55d393398c Mon Sep 17 00:00:00 2001 From: Alexandre Quessy Date: Wed, 27 Jan 2016 11:08:40 -0500 Subject: [PATCH 19/46] update credits in README --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index 5b7e56b..e3e1b3f 100644 --- a/README +++ b/README @@ -39,13 +39,14 @@ or else the menu will not show. Authors ------- * Sofian Audry: lead developer, user interface designer, project manager. +* Dame Diongue: developer. * Alexandre Quessy: release manager, developer, technical writer, project manager. * Mike Latona: user interface designer. -* Dame Diongue: developer. * Vasilis Liaskovitis: developer. Contributors ------------ +* Alex Barry: user experience design. * Maxime Damecour: inspiration. * Christian Ambaud: sponsor, inspiration. * Louis Desjardins: project manager. @@ -56,4 +57,3 @@ Contributors More info --------- Get more info from http://mapmap.info - From 7d9d1d3e1675caa9b6692d68a57fb509e1906bdf Mon Sep 17 00:00:00 2001 From: Alexandre Quessy Date: Wed, 27 Jan 2016 11:10:57 -0500 Subject: [PATCH 20/46] Update list of copyright owners in MM.cpp --- MM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MM.cpp b/MM.cpp index e2d36c2..caa99ef 100644 --- a/MM.cpp +++ b/MM.cpp @@ -21,7 +21,7 @@ const QString MM::APPLICATION_NAME = "MapMap"; const QString MM::VERSION = "0.3.2"; -const QString MM::COPYRIGHT_OWNERS = "Sofian Audry, Alexandre Quessy, Mike Latona, Vasilis Liaskovitis, Dame Diongue"; +const QString MM::COPYRIGHT_OWNERS = "Sofian Audry, Alexandre Quessy, Dame Diongue, Mike Latona, Vasilis Liaskovitis"; const QString MM::ORGANIZATION_NAME = "MapMap"; const QString MM::ORGANIZATION_DOMAIN = "mapmap.info"; const QString MM::FILE_EXTENSION = "mmp"; From eeca30197ab2f353a0dfa8c125f4ea454c8b3ab6 Mon Sep 17 00:00:00 2001 From: baydam Date: Sat, 30 Jan 2016 23:30:11 +0000 Subject: [PATCH 21/46] Fix zoom in key not working --- MapperGLCanvas.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index f6c8b75..a8df2c9 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -447,13 +447,19 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) undoStack->undo(); else if (event->matches(QKeySequence::Redo)) undoStack->redo(); + // Case 1: zoom in with CTRL++ else if (event->matches(QKeySequence::ZoomIn)) increaseZoomLevel(); else if (event->matches(QKeySequence::ZoomOut)) decreaseZoomLevel(); - else if (event->modifiers() == Qt::CTRL) { + else if (event->modifiers() & Qt::ControlModifier) { if(event->key() == Qt::Key_0) resetZoomLevel(); + // Case 2: zoom in with CTRL+SHIFT++ + if (event->modifiers() & Qt::ShiftModifier) { + if (event->key() == Qt::Key_Plus) + increaseZoomLevel(); + } } else handledKey = false; From cb07e630a2f36c3266f74ae295f755ca2556bd6b Mon Sep 17 00:00:00 2001 From: Tats Date: Sat, 30 Jan 2016 18:57:19 -0500 Subject: [PATCH 22/46] Added CTRL+= for zoom-in (closes #192). --- MapperGLCanvas.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index a8df2c9..eb9c2c0 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -455,11 +455,11 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) else if (event->modifiers() & Qt::ControlModifier) { if(event->key() == Qt::Key_0) resetZoomLevel(); - // Case 2: zoom in with CTRL+SHIFT++ - if (event->modifiers() & Qt::ShiftModifier) { - if (event->key() == Qt::Key_Plus) + // Case 2: zoom in with CTRL+= + else if (event->key() == Qt::Key_Equal || + // Case 3: zoom in with CTRL+SHIFT++ + (event->modifiers() & Qt::ShiftModifier && event->key() == Qt::Key_Plus)) increaseZoomLevel(); - } } else handledKey = false; From 6c723fddd9d11598805359310dcd28c169eac167 Mon Sep 17 00:00:00 2001 From: baydam Date: Tue, 2 Feb 2016 18:35:47 +0000 Subject: [PATCH 23/46] Make the console and the application more readable --- ConsoleWindow.cpp | 33 +++++++++++++--------- MainWindow.cpp | 2 +- main.cpp | 10 +++---- mapmap.qrc | 5 ++-- resources/fonts/DroidSans.otf | Bin 0 -> 190776 bytes resources/fonts/Hack-Regular.otf | Bin 0 -> 161056 bytes resources/fonts/HelveticaNeueLTPro-Bd.otf | Bin 35688 -> 0 bytes 7 files changed, 29 insertions(+), 21 deletions(-) create mode 100644 resources/fonts/DroidSans.otf create mode 100644 resources/fonts/Hack-Regular.otf delete mode 100644 resources/fonts/HelveticaNeueLTPro-Bd.otf diff --git a/ConsoleWindow.cpp b/ConsoleWindow.cpp index 8a73026..d2ba154 100644 --- a/ConsoleWindow.cpp +++ b/ConsoleWindow.cpp @@ -32,11 +32,11 @@ ConsoleWindow::ConsoleWindow(QWidget *parent) : QMainWindow(parent) // Make read-only but allow copy of text _console->setReadOnly(true); // Create and customize font -#if QT_VERSION >= 0x050400 - QFont font(QFont(":/base-font", 10, QFont::Medium)); - font.setStyleHint(QFont::Monospace, QFont::PreferAntialias); + int id = QFontDatabase::addApplicationFont(":/console-font"); + QString family = QFontDatabase::applicationFontFamilies(id).at(0); + QFont font(QFont(family, 10, QFont::Normal)); _console->setFont(font); -#endif + // Set color scheme QPalette scheme = palette(); scheme.setColor(QPalette::Base, Qt::black); @@ -83,33 +83,40 @@ void ConsoleWindow::messageLog(QtMsgType type, const QMessageLogContext &context // Message QByteArray message = msg.toLocal8Bit(); // Context - QString contexts(QStringLiteral("%1:%2").arg(context.file).arg(context.line)); - // Date and time - QString time(QDateTime::currentDateTime().toString(tr("MMM dd yy HH:mm"))); + QString contexts(QStringLiteral("%1:%2").arg(context.file).arg(context.line)), + // Date and time + time(QDateTime::currentDateTime().toString(tr("MMM dd yy HH:mm"))), + // Colorized time + timeHtml = "" + time + "", + debug = "Debug:", + info = "Info:", + warning = "Warning:", + critical = "Critical:", + fatal = "Fatal!"; // Output QString output; switch (type) { case QtDebugMsg: - output = time + " | Debug: " + QString(message.constData()) + " - " + contexts; + output = time + " | " + debug + " " + QString(message.constData()) + " - " + contexts + ""; break; #if QT_VERSION >= 0x050400 case QtInfoMsg: - output = time + " | Info: " + QString(message.constData()) + " - " + contexts; + output = time + " | " + info + " " + QString(message.constData()) + " - " + contexts + ""; break; #endif case QtWarningMsg: - output = time + " | Warning: " + QString(message.constData()) + " - " + contexts; + output = time + " | " + warning + " " + QString(message.constData()) + " - " + contexts + ""; break; case QtCriticalMsg: - output = time + " | Critical: " + QString(message.constData()) + " - " + contexts; + output = time + " | " + critical + " " + QString(message.constData()) + " - " + contexts + ""; break; case QtFatalMsg: - output = time + " | Fatal: " + QString(message.constData()) + " - " + contexts; + output = time + " | " + fatal + " " + QString(message.constData()) + " - " + contexts + ""; abort(); } // Print in console - _console->appendPlainText(output); + _console->appendHtml(output); } void ConsoleWindow::closeEvent(QCloseEvent *event) diff --git a/MainWindow.cpp b/MainWindow.cpp index e1888e8..74a3bcf 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -29,7 +29,7 @@ MainWindow::MainWindow() { // Create model. #if QT_VERSION >= 0x050400 - QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no") << endl; + QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no"); #endif mappingManager = new MappingManager; diff --git a/main.cpp b/main.cpp index 09a8a43..8358510 100644 --- a/main.cpp +++ b/main.cpp @@ -116,7 +116,7 @@ int main(int argc, char *argv[]) splash.showMessage(" " + QObject::tr("Initiating program..."), Qt::AlignLeft | Qt::AlignTop, MM::WHITE); - bool FORCE_FRENCH_LANG = false; + //bool FORCE_FRENCH_LANG = false; // set_language_to_french(app); // Let splash for at least one second. @@ -124,10 +124,10 @@ int main(int argc, char *argv[]) // Create window. MainWindow* win = MainWindow::instance(); - - QFontDatabase db; - Q_ASSERT( QFontDatabase::addApplicationFont(":/base-font") != -1); - app.setFont(QFont(":/base-font", 10, QFont::Bold)); + // Add custom font + int id = QFontDatabase::addApplicationFont(":/base-font"); + QString family = QFontDatabase::applicationFontFamilies(id).at(0); + app.setFont(QFont(family, 11, QFont::Normal)); // Load stylesheet. QFile stylesheet(":/stylesheet"); diff --git a/mapmap.qrc b/mapmap.qrc index 699af80..80914a8 100644 --- a/mapmap.qrc +++ b/mapmap.qrc @@ -23,13 +23,14 @@ resources/images/logo/logomapmap.png resources/images/logo/logo_m_big_mapmap.png resources/images/logo/splash.png - resources/fonts/HelveticaNeueLTPro-Bd.otf - resources/fonts/HelveticaNeueLTPro-Bd.otf + resources/fonts/DroidSans.otf + resources/fonts/DroidSans.otf resources/images/test-signal/test-signal.svg resources/qss/mapmap.qss resources/images/icons/zoom_reset_w.png resources/images/icons/zoom_in_w.png resources/images/icons/zoom_out_w.png resources/images/icons/zoom_fit_w.png + resources/fonts/Hack-Regular.otf diff --git a/resources/fonts/DroidSans.otf b/resources/fonts/DroidSans.otf new file mode 100644 index 0000000000000000000000000000000000000000..ad1efca88aed8d9e2d179f27dd713e2a1562fe5f GIT binary patch literal 190776 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 literal 0 HcmV?d00001 diff --git a/resources/fonts/Hack-Regular.otf b/resources/fonts/Hack-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..5f083251bcd39ec556057cbdf9a3a79a10fde95e GIT binary patch literal 161056 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 c{M?+#FuFLH_(fM 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 literal 0 HcmV?d00001 diff --git a/resources/fonts/HelveticaNeueLTPro-Bd.otf b/resources/fonts/HelveticaNeueLTPro-Bd.otf deleted file mode 100644 index 0712e4db4c7eb360894958403ee2c5910e5a50ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35688 zcmaHT2UHYE7w!x*-7{3{sI-I1STh3#3YaF0lj*e|EOK|L7`CGP$)v$^a$w_SnEnNXN4lQp+ceW9~d&Ud+xCZ%N2?tYK20$ z*T2uepniQq@OjKbg+f_BD8$QW$&mqAcI+ptV{GK4h@>YzdGi&Dh(QVkcQGb9BI@xf z|Je$~gu3{?Z44%8ny5SBbANnp95X3pTHx$fz419oq2OyzikOz9T!=*#lhW{qPl%Wl zJ>Y)Bq4=DxP-s(<5~rm6w?N^eP)xPqd$UrZc2FplO6T6u@u|@%v5^r2qo+pqA2KL8 zu~qjd`Hi9m7%MkUo%vkolbuWNrra#W$%xwK|Or{=X9I(gT*+c0p9 zlVTTEsNfVe6?%nH(L&Ki(M8cy5vT}K3{iwB#w#W&k`=QRD-_=;G8MZN2Ng#Yg^FUu zHN_o8x#CB~OT`Dp7sY>-oU)eEplqsaq4ZYzDZ43qD?^lHl+ntGN~?0Fa;|cba=CJ& za=UVm@|g0J@~rZz^0xA^@`duF@{5DQLG3^s>NwPMXz0+~!P}vuLobK^4#ONqIYc_d zIV3sEbeQL`++mHwMu%+P=Bk#f)~GhBcB!&eCsk)urK%gMd#XpO=c-q#&nii+QtQ-p z)kd{h?WS(2Zmn*w?x^mr?x!BC4pom)k5^Apr>YmKSE@Itcc~Al^VMh67u7$ge^URV z{!Lw}{>rJjJnlC4s^`??#Dv6@=*d$f;$suW$0o$4OplMAGR2-SAvroCB|6!DpA?at z5*ra86+3?Xl&O;@MWn%Moo=ONs5h4NQs`191$NhDSARgazqr)aC}4(zMf_; z+ao$YB_cj?Ms&i2=*UDY91$5AosjacThEC2l*kC|ihR>;QbZ))b{m%*of_ROaYAB3 z^u&OO$f+sO0g9m6%dpSr7Yj&+6am3VPZr==pb+p4C+a{!>Yy zJxAc*IRgLHrQZK!>pdYDrfU7}BQoqhkw-0xp?^tboAzr9oa|DBHI z{ry1u`+@&@A5`5;kiC0BF;f$es#7P$M@&r#wwDODmk9n>i4c2w$Uof(iHwel zjgOBA`B$bP_F_Z+oq{79Y9HCq>L!QUn;e=Pn=oPMzuO&JJ~%#{myERMiTtNfq`fnde;10fKS$xr8w-C)m>y z{;zbI|0O3T#Y87ox07h^U*f;%nQSkd{I6ok_KK$1)2IB?lPTZkamv54R&SMm@1GPL z+En|{rdBsO)!yV(c^;?!yWOePL$?0Y!1RA^XV@E`@i!g&^o@;+o|1ypN{Nn&7#|zk z*5cEyy=TJI`1pX}sR^;(-rc-$+owi*Mn)v{u+N;F>SO6ved&&uUhR7Is?OTOUb~$2 zpBC*;_I;1Z_WsK$QL)H$ro>K>@2iI+-`VR7Xm1~w{49@6zW#f7^7G%_|5nJy$I>3l z;-!sTg>U=T_DeT8(c8CsKtN*B^yJtHF)8MQW=s2a?L6?ey|?|>*Td}N?d@ysAB#M4 zdQvprj7yG4o^B4DG_JRY*=n_VBG7w*ic2ou^`zi-0gO$Tj`pr?M zE7zgSJEy#&yrX=hta5O4aB`pyO&q#71UTe49Ci5K;R?#JUr~zvSJgn(PBln1RF#5K zYmRD}YNzUe>XPcJ>W=CMRfX!k3e;MZQBBn?P)ZF$xs;-wt4>$1QEyRatMk<7)Hl^- z>PPBVD4Bj&Gfu))cmAnJb^8#O+_u)J9 zz4?KBFdxOo^2z*6K8;_*FXPwooA^Ea5&k$|z@OzW@;CT<{6qc)|AA*3g{Hp7Q`1h< zNfV&ytr@LJ(M;3K(k#*})2!2M)Ev~D*4)zE)0AtTXkKW3(Y)9ErB!G-t)sSqwz1Zt zZKv&~?X4ZC4bcwQj?qSGCu`?u7i%-LYqcA+TeVr*J=%lXd~Kojoc5x&RC_~vU;9Y= zLi<|#QTw}A(tdSRIXXJlauglwMG-M)2Nk!qBI3j*L_FMs3NRch^?e8vhOrvVmAMXs z8Xy>%#o3?6&~DTyKv%fcn}C}|-;uD^pO_l_z_FqTYUP_)9bTyNJ4%?vHi&Oa*>F&K z!B7YR{#O`k6oRR^-JOVYf{EaiO2vn+R5S}msW{7xif0BALC+lcz8(5K<(QfWRWt!- zUN?c{gIg0SgweC$W~Rbq0*w4gfiQzIgr z_a*|=x9K4OK7x*YgjP~be9jik6T+C9iPndYjM5;PJ{m#a>-_NB@zgkg7`~CY2N8-+ z%o?)FbeMve=5~y!4NS%OSXSTbY0|T4Cc!OkY?t0sPE;77fVl~S*lL%!vjy4`Yu}cFetpDR}BaJX8YjI(r3+&WDZB~0%V}XqW ztO1e)h+*}hJxl6Dh1p~FcUHf0^q-TBLIj8%-t*QJ@<(N+7_XByXMZrQPOr}pIWwV8WdPRAS_H!dzIaDj2eI_~ZI^C!v-_lk#i z8asDVXt*hP>g*Xy=4hA9Svn=g1wvSVz4X=QZTqT`##MRizmBu5uNtS(iN9EIfqdj! zf*ZG#fG=MHz8vh}&of`)0Cdtbx*Eu6s9^v{5KckEcO4G4+inu#NiQna7Lw#ubeoD_ znh{Ye45JsptuM}9qw;Al_h+wIwc7|PP5PW!%VrwF=59P~5`LyIn}3sg|4U}p()3M6 zsISSGH*aN{p-1o0eUnT=))a2_rcEn18+K(bOrA1x-jtZc_3Kkjy5m_xsGv{ZvUS-O z12oDz`=?3DXKuDbnyASO6XwiYk+HxiIGvBCLg?(_L`Vf+?CcgRgjxk$dOE#t($o77 zbMHQRbHLxPTV$^eCgBu?fEiTSv8bM3~&vsOe=2#mZo3o|zq09TU>o();9b*o2 z8=zs{pzR9+#O{F>Z;XN-N_j~56Feaj(wGSx*#HwO6~GNfftxUmFt;0wfVW9-+C81X z%IUack^om7j1!oa3FBD(1=z(_sn{Dw;8T(R)ECyt+b)?1w=bN#b9>17z`&tH1BG2@ zDXhgUd#5kKEqllL0p$hI%!s2x91DHx0UZjK6CrColAFL|TL(S19#6zO3GxPKfd#Sa zF1TE|lyz2ke~3u$tU?}<>Vrj?lbW8E>N1uH(g)|?BxhF49KnYdPLh;4i&72NX`A*5 zpo3P}DSaRQ%$D4uOyf;WyR-qlGJLhH6}V}HOU`qtkhO*MO~pY6BTIG5CcN++@n11v zSSN!}G%;xJKm+sWg8RwD8b4qSWMbU9N}v~ip%~oQOb(eFn*>jg7YB2!6VC$KKu!`F z*3D|$W}K#slV)(C6b66A<>1SMfR8JAsA-$Qfj5scP(x!Wdwq|?E3>d#95ZNy)ibc$ z_16%2ReZ4`w+l5_V%MAm_IWZD4p8VIv|)dorXKJI$6D~v&bFBYcm5^(hE=~|zj4qM z#a&2TLgJiMt(EE^4wvMQxDexnI~1N*3U`or$5vh_DPA#Tc-V?T!NZqazi1TRXKh1v ze*g@u7Si7e3sa#E($40*19w2xXe(0d0J4#0d`vX?fb-`TPlQjYl4w<)kRli2n>s}V zK3FAU6%NuuTq|xW!6^r;I!lzLc~oX@j^Ks`gW)f|0ET;D5Jrt!I(yk9EzTi?|3GmE z{#t?i(vP3tZ^+bs8CrjE5K^VhRv|R^V$wAOc$9-4jNslKnP6L!cw5l-=GX4owmv6A zdsNeP&^$j=cW9!~rJ{6E;~LfptVt^N@yg7xF4&z1*h*(T)AGPWVHj@Ar6;7Xy zFS|L@+q=)q029;Q#s(Z=gjEUS!JvZitixnXY0pF8ZQwu)+Cbn~ph=iamBOk$L>NwR z&Fvx5FeLMkp?gbB0=JYGYz{@FD#-fVBXVmiic$J-2^FeFqZ9#0Cjq)-r9ua5mKDOS z5Ns8s?1xmj_90QN#dU9;yJ(tW+Kf&6Ou}s{DX_PRS#ynZckNmxu%|?eV&Z#jyA=EClt+ZP z*_Fc5cPQYcUmwW|fgAR5I~9Bn5ol?ZVyuF`67HLMVI}Gq!Z|RX6P$6?UBX7+f|phK z28U)q*~LB;k-wT)l|lj0Nsr3?p{X)T(BrN&Wdt0iI^}K5w|{%i^@~DQs?_1Fz(%CP zSmFFtf{e~lP%4x!l}olO7s?u|O2I2yA*ORsIYjx&VYc(csw3v8Ure$1#pE zj#C`ZIG%UB?D(E^B7I31i6e<*BiT*vljr2MpcF*GR~Rl#5M~Oig_pvo8ue;4u3@PW zRAX$7xEjed=GItR<7JIcHU6yGxaNYIYiefKEUbB@=BJuAorlgx*G`wN+phai%db{M ztsAu`)lRH^u1@1R_nn41O>kP^l;O0_X_Hft(_Nq!p4gm?{8A0iLOb9Cf%C!X)>ruSd+LW zTbk@_a&ilEyWa)0nvE*8gS&myyTh3a}SIYhlmV zf=|SJ9+qePbgV|c>U=w-!V4>0wjyJ6d}wuAhVrxyxV^p%$hgF>Y0F@iehafybb#h* z+P0S~G!V9_2uv4UZl!~Yg`PJ~TRn5t%vDRybxum-Hufbq#cPVTRA0K>zgGfs%_xafbg}y;wLtZo=eH!?2Mj&Rsf_SCnM}4W#Rb z$0bK58^x1JhY}7HxEwvOH#hfS{CFcSImxG#;3DfqbU)H_TPgIfO4R$Zx?|V?*20BZ z&M@z1j2eOP{?H^2Z8cvP@IDOQ<=|?>5}&bzn)TJcggU2SFf?-k%Sf=a18QW1FK0~- zp&0gcVcxOK%b#HhHcv97!h2kuZJ(%M@lnzdjatT?O6mgIsBX<~jlBE&{l+)Xbo&4# zFXT+iR3Jnl!Q!OxUN4tyF4QHAv4mex}(H(=0=4h90(& zsHp0EmxE4<1D*0HG=z9;w3`&5zrXLr^U_n}dbep4F>tJr)okb9oB6p&8_=A6&VPo+ zFf|jK*|D8UO~SgJx)k!Zf(6zw^sV z*WM$>_G=$~^+CERmasPIf3^aP0b8&A4BQ`wU+a>IIue?$H?|+Tc*_Oquv&M}Y;NM! zoHbr-JWR`$9W5?1oGXkA>gYRn;A)edp|nNqXo=O%QEtcz(hbPbv;I6P980(i-nLzh z9clXuIC@I$naHz?HV=+D!x;^B8TH^g)(4f9kBDSOGNmJ#YzDrUtsVz;`Mmx6Gm8ul z3I=!Y8Q!;B|IsI|Ei^GVp1Eg0O@C-;0CPIpCMsy`0`)pqGGj=@tf(mC(v|yV%k+di zpRlR&EDSSOI%R(g!A(2Nv9IGc9*n zO#=(-%7!t2*7G7805Q7e7&6{(haDuM521Aq|Ne>l2J>q;8_FKrVR_5$)dDq(`P`?W7vW!m|m;%om~kt z-ooHYr_IPNIo$Ozfa?W2`yTwIwfbvk4_|zlIdDSIsELDuN90^FGW{lfuiTK^(~L_s z;_vOOBm4Wfu$E9S5J_DR>XkvWm*Lm_wi|IS-{0Dmd*P1D?I5VZx-*{X`Z6b@_&chs z*Y#x=^6uO`Ke~6%;bDP+A%$hQZe@#g*x5?hbdJh9AqhN?a3*mU?1I<&?y)y-UeCLJ zyX<)1zP-i|>}q23m_^TOZ++bpY8oKy0Sp6w=ot(HSPXM-&N$X6Bs2KvSksvN(!?u< z+eJG|@=Rjk%B5VF#mTH;BZD|=nyiAIvIpwZY=&{V>I-1~1TD=U@KSqRhHR+=TW!S1W8Z*<=(_Y{VL+qd@VV@ucjhHg8*54_I$o;rq8Ut>E;;>Bzf_ zpC!{H@%*PM2kC^qJwJ0OCtmn;E+ur^SOcry2F*|>&$7-HCUL{3lgGE^?>4RE<1+S5 zIcc~KT`M30`m>Hu6IJ#oT#fY#hm(gVjO-QKJ|H~) zNU>2jh$Qa=VtW|icAhMF<->}I_u#hFMh#A zTk9$`c{TQy?;evVUCTaPc+UkIc%5PmjqDW<7MocQT`}YBf`snfhFAxh(6H7e5#_Nw z+KlMle@~Se6z=8G1fm;8m3Q)}h3G<&wIecv*hGCf<<29DkLQpRp2MUMX#Xzbb&0fu zigTt>v8V;n-J-DX4uKQZc}w90D}6xOK6V23EhXvpY7?mLK2_pIgYJ1$nt7B&Qr)AI z6swAHLl0u$SfZRy9pVDY`W!Bn@$E# z*Po!QoY#TNsMNDiUz&!4PNgbI4+HhL26Aa>2`f_CQE)9rV7QL|jA2O=OdalXkj>WW zeV%exZXf#j510SphwaJjOI!988b5h)x<^_2?X*3VM_W?eB8mWI72=bX2v1hcB)T{h zRgYzUWzD0BL^qZ8B)Zwy(HN_||Eio2PHxMyHnwFrBwuM6hfgp|#yxuSx^u)ye7Kj0 z1q-Nd*Gam_850pzTMpiAIR`;JTPZohboiBH2&gn+)0i2iajY*7GuSVjTmshS(Y{2N zOO?Z^?h>u)3F;U0HtGwIiE4umpLKZ6!+Yj0={e@Y>sVt}=d6;|QA_D(ZRxyS z+ew9hROo1ZL1DafY9`f%QAFwYAxggmQTp+S(r5Rey130KT&zy#0c|L8qtp{N=-Z6% zWOs;^wq8Do#iX!eu_2!cHst z1D>`<=>Hngt)stz<4A8czB&!m^iuqJ$b3REQQ`L8fI&DE zR|NXv7Q%n=)+L0_iuq5sx9xwuq*suUox~T%HP^S?dh&Ela4#eK9-lvIz@<|Wa|jqV zZgjlyTH@eceGOt!;IQ~%<4sHN%5$*^VH5F&+@D26w~}@yy7T1bQzDkZ?O*iQiQlA- zo+h@L?ME1q7xQ5m%C@q-wBL{^AxOfTu}HJaq%zSe)v6qndUHQv6sUMF4Z7phJU{f~ zFRyZZJGPzJ*~@d%kI#(atu(1FY}7MDA0%g);^M@CyZRZJ#h@Hd%ZP@xoOvK z?J7BBTFI7Ule!bcsg#O$22%0pU8-A6#v@hxP;tW)TpjJHcyJ39;|i&c6)ZxO>dq4i zbE;Z*p-AciDrTbFWmYgwQEl8T}iN@BNoGVk22@ltJKN?eDL}8&G%7-mFo@0X6 zn&&-tC1e;gGzT*7W`1x14^7URt(mxJT$pjFymQ-ET2jj@S6Q9J)zUn8uaB9MGJc#PDSF4&@g{L>X4LpC zF@`?TW5=eN@;$lSt-Ft&G87(}IW5N|uAX)%XZBIU)x#%G9+1@v);3j2w>|++yTyEi z_0vN$7{W)Ro!o}Lhh3Zu}1OoayL&~0QH47eX&&d`f|!qcXpPh8Z5CCw5^g`oszsV$-wG`j$%$zOjDT1dGpgf zxHo)%_Tz%^Imw|b8qA)vV&xoEyjfpac?FAAY5+q~>%WZNH6?1qO;Lf(k>*ResNc7` z!yKD3MG)i0Zb{l7Zw#CgH6p-e1segM7cXW+J0@=GIHNc=G_PZZ~jA8A_4R_S-o$(k1LGId&9 z(%iIF84Hc9_XjRz7>e;T{*jqo`KY9DPiEUzNxyP4;lw9J(%!#?hGcFrS&Tq>(WV$%`!i6Cv zT=vl|#U(B!GcP3M7)ve;EFB!oiHG*Z58F1(5E48+G0qfR5*&PSFc%j$YeZ*@SZN z6@3DZNb3sZ@%>R4JWZzPY{7>SWt11+%f11PoJ$r=a+a+$nHEu5^4=v7gK`&ivf%YS zK&5NP@joA>8a|-c+7Z?tm#;ynV+XkD@#DuQPd}|h`WKf(w*0!e*IYfIWPZ+r$0&k!7H7J)=%st>xp<# zbL>1O&nH!+#&nbp&1Y_gZrTE7h}O(tHCg+;EX1X2Dbj2ZH2(DuXp~{pZ6|+9KLyh51g=yi zdf;`G^ph)*-p?YCUKMR7XUKC}HMuFdN3WtSe^q+xL$6Zltrs~@tNi^aOE@+kFyhR_sXiV>E zlh+;CvuoY{wZl8OP##$VbilsUF?c>&khq-(U?FbpSEj!*AeL-(Mz5s&(dXS4Jtnt}K+jLtl zZuK)`pS{7Y9$r$O@Wv2BKPLV({FdqYFC$KM^ue8dCb;W&-?YtE|DgL5xXkpLXr$?!uF3 zuIku9NhpWG<;snfphpl+kdEsMwx2Ede*1{gW2TK5HG10FQ%1A1+pT_o{BisGmoI@g z8a3+O*9~pvt+UZn+~ex&6A<9>_5opakxPUiH?$%%Ih-b~fm{0Pr!JM1AWlsK?(I!*IA~%(#tj4beZei;?n&~^F@>h{rQ>sk4aAwv89iice*_OF3_j#S#mJj<=KH}?{fF2rS3pl z=E~?zuPbuA!2<#*->6vhmmX5|(5?qGV*Lhoo-{nxcqKYuXP|+3HDd&o0rzJ}_11SD z?zwi<)Gxn$N|`~N1CDQQ0C&hvm7?%zaZ`pH+C`R>o7j9-Pv18A&AlgkU%q&|)uWgH zG%pVm%!kSP(u|{L$_x*VjP0Fa(#2JS*&km+uXD5n=X3xV+;B=~l_1GB@mF$=T|97W zvEP8{TIg*n%#te$ujF+j2uOg)>CM!96exk8q02is_D&_aq3!#sBg&tO z&&Yxtd1>DheJp9rb~lFI9BXLveg_3B`9E0!cZdHI3b>W5;2p2)M_}o))SXXIa&>2& zte|-E=VKzR{w)4nECKA$i_ePZ67h90t2L-c;}s^hSL(Z)YQ!Il>fvAz+CJ@EPT;cC2;uE|)$n#bd{;qaSi!d%R(Ox#$2VAEK|W=NWmv%% zVTJbZF=%JSvec8Qub%v2MaXL{c4@>r@oRBa&m0P?-1#4gZG>d2rq#Dj{KwvjNa%dG z@-B2%LOgV?TLJL}`q6ojg{SgPo+ykuI(l^E_;91-t6oJ|C$?E%j*3D1z*NYvd#TV$ zfc90*vBMdayxEqH-s23k7g)N~_6qd4qC9s4I^0l!qjXJwIzRv9$^6K$u*k@F5Vp!@wLBN{sNX*62;OEZ40%RSB*TGstv^HgJMqo>su4M;sk~c(M9?4+_DF*M z)RpDICh?CI z9dMS8>cyit!FRsRuN@Zr$%_7o-KF4g{@CdSV?tvW zhMBtY?O3}083dl=KeIsY1&?4xKdyB3nS&2qejaql&B%OYAbGqVy4)bF3;HBP^dNbm z7o`qv_pZh!&TQIsifF&}24z+wuKKV_uwIWZs6e-sIaMuaXUYJtfuJ$}4*bRX!!NU1119Z` z+c{xJ1Fv5D=Ioz&Ahp2_TamtH!jI2>$a(VSO>U=dGP^SA#vDtP;&BC=Gxg90|5~#) z4;~Bu`hc~@KVQ7-3ch&PhP6fy=4!~q`D$JIj5xtYoGS5qXeUM4Cq|wWlQ`Wz zFD9IqLY$V9#i*Mh`g$J=`9K5k>iFdL6Q`}8pT3joeHKrpNgLs`Uc8+awlI29h#?^S z=A&oFFF!Ehn{)Yz;Tuek_)l}Xp7%1a1|3_XQ>9Kt3vhn*@X~KvO}6B#2wNhlyV^-z z>l>+SRg>C^q_)B|B=t0-t|NslV@OBpdBc?qqQ9KO*s(0?OGTZ}eJ@Ntdn1qzqC3xx zKZhQg@#mZ%>2mO8sDnS^pIPE3MI$1TK@s5Lhq>O(B8><}AB`}R_o#9~a}>}VBFbwi z2GJG4s{Vu%pY6@%5Z$QN8lAuxAvldSc*DG(Qs#Z1q2Dmrls)_K{G&_4de;x4{izf= zhV-W|v1h|%g*~1Gpl7HC7)q)yVwJ*zi(B#A{T3Lcm*$6gVFmVgB7xOo$VAct3#Q9M zngWIhu#7=lwG_j+T6^NiCX!2-b2WYUxD)VAQ?I3_5viTr^JY{kl&*WwW)%8Lon6TU zQUZ>*X;v29i%{}Cj6U^%UQ#bF%m}xo&Vh6Sx%|I6+7fBJblyxB(b80Kvm#{qAAiIw zzosE*`5*t81fEp+yHjs!t}=Px#g;6saV1mb9%3A6N)}C#Tfj(C4_l(N#fx}T_DNb3 zNGDM^R8`M|?wV|$pY~uF1r~IYiKQ6A*4jr}>qT| z!ZyMyR}zLTIL46fNH}LO+^oK|M#+}#j~L-*|B}^*cU~}v2Wy`_F)zp@9`X+%qo^3` zznEyDF^}n8sS)$WQWM^X5zG*Q;8E?VL_AQ;*1`vzfP-c~(ww$}SAjH)W;~=ZB=sSQ zmh~YsHnH7|IOHTV0+G4q9;jIsvq&kx4|CpmY^DdL7&GZ9FBy+YZ!5%qi!(!Hu@L;_ zRa3tI*tLwJZO0EaICXU2x%GFnL-Ex?f*=M)+iEX+zl}2On!kJTzVs12apCw9xG$~p z!0Rwc=}N-ou^*))v#2;5LC3QLiFkUXM7)SEc_ArrxlmXGaUOVWQszo*&RHd792h2m zTMUx;msxWB=TlrT^ki8e-9&zW97o_U7;7dT@@!A?pdRE`c*WZ)>eH!H~>IGg(dU$?F6$xm^cLq~o5GKHQFdH5 zn1&JXsygaHH_Ih{MFLd#5V0YfSk=;td`~LmB{N1|GOerB?i3N8y5LiGq6{cFE2ST* zTI&z>4ay8Qbn25FI?Oa8Jg)!D4%$#YK7jjyUzWan(L$HWks5q@$Zu|aFtBi>c1Y2! zqzc2ubDQ=Rm{vebE@Ig5)RBfRBZ|MInlKh1yNqM8{E8E3E!pqW`JZ*NySNR@%atL)58&4U3S`L=9q&< z_ob>CX1{=f*AeQgs`_BDzh-@P`p+zAQ1u_l@#}vyx|jt>_gz4gchRBN1L~@zA3?2O zIBU+5S%%0JM-G@E;t3Gj6GraZG@zF>(1R_~bjS++<>=n^TMrp^Gg<8Azf_l%r~(*O z($=bAeMyhK;jH@#bRE_++M+dKYr?`@<}9B&%{VFRMIS@lq^U7M_Y#VrMJ7fw2&Ow4 z$)dTisOW;r#uaX$T>$AOJ*?V?L9;w-`}GLI3hP+c&S%_;_o6{o z!eP*)E)*T|`dp}|lq6C^v85$(?u_-@xwUEcB9j) zH?0o9ZD6JBW>r8q(eR6!8?{&HQa}S29deuaj1m+29`?9 za!$_jT+VVXjU8Yqjfw1lwLaWP;RFusz3j04znrk4cp3oepf+)fo+*bG|F~+4&{bQ6 zuG&WEs%?ak)fQH$e*h=CYINzcHiRQjpfEyKE7Ikun?hZYE~t{oRKUn6gFURg*+!%T z`;0TVo;v0I6oOrN2r(C^czpl1oQoHYd(k~>`8xUs{uX*xb`tahV-&946D)VO+7~R= zW^1G(SMq2MsTzHRT*No+<`MBCOzTGM-eGxk;vFl7yu;x!_N1ZUHvb3_k7Am?6zF`6 zgf68x5B0%Qx_E@F!Wu&H)gB12*8n>Zgc*4R&(UD75kLauJ zl7<=1D_~|f)V|8gn_!T+6gCp?^X2u_mcU@?W>eI^s!Y=L?o@UZU&N_9BvYd$&Xg21 zhRBJyPUW&E<_d9c6zPSYGzcAzmgm)Pt9;Ay}k_ z(54)%7R?Go*q9fOj`F`X-kyX7Rq4&Bfa20@MQyXCBO~#_&R2R8+oUSjruewyA(c-# z?S4pP{r4(rr)_Qi($9XVzb>dUb;mix4Lk}Lj@nw4XqB_>e~0mB7Tm-^$LRXancH^l zEMIeF*Z29_^M(7$-n)D|$Rs{%OIz&iUL0;L9Cst->Ec;wbLP*RzmuYO9+!>y6#esO z7Es%esvWLm617N6T~W!sh;L*i*DNirI_5!h=?`eH?7(Gb*L)ER_V7WKvZCBf*-pt} zB&xk<<@*dNr77w8n&KIk&Q?i~Pr1a9cdyYwDsCy3qEC|4xr?mT!Rq3{;{BO9S1uZ# zS*UEDZzyg<#B0T<3}+WFCd1<<%jX#8rl$W)c2vi+?^(9Na3*j2nIkB4;j@0?lGaQW zL5x$0ZV34xnLX$b!uG*hSF)JilXf%K(j3cZwZ1tfJ(0eZ8rbGui z0-)bK=u^|sg|0tL#pP*sH@b{$q91)~8amPu>V*GRHPjy?^RTExc{!F`l?I!o>p1%i z!}rCFa$YOu?E?ns`h)VWWy~!AmjSf4IqC6j20>>$b_)*^j3!Vdt#YT~NWP}Dk7OE& zit|~#9VM-4`ad1|JQzlk^Aho)NKHiTx-*Lv7RkunQM&Y3RDCU zc3ryaL%*HoVHyn0LKb6MP9BhKu$;z%Et0UHXVK!Q+SZgqMdjp>V!?yqgvJ#pU-+dvT6 zaxG`BGQll803uBsP+hLttFqts^^GLKfkoA|4Z9mC&!&3-B&RfQkN+2Bm?`Sr#Q$CzOcH z6)SIzZ%UVTBbx}e7)PW4*<{*8zQ_g)hCtj#s+?OS+t6|DG!%JU5T0bZCkG#F0LvjP z{{}NWUqqne*Jh1L)NER2EyJLK)Lr122A)on!O|CLcysJcZz7(}3L20!Xac&C$EKIX z67g16XBg2K4Xldt=HwZC9f`MRWl_+Xe325H%7)ktX;OE3f;?Y>c9HlHqa6zFQplIP z$kxf7k!4i<*;Y9g;un1T@Ge~;_u~Zl@`7O6Q%pO9C0@wA??B+Zbj1U&{iOD;#B8@q z5$^BHI#@COqP@pkG}yMJL1S4ST=L(4Y|o0_8M{|Ec$Rsq_>+tM2%!-Txy`a6x5fV; z6|bcgV*CwSbFpMq(_2HIPtQ!>mcD)Ih+b%`nz45t_R2e<3o}NpeGOeHyUYx-Q$f6z zg@)mG#d3Yca(!8HeZ_Kp#f3DNU2lwjzD08A#@p-Q=9hZj3Mjyx-XL_X!8w19oO10o zEWtv4!>EoxQXS{vQ~vA;T>!iFzcJ4N^b4|orhb4&Jdta-*$;hob=T-Z=7z0`#%L5= z4&oV%M|rx8+B{{;c^F}ns@z=B_Ps7k6108IQr{}I2mPKrK}j+~mL#%4jG=LJQE?o5 zh+u%lc059Kggil#c1MziB7$_XYNRv9-!YdW0%J;WUw_20PuqnWnnZU1eGP%{}^8D|cG$fBmbG znOvn+2fT=6D^~_rogHa+$NuHjRQA4B`q>?=f3@mPzd2{C4*1YzWFJ{T0>}t5BU9SE z89FcDoXNA$%~J6C&+9dE+C~_Vsb%9gN)y-qw${;@)jsmSH5@DP0J%{4U5y&xwxveR z6*Y9Qv2Im;{avy8GXZ{z{)z>P4T?jGlZtza=ZZ=^lI5oKRJO%W1cWNXm1C7L%Du|N z%8SZ-%16rQ%Gb)b4g!7x$K=q|!Qv3)Fwr5=A;saj!yAX+RgNl)s;jDxDo(Xkbpk&K zP_Fu@VrmgTTGK+^4nI{hTs;;)1h8LyM15L)89z<)R{fDvaspSEYsvX=ZMkk-Uv4lr zlpD=W<`o|O|Ed+Vb+q-gMr|XlpSGj6pEk&T?0=+oG#)Eks9mL9uid2Gq1~@Nj0gTp z?8p6|YTs)mN6t}jbaHIqXmoUQY~^Ti?BE#aIK(mBF$#~KO~S)xR>xV6^BtEvu65kt zxYcoo<3Y!xj;HWI+BL^A$H$J(9bY>B>iE&|4@b$-rcYWhcfk~cb?W+cDW)wGW@cCo zy_Ss|uyByJl;5*>`WL!pvGy94^#rgN+C z@Ohfc#OVp+mlzY5C1xaLXqlrX{lI~x2Mq7e9)6Z>5>Ukhx2D)42Z38Lyp8vmJG5`h zcJ$%xp*=R3glbsWjtPelL5}Nn#k}K~qYrgLAAwfrME$9-nqVa;6Az`KtlFwTS(T$e zS#>B4LCi^tLM-9Cp$#-+J&+Tc(Rb@5bSFAxDp9!+A%#A;lG1jyF@WNLFhV&QBb3kD zk~uu8>28~{lxIcK6prEPWH~Uj7}d7@#j?IvEbDv4vc6XwM1-#&8k1=95s&lMUJgW> z0=3b3)HDZ_uRwViny9M6B`-Y$vt}3r&=3DwV6<&8bG(XQY0yqIPGr3pL1kgArsb~D zW$#?Tq3jK4fxqX?6rSPjTTU~wvG|&>UO5`5vF|eAad8(N)G0=$>?$bH;(^n7cs^0M z$&Z{B6FS4#NAqmM)jR1gwb06b___dPd}~m40p1l12&n29^_lhv;b=nkJ!h`rg8B%d$neb5NI9`JCb!0L_pVWt<@e#mGfaCErOI&q>|;9@TsK_2vh&fI@T}2k zbC)ijYg)Eaxa^#_`#@gao`k5VWc;6UAkV0qIDb@3u%YAF{GXSYgwTj>#pvF4eM8p) z8Tr`&^Rl6F1+Ek-&Xs`|8Fvv_k926>8GH;d{PPDq+EHyGn}lx?8xPY8YcSaG6F4np zbG5=^dNvz%Fi$GJKZr-SDc^7Y_;I}rJ_#?&9~^x1vq{)&m*g^bU0VQk7rX8tRG>?~ z!-u!cv-y)-w&rDSTedXQ_@`#Yl*t*%2Br<}>t%{;>rtT*LNAj7D&A^Iz6Rkw8lsuA zaaUSCMlI%)?!R>OC#shm%WaOxVxBUeYU>TZMX-{8&9-oC058O$8jW%0PKZ%iaQ#@s z)@XK@uKpU^7(YqkhL!++fdnEwXu^)f-FUot_r7Ht4aLW|pUE=`qsDDMcP@YHsda+* z49E5n$A)q9kM)4xDe)@u!YFQ^)*%?$Y8GM$S_N(bbK`_H6d8$K^%LZ9966j`$V4qn zevN0q%ZO}!EJ7-M&XUi;CdKWkupM5V_o@D4v# z0Ik;|`@?hYPO|ckZVj{0aeIfgMJ^``SLYZ71b;k*Q|r#I*qx;nP7zpzEw06}A?T}2egb4rhY$)-&DBj(1TNBnGRme}@asC40 zut_n)gOj5so4SPck8pK?7f)C;fBR=>vIg`nuL8dJGvY3ys;aHY@SU;hjf*?kU1 z@a(eG12G$1>!Cc$VP`lv!z>zM6}8MrC&H!WxX~pHK-9CFJhYVhaPYhBlAdK(h2t3> zo^Adb>~5hURq-O8|#g+^KbBcwPwFK+v!dR?Jv6WA#j-yWh+qe%+3~#ff(>?)A&> zCx3YVe*8nGXf(D%E29u9n_B2l=!_6}XVnGB*RLYF$|Ng%t{jkh$11>j$%G-&-sVMf6$hY$6Ik+QmvUpKgv z3JUx{0CMz|2&8-xB=4$OTw7kSvqlrL#%rZ}E@Ycl2J(X4FiQXStpf;qvQYjk2pUtu z?8<=Dn^s9z8Ip>hDe#le*L$Kbz*GL*0VGJPk5KfsSL%g75 zOOqx_@rsIwfOqLCMiEr(hz*U6vJ|PZ6hWha#)2jqO>Bvg*kVN!k{G+j?klz!V~I!- zqb6!%2W))5nO$%-n*87VzxR8d_uGA@*L&uiGw00SJyY1JDeQ<$&a2*>TV06%?L+ya zs?wD%s_8DDsV3*nylS>|zsmwHN0&8IeQWgYsIjrJQ%u5)s}`L;e61<8X*CQR95PeQ z0(L$M#rq~c*Ib?y;*D_28vHA z$KJP?{Y!rbwk~%gug7<{yZBY#RpMnPRROwuTy)B84_>>g-iuee@cy>L*Ji3bSa_%% zWv^P`Vu^!lmHq|GVfev+nC=Bj)s_XHl$AHF3@Pu}Ix^B{hU*QO9huKhC!zVN9^2Y$ zRXBdZB31hUsUJ6*^{{&1L)EY$6XIM|2VAQ6<~_`-{;paH_>V<%Eb7LI8|B)Qrrn_Q8KPPQV_4n~EJ8e1exhRP9nOUcS7x^7_>c zLBT4#_J;p3;jLxc$5yK2`&Y16`&H36hnk#g0=olhRUZD70}DL(bB-z(cmQ4exC(E2 z%!e#fZI2(K?2RpJ-g)@s9oUT60uxBpwg+LnfvV2_k+&k(rn>1J)p@A!n*d;FV^}5p zGptzY13szBJ(ah;+N$a|jJDz}5oZ zoKnF8N;+27UIoLMFoHmc8QCL#OlWFMb~-U3&O{N~y|+X{`t=EyNOV;Hz7okE6os65 zgw)l+ASNXOF^1*PM#OddCYdiALhSUxe8_#Oi;^)G)7;|i92aaWD=+^QxH>P zNo962!~QF%u=`Vg*BDO<;1f1@VA!2451aZ)t>{tznF_DQQMpk~YML z_>uOcgM<$q6$7J=6!!hJ8VWOd@L|9X{zUFi<^JrrthjvoKKGY!zm)r{xxXPkH93)f z&i!rN|AzZVxqmu7JtK`?;C>bNuX6t;_wUAMrYF)G?muI`py0k4_pK9PiBE9gzBBjT zxbMMzSa(Z|5&XFy!u<&DM{$36YDQeDFoydH+)w3x7Wc=e=cHu`lej;X`z73;%l!oz zS@G$@N8De|{WaV#I(R@lS+gWNyH{nOlsWmmq|1naHC6ai}s`>#m9 zK2-9$mVe<3SV^|pe-~1$HyihLK0{!NzFzGc@%&f&41Y~fuHd05u#Vt~Se_|j^`(^8 zVc5<_c%5&>OJC<(@Y2`$HoUaaYkdb`c_0kWb|?MF5HgCSlUy>1Oe60?fBu-1L4)2! z4wBa04Ik85tbI7qrj#O(1wjFyjKGBTc8-GzVsN^I=$b z5*<$`(zj?XDS?UJcL1-YWC;usZXg>0wM~G@XXJC3C;WnZ2^el6Uz4pc-@BdcAUgrk z-7w_4mwZF^k^STV;CqPXQd?3@YDg`4L>`kT~)Sf!f#?+BEff+<6>P%gzD{V$4+8n1IEoe*H3g&@ZQxDn(MuOW? zFY1l6kVKkE^8pEeV4Wwvf)b9JBgWQNq4ZGtzZqjYo7P9{PVj#2kl43&`6pWd3u4Lv6fcc?~2xJw5FU=DK9eyO~!yK<3X2+pi5TU8qOHAumugf@qSn@ z3_{rmRp{--vPI+%au+2QcnaV&+CT3x36Ok?_bXy#8_tCV%q$Xfs0#4&^Ysh%li~aO z1>xJCNy-2Je29OzZ=kPlSG77YAfSC)40rO;0Vm5D-NA4MS{n<9zyChG7HyX^p+ zi9EIvjz0T|92QTI3rK#*3I(Nb6lD@Z=hjDeL*R%Oz&1@OTN7{S(_;gdb6zcDDd39!%!l2CzLCXSO6`2FW3IYqvO{Cb9bN4_WL$VGCV zTp&L{p8XNO4OM~veZsLm0W_k;WecmwIu+TvST?UNJEJc@*?)MU0hb&51uoLOeTfkLB-&4Z-c{42Y*wDn*oJ% zKvD_LOt5ZDq8*J{O+wvLvH~(+5bX(xb)Mh^lh;RtOXB7UTXXm3K5l}Wk(-s9jhnq&Q#V()wr&w_W85^Yj^0*0-1Tr@P2FSRu@y9N z_F+3Jlc2`{ifp`3$V$kU?P(v3=ZNbfjtJ)(#|=M1MI6?MD$9N<0smc^cZM#$4!PtQL+^whh)q-tPQuPWcFW>xL0 zhF;FQe59&l<@L&&m6r&)oI*(Dk;;9QYb&Q!PQBR1`nDOn`$MZtH418=qWW%h;c)B- z1#}6B>xm$M?%;GET%}=z%QTo)`pOS|gf?(5ekhZOb)Q6FSShakm;(Hp1w2{^31bx? z`U&ul$vSTV|FpoBw;|ii0hWCX?yv&bSH`uD&72NOKnY*!^^UE2y<-U|V;9#vc7sCJ z0HgQob&mtkSv~;090tWyfM$*XpO1rLPH>tz3#wr>^C_t2BIxEkXyyVics}T+l2gu4 z*h_zg5xI7xhRURts>vhjOCD1{@{|UUC)6K0Od!nw_7UI%r5&Kjbc8Mw0=*^}8ciqY zG;ctw=?uN53pATh=r&!U-Go8E35SN$4f@D?&{UG3>-2!O69IjvC-j}((0Y1NTkP1g z$vkL3eW3mHgAUY}_J(4WSE!e;2H zaXKh-8mDze=Q*6>bHQ82fvemgtLbENn~!^+;}tmcsCzYCM_YwFAfkAkA;9)qLM9Ju zA9>aduWPLc6n{WnNc%eUVC{5!gJJ^8hbsbK#!zN)6gcLLgdbHS^w4kPpy zHWCSC;naipQ;)h@x{x?vkCKts3Go1gAyixU0B!8ydg((Ogw}8@WcjV(ELohlLtFIW z!}{T&7m-AXv=lbh)e3t^H{loJ4%bbX0XG1yT9>A+5oi6J*5!+{5Tc%FhVl>fAuF3n z9ECVyfwHbbZe0yHohW=*_Xw^UeKw|j@jRF_LW=P_(fj<_!-Y49gm!@l-4RL%T~LQ0 z?v8l`Qh{`!4t2MXAI9Qh3F*M{c{yu`HuPXGfMo~FbpYsW7h4<9sRQW^*Nuvx zWkXo$=!(%+y?X&(4X|VMX6P6#!U2X=a2FXJ!s%#QPm35=N2>^FIp{*)hJ`P{n$@p& zj7|+5quF|AxE2O+JuP!OX0-g$ny~eF?oMLO3UqXAxJEo~xE3tV)*z$q5!UP|++nPv z4Wo6qbEwbhou+_h1rp5b*00&fy8DLfNcZ|M4)11cZ=^XUU zY5NWI6U2EAaEId(=0KRDIF%3MM49fX`;@Wnd6Yt`*PYq|35hY}XI;KXB*+80xB`;? zZ~C~Bw4}!RxDoaMb{@w*#^e_5qK}&bf4%i_GxT0RmI`a!RiAHe5Vs*sgkemJQQ%~p zju5i+aY};4-e}j5 z`Kmj5hG??1xI0bKbrLyHl4V^qEF(+9a((=Q8#;JpuU@)t8!Ac3S}8`##=UE}F)J%Y z%1DqRG|BOr)L2bcq9#iU&&r8QNsH0OB_*e8(xuQIQeIMWT#}R)lP|?;a8XfWGHxHr z(!@*2=~A2~D?0|^Slk_@#YJxHo;R(Rq!}NVnxjq5)uiT2smZv#O^fQ;Nm&^=iAk@! z9w`RnWTc`&MqWB|p--Pz-MEyLot@dCT|0K|QhhnQcBugnI%qXq zh!hXqI0JHIJ|zESobx0>o|K>sNcfGSJ${)8#;+E-czc}pJdgYFxG(Z#{E{I-pH7C3 zn1R;$=uM-~iAAq5aQR60AZa*Fis0??ps(gZn@oMFl@B!64Ak>M{ZN#qB78nCEl+8n zrD%|w3qPLM{HIUA#)!vw?BrR(89+XI&PF^9p@egSbUvFbJWmFH4pyccv3_n*4KQOZ zqEPPH~NVGH);;SoU$RD)2Uzh!w9sG(B z8P3!{we*T|31c$o#lU5AII|N+28S%1VMrJy0X}=?WIPdrCtI&9;41Saob0gkjX2b0 zZM2B7lh1UNvgZf|-buhUmd8pYUW?(QZq?ZnB=Q-s)n%!8l(F^_>a(0|^r}mb#W)Nb zwWz~-V{6KwrR6xSfzBL<+2tUe%-1}X<2}Q1))T9z>pdIuVC$a4>FwX89R?@%JPbp0 zBV-`Wo|nyBi(X^-4A>m&Y43jzL!WJM!A9i9*Q3Pj?H#=~~$UpYpam z!6UwMbJ>E1VOp|Z5t>XKY6*2%@fwNg=_f?#d& zYunpr&b680=&LjxwIp|jY|$`Ls#Fqrpjw4)#lZ?ATVe1(bz|9{CCqFsv1KL?OioPq zV)x_usN2eISb=EkR$m|uN>0Nidf72)nYa{C8iKrgcCxo_Q1`zZl+9F=B^OgS!v~~FA{J9Cf_yWfnBq5^NRNn1 z-zF7Ibqr6)898bH*URGE>pF#fG_g^zb*sVJ^Es`PpZ41-jri8Aw$#b<*5Dz{W6rr= zyt2bD<_dj#_`5QvGXmnPP31#h-gzpX0D0zR(4aapM^v}>2G)q2Op_#j_)V2xU_ zF3e@K`awk#*^=d3v3!Ln812D?kZz=Kk)2jHksGV+Wm{wb1I-5w3ASIWcv8b3;m*~^k!B5kz#rO)2&Sw?0k>x+gVX@@V@1_y4t>b{9@%s2OeZQotalT z`XkBqvx(hyMOI9?R@ivTr>*BF+ID|@^y@{T;;|10ys4Zuc}>PWr%0!kK6jJfNp-8< ze$?TETjtq&lJd^qSR6ZjuXb+D%sKtAu<*0$Ic>)E^~rIH2)%IoOABex*}T$) z#c|0`O;42E&e?AI;rZG|gWZ?J`0gqYHcyzgYx%xeZeHV01?29SryWtd^=cn`vlhp$ zoId04)3b|xh}D>amIqfQ{ITFf=8ZS5-M5(Z!>NfYa>pg_{iuHrIiUGx%QrQR4QYG+ z-F2SE6V5r7kC^b&(p4GHLS}9R3)m0mt!Du}b~pLp@;g!8!>TW)MOdg;z63J4XqEvv z4iBvdw27_xP+UZ+$x4^PVlp*qJK2W8-`G|ao|6?Dlb(y4ZZ&Ev^u`&6(V(Q5yljmc z%f&KOwsyJF3A-5KS*KBCiuuf7{O+DTaUs9lQd%IXzMRyRE?{5ZK!)X$b< zZgz2=wAG@r^Pw*;Pv1GZV656lTwG+kriXM~t+g2HT`}I@?*p5~Hd`x`+O50#^EV~4 zJ@?IOK0RUQl<1)uIlDvFxlbQ?)Y?8|+0@?#?KMl^|Lj1oOIwW_Ep(fB@r~A}T*u#B zrap4#s#}wb`^$TTEonNs)OGHaQ4fBfc;~J4v2@OZzN*TTZbR05P*FA`x9sV-yr5sp(`#GzD=6C%6ME0{__ZVFM_t<9_U$*mT>9ntABWcM`r^Q(2Pe!wzP<2S z+iyEYIXMNluI}6mG`t$lN>9gW%L{&OmD&ga{@n$cpzwytJL-}-I6=+oEB z4|=*+**ZMm%CmB`*-)#q^D?qh)E(vax>@-S(q!RQUZ|@%T8$KwEit6f>Qzv~y{KJQ zW{l(!*G5)Df%jsKMcY;lz1KfmSVlag6l`BiNWsOzY9^o*Ei(ij6BCNwA#%}70js{h z(T$v2*A`9vFmqvU>}RoiE47^mtlnLEs?ED|ZaO!<@bi?JVr-k!*3q{vX-q?Y+J7jq z@vMzMjO=@0RHEa8(7^C*HQ|lgl`oq#e)8v@4z8((mE^o>i&T#a6)>p<_N!< zyQELg&}^7~$*B9R(ve@r_O^TMbIWV?jxKvD`=tixXswt!LTb_R+?VMloFToW=p-|k zsm4r;pwnu)QRBuU+lK2mRDn7;{}tpo9|q|-$aeKjuknJ(DniV%wVCFIe zh*Gy{e7&*Ue-a@w<6`_c(Z49dGD>xePU{d~u+;qFn5g1go6Gkv@I2tRmS$&^=YBuc z%qzb2LV26#=i7=FZ*MXEfZuzC-a()K@Wrg-+uFaM-Er=uuiS0oGMhU*Y5#C>#<^vV zt!!tu3{S3lKf~5*&b7@$-+yn(vlS06*^AXhO>8Zy8%MTkIl8QB{?xOg_uO$o_7~Kr zhaaesixu&p)CxVN+Fj^xZ9l?oc8i1FHiH+92{S}CCUpPz5DJsz{pA34`v#Ji1LQyh zlD}`jbi%vUivuRMMiIE(U6XDgHFS-Mmm)IKVso+*)vmHLqgOLK`}#Ab7jF4hzafXP za+PgBcyeNLc1)_&GhC{tXm6=+GVVRsW+Y@w1L5Vx;0$j_OlopG7crz<--h;f|FFG& ze&TE9_m}+ROwrUcXK(uToms3Z=ggGrRL@8mALXR@e}@&lViyK8cy~QGth|?H`_7?!5Qer07L&-5Wo`KCl1PJ3mR0yVZ^+_f2R& zyPc~)o|!mL$ir4m}-8n{e9rcicNze*OyhEYh1PJ zP}%Bff&I5bgPJ?X zt*NT%P`+izQ}M#e7RP*C?w)S(z0~E@@crwLo4bIi0YVR*^d$#|im_7z?s&1H-sgb&vUPsmyhS!Pzku#}RoP^=*L3d;)C`*UQj?bqf zs-Hv5m;wXqkM>LrSHKr5;5%Gy_PkV~wozEGUV8iNh~Rw3dFQl)KAyGK=0)fiQxep{ zqTG2eB(|Y*miK~dmgF#ge~#+PPg3k z%bxO;yVXgvyG2|&*!s?Ugung!1*%0)BmXs=f6C6SJtD`=nN0 zf3%r0 Date: Wed, 3 Feb 2016 00:40:12 +0000 Subject: [PATCH 24/46] Fix: #197 Put the zoom toolbar in the bottom-right corner --- MM.h | 2 ++ MainWindow.cpp | 4 ++++ MapperGLCanvas.cpp | 23 +++++++++++++++-------- MapperGLCanvas.h | 2 ++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/MM.h b/MM.h index 754a86a..daf3f4e 100644 --- a/MM.h +++ b/MM.h @@ -47,6 +47,8 @@ public: static const int DEFAULT_WINDOW_HEIGHT = 480; static const int TOP_TOOLBAR_ICON_SIZE = 48; static const int BOTTOM_TOOLBAR_ICON_SIZE = 32; + static const int ZOOM_TOOLBAR_ICON_SIZE = 22; + static const int ZOOM_TOOLBAR_BUTTON_SIZE = 32; // Style. static const QColor WHITE; diff --git a/MainWindow.cpp b/MainWindow.cpp index 74a3bcf..0f069c2 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -2522,6 +2522,10 @@ void MainWindow::updateCanvases() sourceCanvas->update(); destinationCanvas->update(); outputWindow->getCanvas()->update(); + + // Update position of zoom toolbar + sourceCanvas->moveZoomToolbar(canvasSplitter->widget(0)->rect()); + destinationCanvas->moveZoomToolbar(canvasSplitter->widget(1)->rect()); } diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index eb9c2c0..8e9169e 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -133,33 +133,33 @@ void MapperGLCanvas::createZoomToolsLayout() // Zoom In button _zoomInButton = new QPushButton; _zoomInButton->setIcon(QIcon(":/zoom-in")); - _zoomInButton->setIconSize(QSize(22, 22)); + _zoomInButton->setIconSize(QSize(MM::ZOOM_TOOLBAR_ICON_SIZE, MM::ZOOM_TOOLBAR_ICON_SIZE)); _zoomInButton->setToolTip(tr("Enlarge the shape")); - _zoomInButton->setFixedSize(32, 32); + _zoomInButton->setFixedSize(MM::ZOOM_TOOLBAR_BUTTON_SIZE, MM::ZOOM_TOOLBAR_BUTTON_SIZE); _zoomInButton->setObjectName("zoom-in"); connect(_zoomInButton, SIGNAL(clicked()), this, SLOT(increaseZoomLevel())); // Zoom Out button _zoomOutButton = new QPushButton; _zoomOutButton->setIcon(QIcon(":/zoom-out")); - _zoomOutButton->setIconSize(QSize(22, 22)); + _zoomOutButton->setIconSize(QSize(MM::ZOOM_TOOLBAR_ICON_SIZE, MM::ZOOM_TOOLBAR_ICON_SIZE)); _zoomOutButton->setToolTip(tr("Shrink the shape")); - _zoomOutButton->setFixedSize(32, 32); + _zoomOutButton->setFixedSize(MM::ZOOM_TOOLBAR_BUTTON_SIZE, MM::ZOOM_TOOLBAR_BUTTON_SIZE); _zoomOutButton->setObjectName("zoom-out"); connect(_zoomOutButton, SIGNAL(clicked()), this, SLOT(decreaseZoomLevel())); // Reset to normal size button. _resetZoomButton = new QPushButton; _resetZoomButton->setIcon(QIcon(":/reset-zoom")); - _resetZoomButton->setIconSize(QSize(22, 22)); + _resetZoomButton->setIconSize(QSize(MM::ZOOM_TOOLBAR_ICON_SIZE, MM::ZOOM_TOOLBAR_ICON_SIZE)); _resetZoomButton->setToolTip(tr("Reset the shape to the normal size")); - _resetZoomButton->setFixedSize(32, 32); + _resetZoomButton->setFixedSize(MM::ZOOM_TOOLBAR_BUTTON_SIZE, MM::ZOOM_TOOLBAR_BUTTON_SIZE); _resetZoomButton->setObjectName("reset-zoom"); connect(_resetZoomButton, SIGNAL(clicked()), this, SLOT(resetZoomLevel())); // Fit to view button _fitToViewButton = new QPushButton; _fitToViewButton->setIcon(QIcon(":/zoom-fit")); - _fitToViewButton->setIconSize(QSize(22, 22)); + _fitToViewButton->setIconSize(QSize(MM::ZOOM_TOOLBAR_ICON_SIZE, MM::ZOOM_TOOLBAR_ICON_SIZE)); _fitToViewButton->setToolTip(tr("Fit the shape to content view")); - _fitToViewButton->setFixedSize(32, 32); + _fitToViewButton->setFixedSize(MM::ZOOM_TOOLBAR_BUTTON_SIZE, MM::ZOOM_TOOLBAR_BUTTON_SIZE); _fitToViewButton->setObjectName("zoom-fit"); connect(_fitToViewButton, SIGNAL(clicked()), this, SLOT(fitShapeInView())); @@ -189,6 +189,13 @@ void MapperGLCanvas::createZoomToolsLayout() _zoomToolBar->setLayout(buttonsLayout); } +void MapperGLCanvas::moveZoomToolbar(const QRect &rect) +{ + + _zoomToolBar->move(rect.width() - _zoomToolBar->width(), + rect.height() - _zoomToolBar->height()); +} + // void MapperGLCanvas::mousePressEvent(QMouseEvent* event) diff --git a/MapperGLCanvas.h b/MapperGLCanvas.h index 9e72064..79a663b 100644 --- a/MapperGLCanvas.h +++ b/MapperGLCanvas.h @@ -96,6 +96,8 @@ public: // Apply zoom to view void applyZoomToView(); + // Set the zoom toolbar position + void moveZoomToolbar(const QRect &rect); protected: // void initializeGL(); From 3238efbdb482f89f4672289d4af1b3f70a39cbcf Mon Sep 17 00:00:00 2001 From: baydam Date: Wed, 3 Feb 2016 13:14:25 +0000 Subject: [PATCH 25/46] Fix: #199 zoom toolbar moved into the visible area --- MainWindow.cpp | 4 ++-- MapperGLCanvas.cpp | 7 +++---- MapperGLCanvas.h | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 0f069c2..7da5588 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -2524,8 +2524,8 @@ void MainWindow::updateCanvases() outputWindow->getCanvas()->update(); // Update position of zoom toolbar - sourceCanvas->moveZoomToolbar(canvasSplitter->widget(0)->rect()); - destinationCanvas->moveZoomToolbar(canvasSplitter->widget(1)->rect()); + sourceCanvas->updateZoomToolbar(); + destinationCanvas->updateZoomToolbar(); } diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index 8e9169e..c71fc88 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -189,11 +189,10 @@ void MapperGLCanvas::createZoomToolsLayout() _zoomToolBar->setLayout(buttonsLayout); } -void MapperGLCanvas::moveZoomToolbar(const QRect &rect) +void MapperGLCanvas::updateZoomToolbar() { - - _zoomToolBar->move(rect.width() - _zoomToolBar->width(), - rect.height() - _zoomToolBar->height()); + _zoomToolBar->move(this->viewport()->width() - _zoomToolBar->width(), + this->viewport()->height() - _zoomToolBar->height()); } diff --git a/MapperGLCanvas.h b/MapperGLCanvas.h index 79a663b..9ce6715 100644 --- a/MapperGLCanvas.h +++ b/MapperGLCanvas.h @@ -96,8 +96,8 @@ public: // Apply zoom to view void applyZoomToView(); - // Set the zoom toolbar position - void moveZoomToolbar(const QRect &rect); + // Refresh the zoom toolbar position + void updateZoomToolbar(); protected: // void initializeGL(); From 35ab79eb575e99736b9d524bf4a0e61d5150a6bd Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 4 Feb 2016 13:30:17 +0000 Subject: [PATCH 26/46] Translate the view with arrows keys and increase moving speed --- MapperGLCanvas.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index c71fc88..cdc60ca 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -425,16 +425,16 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) // break; // Handle pixel-wise adjustments of vertex. case Qt::Key_Up: - pos.ry()--; + pos.ry() -= 10; break; case Qt::Key_Down: - pos.ry()++; + pos.ry() += 10; break; case Qt::Key_Right: - pos.rx()++; + pos.rx() += 10; break; case Qt::Key_Left: - pos.rx()--; + pos.rx() -= 10; break; default: handledKey = false; @@ -448,6 +448,10 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) // Enable to Undo and Redo when arrow keys move the position of vertices undoStack->push(new MoveVertexCommand(this, TransformShapeCommand::STEP, _activeVertex, scenePos)); } else { + // Take scroll bar current coordinate + int posX = this->horizontalScrollBar()->value(); + int posY = this->verticalScrollBar()->value(); + handledKey = true; if (event->matches(QKeySequence::Undo)) undoStack->undo(); @@ -467,8 +471,20 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) (event->modifiers() & Qt::ShiftModifier && event->key() == Qt::Key_Plus)) increaseZoomLevel(); } + else if(event->key() == Qt::Key_Up) + posY -= 50; + else if(event->key() == Qt::Key_Down) + posY += 50; + else if(event->key() == Qt::Key_Right) + posX += 50; + else if(event->key() == Qt::Key_Left) + posX -= 50; else handledKey = false; + + // Set scroll bar new value + this->verticalScrollBar()->setValue(posY); + this->horizontalScrollBar()->setValue(posX); } // Defer unhandled keys to parent. From 9c5deae1d73f0119322012b6faf1bb3075969b58 Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 4 Feb 2016 13:41:05 +0000 Subject: [PATCH 27/46] Refresh View at startup --- MainWindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MainWindow.cpp b/MainWindow.cpp index 7da5588..ebd569a 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -86,6 +86,9 @@ MainWindow::MainWindow() // after readSettings(): _preferences_dialog = new PreferencesDialog(this, this); + + // Refresh all + updateCanvases(); } MainWindow::~MainWindow() From 03eec503fc23a935f9898bc1341d23f7a7a7ec0c Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 4 Feb 2016 14:02:08 +0000 Subject: [PATCH 28/46] Able to speed up shifting of active vertex with SHIFT+ArrowKey --- MapperGLCanvas.cpp | 105 ++++++--------------------------------------- 1 file changed, 14 insertions(+), 91 deletions(-) diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index cdc60ca..bc669c9 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -414,27 +414,28 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) MShape::ptr shape = getCurrentShape(); QPoint pos = mapFromScene(shape->getVertex(_activeVertex)); handledKey = true; + if (event->modifiers() & Qt::ShiftModifier) { + if (event->key() == Qt::Key_Up) + pos.ry() -= 50; + else if (event->key() == Qt::Key_Down) + pos.ry() += 50; + else if (event->key() == Qt::Key_Right) + pos.rx() += 50; + else if (event->key() == Qt::Key_Left) + pos.rx() -= 50; + } switch (event->key()) { - // TODO: key tab should switch to next vertex: not working because somehow caught at a higher level - // to switch between frames of the layout -// case Qt::Key_Tab: -// if (shape) -// _activeVertex = (_activeVertex + 1) % shape->nVertices(); -// p = shape->getVertex(_activeVertex); // reset to new vertex -// qDebug() << "New active vertex : " << _activeVertex << endl; -// break; - // Handle pixel-wise adjustments of vertex. case Qt::Key_Up: - pos.ry() -= 10; + pos.ry()--; break; case Qt::Key_Down: - pos.ry() += 10; + pos.ry()++; break; case Qt::Key_Right: - pos.rx() += 10; + pos.rx()++; break; case Qt::Key_Left: - pos.rx() -= 10; + pos.rx()--; break; default: handledKey = false; @@ -492,60 +493,7 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) { QWidget::keyPressEvent(event); } - -// std::cout << "Key pressed" << std::endl; -// int xMove = 0; -// int yMove = 0; -// switch (event->key()) { -// case Qt::Key_Tab: -// if (event->modifiers() & Qt::ControlModifier) -// switchImage( (Common::getCurrentSourceId() + 1) % Common::nImages()); -// else -// { -// Quad& quad = getQuad(); -// _active_vertex = (_active_vertex + 1 ) % 4; -// } -// break; -// case Qt::Key_Up: -// yMove = -1; -// break; -// case Qt::Key_Down: -// yMove = +1; -// break; -// case Qt::Key_Left: -// xMove = -1; -// break; -// case Qt::Key_Right: -// xMove = +1; -// break; -// default: -// std::cerr << "Unhandled key" << std::endl; -// QWidget::keyPressEvent(event); -// break; -// } -// -// Quad& quad = getQuad(); -// Point *p = quad.getVertex(_active_vertex); -// p->x += xMove; -// p->y += yMove; -// quad.setVertex(_active_vertex, p); -// -// update(); -// -// emit quadChanged(); } -// -//void MapperGLCanvas::paintEvent(QPaintEvent* ) -//{ -// makeCurrent(); -// -// QPainter painter(this); -// painter.setRenderHint(QPainter::Antialiasing); -// -// draw(&painter); -// -// painter.end(); -//} void MapperGLCanvas::updateCanvas() { @@ -553,31 +501,6 @@ void MapperGLCanvas::updateCanvas() scene()->update(); } -///* Stick vertex p of Shape orig to another Shape's vertex, if the 2 vertices are -// * close enough. The distance per coordinate is currently set in dist_stick -// * variable. Perhaps the sticky-sensitivity should be configurable through GUI */ -//void MapperGLCanvas::glueVertex(MShape *orig, QPointF *p) -//{ -// MappingManager manager = getMainWindow()->getMappingManager(); -// for (int i = 0; i < manager.nMappings(); i++) -// { -// MShape *shape = getShapeFromMappingId(manager.getMapping(i)->getId()); -// if (shape && shape != orig) -// { -// for (int vertex = 0; vertex < shape->nVertices(); vertex++) -// { -// const QPointF& v = shape->getVertex(vertex); -// if (distIsInside(v, *p, MM::VERTEX_STICK_RADIUS)) -// { -// p->setX(v.x()); -// p->setY(v.y()); -// } -// } -// } -// } -//} - - void MapperGLCanvas::deselectVertices() { _activeVertex = NO_VERTEX; From 9fbb31d9493266db5c58a15aa15eb71988c056ea Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 4 Feb 2016 16:47:22 +0000 Subject: [PATCH 29/46] Switch between vertex to turn them active with Shift+Space shortcut --- MM.h | 1 + MapperGLCanvas.cpp | 32 +++++++++++++++++++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/MM.h b/MM.h index daf3f4e..d6bf1da 100644 --- a/MM.h +++ b/MM.h @@ -82,6 +82,7 @@ public: static const int MESH_SUBDIVISION_MAX_DEPTH_EDITING = 4; static const int MESH_SUBDIVISION_MAX_DEPTH = (-1); static const int ELLIPSE_N_TRIANGLES = 100; // n triangles used to draw an ellipse + static const int VERTEX_MOVES_STEP = 25; }; #endif diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index bc669c9..bedd2cb 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -416,13 +416,19 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) handledKey = true; if (event->modifiers() & Qt::ShiftModifier) { if (event->key() == Qt::Key_Up) - pos.ry() -= 50; + pos.ry() -= MM::VERTEX_MOVES_STEP; else if (event->key() == Qt::Key_Down) - pos.ry() += 50; + pos.ry() += MM::VERTEX_MOVES_STEP; else if (event->key() == Qt::Key_Right) - pos.rx() += 50; + pos.rx() += MM::VERTEX_MOVES_STEP; else if (event->key() == Qt::Key_Left) - pos.rx() -= 50; + pos.rx() -= MM::VERTEX_MOVES_STEP; + // SHIFT+Space to switch between vertex + else if (event->key() == Qt::Key_Space) { + if (shape) + _activeVertex = (_activeVertex + 1) % shape->nVertices(); + pos = shape->getVertex(_activeVertex).toPoint(); // reset to new vertex + } } switch (event->key()) { case Qt::Key_Up: @@ -450,8 +456,8 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) undoStack->push(new MoveVertexCommand(this, TransformShapeCommand::STEP, _activeVertex, scenePos)); } else { // Take scroll bar current coordinate - int posX = this->horizontalScrollBar()->value(); - int posY = this->verticalScrollBar()->value(); + int scrollX = this->horizontalScrollBar()->value(); + int scrollY = this->verticalScrollBar()->value(); handledKey = true; if (event->matches(QKeySequence::Undo)) @@ -463,7 +469,7 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) increaseZoomLevel(); else if (event->matches(QKeySequence::ZoomOut)) decreaseZoomLevel(); - else if (event->modifiers() & Qt::ControlModifier) { + else if (event->modifiers() & Qt::ControlModifier) { if(event->key() == Qt::Key_0) resetZoomLevel(); // Case 2: zoom in with CTRL+= @@ -473,19 +479,19 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) increaseZoomLevel(); } else if(event->key() == Qt::Key_Up) - posY -= 50; + scrollY -= 50; else if(event->key() == Qt::Key_Down) - posY += 50; + scrollY += 50; else if(event->key() == Qt::Key_Right) - posX += 50; + scrollX += 50; else if(event->key() == Qt::Key_Left) - posX -= 50; + scrollX -= 50; else handledKey = false; // Set scroll bar new value - this->verticalScrollBar()->setValue(posY); - this->horizontalScrollBar()->setValue(posX); + this->verticalScrollBar()->setValue(scrollY); + this->horizontalScrollBar()->setValue(scrollX); } // Defer unhandled keys to parent. From f4d0e6bd6a80f8c2be05654838cfa1750321db7e Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 4 Feb 2016 18:28:08 +0000 Subject: [PATCH 30/46] Merge import media and image actions --- MainWindow.cpp | 113 +++++++++++++++++++++---------------------------- MainWindow.h | 6 +-- 2 files changed, 50 insertions(+), 69 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index ebd569a..4648864 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -476,22 +476,7 @@ bool MainWindow::saveAs() return saveFile(fileName); } -void MainWindow::importVideo() -{ - // Stop video playback to avoid lags. XXX Hack - videoTimer->stop(); - - // Pop-up file-choosing dialog to choose media file. - // TODO: restrict the type of files that can be imported - QString fileName = QFileDialog::getOpenFileName(this, tr("Import media source file"), settings.value("defaultVideoDir").toString(), tr("Video files (%1);;All files (*)").arg(MM::VIDEO_FILES_FILTER)); - // Restart video playback. XXX Hack - videoTimer->start(); - - if (!fileName.isEmpty()) - importMediaFile(fileName, false); -} - -void MainWindow::importImage() +void MainWindow::importMedia() { // Stop video playback to avoid lags. XXX Hack videoTimer->stop(); @@ -499,13 +484,22 @@ void MainWindow::importImage() // Pop-up file-choosing dialog to choose media file. // TODO: restrict the type of files that can be imported QString fileName = QFileDialog::getOpenFileName(this, - tr("Import media source file"), settings.value("defaultImageDir").toString(), tr("Image files (%1);;All files (*)").arg(MM::IMAGE_FILES_FILTER)); - + tr("Import media source file"), + settings.value("defaultVideoDir").toString(), + tr("Media files (%1 %2);;All files (*)") + .arg(MM::VIDEO_FILES_FILTER) + .arg(MM::IMAGE_FILES_FILTER)); // Restart video playback. XXX Hack videoTimer->start(); - if (!fileName.isEmpty()) - importMediaFile(fileName, true); + // Check if file is image or not + // according to file extension + if (!fileName.isEmpty()) { + if (MM::IMAGE_FILES_FILTER.contains(QFileInfo(fileName).suffix(), Qt::CaseInsensitive)) + importMediaFile(fileName, true); + else + importMediaFile(fileName, false); + } } void MainWindow::addColor() @@ -1361,7 +1355,7 @@ void MainWindow::createActions() newAction = new QAction(tr("&New"), this); newAction->setIcon(QIcon(":/new")); newAction->setShortcut(QKeySequence::New); - newAction->setStatusTip(tr("Create a new project")); + newAction->setToolTip(tr("Create a new project")); newAction->setIconVisibleInMenu(false); addAction(newAction); connect(newAction, SIGNAL(triggered()), this, SLOT(newFile())); @@ -1370,7 +1364,7 @@ void MainWindow::createActions() openAction = new QAction(tr("&Open..."), this); openAction->setIcon(QIcon(":/open")); openAction->setShortcut(QKeySequence::Open); - openAction->setStatusTip(tr("Open an existing project")); + openAction->setToolTip(tr("Open an existing project")); openAction->setIconVisibleInMenu(false); addAction(openAction); connect(openAction, SIGNAL(triggered()), this, SLOT(open())); @@ -1379,7 +1373,7 @@ void MainWindow::createActions() saveAction = new QAction(tr("&Save"), this); saveAction->setIcon(QIcon(":/save")); saveAction->setShortcut(QKeySequence::Save); - saveAction->setStatusTip(tr("Save the project")); + saveAction->setToolTip(tr("Save the project")); saveAction->setIconVisibleInMenu(false); addAction(saveAction); connect(saveAction, SIGNAL(triggered()), this, SLOT(save())); @@ -1388,7 +1382,7 @@ void MainWindow::createActions() saveAsAction = new QAction(tr("Save &As..."), this); saveAsAction->setIcon(QIcon(":/save-as")); saveAsAction->setShortcut(QKeySequence::SaveAs); - saveAsAction->setStatusTip(tr("Save the project as...")); + saveAsAction->setToolTip(tr("Save the project as...")); saveAsAction->setIconVisibleInMenu(false); addAction(saveAsAction); connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs())); @@ -1420,29 +1414,20 @@ void MainWindow::createActions() emptyRecentVideos->setEnabled(false); - // Import video. - importVideoAction = new QAction(tr("&Import Video File..."), this); - importVideoAction->setShortcut(tr("Ctrl+I")); - importVideoAction->setIcon(QIcon(":/add-video")); - importVideoAction->setStatusTip(tr("Import a video source file...")); - importVideoAction->setIconVisibleInMenu(false); - addAction(importVideoAction); - connect(importVideoAction, SIGNAL(triggered()), this, SLOT(importVideo())); - - // Import imiage. - importImageAction = new QAction(tr("&Import Image File..."), this); - importImageAction->setShortcut(tr("Ctrl+Shift+I")); - importImageAction->setIcon(QIcon(":/add-image")); - importImageAction->setStatusTip(tr("Import a image source file...")); - importImageAction->setIconVisibleInMenu(false); - addAction(importImageAction); - connect(importImageAction, SIGNAL(triggered()), this, SLOT(importImage())); + // Import Media. + importMediaAction = new QAction(tr("&Import Media File..."), this); + importMediaAction->setShortcut(tr("Ctrl+I")); + importMediaAction->setIcon(QIcon(":/add-video")); + importMediaAction->setToolTip(tr("Import a video or image file...")); + importMediaAction->setIconVisibleInMenu(false); + addAction(importMediaAction); + connect(importMediaAction, SIGNAL(triggered()), this, SLOT(importMedia())); // Add color. addColorAction = new QAction(tr("Add &Color Paint..."), this); addColorAction->setShortcut(tr("Ctrl+Shift+A")); addColorAction->setIcon(QIcon(":/add-color")); - addColorAction->setStatusTip(tr("Add a color paint...")); + addColorAction->setToolTip(tr("Add a color paint...")); addColorAction->setIconVisibleInMenu(false); addAction(addColorAction); connect(addColorAction, SIGNAL(triggered()), this, SLOT(addColor())); @@ -1450,7 +1435,7 @@ void MainWindow::createActions() // Exit/quit. exitAction = new QAction(tr("E&xit"), this); exitAction->setShortcut(QKeySequence::Quit); - exitAction->setStatusTip(tr("Exit the application")); + exitAction->setToolTip(tr("Exit the application")); exitAction->setIconVisibleInMenu(false); addAction(exitAction); connect(exitAction, SIGNAL(triggered()), this, SLOT(close())); @@ -1471,7 +1456,7 @@ void MainWindow::createActions() // About. aboutAction = new QAction(tr("&About"), this); - aboutAction->setStatusTip(tr("Show the application's About box")); + aboutAction->setToolTip(tr("Show the application's About box")); aboutAction->setIconVisibleInMenu(false); addAction(aboutAction); connect(aboutAction, SIGNAL(triggered()), this, SLOT(about())); @@ -1479,7 +1464,7 @@ void MainWindow::createActions() // Duplicate. cloneMappingAction = new QAction(tr("Duplicate"), this); cloneMappingAction->setShortcut(Qt::CTRL + Qt::Key_D); - cloneMappingAction->setStatusTip(tr("Duplicate item")); + cloneMappingAction->setToolTip(tr("Duplicate item")); cloneMappingAction->setIconVisibleInMenu(false); addAction(cloneMappingAction); connect(cloneMappingAction, SIGNAL(triggered()), this, SLOT(duplicateMappingItem())); @@ -1487,7 +1472,7 @@ void MainWindow::createActions() // Delete mapping. deleteMappingAction = new QAction(tr("Delete mapping"), this); deleteMappingAction->setShortcut(QKeySequence::Delete); - deleteMappingAction->setStatusTip(tr("Delete item")); + deleteMappingAction->setToolTip(tr("Delete item")); deleteMappingAction->setIconVisibleInMenu(false); addAction(deleteMappingAction); connect(deleteMappingAction, SIGNAL(triggered()), this, SLOT(deleteMappingItem())); @@ -1495,7 +1480,7 @@ void MainWindow::createActions() // Rename mapping. renameMappingAction = new QAction(tr("Rename"), this); renameMappingAction->setShortcut(Qt::Key_F2); - renameMappingAction->setStatusTip(tr("Rename item")); + renameMappingAction->setToolTip(tr("Rename item")); renameMappingAction->setIconVisibleInMenu(false); addAction(renameMappingAction); connect(renameMappingAction, SIGNAL(triggered()), this, SLOT(renameMappingItem())); @@ -1503,14 +1488,14 @@ void MainWindow::createActions() // Delete paint. deletePaintAction = new QAction(tr("Delete paint"), this); //deletePaintAction->setShortcut(tr("CTRL+DEL")); - deletePaintAction->setStatusTip(tr("Delete item")); + deletePaintAction->setToolTip(tr("Delete item")); deletePaintAction->setIconVisibleInMenu(false); connect(deletePaintAction, SIGNAL(triggered()), this, SLOT(deletePaintItem())); // Rename paint. renamePaintAction = new QAction(tr("Rename"), this); //renamePaintAction->setShortcut(Qt::Key_F2); - renamePaintAction->setStatusTip(tr("Rename item")); + renamePaintAction->setToolTip(tr("Rename item")); renamePaintAction->setIconVisibleInMenu(false); addAction(renamePaintAction); connect(renamePaintAction, SIGNAL(triggered()), this, SLOT(renamePaintItem())); @@ -1519,7 +1504,7 @@ void MainWindow::createActions() preferencesAction = new QAction(tr("&Preferences..."), this); //preferencesAction->setIcon(QIcon(":/preferences")); preferencesAction->setShortcut(Qt::CTRL + Qt::Key_Comma); - preferencesAction->setStatusTip(tr("Configure preferences...")); + preferencesAction->setToolTip(tr("Configure preferences...")); //preferencesAction->setIconVisibleInMenu(false); addAction(preferencesAction); connect(preferencesAction, SIGNAL(triggered()), this, SLOT(preferences())); @@ -1528,7 +1513,7 @@ void MainWindow::createActions() addMeshAction = new QAction(tr("Add Quad/&Mesh"), this); addMeshAction->setShortcut(tr("CTRL+M")); addMeshAction->setIcon(QIcon(":/add-mesh")); - addMeshAction->setStatusTip(tr("Add quad/mesh")); + addMeshAction->setToolTip(tr("Add quad/mesh")); addMeshAction->setIconVisibleInMenu(false); addAction(addMeshAction); connect(addMeshAction, SIGNAL(triggered()), this, SLOT(addMesh())); @@ -1538,7 +1523,7 @@ void MainWindow::createActions() addTriangleAction = new QAction(tr("Add &Triangle"), this); addTriangleAction->setShortcut(tr("CTRL+T")); addTriangleAction->setIcon(QIcon(":/add-triangle")); - addTriangleAction->setStatusTip(tr("Add triangle")); + addTriangleAction->setToolTip(tr("Add triangle")); addTriangleAction->setIconVisibleInMenu(false); addAction(addTriangleAction); connect(addTriangleAction, SIGNAL(triggered()), this, SLOT(addTriangle())); @@ -1548,7 +1533,7 @@ void MainWindow::createActions() addEllipseAction = new QAction(tr("Add &Ellipse"), this); addEllipseAction->setShortcut(tr("CTRL+E")); addEllipseAction->setIcon(QIcon(":/add-ellipse")); - addEllipseAction->setStatusTip(tr("Add ellipse")); + addEllipseAction->setToolTip(tr("Add ellipse")); addEllipseAction->setIconVisibleInMenu(false); addAction(addEllipseAction); connect(addEllipseAction, SIGNAL(triggered()), this, SLOT(addEllipse())); @@ -1558,7 +1543,7 @@ void MainWindow::createActions() playAction = new QAction(tr("Play"), this); playAction->setShortcut(Qt::Key_Space); playAction->setIcon(QIcon(":/play")); - playAction->setStatusTip(tr("Play")); + playAction->setToolTip(tr("Play")); playAction->setIconVisibleInMenu(false); addAction(playAction); connect(playAction, SIGNAL(triggered()), this, SLOT(play())); @@ -1568,7 +1553,7 @@ void MainWindow::createActions() pauseAction = new QAction(tr("Pause"), this); pauseAction->setShortcut(Qt::Key_Space); pauseAction->setIcon(QIcon(":/pause")); - pauseAction->setStatusTip(tr("Pause")); + pauseAction->setToolTip(tr("Pause")); pauseAction->setIconVisibleInMenu(false); addAction(pauseAction); connect(pauseAction, SIGNAL(triggered()), this, SLOT(pause())); @@ -1578,7 +1563,7 @@ void MainWindow::createActions() rewindAction = new QAction(tr("Rewind"), this); rewindAction->setShortcut(tr("CTRL+R")); rewindAction->setIcon(QIcon(":/rewind")); - rewindAction->setStatusTip(tr("Rewind")); + rewindAction->setToolTip(tr("Rewind")); rewindAction->setIconVisibleInMenu(false); addAction(rewindAction); connect(rewindAction, SIGNAL(triggered()), this, SLOT(rewind())); @@ -1587,7 +1572,7 @@ void MainWindow::createActions() displayOutputWindowAction = new QAction(tr("&Display Output Window"), this); displayOutputWindowAction->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_W); displayOutputWindowAction->setIcon(QIcon(":/output-window")); - displayOutputWindowAction->setStatusTip(tr("Display output window")); + displayOutputWindowAction->setToolTip(tr("Display output window")); displayOutputWindowAction->setIconVisibleInMenu(false); displayOutputWindowAction->setCheckable(true); displayOutputWindowAction->setChecked(true); @@ -1601,7 +1586,7 @@ void MainWindow::createActions() outputWindowFullScreenAction = new QAction(tr("&Fullscreen"), this); outputWindowFullScreenAction->setIcon(QIcon(":/fullscreen")); outputWindowFullScreenAction->setShortcut(Qt::CTRL + Qt::Key_F); - outputWindowFullScreenAction->setStatusTip(tr("Full screen")); + outputWindowFullScreenAction->setToolTip(tr("Full screen")); outputWindowFullScreenAction->setIconVisibleInMenu(false); outputWindowFullScreenAction->setCheckable(true); outputWindowFullScreenAction->setChecked(false); @@ -1617,7 +1602,7 @@ void MainWindow::createActions() displayControlsAction = new QAction(tr("&Display Canvas Controls"), this); displayControlsAction->setShortcut(Qt::ALT + Qt::Key_C); displayControlsAction->setIcon(QIcon(":/control-points")); - displayControlsAction->setStatusTip(tr("Display canvas controls")); + displayControlsAction->setToolTip(tr("Display canvas controls")); displayControlsAction->setIconVisibleInMenu(false); displayControlsAction->setCheckable(true); displayControlsAction->setChecked(_displayControls); @@ -1629,7 +1614,7 @@ void MainWindow::createActions() stickyVerticesAction = new QAction(tr("&Sticky Vertices"), this); stickyVerticesAction->setShortcut(Qt::ALT + Qt::Key_S); stickyVerticesAction->setIcon(QIcon(":/control-points")); - stickyVerticesAction->setStatusTip(tr("Enable sticky vertices")); + stickyVerticesAction->setToolTip(tr("Enable sticky vertices")); stickyVerticesAction->setIconVisibleInMenu(false); stickyVerticesAction->setCheckable(true); stickyVerticesAction->setChecked(_stickyVertices); @@ -1640,7 +1625,7 @@ void MainWindow::createActions() displayTestSignalAction = new QAction(tr("&Display Test Signal"), this); displayTestSignalAction->setShortcut(Qt::ALT + Qt::Key_T); displayTestSignalAction->setIcon(QIcon(":/control-points")); - displayTestSignalAction->setStatusTip(tr("Display test signal")); + displayTestSignalAction->setToolTip(tr("Display test signal")); displayTestSignalAction->setIconVisibleInMenu(false); displayTestSignalAction->setCheckable(true); displayTestSignalAction->setChecked(_displayTestSignal); @@ -1705,8 +1690,7 @@ void MainWindow::createMenus() fileMenu->addAction(saveAction); fileMenu->addAction(saveAsAction); fileMenu->addSeparator(); - fileMenu->addAction(importVideoAction); - fileMenu->addAction(importImageAction); + fileMenu->addAction(importMediaAction); fileMenu->addAction(addColorAction); // Recent file separator @@ -1817,8 +1801,7 @@ void MainWindow::createToolBars() mainToolBar = addToolBar(tr("&File")); mainToolBar->setIconSize(QSize(MM::TOP_TOOLBAR_ICON_SIZE, MM::TOP_TOOLBAR_ICON_SIZE)); mainToolBar->setMovable(false); - mainToolBar->addAction(importVideoAction); - mainToolBar->addAction(importImageAction); + mainToolBar->addAction(importMediaAction); mainToolBar->addAction(addColorAction); mainToolBar->addAction(newAction); mainToolBar->addAction(openAction); diff --git a/MainWindow.h b/MainWindow.h index 31461cd..d606a56 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -83,8 +83,7 @@ private slots: void preferences(); bool save(); bool saveAs(); - void importVideo(); - void importImage(); + void importMedia(); void addColor(); void about(); void updateStatusBar(); @@ -297,8 +296,7 @@ private: QAction *separatorAction; QAction *newAction; QAction *openAction; - QAction *importVideoAction; - QAction *importImageAction; + QAction *importMediaAction; QAction *addColorAction; QAction *saveAction; QAction *saveAsAction; From ce74dace6845fcb9e9cc22f2e42dc266fa730250 Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 4 Feb 2016 20:45:31 +0000 Subject: [PATCH 31/46] Reorder the toolbar icons --- MainWindow.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 4648864..49c4b1a 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -1803,9 +1803,6 @@ void MainWindow::createToolBars() mainToolBar->setMovable(false); mainToolBar->addAction(importMediaAction); mainToolBar->addAction(addColorAction); - mainToolBar->addAction(newAction); - mainToolBar->addAction(openAction); - mainToolBar->addAction(saveAction); mainToolBar->addSeparator(); @@ -1816,9 +1813,6 @@ void MainWindow::createToolBars() mainToolBar->addSeparator(); mainToolBar->addAction(displayOutputWindowAction); - mainToolBar->addAction(outputWindowFullScreenAction); - mainToolBar->addAction(displayControlsAction); - mainToolBar->addAction(stickyVerticesAction); mainToolBar->addAction(displayTestSignalAction); runToolBar = addToolBar(tr("&Run")); From d889a6c616d9aa3a0bda765e3dfb53398744b8be Mon Sep 17 00:00:00 2001 From: baydam Date: Fri, 5 Feb 2016 18:17:47 +0000 Subject: [PATCH 32/46] Output window is fullscreen only if a video projector is connected or not visible --- MainWindow.cpp | 117 ++++++++++++++------------------------------- MainWindow.h | 9 ++-- OutputGLWindow.cpp | 64 +++++++++---------------- OutputGLWindow.h | 2 - 4 files changed, 64 insertions(+), 128 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 49c4b1a..fd06d9a 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -86,9 +86,6 @@ MainWindow::MainWindow() // after readSettings(): _preferences_dialog = new PreferencesDialog(this, this); - - // Refresh all - updateCanvases(); } MainWindow::~MainWindow() @@ -310,14 +307,6 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) if (keyEvent->modifiers() == Qt::CTRL) { switch (keyEvent->key()) { - case Qt::Key_F: - if (outputWindow->windowState() != Qt::WindowFullScreen) - { - outputWindow->setFullScreen(true); - outputWindowFullScreenAction->setChecked(true); - outputWindowFullScreenAction->setEnabled(true); - } - break; case Qt::Key_N: newFile(); break; @@ -358,11 +347,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) undoStack->redo(); } else if (keyEvent->key() == Qt::Key_Escape) - { - outputWindow->setFullScreen(false); - outputWindowFullScreenAction->setChecked(false); - outputWindowFullScreenAction->setEnabled(false); - } + outputWindow->close(); else if (keyEvent->key() == Qt::Key_Space) { if (_isPlaying) @@ -387,9 +372,8 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) void MainWindow::setOutputWindowFullScreen(bool enable) { - outputWindow->setFullScreen(false); + outputWindow->setFullScreen(enable); // setCheckState - outputWindowFullScreenAction->setChecked(enable); displayControlsAction->setChecked(enable); } @@ -1284,7 +1268,6 @@ void MainWindow::createLayout() destinationCanvas->setMinimumSize(CANVAS_MINIMUM_WIDTH, CANVAS_MINIMUM_HEIGHT); outputWindow = new OutputGLWindow(this, destinationCanvas); - outputWindow->setVisible(true); outputWindow->installEventFilter(destinationCanvas); outputWindow->installEventFilter(this); @@ -1569,34 +1552,19 @@ void MainWindow::createActions() connect(rewindAction, SIGNAL(triggered()), this, SLOT(rewind())); // Toggle display of output window. - displayOutputWindowAction = new QAction(tr("&Display Output Window"), this); - displayOutputWindowAction->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_W); - displayOutputWindowAction->setIcon(QIcon(":/output-window")); - displayOutputWindowAction->setToolTip(tr("Display output window")); - displayOutputWindowAction->setIconVisibleInMenu(false); - displayOutputWindowAction->setCheckable(true); - displayOutputWindowAction->setChecked(true); - addAction(displayOutputWindowAction); - // Manage show/hide of GL output window. - connect(displayOutputWindowAction, SIGNAL(toggled(bool)), outputWindow, SLOT(setVisible(bool))); - // When closing the GL output window, uncheck the action in menu. - connect(outputWindow, SIGNAL(closed()), displayOutputWindowAction, SLOT(toggle())); - - // Toggle display of output window. - outputWindowFullScreenAction = new QAction(tr("&Fullscreen"), this); - outputWindowFullScreenAction->setIcon(QIcon(":/fullscreen")); - outputWindowFullScreenAction->setShortcut(Qt::CTRL + Qt::Key_F); - outputWindowFullScreenAction->setToolTip(tr("Full screen")); - outputWindowFullScreenAction->setIconVisibleInMenu(false); - outputWindowFullScreenAction->setCheckable(true); - outputWindowFullScreenAction->setChecked(false); - addAction(displayOutputWindowAction); - // Manage fullscreen mode for output window. - connect(outputWindowFullScreenAction, SIGNAL(toggled(bool)), outputWindow, SLOT(setFullScreen(bool))); - // When fullscreen is toggled by the output window (eg. when pressing ESC), change the action checkbox. - connect(outputWindow, SIGNAL(fullScreenToggled(bool)), outputWindowFullScreenAction, SLOT(setChecked(bool))); - // Output window should be displayed for full screen option to be available. - connect(displayOutputWindowAction, SIGNAL(toggled(bool)), outputWindowFullScreenAction, SLOT(setEnabled(bool))); + outputFullScreenAction = new QAction(tr("&Full Screen"), this); + outputFullScreenAction->setShortcut(Qt::CTRL + Qt::Key_F); + outputFullScreenAction->setIcon(QIcon(":/fullscreen")); + outputFullScreenAction->setToolTip(tr("Full screen mode")); + outputFullScreenAction->setIconVisibleInMenu(false); + outputFullScreenAction->setCheckable(true); + // Don't be displayed by default + outputFullScreenAction->setChecked(false); + addAction(outputFullScreenAction); + // Manage fullscreen/modal show of GL output window. + connect(outputFullScreenAction, SIGNAL(toggled(bool)), outputWindow, SLOT(setFullScreen(bool))); + // When closing the GL output window or hit ESC key, uncheck the action in menu. + connect(outputWindow, SIGNAL(closed()), outputFullScreenAction, SLOT(toggle())); // Toggle display of canvas controls. displayControlsAction = new QAction(tr("&Display Canvas Controls"), this); @@ -1643,14 +1611,14 @@ void MainWindow::createActions() connect(displayUndoStackAction, SIGNAL(toggled(bool)), this, SLOT(displayUndoStack(bool))); // Toggle display of Console output - displayConsoleAction = new QAction(tr("Disp&lay Console"), this); - displayConsoleAction->setShortcut(Qt::ALT + Qt::Key_L); - displayConsoleAction->setCheckable(true); - displayConsoleAction->setChecked(false); - addAction(displayConsoleAction); - connect(displayConsoleAction, SIGNAL(toggled(bool)), consoleWindow, SLOT(setVisible(bool))); + openConsoleAction = new QAction(tr("Open Conso&le"), this); + openConsoleAction->setShortcut(Qt::ALT + Qt::Key_L); + openConsoleAction->setCheckable(true); + openConsoleAction->setChecked(false); + addAction(openConsoleAction); + connect(openConsoleAction, SIGNAL(toggled(bool)), consoleWindow, SLOT(setVisible(bool))); // uncheck action when window is closed - connect(consoleWindow, SIGNAL(windowClosed()), displayConsoleAction, SLOT(toggle())); + connect(consoleWindow, SIGNAL(windowClosed()), openConsoleAction, SLOT(toggle())); // Toggle display of zoom tool buttons displayZoomToolAction = new QAction(tr("Display &Zoom Toolbar"), this); @@ -1667,9 +1635,7 @@ void MainWindow::startFullScreen() // Remove canvas controls. displayControlsAction->setChecked(false); // Display output window. - displayOutputWindowAction->setChecked(true); - // Send fullscreen. - outputWindowFullScreenAction->setChecked(true); + outputFullScreenAction->setChecked(true); } void MainWindow::createMenus() @@ -1734,21 +1700,24 @@ void MainWindow::createMenus() // View. viewMenu = menuBar->addMenu(tr("&View")); - viewMenu->addAction(displayOutputWindowAction); - viewMenu->addAction(outputWindowFullScreenAction); viewMenu->addAction(displayControlsAction); viewMenu->addAction(stickyVerticesAction); viewMenu->addAction(displayTestSignalAction); viewMenu->addSeparator(); viewMenu->addAction(displayUndoStackAction); viewMenu->addAction(displayZoomToolAction); - viewMenu->addAction(displayConsoleAction); + viewMenu->addSeparator(); + viewMenu->addAction(outputFullScreenAction); // Run. - runMenu = menuBar->addMenu(tr("&Run")); - runMenu->addAction(playAction); - runMenu->addAction(pauseAction); - runMenu->addAction(rewindAction); + playbackMenu = menuBar->addMenu(tr("&Playback")); + playbackMenu->addAction(playAction); + playbackMenu->addAction(pauseAction); + playbackMenu->addAction(rewindAction); + + // Tools + toolsMenu = menuBar->addMenu(tr("&Tools")); + toolsMenu->addAction(openConsoleAction); // Help. helpMenu = menuBar->addMenu(tr("&Help")); @@ -1812,7 +1781,7 @@ void MainWindow::createToolBars() mainToolBar->addSeparator(); - mainToolBar->addAction(displayOutputWindowAction); + mainToolBar->addAction(outputFullScreenAction); mainToolBar->addAction(displayTestSignalAction); runToolBar = addToolBar(tr("&Run")); @@ -1830,13 +1799,6 @@ void MainWindow::createToolBars() // Add toolbars. addToolBar(Qt::TopToolBarArea, mainToolBar); addToolBar(Qt::TopToolBarArea, runToolBar); - -// editToolBar = addToolBar(tr("&Edit")); -// editToolBar->addAction(cloneAction); -// editToolBar->addAction(deleteAction); -// editToolBar->addSeparator(); -// editToolBar->addAction(findAction); -// editToolBar->addAction(goToCellAction); } void MainWindow::createStatusBar() @@ -1875,15 +1837,11 @@ void MainWindow::readSettings() // new in 0.1.2: if (settings.contains("displayOutputWindow")) { - displayOutputWindowAction->setChecked(settings.value("displayOutputWindow").toBool()); - } - if (settings.contains("outputWindowFullScreen")) - { - outputWindowFullScreenAction->setChecked(settings.value("outputWindowFullScreen").toBool()); + outputFullScreenAction->setChecked(settings.value("displayOutputWindow").toBool()); } if (settings.contains("displayTestSignal")) { - displayOutputWindowAction->setChecked(settings.value("displayTestSignal").toBool()); + outputFullScreenAction->setChecked(settings.value("displayTestSignal").toBool()); } config_osc_receive_port = settings.value("osc_receive_port", 12345).toInt(); @@ -1908,8 +1866,7 @@ void MainWindow::writeSettings() settings.setValue("mappingSplitter", mappingSplitter->saveState()); settings.setValue("canvasSplitter", canvasSplitter->saveState()); settings.setValue("outputWindow", outputWindow->saveGeometry()); - settings.setValue("displayOutputWindow", displayOutputWindowAction->isChecked()); - settings.setValue("outputWindowFullScreen", outputWindowFullScreenAction->isChecked()); + settings.setValue("displayOutputWindow", outputFullScreenAction->isChecked()); settings.setValue("displayTestSignal", displayTestSignalAction->isChecked()); settings.setValue("osc_receive_port", config_osc_receive_port); settings.setValue("displayUndoStack", displayUndoStackAction->isChecked()); diff --git a/MainWindow.h b/MainWindow.h index d606a56..fd3103b 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -278,7 +278,8 @@ private: QMenu *fileMenu; QMenu *editMenu; QMenu *viewMenu; - QMenu *runMenu; + QMenu *toolsMenu; + QMenu *playbackMenu; QMenu *helpMenu; QMenu *recentFileMenu; QMenu *recentVideoMenu; @@ -321,15 +322,13 @@ private: QAction *pauseAction; QAction *rewindAction; - QAction *displayOutputWindowAction; - //QAction *outputWindowHasCursor; - QAction *outputWindowFullScreenAction; + QAction *outputFullScreenAction; QAction *displayControlsAction; QAction *displayTestSignalAction; QAction *stickyVerticesAction; QAction *displayUndoStackAction; QAction *displayZoomToolAction; - QAction *displayConsoleAction; + QAction *openConsoleAction; enum { MaxRecentFiles = 10 }; enum { MaxRecentVideo = 5 }; diff --git a/OutputGLWindow.cpp b/OutputGLWindow.cpp index 7866224..7681983 100644 --- a/OutputGLWindow.cpp +++ b/OutputGLWindow.cpp @@ -36,9 +36,6 @@ OutputGLWindow:: OutputGLWindow(QWidget* parent, const DestinationGLCanvas* canv layout->addWidget(canvas); setLayout(layout); - // Save window geometry. - _geometry = saveGeometry(); - _pointerIsVisible = true; } @@ -87,61 +84,46 @@ void OutputGLWindow::closeEvent(QCloseEvent *event) void OutputGLWindow::setFullScreen(bool fullscreen) { - setCursorVisible(!fullscreen); - emit fullScreenToggled(fullscreen); - // Activate crosshair in fullscreen mode. - // should be only drawn if the controls should be shown - canvas->setDisplayCrosshair(fullscreen && canvas->getMainWindow()->displayControls()); - - // NOTE: The showFullScreen() method does not work well under Ubuntu Linux. The code below fixes the issue. - // Notice that there might be problems with the fullscreen in other OS / window managers. If so, please add - // the code to fix those issues here. - // See: http://qt-project.org/doc/qt-4.8/qwidget.html#showFullScreen - // Source: http://stackoverflow.com/questions/12645880/fullscreen-for-qdialog-from-within-mainwindow-only-working-sometimes -#ifdef Q_OS_UNIX - const QString session = QString(getenv("DESKTOP_SESSION")).toLower(); -#endif if (fullscreen) { - // Save window geometry. - _geometry = saveGeometry(); - //qDebug() << "Saving Geometry " << _geometry.toHex() << endl; - - // Move window to second screen before fullscreening it. + // Check if user is on multiple screen if (QApplication::desktop()->screenCount() > 1) + { + // Hide cursor + setCursorVisible(!fullscreen); + // Activate crosshair in fullscreen mode. + // should be only drawn if the controls should be shown + canvas->setDisplayCrosshair(fullscreen && canvas->getMainWindow()->displayControls()); + //Move window to second screen before fullscreening it. setGeometry(QApplication::desktop()->screenGeometry(1)); - -#ifdef Q_OS_UNIX - // Special case for Unity. - if (session == "ubuntu" || session == "cinnamon" || session == "default") { + //The problem related to the full screen on linux seems to be resolved + // with Qt 5.5 at least on Debian but define macro anyway +#ifdef Q_OS_LINUX setWindowFlags(Qt::Window); setVisible(true); setWindowState( windowState() ^ Qt::WindowFullScreen ); show(); - } else { - showFullScreen(); - } #else showFullScreen(); #endif + } + else + { + show(); + } } else { - // Restore geometry of window to what it was before full screen call. - //restoreGeometry(_geometry); - -#ifdef Q_OS_UNIX - // Special case for Unity. - if (session == "ubuntu") { - showNormal(); - } else { - restoreGeometry(_geometry); - showNormal(); + if (QApplication::desktop()->screenCount() > 1) { +#ifdef Q_OS_LINUX setWindowFlags( windowFlags() & ~Qt::Window ); - } #else - restoreGeometry(_geometry); showNormal(); #endif + } + else + { + hide(); + } } } diff --git a/OutputGLWindow.h b/OutputGLWindow.h index 4d078de..50dd624 100644 --- a/OutputGLWindow.h +++ b/OutputGLWindow.h @@ -50,7 +50,6 @@ protected: signals: void closed(); - void fullScreenToggled(bool fullScreen); public: DestinationGLCanvas* getCanvas() const { return canvas; } @@ -59,7 +58,6 @@ public: private: OutputGLCanvas* canvas; - QByteArray _geometry; bool _pointerIsVisible; }; From d1af8b42087b365f67f25bb1bd87da49384e37c1 Mon Sep 17 00:00:00 2001 From: baydam Date: Mon, 8 Feb 2016 16:20:45 +0000 Subject: [PATCH 33/46] Now we are able to show and hide menubar with ALT key --- MainWindow.cpp | 15 +++++++++++++++ MainWindow.h | 1 + 2 files changed, 16 insertions(+) diff --git a/MainWindow.cpp b/MainWindow.cpp index fd06d9a..72417c1 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -370,6 +370,18 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) } } +void MainWindow::keyPressEvent(QKeyEvent *event) +{ +#ifdef Q_OS_OSX + // Do nothing +#else + if (event->modifiers() & Qt::AltModifier) { + menuBar()->setHidden(!menuBar()->isHidden()); + menuBar()->setFocus(Qt::MenuBarFocusReason); + } +#endif +} + void MainWindow::setOutputWindowFullScreen(bool enable) { outputWindow->setFullScreen(enable); @@ -1854,6 +1866,8 @@ void MainWindow::readSettings() displayUndoStackAction->setChecked(settings.value("displayUndoStack").toBool()); if (settings.contains("zoomToolBar")) displayZoomToolAction->setChecked(settings.value("zoomToolBar").toBool()); + if (settings.contains("menuBarHidden")) + menuBar()->setHidden(settings.value("menuBarHidden").toBool()); } void MainWindow::writeSettings() @@ -1871,6 +1885,7 @@ void MainWindow::writeSettings() settings.setValue("osc_receive_port", config_osc_receive_port); settings.setValue("displayUndoStack", displayUndoStackAction->isChecked()); settings.setValue("zoomToolBar", displayZoomToolAction->isChecked()); + settings.setValue("menuBarHidden", menuBar()->isHidden()); } bool MainWindow::okToContinue() diff --git a/MainWindow.h b/MainWindow.h index fd3103b..b49eb9e 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -72,6 +72,7 @@ protected: // Events /////////////////////////////////////////////////////////////////////////////////////////////////// void closeEvent(QCloseEvent *event); bool eventFilter(QObject *obj, QEvent *event); + void keyPressEvent(QKeyEvent *event); // Slots //////////////////////////////////////////////////////////////////////////////////////////////////// private slots: From 5c66fa1b8d6fac9d2310d6787e8c39fc78e07ecf Mon Sep 17 00:00:00 2001 From: baydam Date: Mon, 8 Feb 2016 19:08:37 +0000 Subject: [PATCH 34/46] User can show or hide toolbar --- MainWindow.cpp | 34 +++++++++++++++++++++++----------- MainWindow.h | 4 +++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 72417c1..bf1ba3e 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -1640,6 +1640,12 @@ void MainWindow::createActions() addAction(displayZoomToolAction); connect(displayZoomToolAction, SIGNAL(toggled(bool)), sourceCanvas, SLOT(showZoomToolBar(bool))); connect(displayZoomToolAction, SIGNAL(toggled(bool)), destinationCanvas, SLOT(showZoomToolBar(bool))); + + // Toggle show/hide menuBar + showMenuBarAction = new QAction(tr("&Menu Bar"), this); + showMenuBarAction->setCheckable(true); + showMenuBarAction->setChecked(true); + connect(showMenuBarAction, SIGNAL(triggered(bool)), menuBar(), SLOT(setVisible(bool))); } void MainWindow::startFullScreen() @@ -1712,6 +1718,10 @@ void MainWindow::createMenus() // View. viewMenu = menuBar->addMenu(tr("&View")); + // Toolbars menu + toolBarsMenu = viewMenu->addMenu(tr("Toolbars")); + toolBarsMenu->addAction(showMenuBarAction); + viewMenu->addSeparator(); viewMenu->addAction(displayControlsAction); viewMenu->addAction(stickyVerticesAction); viewMenu->addAction(displayTestSignalAction); @@ -1779,7 +1789,7 @@ void MainWindow::createPaintContextMenu() void MainWindow::createToolBars() { - mainToolBar = addToolBar(tr("&File")); + mainToolBar = addToolBar(tr("&Toolbar")); mainToolBar->setIconSize(QSize(MM::TOP_TOOLBAR_ICON_SIZE, MM::TOP_TOOLBAR_ICON_SIZE)); mainToolBar->setMovable(false); mainToolBar->addAction(importMediaAction); @@ -1796,21 +1806,24 @@ void MainWindow::createToolBars() mainToolBar->addAction(outputFullScreenAction); mainToolBar->addAction(displayTestSignalAction); - runToolBar = addToolBar(tr("&Run")); - runToolBar->setIconSize(QSize(MM::TOP_TOOLBAR_ICON_SIZE, MM::TOP_TOOLBAR_ICON_SIZE)); - runToolBar->setMovable(false); // XXX: style hack: dummy expanding widget allows the placement of toolbar at the top right // From: http://www.qtcentre.org/threads/9102-QToolbar-setContentsMargins - QWidget* spacer = new QWidget(runToolBar); + QWidget* spacer = new QWidget(mainToolBar); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - runToolBar->addWidget(spacer); - runToolBar->addAction(playAction); - runToolBar->addAction(pauseAction); - runToolBar->addAction(rewindAction); + mainToolBar->addWidget(spacer); + mainToolBar->addAction(playAction); + mainToolBar->addAction(pauseAction); + mainToolBar->addAction(rewindAction); + + // Disable toolbar context menu + mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu); + + // Toggle show/hide of toolbar + showToolBarAction = mainToolBar->toggleViewAction(); + toolBarsMenu->addAction(showToolBarAction); // Add toolbars. addToolBar(Qt::TopToolBarArea, mainToolBar); - addToolBar(Qt::TopToolBarArea, runToolBar); } void MainWindow::createStatusBar() @@ -2480,7 +2493,6 @@ void MainWindow::updateCanvases() destinationCanvas->updateZoomToolbar(); } - void MainWindow::enableDisplayControls(bool display) { _displayControls = display; diff --git a/MainWindow.h b/MainWindow.h index b49eb9e..c8cf18a 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -289,10 +289,10 @@ private: // Some menus when need to be separated QMenu *sourceMenu; QMenu *destinationMenu; + QMenu *toolBarsMenu; // Toolbar. QToolBar *mainToolBar; - QToolBar *runToolBar; // Actions. QAction *separatorAction; @@ -330,6 +330,8 @@ private: QAction *displayUndoStackAction; QAction *displayZoomToolAction; QAction *openConsoleAction; + QAction *showMenuBarAction; + QAction *showToolBarAction; enum { MaxRecentFiles = 10 }; enum { MaxRecentVideo = 5 }; From b3065af6ba3a1c45730557c77c3c57cf39f84dff Mon Sep 17 00:00:00 2001 From: baydam Date: Tue, 9 Feb 2016 11:52:16 +0000 Subject: [PATCH 35/46] Add a macro to check for Qt >= 5.5 --- ConsoleWindow.cpp | 2 +- MainWindow.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ConsoleWindow.cpp b/ConsoleWindow.cpp index d2ba154..69f2f20 100644 --- a/ConsoleWindow.cpp +++ b/ConsoleWindow.cpp @@ -100,7 +100,7 @@ void ConsoleWindow::messageLog(QtMsgType type, const QMessageLogContext &context case QtDebugMsg: output = time + " | " + debug + " " + QString(message.constData()) + " - " + contexts + ""; break; -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= 0x050500 case QtInfoMsg: output = time + " | " + info + " " + QString(message.constData()) + " - " + contexts + ""; break; diff --git a/MainWindow.cpp b/MainWindow.cpp index bf1ba3e..50215da 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -28,8 +28,10 @@ MainWindow::MainWindow() { // Create model. -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= 0x050500 QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no"); +#else + QMessageLogger(__FILE__, __LINE__, 0).debug(); << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no"); #endif mappingManager = new MappingManager; From 18e00e5cbe1305fc767ee451a884b3e5e151eab2 Mon Sep 17 00:00:00 2001 From: baydam Date: Tue, 9 Feb 2016 12:01:40 +0000 Subject: [PATCH 36/46] Add a macro to check for Qt >= 5.5 --- MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 50215da..d9a098a 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -31,7 +31,7 @@ MainWindow::MainWindow() #if QT_VERSION >= 0x050500 QMessageLogger(__FILE__, __LINE__, 0).info() << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no"); #else - QMessageLogger(__FILE__, __LINE__, 0).debug(); << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no"); + QMessageLogger(__FILE__, __LINE__, 0).debug() << "Video support: " << (Media::hasVideoSupport() ? "yes" : "no"); #endif mappingManager = new MappingManager; From acffd5f75a5a67f6d768c21fa9283bcc13b0c4de Mon Sep 17 00:00:00 2001 From: baydam Date: Tue, 9 Feb 2016 12:04:21 +0000 Subject: [PATCH 37/46] Add a macro to check for Qt >= 5.5 --- MainWindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index d9a098a..e0b2aad 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -2710,8 +2710,10 @@ void MainWindow::startOscReceiver() int port = config_osc_receive_port; std::ostringstream os; os << port; -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= 0x050500 QMessageLogger(__FILE__, __LINE__, 0).info() << "OSC port: " << port ; +#else + QMessageLogger(__FILE__, __LINE__, 0).debug() << "OSC port: " << port ; #endif osc_interface.reset(new OscInterface(os.str())); if (port != 0) From b21c46b3d29497034a2e899725f345391afe7fbd Mon Sep 17 00:00:00 2001 From: Tats Date: Thu, 11 Feb 2016 14:26:01 -0500 Subject: [PATCH 38/46] Fixed bug wrt wheel event scrolling (contains a compat. fix for Qt5/Qt4.8) (closes #198). --- MapperGLCanvas.cpp | 27 +++++++++++++++------------ MapperGLCanvas.h | 7 ++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index bedd2cb..9bac874 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -523,17 +523,22 @@ void MapperGLCanvas::deselectAll() void MapperGLCanvas::wheelEvent(QWheelEvent *event) { // [-120]-----[-1]|[1]++++++[120] - _deltaLevel = event->delta() / 120; + // See: http://doc.qt.io/qt-5/qwheelevent.html#angleDelta +#if QT_VERSION >= 0x050500 + int deltaLevel = event->angleDelta().y() / 120; +#else + int deltaLevel = event->delta() / 120; +#endif - if (_deltaLevel > 0) + if (deltaLevel > 0) { // Increase zoom level - increaseZoomLevel(); + increaseZoomLevel(deltaLevel); } else { // Decrease zoom level - decreaseZoomLevel(); + decreaseZoomLevel(-deltaLevel); } // Accept wheel scrolling event. @@ -555,15 +560,14 @@ bool MapperGLCanvas::eventFilter(QObject *target, QEvent *event) } } -void MapperGLCanvas::increaseZoomLevel() +void MapperGLCanvas::increaseZoomLevel(int steps) { qreal zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); - if (zoomFactor < MM::ZOOM_MAX) { + while (steps > 0 && zoomFactor < MM::ZOOM_MAX) { _zoomLevel++; - if (_deltaLevel) - _deltaLevel--; zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); + steps--; } zoomFactor = qMin(zoomFactor, MM::ZOOM_MAX); @@ -574,15 +578,14 @@ void MapperGLCanvas::increaseZoomLevel() applyZoomToView(); } -void MapperGLCanvas::decreaseZoomLevel() +void MapperGLCanvas::decreaseZoomLevel(int steps) { qreal zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); - if (zoomFactor > MM::ZOOM_MIN) { + while (steps > 0 && zoomFactor > MM::ZOOM_MIN) { _zoomLevel--; - if (_deltaLevel) - _deltaLevel++; zoomFactor = qPow(MM::ZOOM_FACTOR, _zoomLevel); + steps--; } zoomFactor = qMax(zoomFactor, MM::ZOOM_MIN); diff --git a/MapperGLCanvas.h b/MapperGLCanvas.h index 9ce6715..80c7e73 100644 --- a/MapperGLCanvas.h +++ b/MapperGLCanvas.h @@ -160,9 +160,6 @@ private: bool _shapeIsAdapted; - // The delta level - int _deltaLevel; - // Pointer to MainWindow UndoStack QUndoStack *undoStack; @@ -197,8 +194,8 @@ public slots: bool eventFilter(QObject *target, QEvent *event); // Zoom - void increaseZoomLevel(); - void decreaseZoomLevel(); + void increaseZoomLevel(int steps=1); + void decreaseZoomLevel(int steps=1); void resetZoomLevel(); void fitShapeInView(); From 1309305614bd339b40ba2389a514616523329293 Mon Sep 17 00:00:00 2001 From: Tats Date: Thu, 11 Feb 2016 15:52:48 -0500 Subject: [PATCH 39/46] Bug fix: when moving vertex pressing any key (eg. CTRL) added an extra command into the undo stack thus forcing the user who wanted to undo to press CTRL-Z twice. --- MapperGLCanvas.cpp | 55 +++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index 9bac874..c01e9f9 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -408,13 +408,18 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) // Checks if the key has been handled by this function or needs to be deferred to superclass. bool handledKey = false; + // Active vertex selected. if (hasActiveVertex()) { MShape::ptr shape = getCurrentShape(); QPoint pos = mapFromScene(shape->getVertex(_activeVertex)); + handledKey = true; + if (event->modifiers() & Qt::ShiftModifier) { + + // SHIFT + directional keys allow move with large steps if (event->key() == Qt::Key_Up) pos.ry() -= MM::VERTEX_MOVES_STEP; else if (event->key() == Qt::Key_Down) @@ -423,38 +428,44 @@ void MapperGLCanvas::keyPressEvent(QKeyEvent* event) pos.rx() += MM::VERTEX_MOVES_STEP; else if (event->key() == Qt::Key_Left) pos.rx() -= MM::VERTEX_MOVES_STEP; + // SHIFT+Space to switch between vertex else if (event->key() == Qt::Key_Space) { if (shape) _activeVertex = (_activeVertex + 1) % shape->nVertices(); pos = shape->getVertex(_activeVertex).toPoint(); // reset to new vertex } - } - switch (event->key()) { - case Qt::Key_Up: - pos.ry()--; - break; - case Qt::Key_Down: - pos.ry()++; - break; - case Qt::Key_Right: - pos.rx()++; - break; - case Qt::Key_Left: - pos.rx()--; - break; - default: + + else handledKey = false; - break; + } + else + { + switch (event->key()) { + case Qt::Key_Up: + pos.ry()--; + break; + case Qt::Key_Down: + pos.ry()++; + break; + case Qt::Key_Right: + pos.rx()++; + break; + case Qt::Key_Left: + pos.rx()--; + break; + default: + handledKey = false; + break; + } } - // Remap window position to scene. - QPointF scenePos = mapToScene(pos); + if (handledKey) + // Enable to Undo and Redo when arrow keys move the position of vertices + undoStack->push(new MoveVertexCommand(this, TransformShapeCommand::STEP, _activeVertex, mapToScene(pos))); + } - // TODO: this will always be called even if no arrow key has been pressed (small performance issue). - // Enable to Undo and Redo when arrow keys move the position of vertices - undoStack->push(new MoveVertexCommand(this, TransformShapeCommand::STEP, _activeVertex, scenePos)); - } else { + else { // Take scroll bar current coordinate int scrollX = this->horizontalScrollBar()->value(); int scrollY = this->verticalScrollBar()->value(); From 21c91295d160bd604492b5f536a0550e34b5ef34 Mon Sep 17 00:00:00 2001 From: baydam Date: Thu, 11 Feb 2016 21:24:08 +0000 Subject: [PATCH 40/46] Display lock/mute/solo options in the context menu --- MM.cpp | 4 +++ MM.h | 3 ++ MainWindow.cpp | 79 +++++++++++++++++++++++++++++++++++++---- MainWindow.h | 8 +++++ MapperGLCanvas.cpp | 14 ++++++-- MapperGLCanvas.h | 1 + Shape.h | 9 ++++- ShapeControlPainter.cpp | 7 ++-- Util.cpp | 14 +++++--- Util.h | 2 +- 10 files changed, 122 insertions(+), 19 deletions(-) diff --git a/MM.cpp b/MM.cpp index caa99ef..020c8b7 100644 --- a/MM.cpp +++ b/MM.cpp @@ -33,8 +33,11 @@ const QColor MM::BLUE_GRAY("#323541"); const QColor MM::DARK_GRAY("#272a36"); const QColor MM::CONTROL_COLOR(WHITE); +const QColor MM::CONTROL_LOCKED_COLOR("#FF0000"); const QBrush MM::VERTEX_BACKGROUND(QColor(CONTROL_COLOR.red(), CONTROL_COLOR.green(), CONTROL_COLOR.blue(), 63)); const QBrush MM::VERTEX_SELECTED_BACKGROUND(QColor(CONTROL_COLOR.red(), CONTROL_COLOR.green(), CONTROL_COLOR.blue(), 127)); +//const QBrush MM::VERTEX_LOCKED_BACKGROUND(QColor(CONTROL_LOCKED_COLOR.red(), CONTROL_LOCKED_COLOR.green(), CONTROL_LOCKED_COLOR.blue(), 63)); +const QBrush MM::VERTEX_LOCKED_BACKGROUND(CONTROL_LOCKED_COLOR); const qreal MM::SHAPE_STROKE_WIDTH = 1.5; const qreal MM::SHAPE_INNER_STROKE_WIDTH = 0.5; @@ -43,6 +46,7 @@ const QPen MM::SHAPE_INNER_STROKE(QBrush(CONTROL_COLOR), SHAPE_INNER_STROKE_WIDT const qreal MM::VERTEX_STICK_RADIUS = 10; const qreal MM::VERTEX_SELECT_RADIUS = 10; +const qreal MM::VERTEX_LOCKED_RADIUS = 6; const qreal MM::VERTEX_SELECT_STROKE_WIDTH = 1; // Time. diff --git a/MM.h b/MM.h index d6bf1da..0816a9d 100644 --- a/MM.h +++ b/MM.h @@ -56,8 +56,10 @@ public: static const QColor DARK_GRAY; static const QColor CONTROL_COLOR; + static const QColor CONTROL_LOCKED_COLOR; static const QBrush VERTEX_BACKGROUND; static const QBrush VERTEX_SELECTED_BACKGROUND; + static const QBrush VERTEX_LOCKED_BACKGROUND; static const qreal SHAPE_STROKE_WIDTH; static const qreal SHAPE_INNER_STROKE_WIDTH; @@ -67,6 +69,7 @@ public: // Control. static const qreal VERTEX_STICK_RADIUS; static const qreal VERTEX_SELECT_RADIUS; + static const qreal VERTEX_LOCKED_RADIUS; static const qreal VERTEX_SELECT_STROKE_WIDTH; // Time. diff --git a/MainWindow.cpp b/MainWindow.cpp index e0b2aad..459e78b 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -764,6 +764,21 @@ void MainWindow::renameMappingItem() contentTab->setCurrentWidget(mappingSplitter); } +void MainWindow::setMappingitemLocked(bool locked) +{ + setMappingLocked(getItemId(*mappingList->currentItem()), locked); +} + +void MainWindow::setMappingitemVisible(bool visible) +{ + setMappingVisible(getItemId(*mappingList->currentItem()), !visible); +} + +void MainWindow::setMappingItemSolo(bool solo) +{ + setMappingSolo(getItemId(*mappingList->currentItem()), solo); +} + void MainWindow::renameMapping(uid mappingId, const QString &name) { Mapping::ptr mapping = mappingManager->getMappingById(mappingId); @@ -1135,14 +1150,27 @@ void MainWindow::setMappingVisible(uid mappingId, bool visible) void MainWindow::setMappingSolo(uid mappingId, bool solo) { - Q_UNUSED(mappingId); - Q_UNUSED(solo); + Mapping::ptr mapping = mappingManager->getMappingById(mappingId); + if (!mapping.isNull()) { + // Turn this mapping into solo mode + mapping->setSolo(solo); + // Update canvases + updateCanvases(); + } } void MainWindow::setMappingLocked(uid mappingId, bool locked) { - Q_UNUSED(mappingId); - Q_UNUSED(locked); + Mapping::ptr mapping = mappingManager->getMappingById(mappingId); + + if (!mapping.isNull()) { + // Lock position of mapping + mapping->setLocked(locked); + // Lock shape too. + mapping->getShape()->setLocked(locked); + // Update canvases + updateCanvases(); + } } void MainWindow::deleteMapping(uid mappingId) @@ -1482,6 +1510,33 @@ void MainWindow::createActions() addAction(renameMappingAction); connect(renameMappingAction, SIGNAL(triggered()), this, SLOT(renameMappingItem())); + // Lock mapping. + mappingLockedAction = new QAction(tr("Lock mapping"), this); + mappingLockedAction->setToolTip(tr("Lock mapping item")); + mappingLockedAction->setIconVisibleInMenu(false); + mappingLockedAction->setCheckable(true); + mappingLockedAction->setChecked(false); + addAction(mappingLockedAction); + connect(mappingLockedAction, SIGNAL(triggered(bool)), this, SLOT(setMappingitemLocked(bool))); + + // Mute mapping. + mappingMuteAction = new QAction(tr("Mute mapping"), this); + mappingMuteAction->setToolTip(tr("Mute mapping item")); + mappingMuteAction->setIconVisibleInMenu(false); + mappingMuteAction->setCheckable(true); + mappingMuteAction->setChecked(false); + addAction(mappingMuteAction); + connect(mappingMuteAction, SIGNAL(triggered(bool)), this, SLOT(setMappingitemVisible(bool))); + + // Solo mapping. + mappingSoloAction = new QAction(tr("Solo mapping"), this); + mappingSoloAction->setToolTip(tr("solo mapping item")); + mappingSoloAction->setIconVisibleInMenu(false); + mappingSoloAction->setCheckable(true); + mappingSoloAction->setChecked(false); + addAction(mappingSoloAction); + connect(mappingSoloAction, SIGNAL(triggered(bool)), this, SLOT(setMappingItemSolo(bool))); + // Delete paint. deletePaintAction = new QAction(tr("Delete paint"), this); //deletePaintAction->setShortcut(tr("CTRL+DEL")); @@ -1759,6 +1814,9 @@ void MainWindow::createMappingContextMenu() mappingContextMenu->addAction(cloneMappingAction); mappingContextMenu->addAction(deleteMappingAction); mappingContextMenu->addAction(renameMappingAction); + mappingContextMenu->addAction(mappingLockedAction); + mappingContextMenu->addAction(mappingMuteAction); + mappingContextMenu->addAction(mappingSoloAction); // Set context menu policy mappingList->setContextMenuPolicy(Qt::CustomContextMenu); @@ -1767,8 +1825,8 @@ void MainWindow::createMappingContextMenu() // Context Menu Connexions connect(mappingList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMappingContextMenu(const QPoint&))); - connect(destinationCanvas, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMappingContextMenu(const QPoint&))); - connect(outputWindow, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMappingContextMenu(const QPoint&))); + connect(destinationCanvas, SIGNAL(shapeContextMenuRequested(const QPoint&)), this, SLOT(showMappingContextMenu(const QPoint&))); + connect(outputWindow->getCanvas(), SIGNAL(shapeContextMenuRequested(const QPoint&)), this, SLOT(showMappingContextMenu(const QPoint&))); } void MainWindow::createPaintContextMenu() @@ -1786,7 +1844,7 @@ void MainWindow::createPaintContextMenu() // Connexions connect(paintList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPaintContextMenu(const QPoint&))); - connect(sourceCanvas, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPaintContextMenu(const QPoint&))); + connect(sourceCanvas, SIGNAL(shapeContextMenuRequested(const QPoint&)), this, SLOT(showPaintContextMenu(const QPoint&))); } void MainWindow::createToolBars() @@ -2529,6 +2587,13 @@ void MainWindow::enableStickyVertices(bool value) void MainWindow::showMappingContextMenu(const QPoint &point) { QWidget *objectSender = dynamic_cast(sender()); + uid mappingId = getItemId(*mappingList->currentItem()); + Mapping::ptr mapping = mappingManager->getMappingById(mappingId); + + // Switch to right action check state + mappingLockedAction->setChecked(mapping->isLocked()); + mappingMuteAction->setChecked(!mapping->isVisible()); + mappingSoloAction->setChecked(mapping->isSolo()); if (objectSender != NULL && mappingList->count() > 0) mappingContextMenu->exec(objectSender->mapToGlobal(point)); diff --git a/MainWindow.h b/MainWindow.h index c8cf18a..aca49e8 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -98,6 +98,9 @@ private slots: void duplicateMappingItem(); void deleteMappingItem(); void renameMappingItem(); + void setMappingitemLocked(bool locked); + void setMappingitemVisible(bool visible); + void setMappingItemSolo(bool solo); void mappingListEditEnd(QWidget* editor); // Context menu for paints void deletePaintItem(); @@ -305,9 +308,14 @@ private: QAction *exitAction; QAction *undoAction; QAction *redoAction; + // Mappings context menu actions QAction *cloneMappingAction; QAction *deleteMappingAction; QAction *renameMappingAction; + QAction *mappingSoloAction; + QAction *mappingLockedAction; + QAction *mappingMuteAction; + // Paints context menu action QAction *deletePaintAction; QAction *renamePaintAction; QAction *preferencesAction; diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index c01e9f9..b6fc26d 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -236,7 +236,8 @@ void MapperGLCanvas::mousePressEvent(QMouseEvent* event) _activeVertex = i; minDistance = dist; - _vertexGrabbed = true; + // Vertex can be grabbed only if the mapping is not locked + _vertexGrabbed = shape->isLocked() ? false : true; mousePressedOnSomething = true; _grabbedObjectStartScenePosition = shape->getVertex(i); @@ -287,12 +288,21 @@ void MapperGLCanvas::mousePressEvent(QMouseEvent* event) { if (selectedShape && selectedShape->includesPoint(pos)) { - _shapeGrabbed = true; + // Shape can be grabbed only if it is not locked + _shapeGrabbed = selectedShape->isLocked() ? false : true; _shapeFirstGrab = true; _grabbedObjectStartScenePosition = pos; } } + // Show the shape/mapping context menu + if (event->button() & Qt::RightButton) + { + if (selectedShape && selectedShape->includesPoint(pos)) + { + emit shapeContextMenuRequested(event->pos()); + } + } } if (mousePressedOnSomething) diff --git a/MapperGLCanvas.h b/MapperGLCanvas.h index 80c7e73..83c5176 100644 --- a/MapperGLCanvas.h +++ b/MapperGLCanvas.h @@ -178,6 +178,7 @@ private: signals: void shapeChanged(MShape*); void imageChanged(); + void shapeContextMenuRequested(const QPoint &pos); public slots: void updateCanvas(); diff --git a/Shape.h b/Shape.h index bf7515e..f8f3349 100644 --- a/Shape.h +++ b/Shape.h @@ -46,7 +46,7 @@ class MShape public: typedef QSharedPointer ptr; - MShape() {} + MShape() : _isLocked(false) {} MShape(QVector vertices_) : vertices(vertices_) {} @@ -89,6 +89,9 @@ public: virtual void copyFrom(const MShape& shape); virtual MShape* clone() const; + // Handle shape lock + bool isLocked() const { return _isLocked; } + void setLocked(bool locked) { _isLocked = locked; } protected: QVector vertices; @@ -105,6 +108,10 @@ protected: /// Returns a new MShape (using default constructor). virtual MShape* _create() const = 0; + +private: + // Shape lock state + bool _isLocked; }; /** diff --git a/ShapeControlPainter.cpp b/ShapeControlPainter.cpp index 1528830..64e290e 100644 --- a/ShapeControlPainter.cpp +++ b/ShapeControlPainter.cpp @@ -36,16 +36,17 @@ void ShapeControlPainter::paint(QPainter *painter, MapperGLCanvas* canvas, const void ShapeControlPainter::_paintVertices(QPainter *painter, MapperGLCanvas* canvas, const QList& selectedVertices) { qreal zoomFactor = canvas->getZoomFactor(); - qreal selectRadius = MM::VERTEX_SELECT_RADIUS / zoomFactor; + qreal selectRadius = (getShape()->isLocked() ? MM::VERTEX_LOCKED_RADIUS : MM::VERTEX_SELECT_RADIUS) / zoomFactor; qreal strokeWidth = MM::VERTEX_SELECT_STROKE_WIDTH / zoomFactor; for (int i=0; inVertices(); i++) - Util::drawControlsVertex(painter, getShape()->getVertex(i), selectedVertices.contains(i), selectRadius, strokeWidth); + Util::drawControlsVertex(painter, getShape()->getVertex(i), selectedVertices.contains(i), getShape()->isLocked(), selectRadius, strokeWidth); } QPen ShapeControlPainter::getRescaledShapeStroke(MapperGLCanvas* canvas, bool innerStroke) { - return QPen(QBrush(MM::CONTROL_COLOR), (innerStroke ? MM::SHAPE_INNER_STROKE_WIDTH : MM::SHAPE_STROKE_WIDTH) / canvas->getZoomFactor()); + return QPen(getShape()->isLocked() ? QBrush(MM::CONTROL_LOCKED_COLOR) : QBrush(MM::CONTROL_COLOR), + (innerStroke ? MM::SHAPE_INNER_STROKE_WIDTH : MM::SHAPE_STROKE_WIDTH) / canvas->getZoomFactor()); } void PolygonControlPainter::_paintShape(QPainter *painter, MapperGLCanvas* canvas) diff --git a/Util.cpp b/Util.cpp index 516157d..7cf9035 100644 --- a/Util.cpp +++ b/Util.cpp @@ -150,11 +150,15 @@ Ellipse* createEllipseForColor(int frameWidth, int frameHeight) ); } -void drawControlsVertex(QPainter* painter, const QPointF& vertex, bool selected, qreal radius, qreal strokeWidth) +void drawControlsVertex(QPainter* painter, const QPointF& vertex, bool selected, bool locked, qreal radius, qreal strokeWidth) { // Init colors and stroke. - painter->setBrush(selected ? MM::VERTEX_SELECTED_BACKGROUND : MM::VERTEX_BACKGROUND); - painter->setPen(QPen(MM::CONTROL_COLOR, strokeWidth)); + if (locked) + painter->setBrush(MM::VERTEX_LOCKED_BACKGROUND); + else + painter->setBrush(selected ? MM::VERTEX_SELECTED_BACKGROUND : MM::VERTEX_BACKGROUND); + + painter->setPen(locked ? QPen(MM::CONTROL_LOCKED_COLOR) : QPen(MM::CONTROL_COLOR, strokeWidth)); // Draw ellipse. painter->drawEllipse(vertex, radius, radius); @@ -169,10 +173,10 @@ void drawControlsVertices(QPainter* painter, const QList* selectedVertices, { if (!selectedVertices) for (int i=0; icontains(i)); + drawControlsVertex(painter, shape.getVertex(i), selectedVertices->contains(i), shape.isLocked()); } void drawControlsEllipse(QPainter* painter, const QList* selectedVertices, const Ellipse& ellipse) diff --git a/Util.h b/Util.h index 5dc8412..a55f4c5 100644 --- a/Util.h +++ b/Util.h @@ -57,7 +57,7 @@ Quad* createQuadForColor(int frameWidth, int frameHeight); Triangle* createTriangleForColor(int frameWidth, int frameHeight); Ellipse* createEllipseForColor(int frameWidth, int frameHeight); -void drawControlsVertex(QPainter* painter, const QPointF& vertex, bool selected, qreal radius = MM::VERTEX_SELECT_RADIUS, qreal strokeWidth = MM::VERTEX_SELECT_STROKE_WIDTH); +void drawControlsVertex(QPainter* painter, const QPointF& vertex, bool selected, bool locked, qreal radius = MM::VERTEX_SELECT_RADIUS, qreal strokeWidth = MM::VERTEX_SELECT_STROKE_WIDTH); void drawControlsVertices(QPainter* painter, const QList* selectedVertices, const MShape& shape); void drawControlsEllipse(QPainter* painter, const QList* selectedVertices, const Ellipse& ellipse); From f837b80c20528f7fead4fa547ffa3d2da0bbb56e Mon Sep 17 00:00:00 2001 From: Alexandre Quessy Date: Fri, 12 Feb 2016 11:39:53 -0500 Subject: [PATCH 41/46] update NEWS --- NEWS | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 1d63df0..0ac5e54 100644 --- a/NEWS +++ b/NEWS @@ -10,7 +10,7 @@ Release notes for MapMap * Fix #154: Problem with some video files: shape is size of single point * Can rename paints and mappings via OSC * Can rename paints and mappings with double click -* Fix #156 White rectangle around the fullscreen window +* Fix #156: White rectangle around the fullscreen window * Fix #152: The software frozen when we load a project and the video files are not found * Abled to locate the video files if is not found when load a project * Fix #149: Deleting a mapping actually deletes a paint when the paint tab is chosen @@ -19,6 +19,16 @@ Release notes for MapMap * Performance improvements * OSC general bug fixes * OSC support on OSX +* Done #174: Be able to rename a Paint +* DOne #72: Be able to name paints and mappings - for OSC controls +* Center the test signal #97 (must use all the space available) +* Fix #159: Program just freezes when importing corrupted video file +* Done #145: The user doesn't need to see the undo stack +* Done #40: Ctrl-Q should quit the application +* Done #183: Display logging output in a console and be able to turn it on and off +* Done #203: The toolbar can be shown or hidden at will by the user +* Done #147: Be able to delete a mapping with the delete key #147 (tested on Ubuntu) + 2015-10-30 - MapMap 0.3.1 ------------------------- From ed859fadf5b33606d5253ec8118f2cd46492d198 Mon Sep 17 00:00:00 2001 From: Tats Date: Fri, 12 Feb 2016 12:16:11 -0500 Subject: [PATCH 42/46] Fix bug: solo was not working. --- MappingManager.cpp | 25 +++++++++++++++++++++++++ MappingManager.h | 4 ++++ ShapeGraphicsItem.cpp | 4 ++++ ShapeGraphicsItem.h | 2 +- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/MappingManager.cpp b/MappingManager.cpp index b421f3f..e48a767 100644 --- a/MappingManager.cpp +++ b/MappingManager.cpp @@ -145,6 +145,31 @@ QVector MappingManager::getVisibleMappings() const return visible; } +/// Returns true iff the mapping is visible. +bool MappingManager::mappingIsVisible(Mapping::ptr mapping) const +{ + // Solo mappings are always visible. + if (mapping->isSolo()) + return true; + + // Non-solo invisible mappings are always invisible. + else if (!mapping->isVisible()) + return false; + + // Mapping is non-solo yet visible: check if another mapping is solo (which would thus make it invisible). + else + { + for (QVector::const_iterator it = mappingVector.begin(); it != mappingVector.end(); ++it) + { + if ((*it)->isSolo()) + return false; + } + + // Mapping is non-solo yet visible and there are no solo mappings. + return true; + } +} + void MappingManager::reorderMappings(QVector mappingIds) { // Both vector needs to have the same size. diff --git a/MappingManager.h b/MappingManager.h index 2f2a9c0..f81158f 100644 --- a/MappingManager.h +++ b/MappingManager.h @@ -100,8 +100,12 @@ public: /// Reorders the mappings according to given list of uids. QVector needs to void reorderMappings(QVector mappingIds); + /// Returns the ordered list of visible mappings, using both the "visible" and "solo" properties. QVector getVisibleMappings() const; + /// Returns true iff the mapping is visible. + bool mappingIsVisible(Mapping::ptr mapping) const; + void clearAll(); }; diff --git a/ShapeGraphicsItem.cpp b/ShapeGraphicsItem.cpp index c935be7..e47350c 100644 --- a/ShapeGraphicsItem.cpp +++ b/ShapeGraphicsItem.cpp @@ -38,6 +38,10 @@ bool ShapeGraphicsItem::isMappingCurrent() const { return MainWindow::instance()->getCurrentMappingId() == getMapping()->getId(); } +bool ShapeGraphicsItem::isMappingVisible() const { + return MainWindow::instance()->getMappingManager().mappingIsVisible(getMapping()); +} + void ShapeGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { diff --git a/ShapeGraphicsItem.h b/ShapeGraphicsItem.h index 34541bb..9fda9a1 100644 --- a/ShapeGraphicsItem.h +++ b/ShapeGraphicsItem.h @@ -75,7 +75,7 @@ public: bool isMappingCurrent() const; /// Returns whether the mapping this shape is associated should be visible. - bool isMappingVisible() const { return getMapping()->isVisible(); } + bool isMappingVisible() const; /// Returns the bounding rectangle of this item. virtual QRectF boundingRect() const { return shape().boundingRect(); } From 6a0b3afdebf9f3b4bd6d40b308e5c611eac5838f Mon Sep 17 00:00:00 2001 From: Alexandre Quessy Date: Fri, 12 Feb 2016 12:23:35 -0500 Subject: [PATCH 43/46] update NEWS --- NEWS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 0ac5e54..3cba2f3 100644 --- a/NEWS +++ b/NEWS @@ -28,7 +28,8 @@ Release notes for MapMap * Done #183: Display logging output in a console and be able to turn it on and off * Done #203: The toolbar can be shown or hidden at will by the user * Done #147: Be able to delete a mapping with the delete key #147 (tested on Ubuntu) - +* Done #184: Make sure names support UTF-8 characters +* Done #201 UX Design document: implement main toolbar improvements 2015-10-30 - MapMap 0.3.1 ------------------------- From 420e30b187b68fd152cc646bbf784849caebef83 Mon Sep 17 00:00:00 2001 From: baydam Date: Sun, 14 Feb 2016 17:04:22 +0000 Subject: [PATCH 44/46] UX Design document: status bar --- MainWindow.cpp | 499 +++++++++++++++++++++------------------ MainWindow.h | 6 + resources/qss/mapmap.qss | 4 + 3 files changed, 273 insertions(+), 236 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 459e78b..d11ea94 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -93,7 +93,7 @@ MainWindow::MainWindow() MainWindow::~MainWindow() { delete mappingManager; -// delete _facade; + // delete _facade; #ifdef HAVE_OSC delete osc_timer; #endif // ifdef @@ -244,21 +244,21 @@ void MainWindow::handlePaintChanged(Paint::ptr paint) { QSharedPointer media = qSharedPointerCast(paint); Q_CHECK_PTR(media); updatePaintItem(paintId, createFileIcon(media->getUri()), strippedName(media->getUri())); -// QString fileName = QFileDialog::getOpenFileName(this, -// tr("Import media source file"), "."); -// // Restart video playback. XXX Hack -// if (!fileName.isEmpty()) -// importMediaFile(fileName, paint, false); + // QString fileName = QFileDialog::getOpenFileName(this, + // tr("Import media source file"), "."); + // // Restart video playback. XXX Hack + // if (!fileName.isEmpty()) + // importMediaFile(fileName, paint, false); } if (paint->getType() == "image") { QSharedPointer image = qSharedPointerCast(paint); Q_CHECK_PTR(image); updatePaintItem(paintId, createImageIcon(image->getUri()), strippedName(image->getUri())); -// QString fileName = QFileDialog::getOpenFileName(this, -// tr("Import media source file"), "."); -// // Restart video playback. XXX Hack -// if (!fileName.isEmpty()) -// importMediaFile(fileName, paint, true); + // QString fileName = QFileDialog::getOpenFileName(this, + // tr("Import media source file"), "."); + // // Restart video playback. XXX Hack + // if (!fileName.isEmpty()) + // importMediaFile(fileName, paint, true); } else if (paint->getType() == "color") { // Pop-up color-choosing dialog to choose color paint. @@ -300,7 +300,7 @@ void MainWindow::closeEvent(QCloseEvent *event) bool MainWindow::eventFilter(QObject *obj, QEvent *event) { - bool eventKey = false; + bool eventKey = false; if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); @@ -308,48 +308,48 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) // Menubar shortcut if (keyEvent->modifiers() == Qt::CTRL) { - switch (keyEvent->key()) { - case Qt::Key_N: - newFile(); - break; - case Qt::Key_O: - open(); - break; - case Qt::Key_S: - save(); - break; - case Qt::Key_Q: - close(); - break; - case Qt::Key_Delete: - deleteItem(); - break; - case Qt::Key_M: - addMesh(); - break; - case Qt::Key_T: - addTriangle(); - break; - case Qt::Key_E: - addEllipse(); - break; - case Qt::Key_W: - outputWindow->setVisible(true); - break; - case Qt::Key_R: - rewind(); - break; - case Qt::Key_Z: - undoStack->undo(); - break; - } + switch (keyEvent->key()) { + case Qt::Key_N: + newFile(); + break; + case Qt::Key_O: + open(); + break; + case Qt::Key_S: + save(); + break; + case Qt::Key_Q: + close(); + break; + case Qt::Key_Delete: + deleteItem(); + break; + case Qt::Key_M: + addMesh(); + break; + case Qt::Key_T: + addTriangle(); + break; + case Qt::Key_E: + addEllipse(); + break; + case Qt::Key_W: + outputWindow->setVisible(true); + break; + case Qt::Key_R: + rewind(); + break; + case Qt::Key_Z: + undoStack->undo(); + break; + } } else if (keyEvent->matches(QKeySequence::Redo)) { undoStack->redo(); } else if (keyEvent->key() == Qt::Key_Escape) - outputWindow->close(); + outputWindow->close(); else if (keyEvent->key() == Qt::Key_Space) { if (_isPlaying) @@ -417,9 +417,9 @@ void MainWindow::open() if (okToContinue()) { QString fileName = QFileDialog::getOpenFileName(this, - tr("Open project"), - settings.value("defaultProjectDir").toString(), - tr("MapMap files (*.%1)").arg(MM::FILE_EXTENSION)); + tr("Open project"), + settings.value("defaultProjectDir").toString(), + tr("MapMap files (*.%1)").arg(MM::FILE_EXTENSION)); if (! fileName.isEmpty()) loadFile(fileName); } @@ -453,8 +453,8 @@ bool MainWindow::saveAs() // Popul file dialog to choose filename. QString fileName = QFileDialog::getSaveFileName(this, - tr("Save project"), settings.value("defaultProjectDir").toString(), - tr("MapMap files (*.%1)").arg(MM::FILE_EXTENSION)); + tr("Save project"), settings.value("defaultProjectDir").toString(), + tr("MapMap files (*.%1)").arg(MM::FILE_EXTENSION)); // Restart video playback. XXX Hack videoTimer->start(); @@ -465,9 +465,9 @@ bool MainWindow::saveAs() if (! fileName.endsWith(MM::FILE_EXTENSION)) { std::cout << "filename doesn't end with expected extension: " << - fileName.toStdString() << std::endl; - fileName.append("."); - fileName.append(MM::FILE_EXTENSION); + fileName.toStdString() << std::endl; + fileName.append("."); + fileName.append(MM::FILE_EXTENSION); } // Save to filename. @@ -510,8 +510,8 @@ void MainWindow::addColor() // it should rather be a member of this class, or so. static QColor color = QColor(0, 255, 0, 255); color = QColorDialog::getColor(color, this, tr("Select Color"), - // QColorDialog::DontUseNativeDialog | - QColorDialog::ShowAlphaChannel); + // QColorDialog::DontUseNativeDialog | + QColorDialog::ShowAlphaChannel); if (color.isValid()) { addColorPaint(color); @@ -667,25 +667,25 @@ void MainWindow::about() // Pop-up about dialog. QMessageBox::about(this, tr("About MapMap"), - tr("

%1

" - "

Copyright © 2013 %2.

" - "

MapMap is a free software for video mapping.

" - "

Projection mapping, also known as video mapping and spatial augmented reality, " - "is a projection technology used to turn objects, often irregularly shaped, into " - "a display surface for video projection. These objects may be complex industrial " - "landscapes, such as buildings. By using specialized software, a two or three " - "dimensional object is spatially mapped on the virtual program which mimics the " - "real environment it is to be projected on. The software can interact with a " - "projector to fit any desired image onto the surface of that object. This " - "technique is used by artists and advertisers alike who can add extra dimensions, " - "optical illusions, and notions of movement onto previously static objects. The " - "video is commonly combined with, or triggered by, audio to create an " - "audio-visual narrative." - "This project was made possible by the support of the International Organization of " - "La Francophonie.

" - "

http://mapmap.info
" - "http://www.francophonie.org

" - ).arg(MM::VERSION, MM::COPYRIGHT_OWNERS)); + tr("

%1

" + "

Copyright © 2013 %2.

" + "

MapMap is a free software for video mapping.

" + "

Projection mapping, also known as video mapping and spatial augmented reality, " + "is a projection technology used to turn objects, often irregularly shaped, into " + "a display surface for video projection. These objects may be complex industrial " + "landscapes, such as buildings. By using specialized software, a two or three " + "dimensional object is spatially mapped on the virtual program which mimics the " + "real environment it is to be projected on. The software can interact with a " + "projector to fit any desired image onto the surface of that object. This " + "technique is used by artists and advertisers alike who can add extra dimensions, " + "optical illusions, and notions of movement onto previously static objects. The " + "video is commonly combined with, or triggered by, audio to create an " + "audio-visual narrative." + "This project was made possible by the support of the International Organization of " + "La Francophonie.

" + "

http://mapmap.info
" + "http://www.francophonie.org

" + ).arg(MM::VERSION, MM::COPYRIGHT_OWNERS)); // Restart video playback. XXX Hack videoTimer->start(); @@ -693,14 +693,18 @@ void MainWindow::about() void MainWindow::updateStatusBar() { - // Nothing to do for now. -// locationLabel->setText(spreadsheet->currentLocation()); -// formulaLabel->setText(spreadsheet->currentFormula()); + QPointF mousePos = destinationCanvas->mapToScene(destinationCanvas->mapFromGlobal(destinationCanvas->cursor().pos())); + if (currentSelectedItem) // Show mouse coordinate only if mappingList is not empty + mousePosLabel->setText("Mouse coordinate: X " + QString::number(mousePos.x()) + " Y " + QString::number(mousePos.y())); + currentMessageLabel->setText(statusBar()->currentMessage()); + sourceZoomLabel->setText("Source: " + QString::number(int(sourceCanvas->getZoomFactor() * 100)).append(QChar('%'))); + destinationZoomLabel->setText("Destination: " + QString::number(int(destinationCanvas->getZoomFactor() * 100)).append(QChar('%'))); + undoLabel->setText(undoStack->text(undoStack->count() - 1)); } /** * Called when the user wants to delete an item. - * + * * Deletes either a Paint or a Mapping. */ void MainWindow::deleteItem() @@ -726,7 +730,7 @@ void MainWindow::deleteItem() { qCritical() << "Selected item neither a mapping nor a paint." << endl; } - } + } } void MainWindow::duplicateMappingItem() @@ -834,16 +838,16 @@ void MainWindow::paintListEditEnd(QWidget *editor) void MainWindow::openRecentFile() { - QAction *action = qobject_cast(sender()); - if (action) - loadFile(action->data().toString()); + QAction *action = qobject_cast(sender()); + if (action) + loadFile(action->data().toString()); } void MainWindow::openRecentVideo() { - QAction *action = qobject_cast(sender()); - if (action) - importMediaFile(action->data().toString(),false); + QAction *action = qobject_cast(sender()); + if (action) + importMediaFile(action->data().toString(),false); } bool MainWindow::clearProject() @@ -899,7 +903,7 @@ uid MainWindow::createMediaPaint(uid paintId, QString uri, float x, float y, { // Check if file exists before if (! fileExists(uri)) - uri = locateMediaFile(uri, isImage); + uri = locateMediaFile(uri, isImage); Texture* tex = 0; if (isImage) @@ -1179,7 +1183,7 @@ void MainWindow::deleteMapping(uid mappingId) if (Mapping::getUidAllocator().exists(mappingId)) { removeMappingItem(mappingId); - } + } } void MainWindow::duplicateMapping(uid mappingId) @@ -1202,14 +1206,14 @@ void MainWindow::duplicateMapping(uid mappingId) { if (shapeType == "quad") shapePtr = MShape::ptr(new Quad(shape->getVertex(0), shape->getVertex(1), - shape->getVertex(2), shape->getVertex(3))); + shape->getVertex(2), shape->getVertex(3))); if (shapeType == "triangle") shapePtr = MShape::ptr(new Triangle(shape->getVertex(0), shape->getVertex(1), shape->getVertex(2))); if (shapeType == "ellipse") shapePtr = MShape::ptr(new Ellipse(shape->getVertex(0), shape->getVertex(1), shape->getVertex(2), - shape->getVertex(3))); + shape->getVertex(3))); mapping = new ColorMapping(paint, shapePtr); } @@ -1219,14 +1223,14 @@ void MainWindow::duplicateMapping(uid mappingId) if (shapeType == "mesh") shapePtr = MShape::ptr(new Mesh(shape->getVertex(0), shape->getVertex(1), - shape->getVertex(3), shape->getVertex(2))); + shape->getVertex(3), shape->getVertex(2))); if (shapeType == "triangle") shapePtr = MShape::ptr(new Triangle(shape->getVertex(0), shape->getVertex(1), shape->getVertex(2))); if (shapeType == "ellipse") shapePtr = MShape::ptr(new Ellipse(shape->getVertex(0), shape->getVertex(1), shape->getVertex(2), - shape->getVertex(3), shape->getVertex(4))); + shape->getVertex(3), shape->getVertex(4))); mapping = new TextureMapping(paint, shapePtr, inputShape); } @@ -1251,8 +1255,8 @@ void MainWindow::deletePaint(uid paintId, bool replace) { if (replace == false) { int r = QMessageBox::warning(this, tr("MapMap"), - tr("Remove this paint and all its associated mappings?"), - QMessageBox::Ok | QMessageBox::Cancel); + tr("Remove this paint and all its associated mappings?"), + QMessageBox::Ok | QMessageBox::Cancel); if (r == QMessageBox::Ok) { removePaintItem(paintId); @@ -1323,8 +1327,8 @@ void MainWindow::createLayout() // Output changed -> change destinatioin // XXX si je decommente cette ligne alors quand je clique sur ajouter media ca gele... -// connect(outputWindow->getCanvas()->scene(), SIGNAL(changed(const QList&)), -// destinationCanvas, SLOT(updateCanvas())); + // connect(outputWindow->getCanvas()->scene(), SIGNAL(changed(const QList&)), + // destinationCanvas, SLOT(updateCanvas())); // Create console logging output consoleWindow = ConsoleWindow::getInstance(); @@ -1415,18 +1419,18 @@ void MainWindow::createActions() // Recents file for (int i = 0; i < MaxRecentFiles; i++) { - recentFileActions[i] = new QAction(this); - recentFileActions[i]->setVisible(false); - connect(recentFileActions[i], SIGNAL(triggered()), - this, SLOT(openRecentFile())); + recentFileActions[i] = new QAction(this); + recentFileActions[i]->setVisible(false); + connect(recentFileActions[i], SIGNAL(triggered()), + this, SLOT(openRecentFile())); } // Recent video for (int i = 0; i < MaxRecentVideo; i++) { - recentVideoActions[i] = new QAction(this); - recentVideoActions[i]->setVisible(false); - connect(recentVideoActions[i], SIGNAL(triggered()), this, SLOT(openRecentVideo())); + recentVideoActions[i] = new QAction(this); + recentVideoActions[i]->setVisible(false); + connect(recentVideoActions[i], SIGNAL(triggered()), this, SLOT(openRecentVideo())); } // Clear recent video list action @@ -1738,14 +1742,14 @@ void MainWindow::createMenus() separatorAction = fileMenu->addSeparator(); recentFileMenu = fileMenu->addMenu(tr("Open Recents Projects")); for (int i = 0; i < MaxRecentFiles; ++i) - recentFileMenu->addAction(recentFileActions[i]); + recentFileMenu->addAction(recentFileActions[i]); recentFileMenu->addAction(clearRecentFileActions); // Recent import video recentVideoMenu = fileMenu->addMenu(tr("Open Recents Videos")); recentVideoMenu->addAction(emptyRecentVideos); for (int i = 0; i < MaxRecentVideo; ++i) - recentVideoMenu->addAction(recentVideoActions[i]); + recentVideoMenu->addAction(recentVideoActions[i]); // Exit fileMenu->addSeparator(); @@ -1801,7 +1805,7 @@ void MainWindow::createMenus() // Help. helpMenu = menuBar->addMenu(tr("&Help")); helpMenu->addAction(aboutAction); -// helpMenu->addAction(aboutQtAction); + // helpMenu->addAction(aboutQtAction); } @@ -1888,20 +1892,40 @@ void MainWindow::createToolBars() void MainWindow::createStatusBar() { -// locationLabel = new QLabel(" W999 "); -// locationLabel->setAlignment(Qt::AlignHCenter); -// locationLabel->setMinimumSize(locationLabel->sizeHint()); -// -// formulaLabel = new QLabel; -// formulaLabel->setIndent(3); -// -// statusBar()->addWidget(locationLabel); -// statusBar()->addWidget(formulaLabel, 1); -// -// connect(spreadsheet, SIGNAL(currentCellChanged(int, int, int, int)), this, -// SLOT(updateStatusBar())); -// connect(spreadsheet, SIGNAL(modified()), this, SLOT(spreadsheetModified())); + // Create canvases zoom level statut + destinationZoomLabel = new QLabel(statusBar()); + destinationZoomLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + destinationZoomLabel->setContentsMargins(2, 0, 0, 0); + sourceZoomLabel = new QLabel(statusBar()); + sourceZoomLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + sourceZoomLabel->setContentsMargins(2, 0, 0, 0); + // Undoview statut + undoLabel = new QLabel(statusBar()); + undoLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + undoLabel->setContentsMargins(2, 0, 0, 0); + // Standard message + currentMessageLabel = new QLabel(statusBar()); + currentMessageLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + currentMessageLabel->setContentsMargins(0, 0, 0, 0); + // Current location of the mouse + mousePosLabel = new QLabel(statusBar()); + mousePosLabel->setText(""); // set empty text. + mousePosLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + mousePosLabel->setContentsMargins(2, 0, 0, 0); + // Create separator + QFrame *separator = new QFrame(statusBar()); + separator->setFrameStyle(QFrame::Panel | QFrame::Sunken); + + // Add permanently into the statut bar + statusBar()->addPermanentWidget(currentMessageLabel, 5); + statusBar()->addPermanentWidget(undoLabel, 4); + statusBar()->addPermanentWidget(mousePosLabel, 3); + statusBar()->addPermanentWidget(sourceZoomLabel, 1); + //statusBar()->addPermanentWidget(separator); + statusBar()->addPermanentWidget(destinationZoomLabel, 1); + + // Update the status bar updateStatusBar(); } @@ -1966,9 +1990,9 @@ bool MainWindow::okToContinue() if (isWindowModified()) { int r = QMessageBox::warning(this, tr("MapMap"), - tr("The document has been modified.\n" - "Do you want to save your changes?"), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + tr("The document has been modified.\n" + "Do you want to save your changes?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); if (r == QMessageBox::Yes) { return save(); @@ -1989,10 +2013,10 @@ bool MainWindow::loadFile(const QString &fileName) 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; + tr("Cannot read file %1:\n%2.") + .arg(fileName) + .arg(file.errorString())); + return false; } // Clear current project. @@ -2003,9 +2027,9 @@ bool MainWindow::loadFile(const QString &fileName) 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())); + tr("Parse error in file %1:\n\n%2") + .arg(fileName) + .arg(reader.errorString())); } else { @@ -2023,9 +2047,9 @@ bool MainWindow::saveFile(const QString &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())); + tr("Cannot write file %1:\n%2.") + .arg(fileName) + .arg(file.errorString())); return false; } @@ -2065,15 +2089,15 @@ void MainWindow::setCurrentFile(const QString &fileName) void MainWindow::setCurrentVideo(const QString &fileName) { - curVideo = fileName; + curVideo = fileName; - recentVideos = settings.value("recentVideos").toStringList(); - recentVideos.removeAll(curVideo); - recentVideos.prepend(curVideo); - while (recentVideos.size() > MaxRecentVideo) - recentVideos.removeLast(); - settings.setValue("recentVideos", recentVideos); - updateRecentVideoActions(); + recentVideos = settings.value("recentVideos").toStringList(); + recentVideos.removeAll(curVideo); + recentVideos.prepend(curVideo); + while (recentVideos.size() > MaxRecentVideo) + recentVideos.removeLast(); + settings.setValue("recentVideos", recentVideos); + updateRecentVideoActions(); } void MainWindow::updateRecentFileActions() @@ -2084,14 +2108,14 @@ void MainWindow::updateRecentFileActions() for (int j = 0; j < numRecentFiles; ++j) { QString text = tr("&%1 %2") - .arg(j + 1) - .arg(strippedName(recentFiles[j])); + .arg(j + 1) + .arg(strippedName(recentFiles[j])); recentFileActions[j]->setText(text); recentFileActions[j]->setData(recentFiles[j]); recentFileActions[j]->setVisible(true); clearRecentFileActions->setVisible(true); } - + for (int i = numRecentFiles; i < MaxRecentFiles; ++i) { recentFileActions[i]->setVisible(false); @@ -2110,37 +2134,37 @@ void MainWindow::updateRecentFileActions() void MainWindow::updateRecentVideoActions() { - recentVideos = settings.value("recentVideos").toStringList(); - int numRecentVideos = qMin(recentVideos.size(), int(MaxRecentVideo)); + recentVideos = settings.value("recentVideos").toStringList(); + int numRecentVideos = qMin(recentVideos.size(), int(MaxRecentVideo)); - for (int i = 0; i < numRecentVideos; ++i) - { - QString text = tr("&%1 %2") - .arg(i + 1) - .arg(strippedName(recentVideos[i])); - recentVideoActions[i]->setText(text); - recentVideoActions[i]->setData(recentVideos[i]); - recentVideoActions[i]->setVisible(true); - } + for (int i = 0; i < numRecentVideos; ++i) + { + QString text = tr("&%1 %2") + .arg(i + 1) + .arg(strippedName(recentVideos[i])); + recentVideoActions[i]->setText(text); + recentVideoActions[i]->setData(recentVideos[i]); + recentVideoActions[i]->setVisible(true); + } - for (int j = numRecentVideos; j < MaxRecentVideo; ++j) - recentVideoActions[j]->setVisible(false); + for (int j = numRecentVideos; j < MaxRecentVideo; ++j) + recentVideoActions[j]->setVisible(false); - if (numRecentVideos > 0) - { - emptyRecentVideos->setVisible(false); - } + if (numRecentVideos > 0) + { + emptyRecentVideos->setVisible(false); + } } void MainWindow::clearRecentFileList() { - recentFiles = settings.value("recentFiles").toStringList(); + recentFiles = settings.value("recentFiles").toStringList(); - while (recentFiles.size() > 0) - recentFiles.clear(); + while (recentFiles.size() > 0) + recentFiles.clear(); - settings.setValue("recentFiles", recentFiles); - updateRecentFileActions(); + settings.setValue("recentFiles", recentFiles); + updateRecentFileActions(); } // TODO @@ -2252,8 +2276,8 @@ void MainWindow::addPaintItem(uid paintId, const QIcon& icon, const QString& nam paintPropertyPanel->setEnabled(true); // When paint value is changed, update canvases. -// connect(paintGui.get(), SIGNAL(valueChanged()), -// this, SLOT(updateCanvases())); + // connect(paintGui.get(), SIGNAL(valueChanged()), + // this, SLOT(updateCanvases())); connect(paintGui.data(), SIGNAL(valueChanged(Paint::ptr)), this, SLOT(handlePaintChanged(Paint::ptr))); @@ -2365,7 +2389,7 @@ void MainWindow::addMappingItem(uid mappingId) connect(destinationCanvas, SIGNAL(shapeChanged(MShape*)), mapper.data(), SLOT(updateShape(MShape*))); - + // Switch to mapping tab. contentTab->setCurrentWidget(mappingSplitter); @@ -2513,18 +2537,18 @@ QString MainWindow::locateMediaFile(const QString &uri, bool isImage) // Show a warning and offer to locate the file QMessageBox::warning(this, - tr("Cannot load movie"), - tr("Unable to use the file « %1 » \n" - "The original file is not found. Will you locate?") - .arg(filename)); + tr("Cannot load movie"), + tr("Unable to use the file « %1 » \n" + "The original file is not found. Will you locate?") + .arg(filename)); // Set the new uri url = QFileDialog::getOpenFileName(this, - tr("Locate file « %1 »").arg(filename), - directory, - tr("%1 files (%2)") - .arg(mediaType) - .arg(mediaFilter)); + tr("Locate file « %1 »").arg(filename), + directory, + tr("%1 files (%2)") + .arg(mediaType) + .arg(mediaFilter)); return url; } @@ -2551,6 +2575,9 @@ void MainWindow::updateCanvases() // Update position of zoom toolbar sourceCanvas->updateZoomToolbar(); destinationCanvas->updateZoomToolbar(); + + // Update statut bar + updateStatusBar(); } void MainWindow::enableDisplayControls(bool display) @@ -2620,8 +2647,8 @@ void MainWindow::connectProjectWidgets() connect(paintList, SIGNAL(itemPressed(QListWidgetItem*)), this, SLOT(handleItemSelected(QListWidgetItem*))); -// connect(paintList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), -// this, SLOT(handleItemDoubleClicked(QListWidgetItem*))); + // connect(paintList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), + // this, SLOT(handleItemDoubleClicked(QListWidgetItem*))); connect(paintList, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(handleItemSelected(QListWidgetItem*))); @@ -2649,12 +2676,12 @@ void MainWindow::connectProjectWidgets() connect(mappingList->model(), SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex &, int)), this, SLOT(handleMappingIndexesMoved())); - // Rename mapping with double click - connect(mappingList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), - this, SLOT(renameMappingItem())); - // When finish to edit mapping item - connect(mappingList->itemDelegate(), SIGNAL(commitData(QWidget*)), - this, SLOT(mappingListEditEnd(QWidget*))); + // Rename mapping with double click + connect(mappingList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), + this, SLOT(renameMappingItem())); + // When finish to edit mapping item + connect(mappingList->itemDelegate(), SIGNAL(commitData(QWidget*)), + this, SLOT(mappingListEditEnd(QWidget*))); } void MainWindow::disconnectProjectWidgets() @@ -2732,7 +2759,7 @@ QIcon MainWindow::createImageIcon(const QString& filename) { void MainWindow::setCurrentPaint(int uid) { if (uid == NULL_UID) - removeCurrentPaint(); + removeCurrentPaint(); else { if (currentPaintId != uid) { currentPaintId = uid; @@ -2857,7 +2884,7 @@ void MainWindow::pollOscInterface() // std::cout << std::endl; // std::cout.flush(); // } -// +// // if (command.size() < 2) // return; // if (command.at(0).type() != QVariant::String) @@ -2866,7 +2893,7 @@ void MainWindow::pollOscInterface() // 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") // { @@ -2887,38 +2914,38 @@ void MainWindow::pollOscInterface() bool MainWindow::setTextureUri(int texture_id, const std::string &uri) { - // TODO: const QString & + // TODO: const QString & - bool success = false; - Paint::ptr paint = this->mappingManager->getPaintById(texture_id); - if (paint.isNull()) + bool success = false; + Paint::ptr paint = this->mappingManager->getPaintById(texture_id); + if (paint.isNull()) + { + std::cout << "No such texture paint id " << texture_id << std::endl; + success = false; + } + else + { + if (paint->getType() == "media") { - std::cout << "No such texture paint id " << texture_id << std::endl; - success = false; + Media *media = static_cast(paint.data()); // FIXME: use sharedptr cast + videoTimer->stop(); + success = media->setUri(QString(uri.c_str())); + videoTimer->start(); + } + else if (paint->getType() == "image") + { + Image *media = (Image*) paint.data(); // FIXME: use sharedptr cast + videoTimer->stop(); + success = media->setUri(QString(uri.c_str())); + videoTimer->start(); } else { - if (paint->getType() == "media") - { - Media *media = static_cast(paint.data()); // FIXME: use sharedptr cast - videoTimer->stop(); - success = media->setUri(QString(uri.c_str())); - videoTimer->start(); - } - else if (paint->getType() == "image") - { - Image *media = (Image*) paint.data(); // FIXME: use sharedptr cast - videoTimer->stop(); - success = media->setUri(QString(uri.c_str())); - videoTimer->start(); - } - else - { - std::cout << "Paint id " << texture_id << " is not a media texture." << std::endl; - return false; - } + std::cout << "Paint id " << texture_id << " is not a media texture." << std::endl; + return false; } - return success; + } + return success; } bool MainWindow::setTextureRate(int texture_id, double rate) @@ -2926,23 +2953,23 @@ bool MainWindow::setTextureRate(int texture_id, double rate) Paint::ptr paint = this->mappingManager->getPaintById(texture_id); if (paint.isNull()) { - std::cout << "No such texture paint id " << texture_id << std::endl; - return false; + std::cout << "No such texture paint id " << texture_id << std::endl; + return false; } else { - if (paint->getType() == "media") - { - Media *media = static_cast(paint.data()); // FIXME: use sharedptr cast - videoTimer->stop(); - media->setRate(rate); - videoTimer->start(); - } - else - { - std::cout << "Paint id " << texture_id << " is not a media texture." << std::endl; - return false; - } + if (paint->getType() == "media") + { + Media *media = static_cast(paint.data()); // FIXME: use sharedptr cast + videoTimer->stop(); + media->setRate(rate); + videoTimer->start(); + } + else + { + std::cout << "Paint id " << texture_id << " is not a media texture." << std::endl; + return false; + } } return true; } @@ -2959,15 +2986,15 @@ bool MainWindow::setTextureVolume(int texture_id, double volume) { if (paint->getType() == "media") { - Media *media = static_cast(paint.data()); // FIXME: use sharedptr cast - videoTimer->stop(); - media->setVolume(volume); - videoTimer->start(); + Media *media = static_cast(paint.data()); // FIXME: use sharedptr cast + videoTimer->stop(); + media->setVolume(volume); + videoTimer->start(); } else { - std::cout << "Paint id " << texture_id << " is not a media texture." << std::endl; - return false; + std::cout << "Paint id " << texture_id << " is not a media texture." << std::endl; + return false; } } return true; diff --git a/MainWindow.h b/MainWindow.h index aca49e8..fb25149 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -427,6 +427,12 @@ private: // UndoStack QUndoStack *undoStack; + // Labels for status bar + QLabel *destinationZoomLabel; + QLabel *sourceZoomLabel; + QLabel *undoLabel; + QLabel *currentMessageLabel; + QLabel *mousePosLabel; public: diff --git a/resources/qss/mapmap.qss b/resources/qss/mapmap.qss index bfef9e9..dbe2406 100644 --- a/resources/qss/mapmap.qss +++ b/resources/qss/mapmap.qss @@ -87,6 +87,10 @@ QWidget#zoom-toolbox { background-color: #272a36; } +QStatusBar::item { + border: 0px solid black; +} + /* QListView::item:selected:!active { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, From 8281f7dfef10a980cd5bcc36d1098dafdc387a49 Mon Sep 17 00:00:00 2001 From: baydam Date: Sun, 14 Feb 2016 22:14:02 +0000 Subject: [PATCH 45/46] Show and hide menu bar option not available on Mac & Ubuntu --- MainWindow.cpp | 63 ++++++++++++++++++++++++++++++++++++++------------ MainWindow.h | 4 ++++ 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index d11ea94..aba5c8a 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -52,6 +52,7 @@ MainWindow::MainWindow() _stickyVertices = true; _displayTestSignal = false; _displayUndoStack = false; + _showMenuBar = true; // Show menubar by default // UndoStack undoStack = new QUndoStack(this); @@ -374,12 +375,25 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) void MainWindow::keyPressEvent(QKeyEvent *event) { -#ifdef Q_OS_OSX +#ifdef Q_OS_OSX // On Mac OS X // Do nothing -#else +#endif + +#ifdef Q_OS_LINUX // On Linux if (event->modifiers() & Qt::AltModifier) { - menuBar()->setHidden(!menuBar()->isHidden()); - menuBar()->setFocus(Qt::MenuBarFocusReason); + QString currentDesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower(); + if (currentDesktop != "unity" && !_showMenuBar) { + menuBar()->setHidden(!menuBar()->isHidden()); + menuBar()->setFocus(Qt::MenuBarFocusReason); + } + } +#endif +#ifdef Q_OS_WIN + if (event->modifiers() & Qt::AltModifier) { + if (!_showMenuBar) { + menuBar()->setHidden(!menuBar()->isHidden()); + menuBar()->setFocus(Qt::MenuBarFocusReason); + } } #endif } @@ -696,12 +710,31 @@ void MainWindow::updateStatusBar() QPointF mousePos = destinationCanvas->mapToScene(destinationCanvas->mapFromGlobal(destinationCanvas->cursor().pos())); if (currentSelectedItem) // Show mouse coordinate only if mappingList is not empty mousePosLabel->setText("Mouse coordinate: X " + QString::number(mousePos.x()) + " Y " + QString::number(mousePos.y())); + else + mousePosLabel->setText(""); // Otherwise set empty text. currentMessageLabel->setText(statusBar()->currentMessage()); sourceZoomLabel->setText("Source: " + QString::number(int(sourceCanvas->getZoomFactor() * 100)).append(QChar('%'))); destinationZoomLabel->setText("Destination: " + QString::number(int(destinationCanvas->getZoomFactor() * 100)).append(QChar('%'))); undoLabel->setText(undoStack->text(undoStack->count() - 1)); } +void MainWindow::showMenuBar(bool shown) +{ + _showMenuBar = shown; + +#ifdef Q_OS_OSX // On Mac OS X + // Do nothing +#endif +#ifdef Q_OS_LINUX // On Linux + QString currentDesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower(); + if (currentDesktop != "unity") + menuBar()->setVisible(shown); +#endif +#ifdef Q_OS_WIN // On Windows + menuBar()->setVisible(shown); +#endif +} + /** * Called when the user wants to delete an item. * @@ -1705,8 +1738,8 @@ void MainWindow::createActions() // Toggle show/hide menuBar showMenuBarAction = new QAction(tr("&Menu Bar"), this); showMenuBarAction->setCheckable(true); - showMenuBarAction->setChecked(true); - connect(showMenuBarAction, SIGNAL(triggered(bool)), menuBar(), SLOT(setVisible(bool))); + showMenuBarAction->setChecked(_showMenuBar); + connect(showMenuBarAction, SIGNAL(toggled(bool)), this, SLOT(showMenuBar(bool))); } void MainWindow::startFullScreen() @@ -1781,7 +1814,13 @@ void MainWindow::createMenus() viewMenu = menuBar->addMenu(tr("&View")); // Toolbars menu toolBarsMenu = viewMenu->addMenu(tr("Toolbars")); +#ifdef Q_OS_LINUX + if (QString(getenv("XDG_CURRENT_DESKTOP")).toLower() != "unity") + toolBarsMenu->addAction(showMenuBarAction); +#endif +#ifdef Q_OS_WIN toolBarsMenu->addAction(showMenuBarAction); +#endif viewMenu->addSeparator(); viewMenu->addAction(displayControlsAction); viewMenu->addAction(stickyVerticesAction); @@ -1909,20 +1948,14 @@ void MainWindow::createStatusBar() currentMessageLabel->setContentsMargins(0, 0, 0, 0); // Current location of the mouse mousePosLabel = new QLabel(statusBar()); - mousePosLabel->setText(""); // set empty text. mousePosLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); mousePosLabel->setContentsMargins(2, 0, 0, 0); - // Create separator - QFrame *separator = new QFrame(statusBar()); - separator->setFrameStyle(QFrame::Panel | QFrame::Sunken); - // Add permanently into the statut bar statusBar()->addPermanentWidget(currentMessageLabel, 5); statusBar()->addPermanentWidget(undoLabel, 4); statusBar()->addPermanentWidget(mousePosLabel, 3); statusBar()->addPermanentWidget(sourceZoomLabel, 1); - //statusBar()->addPermanentWidget(separator); statusBar()->addPermanentWidget(destinationZoomLabel, 1); // Update the status bar @@ -1963,8 +1996,8 @@ void MainWindow::readSettings() displayUndoStackAction->setChecked(settings.value("displayUndoStack").toBool()); if (settings.contains("zoomToolBar")) displayZoomToolAction->setChecked(settings.value("zoomToolBar").toBool()); - if (settings.contains("menuBarHidden")) - menuBar()->setHidden(settings.value("menuBarHidden").toBool()); + if (settings.contains("showMenuBar")) + showMenuBarAction->setChecked(settings.value("showMenuBar").toBool()); } void MainWindow::writeSettings() @@ -1982,7 +2015,7 @@ void MainWindow::writeSettings() settings.setValue("osc_receive_port", config_osc_receive_port); settings.setValue("displayUndoStack", displayUndoStackAction->isChecked()); settings.setValue("zoomToolBar", displayZoomToolAction->isChecked()); - settings.setValue("menuBarHidden", menuBar()->isHidden()); + settings.setValue("showMenuBar", showMenuBarAction->isChecked()); } bool MainWindow::okToContinue() diff --git a/MainWindow.h b/MainWindow.h index fb25149..50e9a97 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -88,6 +88,7 @@ private slots: void addColor(); void about(); void updateStatusBar(); + void showMenuBar(bool shown); void openRecentFile(); void clearRecentFileList(); void openRecentVideo(); @@ -418,6 +419,9 @@ private: bool _displayUndoStack; + // Menu bar hidden state + bool _showMenuBar; + // Keeps track of the current selected item, wether it's a paint or mapping. QListWidgetItem* currentSelectedItem; QTimer *videoTimer; From 89f95d9d4650acdb17267967481555d934766625 Mon Sep 17 00:00:00 2001 From: Tats Date: Sun, 14 Feb 2016 18:36:22 -0500 Subject: [PATCH 46/46] Renamed concurrentqueue.h -> ConcurrentQueue.h. --- concurrentqueue.h => ConcurrentQueue.h | 0 OscInterface.h | 2 +- mapmap.pro | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) rename concurrentqueue.h => ConcurrentQueue.h (100%) diff --git a/concurrentqueue.h b/ConcurrentQueue.h similarity index 100% rename from concurrentqueue.h rename to ConcurrentQueue.h diff --git a/OscInterface.h b/OscInterface.h index 257a0c9..78f70b0 100644 --- a/OscInterface.h +++ b/OscInterface.h @@ -29,7 +29,7 @@ #include #include -#include "concurrentqueue.h" +#include "ConcurrentQueue.h" #include "OscReceiver.h" class MainWindow; diff --git a/mapmap.pro b/mapmap.pro index 1143d4e..80f0582 100644 --- a/mapmap.pro +++ b/mapmap.pro @@ -8,6 +8,7 @@ DEFINES += UNICODE QT_THREAD_SUPPORT QT_CORE_LIB QT_GUI_LIB HEADERS = \ Commands.h \ + ConcurrentQueue.h \ ConsoleWindow.h \ DestinationGLCanvas.h \ MM.h \