diff --git a/src/plugins/editing/MappingView/src/mappingviewwidget.cpp b/src/plugins/editing/MappingView/src/mappingviewwidget.cpp index ab070282da..ef39bfba90 100644 --- a/src/plugins/editing/MappingView/src/mappingviewwidget.cpp +++ b/src/plugins/editing/MappingView/src/mappingviewwidget.cpp @@ -22,16 +22,19 @@ along with this program. If not, see . //============================================================================== #include "borderedwidget.h" +#include "interfaces.h" #include "mappingviewwidget.h" -#include "zincwidget.h" #include "toolbarwidget.h" +#include "zincwidget.h" //============================================================================== -#include #include -#include +#include +#include #include +#include +#include //============================================================================== @@ -89,6 +92,7 @@ MappingViewWidget::MappingViewWidget(QWidget *pParent) : //create and add the variable tree: mVariableTree = new QTreeView(this); + mVariableTree->setDragEnabled(true); mHorizontalSplitterWidget->addWidget(mVariableTree); // Keep track of our movement @@ -101,14 +105,14 @@ MappingViewWidget::MappingViewWidget(QWidget *pParent) : // add a Zinc widget - mMappingViewZincWidget = new MappingViewZincWidget(this, mMeshFileName); + mZincWidget = new MappingViewZincWidget(this, mMeshFileName); - connect(mMappingViewZincWidget, &MappingViewZincWidget::nodeSelection, + connect(mZincWidget, &MappingViewZincWidget::nodeSelection, this, &MappingViewWidget::nodeSelection); connect(mDelayWidget, &QwtWheel::valueChanged, - mMappingViewZincWidget, &MappingViewZincWidget::setNodeSizes ); + mZincWidget, &MappingViewZincWidget::setNodeSizes ); - mHorizontalSplitterWidget->addWidget(mMappingViewZincWidget); + mHorizontalSplitterWidget->addWidget(mZincWidget); //create vertical splitterwidget @@ -141,6 +145,9 @@ MappingViewWidget::MappingViewWidget(QWidget *pParent) : layout->addWidget(mVerticalSplitterWidget); + // Allow for things to be dropped on us + + setAcceptDrops(true); } //============================================================================== @@ -255,6 +262,82 @@ void MappingViewWidget::fileRenamed(const QString &pOldFileName, const QString & //============================================================================== +void MappingViewWidget::dragEnterEvent(QDragEnterEvent *pEvent) +{ + // Accept the proposed action for the event, but only if it refers to one or + // several data store files + + bool acceptEvent = false; + + for (const auto &fileName : Core::droppedFileNames(pEvent)) { + for (auto fileTypeInterface : Core::dataStoreFileTypeInterfaces()) { + if (fileTypeInterface->isFile(fileName)) { + mFileTypeInterfaces.insert(fileName, fileTypeInterface); + + acceptEvent = true; + + break; + } + } + + //TODO + if (fileName.contains(".exelem")||fileName.contains(".exnode")||fileName.contains(".exfile")) { + acceptEvent = true; + } + } + + if (acceptEvent) { + pEvent->acceptProposedAction(); + } else { + pEvent->ignore(); + } +} + +//============================================================================== + +void MappingViewWidget::dragMoveEvent(QDragMoveEvent *pEvent) +{ + // Accept the proposed action for the event + + pEvent->acceptProposedAction(); +} + +//============================================================================== + +void MappingViewWidget::dropEvent(QDropEvent *pEvent) +{ + // Import/open the one or several files + + for (const auto &fileName : Core::droppedFileNames(pEvent)) { + if (mFileTypeInterfaces.contains(fileName)) { + import(fileName); //? + //TODO + } else if (fileName.contains(".exelem")||fileName.contains(".exnode")||fileName.contains(".exfile")) { + import(fileName); + } else { + QDesktopServices::openUrl("opencor://openFile/"+fileName); + } + } + + // Accept the proposed action for the event + + pEvent->acceptProposedAction(); +} + +//============================================================================== + +bool MappingViewWidget::import(const QString &pFileName, bool pShowWarning) +{ +Q_UNUSED(pShowWarning) + + //todo + mZincWidget->changeSource(pFileName); + + return true; +} + +//============================================================================== + void MappingViewWidget::nodeSelection(int pId) { if (pId==-1) { diff --git a/src/plugins/editing/MappingView/src/mappingviewwidget.h b/src/plugins/editing/MappingView/src/mappingviewwidget.h index 5e6f19efee..0fc46fad4f 100644 --- a/src/plugins/editing/MappingView/src/mappingviewwidget.h +++ b/src/plugins/editing/MappingView/src/mappingviewwidget.h @@ -33,7 +33,6 @@ along with this program. If not, see . //============================================================================== -#include //TODO remove when over #include #include #include @@ -89,6 +88,12 @@ class MappingViewWidget : public Core::Widget bool saveFile(const QString &pOldFileName, const QString &pNewFileName); +protected: +// void changeEvent(QEvent *pEvent) override; + void dragEnterEvent(QDragEnterEvent *pEvent) override; + void dragMoveEvent(QDragMoveEvent *pEvent) override; + void dropEvent(QDropEvent *pEvent) override; + private: QwtWheel *mDelayWidget; @@ -97,21 +102,21 @@ class MappingViewWidget : public Core::Widget Core::SplitterWidget *mVerticalSplitterWidget; Core::SplitterWidget *mHorizontalSplitterWidget; - MappingViewZincWidget *mMappingViewZincWidget; + MappingViewZincWidget *mZincWidget; QLabel *mNodeValue; QLabel *mVariableValue; QTreeView *mVariableTree; - //TODO to move away - QListWidget *mListWidgetVariables; - QListWidget *mListWidgetOutput; - MappingViewEditingWidget* mEditingWidget = nullptr; QMap mEditingWidgets; QString mMeshFileName; + QMap mFileTypeInterfaces; + + bool import(const QString &pFileName, bool pShowWarning = true); + signals: void horizontalSplitterMoved(const QIntList &pSizes); void verticalSplitterMoved(const QIntList &pSizes); diff --git a/src/plugins/editing/MappingView/src/mappingviewzincwidget.cpp b/src/plugins/editing/MappingView/src/mappingviewzincwidget.cpp index c03863f7c9..0ac504c45f 100644 --- a/src/plugins/editing/MappingView/src/mappingviewzincwidget.cpp +++ b/src/plugins/editing/MappingView/src/mappingviewzincwidget.cpp @@ -28,6 +28,7 @@ along with this program. If not, see . //============================================================================== +#include #include #include #include @@ -57,25 +58,286 @@ namespace MappingView { MappingViewZincWidget::MappingViewZincWidget(QWidget *pParent, const QString &pMainFileName) : ZincWidget::ZincWidget(pParent), mMainFileName(pMainFileName), - mAuxFileName(pMainFileName), mNodeSize(nodeSizeOrigin) { + // Allow for things to be dropped on us + + setAcceptDrops(true); + // Keep track of our current scene viewer's description //TODO usefull ? mZincSceneViewerDescription = sceneViewer().writeDescription(); - //seek and read .exelem file + initAuxFile(); - mAuxFileName.remove(".exnode"); - mAuxFileName.append(".exelem"); + setup(); +} - QFileInfo check_file; - check_file.setFile(mAuxFileName); +//============================================================================== - if (!check_file.exists()) { - mAuxFileName = ""; +MappingViewZincWidget::~MappingViewZincWidget() +{ + delete mZincContext; + delete mScene; + delete mRegion; +} + +//============================================================================== + +void MappingViewZincWidget::changeSource(const QString &pMainFileName) +{ + mMainFileName = pMainFileName; + initAuxFile(); + setup(); + initializeGL(); + +qDebug(">>>zincwidget charging %s",qPrintable(mMainFileName)); +} + +//============================================================================== + +void MappingViewZincWidget::initializeGL() +{ + ZincWidget::initializeGL(); + + //mSceneViewer.readDescription(mZincSceneViewerDescription); + + // background colour + + std::array backgroundColor = { 0.85, 0.85, 0.85, 1.0 }; + + mSceneViewer.setBackgroundColourRGBA(backgroundColor.data()); + + mSceneViewer.setScene(mRegion->getScene()); + + draw(); +} + +//============================================================================== + +void MappingViewZincWidget::mouseMoveEvent(QMouseEvent *pEvent) +{ + ZincWidget::mouseMoveEvent(pEvent); +} + +//============================================================================== + +void MappingViewZincWidget::mousePressEvent(QMouseEvent *pEvent) +{ + ZincWidget::mousePressEvent(pEvent); + mMousePosClick = pEvent->pos(); +} + +//============================================================================== + +void MappingViewZincWidget::mouseReleaseEvent(QMouseEvent *pEvent) +{ + ZincWidget::mouseReleaseEvent(pEvent); + + if (mMousePosClick==pEvent->pos()) { + click(pEvent); } +} + +//============================================================================== + +void MappingViewZincWidget::wheelEvent(QWheelEvent *pEvent) +{ + ZincWidget::wheelEvent(pEvent); +} + +//============================================================================== + +void MappingViewZincWidget::dragEnterEvent(QDragEnterEvent *pEvent) +{ + // Accept the proposed action for the event, but only if we are dropping + // URIs +qDebug(">>> dragEnterZincWidget text:%s html:%s", + qPrintable(pEvent->mimeData()->text()), + qPrintable(pEvent->mimeData()->html())); +for (auto format : pEvent->mimeData()->formats()) + qDebug("%s",qPrintable(format)); + if ( pEvent->mimeData()->hasFormat(Core::FileSystemMimeType)) { + pEvent->acceptProposedAction(); + } else { + pEvent->ignore(); + } +} + +//============================================================================== + +void MappingViewZincWidget::dragMoveEvent(QDragMoveEvent *pEvent) +{ + /* + // Set the state to dragging, since we can only come here when dragging + // Note: the state is properly set for file organiser objects being dragged, + // but should we be dragging external objects over our file organiser + // widget, then the state will (obviously) not be set. This wouldn't + // be a problem in itself if it was for the fact that this prevents + // the drop indicator from being painted... + + setState(QAbstractItemView::DraggingState); + + // Default handling of the event + // Note: this gives us the drop indicator... + + TreeViewWidget::dragMoveEvent(pEvent); + + // Accept the proposed action for the event, but only if there are objects + // to drop and if we are not trying to drop the objects above/on/below one + // of them (should the objects come from the file organiser widget) or on a + // file item + // Note #1: for the number of objects being dropped, we have to check the + // number of URLs information (i.e. external objects), as well as + // the MIME data associated with FileOrganiserWindowMimeType (i.e. + // objects from the file organiser widget, after we have ) + // Note #2: for the dropping location, it can be either a folder or a file + // (as long as the indicator position isn't on the item itself), + // but not above/on/below any of the objects (or any of their + // children) being dragged (only relevant when dragging items from + // the file organiser widget) + + QByteArray data = pEvent->mimeData()->data(FileOrganiserWindowMimeType); + QModelIndexList indexes = mModel->decodeData(data); + FileOrganiserWindowItem *dropItem = static_cast(mModel->itemFromIndex(indexAt(pEvent->pos()))); + bool draggingOnSelfOrChild = false; + + if (dropItem != nullptr) { + for (int i = 0; (i < indexes.count()) && !draggingOnSelfOrChild; ++i) { + draggingOnSelfOrChild = itemIsOrIsChildOf(dropItem, + mModel->itemFromIndex(indexes[i])); + } + } + + if ( (!pEvent->mimeData()->urls().isEmpty() || !indexes.isEmpty()) + && ( ((dropItem != nullptr) && dropItem->isFolder()) + || (dropIndicatorPosition() != QAbstractItemView::OnItem)) + && !draggingOnSelfOrChild) { + pEvent->acceptProposedAction(); + } else { + pEvent->ignore(); + } + */ + pEvent->accept(); +} + +//============================================================================== + +void MappingViewZincWidget::dropEvent(QDropEvent *pEvent) +{ + /* + // Note: the MIME data definitely contains the FileSystemMimeType MIME type + // (for objects originating from outside this widget), but it may also + // contain the FileOrganiserWindowMimeType MIME type (for objects + // originating from within this widget). FileOrganiserWindowMimeType + // is used by this widget while FileSystemMimeType by external + // widgets. So, this means that we must check for + // FileOrganiserWindowMimeType first + + // Files have been dropped, so add them to the widget and this at the right + // place (i.e. above/on/below a folder, above/below a file or on the + // invisible root folder) + + // First, determine the item above/on/below which objects are to be dropped, + // as well as the drop position (i.e. above, on or below) + + QStandardItem *dropItem; + DropIndicatorPosition dropPosition = dropIndicatorPosition(); + + if (dropPosition == QAbstractItemView::OnViewport) { + // We dropped the files on the viewport + + dropItem = mModel->invisibleRootItem(); + + // Change the drop position since we know that we want want the objects + // to be dropped on the root folder + dropPosition = QAbstractItemView::OnItem; + } else { + // We dropped the files above/on/below a folder or above/below a file + + dropItem = mModel->itemFromIndex(indexAt(pEvent->pos())); + } + + // Check the type of MIME data to be dropped + + if (pEvent->mimeData()->hasFormat(FileOrganiserWindowMimeType)) { + // The user is dropping folders/files from ourselves, i.e. s/he wants + // some folders/files to be moved around + + // Retrieve the list of indexes to move around and clean it + + QByteArray data = pEvent->mimeData()->data(FileOrganiserWindowMimeType); + QModelIndexList indexes = cleanIndexList(mModel->decodeData(data)); + + // Convert our list of indexes to a list of items + // Note: indeed, by moving the item corresponding to a particular index, + // we may mess up the other indexes, meaning that we may not be + // able to retrieve their corresponding item... + + QList items; + + for (int i = 0, iMax = indexes.count(); i < iMax; ++i) { + items << mModel->itemFromIndex(indexes[i]); + } + + // Move the contents of the list to its final destination + + if (dropPosition != QAbstractItemView::BelowItem) { + // Move the items in the order they were dropped + + for (int i = 0, iMax = items.count(); i < iMax; ++i) { + moveItem(items[i], dropItem, dropPosition); + } + } else { + // Move the items in a reverse order to that they were dropped since + // we want them moved below the current item + + for (int i = items.count()-1; i >= 0; --i) { + moveItem(items[i], dropItem, dropPosition); + } + } + } else { + // The user wants to drop files, so add them to the widget and this at + // the right place + + QList urls = pEvent->mimeData()->urls(); + + if (dropPosition != QAbstractItemView::BelowItem) { + // Add the files in the order they were dropped + + for (int i = 0, iMax = urls.count(); i < iMax; ++i) { + addFile(urls[i].toLocalFile(), dropItem, dropPosition); + } + } else { + // Add the files in a reverse order to that they were dropped since + // we want them added below the current item + + for (int i = urls.count()-1; i >= 0; --i) { + addFile(urls[i].toLocalFile(), dropItem, dropPosition); + } + } + } + + // Accept the proposed action for the event + + pEvent->acceptProposedAction(); + + // Reset the state of the widget + // Note: there doesn't seem to be and there shouldn't be a need to reset the + // state after the widget (the resetting seems to be done elsewhere), + // but then if we don't reset the state of the widget, then the drop + // indicator may, in some cases, remain visible (a bug in Qt?)... + + setState(QAbstractItemView::NoState); + */ + Q_UNUSED(pEvent); +} + +//============================================================================== + +void MappingViewZincWidget::setup() +{ // Create and set our Zinc context mZincContext = new OpenCMISS::Zinc::Context("MappingViewZincContext"); @@ -98,37 +360,28 @@ MappingViewZincWidget::MappingViewZincWidget(QWidget *pParent, const QString &pM OpenCMISS::Zinc::Scenefilter nodeFilter = sceneFilterModule.createScenefilterFieldDomainType(OpenCMISS::Zinc::Field::DOMAIN_TYPE_NODES); mScenePicker->setScenefilter(nodeFilter); - - // Allow for things to be dropped on us - - //TODO remove this ? - //setAcceptDrops(true); } //============================================================================== -MappingViewZincWidget::~MappingViewZincWidget() +void MappingViewZincWidget::initAuxFile() { - delete mZincContext; - delete mScene; - delete mRegion; + mAuxFileName = mMainFileName; + mAuxFileName.remove(".exnode"); + mAuxFileName.append(".exelem"); + + QFileInfo check_file; + check_file.setFile(mAuxFileName); + + if (!check_file.exists()) { + mAuxFileName = ""; + } } //============================================================================== -void MappingViewZincWidget::initializeGL() +void MappingViewZincWidget::draw() { - ZincWidget::initializeGL(); - - //mSceneViewer.readDescription(mZincSceneViewerDescription); - - // background colour - - std::array backgroundColor = { 0.85, 0.85, 0.85, 1.0 }; - - mSceneViewer.setBackgroundColourRGBA(backgroundColor.data()); - - mSceneViewer.setScene(mRegion->getScene()); //read files mRegion->readFile(qPrintable(mMainFileName)); @@ -177,39 +430,6 @@ void MappingViewZincWidget::initializeGL() //============================================================================== -void MappingViewZincWidget::mouseMoveEvent(QMouseEvent *pEvent) -{ - ZincWidget::mouseMoveEvent(pEvent); -} - -//============================================================================== - -void MappingViewZincWidget::mousePressEvent(QMouseEvent *pEvent) -{ - ZincWidget::mousePressEvent(pEvent); - mMousePosClick = pEvent->pos(); -} - -//============================================================================== - -void MappingViewZincWidget::mouseReleaseEvent(QMouseEvent *pEvent) -{ - ZincWidget::mouseReleaseEvent(pEvent); - - if (mMousePosClick==pEvent->pos()) { - click(pEvent); - } -} - -//============================================================================== - -void MappingViewZincWidget::wheelEvent(QWheelEvent *pEvent) -{ - ZincWidget::wheelEvent(pEvent); -} - -//============================================================================== - void MappingViewZincWidget::click(QMouseEvent *pEvent) { mScenePicker->setSceneviewerRectangle(mSceneViewer, OpenCMISS::Zinc::SCENECOORDINATESYSTEM_WINDOW_PIXEL_TOP_LEFT, @@ -260,7 +480,8 @@ void MappingViewZincWidget::click(QMouseEvent *pEvent) void MappingViewZincWidget::setNodeSizes(int pSize) { mNodeSize = pSize; //TODO - // draw or modifiate + setup(); + initializeGL(); } } // namespace ZincWidget diff --git a/src/plugins/editing/MappingView/src/mappingviewzincwidget.h b/src/plugins/editing/MappingView/src/mappingviewzincwidget.h index 6e179d93ca..f01b6caed2 100644 --- a/src/plugins/editing/MappingView/src/mappingviewzincwidget.h +++ b/src/plugins/editing/MappingView/src/mappingviewzincwidget.h @@ -55,8 +55,14 @@ class MappingViewZincWidget : public ZincWidget::ZincWidget ~MappingViewZincWidget() override; + void changeSource(const QString &pMainFileName); + static constexpr double nodeSizeOrigin = 20.; +public slots: + //TODO keep slot here or manage signal through parent class ? + void setNodeSizes(int pSize); + protected: void initializeGL() override; @@ -65,6 +71,11 @@ class MappingViewZincWidget : public ZincWidget::ZincWidget void mouseReleaseEvent(QMouseEvent *pEvent) override; void wheelEvent(QWheelEvent *pEvent) override; +// void changeEvent(QEvent *pEvent) override; + void dragEnterEvent(QDragEnterEvent *pEvent) override; + void dragMoveEvent(QDragMoveEvent *pEvent) override; + void dropEvent(QDropEvent *pEvent) override; + private: QString mMainFileName; @@ -86,10 +97,11 @@ class MappingViewZincWidget : public ZincWidget::ZincWidget OpenCMISS::Zinc::Region *mRegion; OpenCMISS::Zinc::Scenepicker *mScenePicker; - void click(QMouseEvent *pEvent); + void initAuxFile(); + void setup(); + void draw(); -public slots: - void setNodeSizes(int pSize); + void click(QMouseEvent *pEvent); signals: void nodeSelection(int pId);