Added contextual menus for reorder actions: raise, lower, etc. (closes # #296).

This commit is contained in:
Sofian Audry
2020-04-08 10:10:25 -04:00
parent b5b751faa3
commit d89b617ddd
11 changed files with 300 additions and 19 deletions
+43
View File
@@ -315,6 +315,49 @@ void DeleteMappingCommand::redo()
_mainWindow->deleteMapping(_mappingId);
}
MoveMappingCommand::MoveMappingCommand(MainWindow *mainWindow, uid mappingId, MM::MoveElement moveType, QUndoCommand *parent) :
QUndoCommand(parent),
_mainWindow(mainWindow),
_mappingId(mappingId),
_moveType(moveType)
{
switch (moveType) {
case MM::Raise: setText(QObject::tr("Raise layer")); break;
case MM::Lower: setText(QObject::tr("Lower layer")); break;
case MM::Top: setText(QObject::tr("Raise layer to top")); break;
case MM::Bottom: setText(QObject::tr("Lower layer to bottom")); break;
default:; // should not happen
}
}
void MoveMappingCommand::undo()
{
if (!_mapping.isNull())
{
// Do the inverse move.
_mainWindow->moveMapping(_mappingId, _fromIdx);
}
}
void MoveMappingCommand::redo()
{
// Store mapping pointer before delete it
_mapping = _mainWindow->getMappingManager().getMappingById(_mappingId);
_fromIdx = _mainWindow->getMappingManager().getMappingIndex(_mapping);
int maxMappingIdx = _mainWindow->getMappingManager().nMappings()-1;
switch (_moveType) {
case MM::Raise: _toIdx = qMax(_fromIdx - 1, 0); break;
case MM::Lower: _toIdx = qMin(_fromIdx + 1, maxMappingIdx); break;
case MM::Top: _toIdx = 0; break;
case MM::Bottom: _toIdx = maxMappingIdx; break;
default:; // should not happen
}
// Do the move.
_mainWindow->moveMapping(_mappingId, _toIdx);
}
FlipShapeCommand::FlipShapeCommand(MapperGLCanvas *canvas, TransformShapeCommand::TransformShapeOption option, const MShape::ptr &initialShape, MShape::FlipDirection direction, QUndoCommand *parent)
: TransformShapeCommand (canvas, option, parent),
_initialShape(initialShape)
+17
View File
@@ -223,6 +223,23 @@ private:
uid _mappingId;
};
class MoveMappingCommand : public QUndoCommand
{
public:
explicit MoveMappingCommand(MainWindow *mainWindow, uid mappingId, MM::MoveElement moveType, QUndoCommand *parent = 0);
void undo() Q_DECL_OVERRIDE;
void redo() Q_DECL_OVERRIDE;
private:
MainWindow *_mainWindow;
Mapping::ptr _mapping;
uid _mappingId;
MM::MoveElement _moveType;
int _fromIdx;
int _toIdx;
};
}
#endif /* COMMANDS_H_ */
+7
View File
@@ -152,6 +152,13 @@ public:
MediumStep = 2,
BigStep = 20
};
enum MoveElement {
Raise,
Lower,
Top,
Bottom,
};
};
}
+30 -1
View File
@@ -140,7 +140,7 @@ uid MappingManager::addMapping(Mapping::ptr mapping)
// Make sure the paint to which this mapping refers to exists in the manager.
Q_ASSERT ( paintVector.contains(mapping->getPaint()) );
mappingVector.push_back(mapping);
mappingVector.insert(0, mapping);
mappingMap[mapping->getId()] = mapping;
return mapping->getId();
@@ -156,6 +156,7 @@ bool MappingManager::removeMapping(uid mappingId)
Q_ASSERT( idx != -1 ); // Q_ASSERT(mappingVector.contains(mapping));
mappingVector.remove(idx);
mappingMap.remove(mappingId);
updateMappingsDepths();
return true;
}
@@ -165,6 +166,23 @@ bool MappingManager::removeMapping(uid mappingId)
}
}
/// Moves a mapping of given uid by a certain number of steps up or down.
bool MappingManager::moveMapping(uid mappingId, int toIndex)
{
// Make sure the paint to which this mapping refers to exists in the manager.
int idx = getMappingIndex(mappingId);
if (idx >= 0)
{
mappingVector.move(idx, toIndex);
updateMappingsDepths();
return true;
}
else
{
return false;
}
}
QVector<Mapping::ptr> MappingManager::getVisibleMappings() const
{
QVector<Mapping::ptr> visible;
@@ -266,6 +284,17 @@ void MappingManager::reorderMappings(QVector<uid> mappingIds)
}
}
void MappingManager::updateMappingsDepths()
{
int depth = 0;
for (QVector<Mapping::ptr>::iterator it = mappingVector.begin();
it != mappingVector.end(); ++it)
{
(*it)->setDepth(depth);
depth++;
}
}
//bool MappingManager::removeMapping(Mapping::ptr mapping)
//{
//}
+18 -2
View File
@@ -66,6 +66,10 @@ public:
/// Returns the uid of a paint.
uid getPaintId(Paint::ptr paint) const { return paintMap.key(paint); }
/// Returns indices of paint or (-1) if not found.
int getPaintIndex(Paint::ptr paint) const { return paintVector.lastIndexOf(paint); }
int getPaintIndex(uint paintId) const { return getPaintIndex(paintMap[paintId]); }
/// Removes a paint of given uid.
bool removePaint(uid paintId);
@@ -96,17 +100,20 @@ public:
/// Removes a mapping of given uid.
bool removeMapping(uid mappingId);
/// Moves a mapping of given uid by a certain number of steps up or down.
bool moveMapping(uid mappingId, int toIndex);
/// Returns the number of mappings.
int nMappings() const { return mappingVector.size(); }
/**
* Returns the i-th mapping in the vector. Good for iterating over all mappings. Vector is
* ordered from bottom to top layer.
* ordered from bottom (deepest) to top (shallowest) layer.
*/
Mapping::ptr getMapping(int i) { return mappingVector[i]; }
/// Returns mapping with given uid.
Mapping::ptr getMappingById(uid id) { return mappingMap[id]; }
Mapping::ptr getMappingById(uid id) const { return mappingMap[id]; }
/// Returns mapping with given name (first match).
Mapping::ptr getMappingByName(QString name);
@@ -114,9 +121,18 @@ public:
/// Returns all mappings with given regexp.
QVector<Mapping::ptr> getMappingsByNameRegExp(QString namePattern);
/// Returns indices of mapping or (-1) if not found.
int getMappingIndex(Mapping::ptr mapping) const { return mappingVector.lastIndexOf(mapping); }
int getMappingIndex(uint mappingId) const { return getMappingIndex(getMappingById(mappingId)); }
int getMappingDepth(Mapping::ptr mapping) const { return -getMappingIndex(mapping); }
/// Reorders the mappings according to given list of uids. QVector needs to
void reorderMappings(QVector<uid> mappingIds);
/// Update mapping depths after a move.
void updateMappingsDepths();
/// Returns the ordered list of visible mappings, using both the "visible" and "solo" properties.
QVector<Mapping::ptr> getVisibleMappings() const;
+10 -2
View File
@@ -121,6 +121,7 @@ void ProjectReader::parseProject(const QDomElement& project)
// Parse mappings.
QDomNode mappingNode = mappings.firstChild();
QVector<Mapping::ptr> allMappings;
while (!mappingNode.isNull())
{
Mapping::ptr mapping = parseMapping(mappingNode.toElement());
@@ -130,12 +131,19 @@ void ProjectReader::parseProject(const QDomElement& project)
}
else
{
manager.addMapping(mapping);
_window->addMappingItem(mapping->getId());
allMappings.push_back(mapping);
}
mappingNode = mappingNode.nextSibling();
}
// Add all mappings in reverse order.
for (QVector<Mapping::ptr>::const_reverse_iterator it = allMappings.rbegin();
it != allMappings.rend(); ++it)
{
manager.addMapping(*it);
_window->addMappingItem((*it)->getId());
}
}
Paint::ptr ProjectReader::parsePaint(const QDomElement& paintElem)
+148 -8
View File
@@ -176,6 +176,10 @@ void MainWindow::handleMappingItemSelectionChanged(const QModelIndex &index)
mappingRotate180Action->setEnabled(true);
mappingHorizontalFlipAction->setEnabled(true);
mappingVerticalFlipAction->setEnabled(true);
mappingRaiseAction->setEnabled(true);
mappingLowerAction->setEnabled(true);
mappingRaiseToTopAction->setEnabled(true);
mappingLowerToBottomAction->setEnabled(true);
// Enable zoom action
zoomInAction->setEnabled(true);
zoomOutAction->setEnabled(true);
@@ -211,14 +215,8 @@ void MainWindow::handleMappingItemChanged(const QModelIndex &index)
void MainWindow::handleMappingIndexesMoved()
{
// Reorder mappings.
QVector<uid> newOrder;
for (int row=mappingListModel->rowCount()-1; row>=0; row--)
{
uid layerId = mappingListModel->getIndexFromRow(row).data(Qt::UserRole).toInt();
newOrder.push_back(layerId);
}
mappingManager->reorderMappings(newOrder);
// Resync mapping manager.
syncMappingManager();
// Update canvases according to new order.
updateCanvases();
@@ -992,6 +990,24 @@ void MainWindow::transformActionMappingItem()
}
void MainWindow::reorderMappingItem()
{
QAction *actionSender = qobject_cast<QAction *>(sender());
if (actionSender == mappingRaiseAction) {
undoStack->push(new MoveMappingCommand(this, getCurrentMappingId(), MM::Raise));
}
else if (actionSender == mappingLowerAction) {
undoStack->push(new MoveMappingCommand(this, getCurrentMappingId(), MM::Lower));
}
else if (actionSender == mappingRaiseToTopAction) {
undoStack->push(new MoveMappingCommand(this, getCurrentMappingId(), MM::Top));
}
else if (actionSender == mappingLowerToBottomAction) {
undoStack->push(new MoveMappingCommand(this, getCurrentMappingId(), MM::Bottom));
}
}
void MainWindow::renameMapping(uid mappingId, const QString &name)
{
Mapping::ptr mapping = mappingManager->getMappingById(mappingId);
@@ -1432,6 +1448,15 @@ void MainWindow::deleteMapping(uid mappingId)
}
}
void MainWindow::moveMapping(uid mappingId, int idx)
{
// Cannot delete unexisting mapping.
if (Mapping::getUidAllocator().exists(mappingId))
{
moveMappingItem(mappingId, idx);
}
}
void MainWindow::duplicateMapping(uid mappingId)
{
// Clone current Mapping.
@@ -1855,6 +1880,38 @@ void MainWindow::createActions()
addAction(mappingVerticalFlipAction);
connect(mappingVerticalFlipAction, SIGNAL(triggered()), SLOT(transformActionMappingItem()));
mappingRaiseAction = new QAction(tr("Raise"), this);
mappingRaiseAction->setShortcut(Qt::Key_PageUp);
mappingRaiseAction->setToolTip(tr("Raise"));
mappingRaiseAction->setIconVisibleInMenu(true);
mappingRaiseAction->setEnabled(false);
addAction(mappingRaiseAction);
connect(mappingRaiseAction, SIGNAL(triggered()), SLOT(reorderMappingItem()));
mappingLowerAction = new QAction(tr("Lower"), this);
mappingLowerAction->setShortcut(Qt::Key_PageDown);
mappingLowerAction->setToolTip(tr("Lower"));
mappingLowerAction->setIconVisibleInMenu(true);
mappingLowerAction->setEnabled(false);
addAction(mappingLowerAction);
connect(mappingLowerAction, SIGNAL(triggered()), SLOT(reorderMappingItem()));
mappingRaiseToTopAction = new QAction(tr("Raise to Top"), this);
mappingRaiseToTopAction->setShortcut(Qt::Key_Home); // bottom = end
mappingRaiseToTopAction->setToolTip(tr("Raise to top"));
mappingRaiseToTopAction->setIconVisibleInMenu(true);
mappingRaiseToTopAction->setEnabled(false);
addAction(mappingRaiseToTopAction);
connect(mappingRaiseToTopAction, SIGNAL(triggered()), SLOT(reorderMappingItem()));
mappingLowerToBottomAction = new QAction(tr("Lower to Bottom"), this);
mappingLowerToBottomAction->setShortcut(Qt::Key_End);
mappingLowerToBottomAction->setToolTip(tr("Lower to bottom"));
mappingLowerToBottomAction->setIconVisibleInMenu(true);
mappingLowerToBottomAction->setEnabled(false);
addAction(mappingLowerToBottomAction);
connect(mappingLowerToBottomAction, SIGNAL(triggered()), SLOT(reorderMappingItem()));
// Delete paint.
deletePaintAction = new QAction(tr("Delete Source"), this);
//deletePaintAction->setShortcut(tr("CTRL+DEL"));
@@ -2304,6 +2361,11 @@ void MainWindow::createMappingContextMenu()
mappingContextMenu->addSeparator();
mappingContextMenu->addAction(mappingHorizontalFlipAction);
mappingContextMenu->addAction(mappingVerticalFlipAction);
mappingContextMenu->addSeparator();
mappingContextMenu->addAction(mappingRaiseAction);
mappingContextMenu->addAction(mappingLowerAction);
mappingContextMenu->addAction(mappingRaiseToTopAction);
mappingContextMenu->addAction(mappingLowerToBottomAction);
// Set context menu policy
mappingList->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -2711,6 +2773,10 @@ void MainWindow::updateLayerActions()
mappingRotate180Action->setEnabled(true);
mappingHorizontalFlipAction->setEnabled(false);
mappingVerticalFlipAction->setEnabled(false);
mappingRaiseAction->setEnabled(false);
mappingLowerAction->setEnabled(false);
mappingRaiseToTopAction->setEnabled(false);
mappingLowerToBottomAction->setEnabled(false);
//Disable zoom menus
zoomInAction->setEnabled(false);
zoomOutAction->setEnabled(false);
@@ -3052,6 +3118,67 @@ void MainWindow::removeMappingItem(uid mappingId)
updatePlayingState();
}
void MainWindow::moveMappingItem(uid mappingId, int idx)
{
Mapping::ptr mapping = mappingManager->getMappingById(mappingId);
Q_CHECK_PTR(mapping);
// Remove mapping from model.
qDebug() << "BEF: " << mappingId << " " << mappingManager->getMappingIndex(mapping) << " , "
<< idx << endl;
for (int i=0; i<mappingManager->nMappings(); i++)
qDebug() << mappingManager->getMapping(i)->getId() << " " ;
qDebug() << endl;
uid exchangeMappingId = mappingManager->getMapping(idx)->getId();
mappingManager->moveMapping(mappingId, idx);
qDebug() << "AFT: " << mappingManager->getMappingIndex(mapping) << " , "
<< idx << endl;
for (int i=0; i<mappingManager->nMappings(); i++)
qDebug() << mappingManager->getMapping(i)->getId() << " ";
qDebug() << endl;
// Remove widget from mappingList.
int row = mappingListModel->getItemRowFromId(mappingId);
int rowTo = mappingListModel->getItemRowFromId(exchangeMappingId);
Q_ASSERT( row >= 0 );
mappingListModel->moveItem(row, idx);
qDebug() << "INFO: " << idx << " " << row << " " << rowTo << endl;
// mappingListModel->moveItem(row, mappingManager->nMappings()-1-idx);
// // TODO: not sure if we need what lies below
// Update list.
mappingListModel->updateModel();
QModelIndex index = mappingListModel->getIndexFromRow(idx);
mappingList->selectionModel()->select(index, QItemSelectionModel::Select);
mappingList->setCurrentIndex(index);
//
// if (mappingListModel->rowCount() == 0)
// removeCurrentMapping();
// else
// {
// int nextSelectedRow = row == mappingListModel->rowCount() ? row - 1 : row;
// QModelIndex index = mappingListModel->getIndexFromRow(nextSelectedRow);
// mappingList->selectionModel()->select(index, QItemSelectionModel::Select);
// mappingList->setCurrentIndex(index);
// }
// Update everything.
updateCanvases();
// Window was modified.
windowModified();
// Update playing state.
updatePlayingState();
}
void MainWindow::removePaintItem(uid paintId)
{
Paint::ptr paint = mappingManager->getPaintById(paintId);
@@ -3103,6 +3230,19 @@ void MainWindow::clearWindow()
clearProject();
}
void MainWindow::syncMappingManager()
{
// Reorder mappings.
QVector<uid> newOrder;
for (int row=0; row<mappingListModel->rowCount(); row++)
// for (int row=mappingListModel->rowCount()-1; row>=0; row--)
{
uid layerId = mappingListModel->getIndexFromRow(row).data(Qt::UserRole).toInt();
newOrder.push_back(layerId);
}
mappingManager->reorderMappings(newOrder);
}
bool MainWindow::fileExists(const QString &file)
{
QFileInfo checkFile(file);
+13
View File
@@ -116,6 +116,7 @@ private slots:
void setMappingItemSolo(bool solo);
void loadLayerMedia();
void transformActionMappingItem();
void reorderMappingItem();
// Context menu for paints
void deletePaintItem();
void renamePaintItem();
@@ -227,6 +228,9 @@ public slots:
/// Deletes/removes a mapping.
void deleteMapping(uid mappingId);
/// Moves a mapping to given index.
void moveMapping(uid mappingId, int idx);
/// Clone/duplicate a mapping
void duplicateMapping(uid mappingId);
@@ -308,12 +312,15 @@ public:
bool addColorPaint(const QColor& color);
void addMappingItem(uid mappingId);
void removeMappingItem(uid mappingId);
void moveMappingItem(uid mappingId, int steps);
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, const QString& name);
void renamePaint(uid paintId, const QString& name);
void clearWindow();
// Resync mapping manager order the same as the GUI.
void syncMappingManager();
// Check if the file exists
bool fileExists(const QString& file);
// Check if the file is supported
@@ -398,6 +405,12 @@ private:
QAction *mappingRotate180Action;
QAction *mappingHorizontalFlipAction;
QAction *mappingVerticalFlipAction;
// Layer reordering.
QAction *mappingRaiseAction;
QAction *mappingLowerAction;
QAction *mappingRaiseToTopAction;
QAction *mappingLowerToBottomAction;
// Paints context menu action
QAction *deletePaintAction;
QAction *renamePaintAction;
+11 -5
View File
@@ -155,11 +155,8 @@ bool MappingListModel::dropMimeData(const QMimeData *data, Qt::DropAction action
int id;
stream >> id;
int rows = getItemRowFromId(id);
if (!beginMoveRows(QModelIndex(), rows, rows, QModelIndex(), endRow))
continue;
mappingList.move(rows, endRow);
endMoveRows();
int row = getItemRowFromId(id);
moveItem(row, endRow);
++endRow;
}
@@ -214,6 +211,15 @@ void MappingListModel::removeItem(int index)
mappingList.erase(it + index);
}
void MappingListModel::moveItem(int row, int endRow)
{
if (beginMoveRows(QModelIndex(), row, row, QModelIndex(), (row < endRow ? endRow+1 : endRow)))
{
mappingList.move(row, endRow);
endMoveRows();
}
}
void MappingListModel::addItem(Mapping::ptr mapping, const QIcon &icon, const QString &label)
{
MappingItem item;
+1
View File
@@ -57,6 +57,7 @@ public:
void removeItem(int index);
void addItem(Mapping::ptr mapping, const QIcon &icon, const QString &label);
void moveItem(int row, int endRow);
void updateModel();
void clear();
+2 -1
View File
@@ -52,7 +52,8 @@ void ShapeGraphicsItem::paint(QPainter *painter,
// Sync depth of figure with that of mapping (for layered output).
if (isOutput())
setZValue(getMapping()->getDepth());
setZValue(MainWindow::window()->getMappingManager().getMappingDepth(getMapping()));
//setZValue(getMapping()->getDepth());
// Paint if visible.
if (isMappingVisible())