diff --git a/MM.h b/MM.h index 0816a9d..87bda9e 100644 --- a/MM.h +++ b/MM.h @@ -86,6 +86,13 @@ public: 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; + + // Enumerations + enum ItemColumn { + MuteColunm, + IconAndNameColum, + GroupButtonColum + }; }; #endif diff --git a/MainWindow.cpp b/MainWindow.cpp index 790fb78..64398a5 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -131,107 +131,61 @@ void MainWindow::handlePaintItemSelectionChanged() updateCanvases(); } -void MainWindow::handleMappingItemSelectionChanged() +void MainWindow::mappingItemSelectionChanged(const QModelIndex &index) { - 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 - { - QListWidgetItem* item = mappingList->currentItem(); - currentSelectedItem = item; + // Set current paint and mappings. + uid mappingId = mappingListModel->getItemId(index); + Mapping::ptr mapping = mappingManager->getMappingById(mappingId); + uid paintId = mapping->getPaint()->getId(); + setCurrentMapping(mappingId); + setCurrentPaint(paintId); + // Enable some menus and buttons + sourceCanvas->enableZoomToolBar(true); + sourceMenu->setEnabled(true); + destinationCanvas->enableZoomToolBar(true); + destinationMenu->setEnabled(true); - // 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 some menus and buttons - sourceCanvas->enableZoomToolBar(true); - sourceMenu->setEnabled(true); - destinationCanvas->enableZoomToolBar(true); - destinationMenu->setEnabled(true); - } - - // Update canvases. - updateCanvases(); +// // Update canvases. +// updateCanvases(); } -void MainWindow::handleMappingItemChanged(QListWidgetItem* item) +void MainWindow::handleMappingItemChanged(const QModelIndex &index) { // Toggle visibility of mapping depending on checkbox of item. - uid mappingId = getItemId(*item); - setMappingVisible(mappingId, item->checkState() == Qt::Checked); -} + uid mappingId = mappingListModel->getItemId(index); + setMappingVisible(mappingId, index.data(Qt::CheckStateRole) == Qt::Checked); + } void MainWindow::handleMappingIndexesMoved() { // Reorder mappings. - QVector newOrder; - for (int row=mappingList->count()-1; row>=0; row--) + //QVector newOrder; + for (int row=mappingList->model()->rowCount()-1; row>=0; row--) { - uid layerId = mappingList->item(row)->data(Qt::UserRole).toInt(); - newOrder.push_back(layerId); + //uid layerId = mappingList->item(row)->data(Qt::UserRole).toInt(); + //newOrder.push_back(layerId); } - mappingManager->reorderMappings(newOrder); + //mappingManager->reorderMappings(newOrder); // Update canvases according to new order. updateCanvases(); } -void MainWindow::handleItemSelected(QListWidgetItem* item) +void MainWindow::handlePaintItemSelected(QListWidgetItem* item) { Q_UNUSED(item); // Change currently selected item. currentSelectedItem = item; } -//void MainWindow::handleItemDoubleClicked(QListWidgetItem* item) -//{ -// // Change currently selected item. -// Paint::ptr paint = mappingManager->getPaintById(getItemId(*item)); -// uid curMappingId = getCurrentMappingId(); -// removeCurrentMapping(); -// removeCurrentPaint(); -// -// //qDebug() << "DOUBLE CLICK! " << endl; -// videoTimer->stop(); -// if (paint->getType() == "media") { -// QString fileName = QFileDialog::getOpenFileName(this, -// tr("Import media source file"), "."); -// // Restart video playback. XXX Hack -// videoTimer->start(); -// if (!fileName.isEmpty()) -// importMediaFile(fileName, paint, false); -// } -// if (paint->getType() == "image") { -// QString fileName = QFileDialog::getOpenFileName(this, -// tr("Import media source file"), "."); -// // Restart video playback. XXX Hack -// videoTimer->start(); -// if (!fileName.isEmpty()) -// importMediaFile(fileName, paint, true); -// } -// else if (paint->getType() == "color") { -// // Pop-up color-choosing dialog to choose color paint. -// QColor initialColor; -// QColor color = QColorDialog::getColor(initialColor, this); -// videoTimer->start(); -// if (color.isValid()) -// addColorPaint(color, paint); -// } -// -// if (curMappingId != NULL_UID) -// setCurrentMapping(curMappingId); -//} +void MainWindow::handleMappingItemSelected(const QModelIndex &index) +{ + if (index.isValid()) { + if (index.column() == MM::MuteColunm) { + mappingListModel->setVisibility(index); + } + } +} void MainWindow::handlePaintChanged(Paint::ptr paint) { // Change currently selected item. @@ -750,7 +704,7 @@ void MainWindow::deleteItem() if (isMappingTabSelected) //currentSelectedItem->listWidget() == mappingList) { // Delete mapping. - undoStack->push(new DeleteMappingCommand(this, getItemId(*mappingList->currentItem()))); + undoStack->push(new DeleteMappingCommand(this, mappingList->currentIndex().data(Qt::UserRole).toInt())); //currentSelectedItem = NULL; } else if (isPaintTabSelected) //currentSelectedItem->listWidget() == paintList) @@ -768,9 +722,9 @@ void MainWindow::deleteItem() void MainWindow::duplicateMappingItem() { - if (currentSelectedItem) + if (currentSelectedIndex.isValid()) { - duplicateMapping(getItemId(*mappingList->currentItem())); + duplicateMapping(currentMappingItemId()); } else { @@ -780,9 +734,9 @@ void MainWindow::duplicateMappingItem() void MainWindow::deleteMappingItem() { - if (currentSelectedItem) + if (currentSelectedIndex.isValid()) { - deleteMapping(getItemId(*mappingList->currentItem())); + deleteMapping(currentMappingItemId()); } else { @@ -793,42 +747,42 @@ void MainWindow::deleteMappingItem() 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); +// 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::setMappingitemLocked(bool locked) { - setMappingLocked(getItemId(*mappingList->currentItem()), locked); + setMappingLocked(currentMappingItemId(), locked); } void MainWindow::setMappingitemVisible(bool visible) { - setMappingVisible(getItemId(*mappingList->currentItem()), !visible); + setMappingVisible(currentMappingItemId(), !visible); } void MainWindow::setMappingItemSolo(bool solo) { - setMappingSolo(getItemId(*mappingList->currentItem()), solo); + setMappingSolo(currentMappingItemId(), solo); } void MainWindow::renameMapping(uid mappingId, const QString &name) { - Mapping::ptr mapping = mappingManager->getMappingById(mappingId); - if (!mapping.isNull()) { - getItemFromId(*mappingList, mappingId)->setText(name); - mapping->setName(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); + renameMapping(currentMappingItemId(), name); } void MainWindow::deletePaintItem() @@ -893,7 +847,8 @@ bool MainWindow::clearProject() removeCurrentMapping(); // Empty list widgets. - mappingList->clear(); + for (int i = 0; i < mappingList->model()->rowCount(); i++) + mappingList->model()->removeRow(i); paintList->clear(); // Clear property panel. @@ -1177,9 +1132,8 @@ void MainWindow::setMappingVisible(uid mappingId, bool visible) { mapping->setVisible(visible); // Change list item check state - QListWidgetItem* item = getItemFromId(*mappingList, mappingId); - Q_ASSERT( item ); - item->setCheckState(visible ? Qt::Checked : Qt::Unchecked ); + //QModelIndex index = mappingListModel->getIndexFromId(mappingId); + //mappingListModel->setData(index, visible, Qt::CheckStateRole); // Update canvases. updateCanvases(); } @@ -1322,13 +1276,26 @@ void MainWindow::createLayout() paintPropertyPanel->setMinimumHeight(PAINT_PROPERTY_PANEL_MINIMUM_HEIGHT); // Create mapping list. - mappingList = new QListWidget; + mappingList = new QTableView; mappingList->setSelectionMode(QAbstractItemView::SingleSelection); + mappingList->setSelectionBehavior(QAbstractItemView::SelectRows); mappingList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - //layerList->setDragDropMode(QAbstractItemView::DragDrop); mappingList->setDefaultDropAction(Qt::MoveAction); mappingList->setDragDropMode(QAbstractItemView::InternalMove); + mappingList->setEditTriggers(QAbstractItemView::DoubleClicked); mappingList->setMinimumHeight(MAPPING_LIST_MINIMUM_HEIGHT); + mappingList->setContentsMargins(0, 0, 0, 0); + // Set view delegate + mappingList->setItemDelegate(new MappingItemDelegate(this)); + mappingListModel = new MappingListModel(this); + mappingList->setModel(mappingListModel); + // Pimp Mapping table widget + mappingList->horizontalHeader()->setStretchLastSection(true); + mappingList->horizontalHeader()->setHighlightSections(false); + mappingList->setFrameShape(QFrame::NoFrame); + mappingList->horizontalHeader()->setVisible(false); + mappingList->verticalHeader()->setVisible(false); + mappingList->setMouseTracking(true);// Important // Create property panel. mappingPropertyPanel = new QStackedWidget; @@ -1862,12 +1829,12 @@ void MainWindow::createMappingContextMenu() mappingContextMenu->addAction(mappingSoloAction); // Set context menu policy - mappingList->setContextMenuPolicy(Qt::CustomContextMenu); + mappingList->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); destinationCanvas->setContextMenuPolicy(Qt::CustomContextMenu); outputWindow->setContextMenuPolicy(Qt::CustomContextMenu); // Context Menu Connexions - connect(mappingList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMappingContextMenu(const QPoint&))); + connect(mappingList->horizontalHeader(), 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&))); } @@ -2427,14 +2394,19 @@ void MainWindow::addMappingItem(uid mappingId) contentTab->setCurrentWidget(mappingSplitter); // Add item to layerList widget. - QListWidgetItem* item = new QListWidgetItem(label); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState(Qt::Checked); - setItemId(*item, mappingId); // TODO: could possibly be replaced by a Paint pointer - item->setIcon(icon); - item->setSizeHint(QSize(item->sizeHint().width(), MainWindow::SHAPE_LIST_ITEM_HEIGHT)); - mappingList->insertItem(0, item); - mappingList->setCurrentItem(item); +// QListWidgetItem* item = new QListWidgetItem(label); +// item->setFlags(item->flags() | Qt::ItemIsUserCheckable); +// item->setCheckState(Qt::Checked); +// setItemId(*item, mappingId); // TODO: could possibly be replaced by a Paint pointer +// item->setIcon(icon); +// item->setSizeHint(QSize(item->sizeHint().width(), MainWindow::SHAPE_LIST_ITEM_HEIGHT)); +// mappingList->insertItem(0, item); +// mappingList->setCurrentItem(item); + mappingListModel->addItem(icon, label, mappingId); + mappingListModel->updateModel(); + mappingList->resizeRowsToContents(); + mappingList->resizeColumnsToContents(); + setCurrentMapping(mappingId); // Disable Test signal when add Shapes enableTestSignal(false); @@ -2461,16 +2433,18 @@ void MainWindow::removeMappingItem(uid mappingId) mappingPropertyPanel->removeWidget(mappers[mappingId]->getPropertiesEditor()); mappers.remove(mappingId); - // Remove widget from mappingList. - int row = getItemRowFromId(*mappingList, mappingId); - Q_ASSERT( row >= 0 ); - QListWidgetItem* item = mappingList->takeItem(row); - if (item == currentSelectedItem) - currentSelectedItem = NULL; - delete item; + + +// // Remove widget from mappingList. +// QModelIndex index = getIndexFromId(*mappingListModel, mappingId); +// //Q_ASSERT( row >= 0 ); +// QStandardItem* item = mappingListModel->itemFromIndex(index); +// if (item == currentSelectedMappingItem) +// currentSelectedMappingItem= NULL; +// delete item; // Update list. - mappingList->update(); + //mappingList->update(); // Update everything. updateCanvases(); @@ -2647,7 +2621,7 @@ void MainWindow::enableStickyVertices(bool value) void MainWindow::showMappingContextMenu(const QPoint &point) { QWidget *objectSender = dynamic_cast(sender()); - uid mappingId = getItemId(*mappingList->currentItem()); + uid mappingId = currentMappingItemId(); Mapping::ptr mapping = mappingManager->getMappingById(mappingId); // Switch to right action check state @@ -2655,7 +2629,7 @@ void MainWindow::showMappingContextMenu(const QPoint &point) mappingMuteAction->setChecked(!mapping->isVisible()); mappingSoloAction->setChecked(mapping->isSolo()); - if (objectSender != NULL && mappingList->count() > 0) + if (objectSender != NULL && mappingListModel->rowCount() > 0) mappingContextMenu->exec(objectSender->mapToGlobal(point)); } @@ -2678,13 +2652,10 @@ void MainWindow::connectProjectWidgets() this, SLOT(handlePaintItemSelectionChanged())); connect(paintList, SIGNAL(itemPressed(QListWidgetItem*)), - this, SLOT(handleItemSelected(QListWidgetItem*))); - - // connect(paintList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), - // this, SLOT(handleItemDoubleClicked(QListWidgetItem*))); + this, SLOT(handlePaintItemSelected(QListWidgetItem*))); connect(paintList, SIGNAL(itemActivated(QListWidgetItem*)), - this, SLOT(handleItemSelected(QListWidgetItem*))); + this, SLOT(handlePaintItemSelected(QListWidgetItem*))); // Rename Paint with double click connect(paintList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(renamePaintItem())); @@ -2692,29 +2663,29 @@ void MainWindow::connectProjectWidgets() connect(paintList->itemDelegate(), SIGNAL(commitData(QWidget*)), this, SLOT(paintListEditEnd(QWidget*))); - connect(mappingList, SIGNAL(itemSelectionChanged()), - this, SLOT(handleMappingItemSelectionChanged())); + connect(mappingList->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), + this, SLOT(mappingItemSelectionChanged(QModelIndex))); - connect(mappingList, SIGNAL(itemChanged(QListWidgetItem*)), - this, SLOT(handleMappingItemChanged(QListWidgetItem*))); + connect(mappingListModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(handleMappingItemChanged(QModelIndex))); - connect(mappingList, SIGNAL(itemPressed(QListWidgetItem*)), - this, SLOT(handleItemSelected(QListWidgetItem*))); + connect(mappingList, SIGNAL(pressed(QModelIndex)), + this, SLOT(handleMappingItemSelected(const QModelIndex&))); - connect(mappingList, SIGNAL(itemActivated(QListWidgetItem*)), - this, SLOT(handleItemSelected(QListWidgetItem*))); + connect(mappingList, SIGNAL(activated(const QModelIndex&)), + this, SLOT(handleMappingItemSelected(const QModelIndex&))); - connect(mappingList, SIGNAL(indexesMoved(const QModelIndexList&)), - this, SLOT(handleMappingIndexesMoved())); +// connect(mappingList, SIGNAL(indexesMoved(const QModelIndexList&)), +// this, SLOT(handleMappingIndexesMoved())); - 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*))); +// 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*))); } void MainWindow::disconnectProjectWidgets() @@ -2723,25 +2694,34 @@ void MainWindow::disconnectProjectWidgets() this, SLOT(handlePaintItemSelectionChanged())); disconnect(paintList, SIGNAL(itemPressed(QListWidgetItem*)), - this, SLOT(handleItemSelected(QListWidgetItem*))); + this, SLOT(handlePaintItemSelected(QListWidgetItem*))); disconnect(paintList, SIGNAL(itemActivated(QListWidgetItem*)), - this, SLOT(handleItemSelected(QListWidgetItem*))); + this, SLOT(handlePaintItemSelected(QListWidgetItem*))); - disconnect(mappingList, SIGNAL(itemSelectionChanged()), - this, SLOT(handleMappingItemSelectionChanged())); + disconnect(mappingList->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), + this, SLOT(mappingItemSelectionChanged(QModelIndex))); - disconnect(mappingList, SIGNAL(itemChanged(QListWidgetItem*)), - this, SLOT(handleMappingItemChanged(QListWidgetItem*))); + disconnect(mappingListModel, SIGNAL(itemChanged(QStandardItem*)), + this, SLOT(handleMappingItemChanged(QStandardItem*))); - disconnect(mappingList, SIGNAL(itemPressed(QListWidgetItem*)), - this, SLOT(handleItemSelected(QListWidgetItem*))); + disconnect(mappingList, SIGNAL(pressed(const QModelIndex&)), + this, SLOT(handleMappingItemSelected(const QModelIndex&))); - disconnect(mappingList, SIGNAL(itemActivated(QListWidgetItem*)), - this, SLOT(handleItemSelected(QListWidgetItem*))); + disconnect(mappingList, SIGNAL(activated(const QModelIndex&)), + this, SLOT(handleMappingItemSelected(const QModelIndex&))); + + disconnect(mappingList->model(), SIGNAL(indexesMoved(const QModelIndexList&)), + this, SLOT(handleMappingIndexesMoved())); disconnect(mappingList->model(), SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex &, int)), - this, SLOT(handleMappingIndexesMoved())); + this, SLOT(handleMappingIndexesMoved())); + + disconnect(mappingList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), + this, SLOT(renameMappingItem())); + + disconnect(mappingList->itemDelegate(), SIGNAL(commitData(QWidget*)), + this, SLOT(mappingListEditEnd(QWidget*))); } uid MainWindow::getItemId(const QListWidgetItem& item) @@ -2789,6 +2769,11 @@ QIcon MainWindow::createImageIcon(const QString& filename) { return QIcon(filename); } +uid MainWindow::currentMappingItemId() const +{ + return mappingList->selectionModel()->selectedRows().first().data(Qt::UserRole).toInt(); +} + void MainWindow::setCurrentPaint(int uid) { if (uid == NULL_UID) @@ -2810,7 +2795,9 @@ void MainWindow::setCurrentMapping(int uid) else { if (currentMappingId != uid) { currentMappingId = uid; - mappingList->setCurrentRow( getItemRowFromId(*mappingList, uid) ); + currentSelectedIndex = mappingListModel->selectedIndex(mappingListModel->getItemRowFromId(uid)); + mappingList->selectionModel()->select(currentSelectedIndex, QItemSelectionModel::Select); + mappingList->setCurrentIndex(currentSelectedIndex); mappingPropertyPanel->setCurrentWidget(mappers[uid]->getPropertiesEditor()); } _hasCurrentMapping = true; diff --git a/MainWindow.h b/MainWindow.h index 7dbda87..197f7af 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -43,6 +43,8 @@ #include "ConsoleWindow.h" #include "MappingManager.h" +#include "MappingItemDelegate.h" +#include "MappingListModel.h" #include "qtpropertymanager.h" #include "qtvariantproperty.h" @@ -111,10 +113,11 @@ private slots: // Widget callbacks. void handlePaintItemSelectionChanged(); // void handleItemDoubleClicked(QListWidgetItem* item); - void handleMappingItemSelectionChanged(); - void handleMappingItemChanged(QListWidgetItem* item); + void mappingItemSelectionChanged(const QModelIndex &index); + void handleMappingItemChanged(const QModelIndex &index); void handleMappingIndexesMoved(); - void handleItemSelected(QListWidgetItem* item); + void handlePaintItemSelected(QListWidgetItem* item); + void handleMappingItemSelected(const QModelIndex &index); void handlePaintChanged(Paint::ptr paint); void addMesh(); @@ -276,6 +279,7 @@ private: static QIcon createColorIcon(const QColor& color); static QIcon createFileIcon(const QString& filename); static QIcon createImageIcon(const QString& filename); + uid currentMappingItemId() const; // GUI elements. //////////////////////////////////////////////////////////////////////////////////////// @@ -355,7 +359,7 @@ private: QStackedWidget* paintPropertyPanel; QSplitter* mappingSplitter; - QListWidget* mappingList; + QTableView* mappingList; QStackedWidget* mappingPropertyPanel; QUndoView* undoView; @@ -385,6 +389,7 @@ private: // Model. MappingManager* mappingManager; + MappingListModel *mappingListModel; // OSC. #ifdef HAVE_OSC @@ -424,6 +429,7 @@ private: // Keeps track of the current selected item, wether it's a paint or mapping. QListWidgetItem* currentSelectedItem; + QModelIndex currentSelectedIndex; QTimer *videoTimer; PreferencesDialog* _preferences_dialog; diff --git a/MappingItemDelegate.cpp b/MappingItemDelegate.cpp new file mode 100644 index 0000000..70ad015 --- /dev/null +++ b/MappingItemDelegate.cpp @@ -0,0 +1,157 @@ +/* + * LayerItemDelegate.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 . + */ + +#include "MappingItemDelegate.h" + +MappingItemDelegate::MappingItemDelegate(QObject *parent) : + QStyledItemDelegate(parent) +{ + +} + +MappingItemDelegate::~MappingItemDelegate() +{ + +} + +void MappingItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (index.isValid()) { + QRect rect = option.rect; + int x = rect.x(); + int y = rect.y(); + + if (option.state & QStyle::State_Selected) + painter->fillRect(rect, MM::DARK_GRAY); + + if (index.column() == MM::MuteColunm) { + bool isVisible = index.model()->data(index, Qt::CheckStateRole).toBool(); + if (isVisible) { + QStyleOptionButton mappingMuteButton; + mappingMuteButton.state |= QStyle::State_Enabled; + mappingMuteButton.rect = QRect(x + 7, y + 12, 16, 16); + mappingMuteButton.icon = QIcon(":/visible-mapping"); + mappingMuteButton.iconSize = QSize(16, 16); + + QApplication::style()->drawControl( + QStyle::CE_PushButtonLabel, &mappingMuteButton, painter); + } + } + + if(index.column() == MM::IconAndNameColum) { + // Draw Icon + QIcon mappingIcon = qvariant_cast(index.model()->data(index, Qt::DecorationRole)); + QPixmap iconPixmap = mappingIcon.pixmap(24, 24); + QRect iconRect(x + 5, y, 24, rect.height()); + QApplication::style()->drawItemPixmap(painter, iconRect, + Qt::AlignLeft | Qt::AlignVCenter, iconPixmap); + + // Draw Text + QString mappingName = index.model()->data(index, Qt::DisplayRole).toString(); + QRect textRect(x + 40, y, rect.width() - 40, rect.height()); + QPalette textColor = QPalette(MM::WHITE); + + QApplication::style()->drawItemText(painter, textRect, Qt::AlignLeft | Qt::AlignVCenter, + textColor, true, mappingName, QPalette::Window); + } + + if (index.column() == MM::GroupButtonColum) { + // Draw Buttons + QStyleOptionButton mappingSoloButton; + mappingSoloButton.state |= QStyle::State_Enabled; + mappingSoloButton.rect = QRect(x + 10, y + 12, 16, 16); + mappingSoloButton.icon = QIcon(":/solo-mapping"); + mappingSoloButton.iconSize = QSize(16, 16); + + QStyleOptionButton mappingLockButton; + mappingLockButton.state |= QStyle::State_Enabled; + mappingLockButton.rect = QRect(x + 40, y + 12, 16, 16); + mappingLockButton.icon = QIcon(":/lock-mapping"); + mappingLockButton.iconSize = QSize(16, 16); + + QStyleOptionButton mappingDuplicateButton; + mappingDuplicateButton.state |= QStyle::State_Enabled; + mappingDuplicateButton.rect = QRect(x + 70, y + 12, 16, 16); + mappingDuplicateButton.icon = QIcon(":/duplicate-mapping"); + mappingDuplicateButton.iconSize = QSize(16, 16); + + QStyleOptionButton mappingDeleteButton; + mappingDeleteButton.state |= QStyle::State_Enabled; + mappingDeleteButton.rect = QRect(x + 100, y + 12, 16, 16); + mappingDeleteButton.icon = QIcon(":/delete-mapping"); + mappingDeleteButton.iconSize = QSize(16, 16); + + QApplication::style()->drawControl( + QStyle::CE_PushButtonLabel, &mappingSoloButton, painter); + QApplication::style()->drawControl( + QStyle::CE_PushButtonLabel, &mappingLockButton, painter); + QApplication::style()->drawControl( + QStyle::CE_PushButtonLabel, &mappingDuplicateButton, painter); + QApplication::style()->drawControl( + QStyle::CE_PushButtonLabel, &mappingDeleteButton, painter); + + } + } else { + QStyledItemDelegate::paint(painter, option, index); + } +} + +QWidget *MappingItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + qDebug() << "createEditor"; + if (index.column() == MM::IconAndNameColum) { + QLineEdit *editor = new QLineEdit(parent); + editor->setFixedHeight(option.rect.height()); + editor->setContentsMargins(option.rect.x() + 4, 0, 0, 0); + return editor; + } else + return 0; +} + +void MappingItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + QString value = index.model()->data(index, Qt::EditRole).toString(); + + QLineEdit *nameEdit = static_cast(editor); // TODO: use reinterpret_cast instead static_cast + nameEdit->setText(value); + qDebug() << "setEditorData"; +} + +void MappingItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + qDebug() << "setModelData"; + QLineEdit *nameEdit = static_cast(editor); // TODO: use reinterpret_cast instead static_cast + model->setData(index, nameEdit->text(), Qt::EditRole); +} + +void MappingItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(index); + editor->setGeometry(option.rect); +} + +bool MappingItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) +{ + if (event->type() == QEvent::MouseButtonPress) { + QMouseEvent *mouseEvent = static_cast(event); + if (index.column() == MM::GroupButtonColum) + qDebug() << "Mouse pos" << mouseEvent->pos(); + } + return false; +} diff --git a/MappingItemDelegate.h b/MappingItemDelegate.h new file mode 100644 index 0000000..2d594c7 --- /dev/null +++ b/MappingItemDelegate.h @@ -0,0 +1,55 @@ +/* + * MappingItemDelegate.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 MAPPINGITEMDELEGATE_H +#define MAPPINGITEMDELEGATE_H + +#include +#include +#include +#include +#include +#include +#include + +#include "MM.h" + +class MappingItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + MappingItemDelegate(QObject *parent = 0); + ~MappingItemDelegate(); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const /*Q_DECL_OVERRIDE*/; + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const /*Q_DECL_OVERRIDE*/; + void setEditorData(QWidget *editor, const QModelIndex &index) const /*Q_DECL_OVERRIDE*/; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const /*Q_DECL_OVERRIDE*/; + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, + const QModelIndex &index) const /*Q_DECL_OVERRIDE*/; +protected: + bool editorEvent(QEvent *event, QAbstractItemModel *model, + const QStyleOptionViewItem &option, const QModelIndex &index); +}; + +#endif // MAPPINGITEMDELEGATE_H diff --git a/MappingListModel.cpp b/MappingListModel.cpp new file mode 100644 index 0000000..9ad3e2b --- /dev/null +++ b/MappingListModel.cpp @@ -0,0 +1,181 @@ +/* + * MappingListModel.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 . + */ + +#include "MappingListModel.h" + +MappingListModel::MappingListModel(QObject *parent) : + QAbstractTableModel(parent) +{ + +} + +MappingListModel::~MappingListModel() +{ + +} + +int MappingListModel::rowCount(const QModelIndex &parent) const +{ + return (parent.isValid() && parent.column() != 0) ? 0 : mappingList.size(); +} + +int MappingListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 3; +} + +QVariant MappingListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.column() == MM::MuteColunm) { + + if (role == Qt::CheckStateRole) + return mappingList.at(index.row()).isVisible ? Qt::Checked : Qt::Unchecked; + + if (role == Qt::SizeHintRole) + return QSize(30, 40); + + } else { + + if (role == Qt::EditRole || role == Qt::DisplayRole) + return QVariant(mappingList.at(index.row()).name); + + if (role == Qt::UserRole) + return QVariant(mappingList.at(index.row()).id); + + if (role == Qt::DecorationRole) + return mappingList.at(index.row()).icon; + + if (role == Qt::SizeHintRole) + return QSize(130, 40); + + if (role == Qt::TextAlignmentRole) + return int(Qt::AlignVCenter); + } + + return QVariant(); +} + +QVariant MappingListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::DisplayRole) + return QString::number(section); + + return QAbstractItemModel::headerData(section, orientation, role); +} + +Qt::ItemFlags MappingListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + if (index.column() == MM::MuteColunm) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | + Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;; + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | + Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; +} + +bool MappingListModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + return false; + + if (role == Qt::CheckStateRole && value.type() == QVariant::Bool) { + mappingList[index.row()].isVisible = value.toBool(); + emit dataChanged(index, index); + return true; + } + + if (role == Qt::EditRole && index.column() == MM::IconAndNameColum) { + mappingList[index.row()].name = value.toString(); + emit dataChanged(index, index); + return true; + } + + return false; +} + +void MappingListModel::removeItem(int index) +{ + QList::iterator it = mappingList.begin(); + mappingList.erase(it + index); +} + +void MappingListModel::addItem(const QIcon &icon, const QString &name, int id) +{ + MappingItem item; + + item.icon = icon; + item.name = name; + item.isVisible = true; + item.id = id; + mappingList.insert(0, item); +} + +void MappingListModel::updateModel() +{ + beginResetModel(); + endResetModel(); +} + +QModelIndex MappingListModel::selectedIndex(int row) +{ + return this->createIndex(row, 1); +} + +void MappingListModel::setSelectedRow(int row) +{ + selectedRow = row; +} + +int MappingListModel::getSelectedRow() const +{ + return selectedRow; +} + +int MappingListModel::getItemRowFromId(int id) const +{ + for ( int row = 0; row < mappingList.size(); row++) { + int itemId = mappingList.at(row).id; + if (itemId == id) + return row; + } +} + +QModelIndex MappingListModel::getIndexFromId(int id) const +{ + return this->createIndex(getItemRowFromId(id), 0); +} + +int MappingListModel::getItemId(const QModelIndex &index) const +{ + return mappingList.at(index.row()).id; +} + +void MappingListModel::setVisibility(const QModelIndex &index) +{ + if (index.isValid() && index.column() == MM::MuteColunm) { + setData(index, !(mappingList.at(index.row()).isVisible), Qt::CheckStateRole); + } +} diff --git a/MappingListModel.h b/MappingListModel.h new file mode 100644 index 0000000..a4da825 --- /dev/null +++ b/MappingListModel.h @@ -0,0 +1,76 @@ +/* + * MappingListModel.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 MAPPINGLISTMODEL_H +#define MAPPINGLISTMODEL_H + +#include +#include +#include +#include +#include + +#include "MM.h" + +class MappingListModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + MappingListModel(QObject *parent = 0); + ~MappingListModel(); + + int rowCount(const QModelIndex & parent = QModelIndex()) const; + int columnCount(const QModelIndex & parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + bool setData(const QModelIndex &index, const QVariant &value, int role); + + void removeItem(int index); + void addItem(const QIcon &icon, const QString &name, int id); + + void updateModel(); + QModelIndex selectedIndex(int row); + + void setSelectedRow(int row); + int getSelectedRow() const; + int getItemRowFromId(int id) const; + int getItemId(const QModelIndex &index) const; + QModelIndex getIndexFromId(int id) const; + +public slots: + void setVisibility(const QModelIndex &index); + +private: + struct MappingItem { + int id; + QIcon icon; + QString name; + bool isVisible; + }; + + QList mappingList; + + int selectedRow; +}; + +#endif // MAPPINGLISTMODEL_H diff --git a/mapmap.pro b/mapmap.pro index 44f1125..ef07215 100644 --- a/mapmap.pro +++ b/mapmap.pro @@ -2,7 +2,7 @@ CONFIG += qt debug c++11 TEMPLATE = app VERSION = 0.3.2 TARGET = mapmap -QT += gui opengl xml +QT += gui opengl xml core greaterThan(QT_MAJOR_VERSION, 4): QT += widgets core DEFINES += UNICODE QT_THREAD_SUPPORT QT_CORE_LIB QT_GUI_LIB @@ -17,6 +17,8 @@ HEADERS = \ MainApplication.h \ MainWindow.h \ MappingGui.h \ + MappingItemDelegate.h \ + MappingListModel.h \ MapperGLCanvas.h \ Mapping.h \ MappingManager.h \ @@ -56,6 +58,8 @@ SOURCES = \ MainApplication.cpp \ MainWindow.cpp \ MappingGui.cpp \ + MappingItemDelegate.cpp \ + MappingListModel.cpp \ MapperGLCanvas.cpp \ Mapping.cpp \ MappingManager.cpp \ diff --git a/mapmap.qrc b/mapmap.qrc index 80914a8..871ee18 100644 --- a/mapmap.qrc +++ b/mapmap.qrc @@ -32,5 +32,10 @@ resources/images/icons/zoom_out_w.png resources/images/icons/zoom_fit_w.png resources/fonts/Hack-Regular.otf + resources/images/icons/small/delete_w.png + resources/images/icons/small/lock_w.png + resources/images/icons/small/visible_w.png + resources/images/icons/small/duplicate_w.png + resources/images/icons/small/solo_w.png diff --git a/resources/images/icons/small/delete.png b/resources/images/icons/small/delete.png new file mode 100644 index 0000000..bbf8a1c Binary files /dev/null and b/resources/images/icons/small/delete.png differ diff --git a/resources/images/icons/small/delete_w.png b/resources/images/icons/small/delete_w.png new file mode 100644 index 0000000..1484b60 Binary files /dev/null and b/resources/images/icons/small/delete_w.png differ diff --git a/resources/images/icons/small/duplicate.png b/resources/images/icons/small/duplicate.png new file mode 100644 index 0000000..3ae8674 Binary files /dev/null and b/resources/images/icons/small/duplicate.png differ diff --git a/resources/images/icons/small/duplicate_w.png b/resources/images/icons/small/duplicate_w.png new file mode 100644 index 0000000..bc5d41c Binary files /dev/null and b/resources/images/icons/small/duplicate_w.png differ diff --git a/resources/images/icons/small/lock.png b/resources/images/icons/small/lock.png new file mode 100644 index 0000000..7025fc4 Binary files /dev/null and b/resources/images/icons/small/lock.png differ diff --git a/resources/images/icons/small/lock_w.png b/resources/images/icons/small/lock_w.png new file mode 100644 index 0000000..d0080cc Binary files /dev/null and b/resources/images/icons/small/lock_w.png differ diff --git a/resources/images/icons/small/solo.png b/resources/images/icons/small/solo.png new file mode 100644 index 0000000..004b0ac Binary files /dev/null and b/resources/images/icons/small/solo.png differ diff --git a/resources/images/icons/small/solo_w.png b/resources/images/icons/small/solo_w.png new file mode 100644 index 0000000..b54b137 Binary files /dev/null and b/resources/images/icons/small/solo_w.png differ diff --git a/resources/images/icons/small/visible.png b/resources/images/icons/small/visible.png new file mode 100644 index 0000000..a164890 Binary files /dev/null and b/resources/images/icons/small/visible.png differ diff --git a/resources/images/icons/small/visible_w.png b/resources/images/icons/small/visible_w.png new file mode 100644 index 0000000..8cef575 Binary files /dev/null and b/resources/images/icons/small/visible_w.png differ diff --git a/resources/qss/mapmap.qss b/resources/qss/mapmap.qss index dbe2406..a26a1c9 100644 --- a/resources/qss/mapmap.qss +++ b/resources/qss/mapmap.qss @@ -37,7 +37,7 @@ QToolBar::separator:horizontal { width: 64; } -QListView { +QListView, QTableView { background-color: #323541; border: 1px solid #323541; }