Hide menu
visualization/qtquick_qml/selectionhandling/main.cxx

Refer to Selection Handling Example

SelectionHandlingApplication.hxx

// ****************************************************************************
// $Id$
//
// Copyright (C) 2008-2014, Roman Lygin. All rights reserved.
// Copyright (C) 2014-2022, CADEX. All rights reserved.
//
// This file is part of the CAD Exchanger software.
//
// You may use this file under the terms of the BSD license as follows:
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ****************************************************************************
#ifndef __SelectionHandlingApplication_HeaderFile
#define __SelectionHandlingApplication_HeaderFile
#include "../baseviewer/BaseViewerApplication.hxx"
#include <cadex/ModelPrs_SelectionChangesObserver.hxx>
namespace cadex {
class ModelPrs_Selection;
}
class SelectionChangesObserver : public cadex::ModelPrs_SelectionChangesObserver
{
public:
const cadex::ModelPrs_Selection& theSelected,
const cadex::ModelPrs_Selection& theDeselected) override;
const cadex::ModelPrs_Selection& /*theSelected*/,
const cadex::ModelPrs_Selection& /*theDeselected*/) override { }
};
class SelectionHandlingApplication : public BaseViewerApplication
{
Q_OBJECT
public:
SelectionHandlingApplication();
void CreateSceneNodes() override;
public slots:
void onInitialized();
void onSelectionModeChanged (const QVariant& theMode);
void onSelectionFilterChanged (const QVariant& theFilter);
protected:
SelectionChangesObserver mySelectionObserver;
};
#endif // __SelectionHandlingApplication_HeaderFile

SelectionHandlingApplication.cxx

// ****************************************************************************
// $Id$
//
// Copyright (C) 2008-2014, Roman Lygin. All rights reserved.
// Copyright (C) 2014-2022, CADEX. All rights reserved.
//
// This file is part of the CAD Exchanger software.
//
// You may use this file under the terms of the BSD license as follows:
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ****************************************************************************
#include "SelectionHandlingApplication.hxx"
#include <cadex/Base_String.hxx>
#include <cadex/Base_UTF16String.hxx>
#include <cadex/ModelData_Appearance.hxx>
#include <cadex/ModelData_Instance.hxx>
#include <cadex/ModelData_Part.hxx>
#include <cadex/ModelData_Transformation.hxx>
#include <cadex/ModelPrs_Geometry.hxx>
#include <cadex/ModelPrs_SceneNode.hxx>
#include <cadex/ModelPrs_SceneNodeFactory.hxx>
#include <cadex/ModelPrs_Selection.hxx>
#include <cadex/ModelPrs_SelectionManager.hxx>
#include <cadex/ModelPrs_SelectionVisitor.hxx>
#include <QtCore/QDebug>
#include <QtQuick/QQuickWindow>
#include <memory>
#include <deque>
using namespace cadex;
namespace {
class SceneNodeSGEData : public cadex::ModelPrs_SceneNode::Data
{
public:
SceneNodeSGEData (const cadex::ModelData_SceneGraphElement& theSGE);
};
template<typename T>
cadex::ModelPrs_SceneNode FindAncestorWithSGE (const cadex::ModelPrs_SceneNode& theNode)
{
for (auto aParent = theNode.Parent(); aParent; aParent = aParent.Parent()) {
auto anSGEData = std::static_pointer_cast<SceneNodeSGEData> (aParent.UserData());
if (anSGEData && anSGEData->mySGE.IsOfType<T>()) {
return aParent;
}
}
}
class ModelVisitor : public ModelData_Model::CombinedElementVisitor
{
public:
ModelVisitor (const ModelPrs_SceneNode& theRoot, const ModelPrs_SceneNodeFactory& theFactory)
: myFactory (theFactory)
{
myNodes.push_back (theRoot);
}
void VisitLeave (const ModelData_SceneGraphElement& /*theSGE*/) override
{
myNodes.pop_back();
}
bool VisitEnter (const ModelData_SceneGraphElement& theSGE) override
{
auto anSGENode = myFactory.CreateNode (theSGE);
myNodes.back().AddChildNode (anSGENode);
myNodes.push_back (anSGENode);
return true;
}
void operator() (const ModelData_Part& thePart) override
{
auto aPartNode = myFactory.CreateNode (thePart);
aPartNode.SetUserData (std::make_shared<SceneNodeSGEData> (thePart));
myNodes.back().AddChildNode (aPartNode);
auto aRep = thePart.BRepRepresentation();
auto aRepNode = myFactory.CreateNode (aRep);
aPartNode.AddChildNode (aRepNode);
}
private:
std::deque<ModelPrs_SceneNode> myNodes;
};
class SelectionVisitor : public ModelPrs_SelectionVisitor
{
public:
Base_UTF16String PartOrInstanceName (const ModelPrs_SceneNode& theNode)
{
auto aPartAncestor = FindAncestorWithSGE<ModelData_Part> (theNode);
if (aPartAncestor) {
auto anInstanceAncestor = FindAncestorWithSGE<ModelData_Instance> (theNode);
if (anInstanceAncestor) {
aName = GetSGEName (anInstanceAncestor);
}
if (aName.IsEmpty()) {
aName = GetSGEName (aPartAncestor);
}
}
return aName;
}
Base_UTF16String GetSGEName (const ModelPrs_SceneNode& theNode)
{
auto anSGEData = std::static_pointer_cast<SceneNodeSGEData> (theNode.UserData());
if (anSGEData) {
return anSGEData->mySGE.Name();
}
return Base_UTF16String();
}
void Visit (const ModelPrs_SceneNode& theNode) override
{
auto aName = PartOrInstanceName (theNode).ToUTF8().Data();
qDebug() << "Part: " << aName;
}
void Visit (const ModelPrs_SceneNode& theNode, const std::vector<ModelData_Shape>& theShapes) override
{
auto aName = PartOrInstanceName (theNode).ToUTF8().Data();
qDebug() << theShapes.size() << " shapes of part: " << aName;
}
};
} // end of unnamed namespace
SceneNodeSGEData::SceneNodeSGEData (const ModelData_SceneGraphElement& theSGE)
: mySGE (theSGE)
{
}
void SelectionChangesObserver::SelectionChangedByScene (const cadex::ModelPrs_Selection& /*theCurrent*/,
const cadex::ModelPrs_Selection& theSelected,
const cadex::ModelPrs_Selection& theDeselected)
{
qDebug() << "====================";
if (theSelected) {
qDebug() << "Next items have been selected:";
SelectionVisitor aVisitor1;
theSelected.Accept (aVisitor1);
}
if (theDeselected) {
qDebug() << "Next items have been deselected:";
SelectionVisitor aVisitor2;
theDeselected.Accept (aVisitor2);
}
}
SelectionHandlingApplication::SelectionHandlingApplication()
{
myScene.SelectionManager().Register (mySelectionObserver);
connect (this, &BaseViewerApplication::initialized, this, &SelectionHandlingApplication::onInitialized);
}
void SelectionHandlingApplication::CreateSceneNodes()
{
ModelVisitor aVisitor (myRoot, aFactory);
myModel.Accept (aVisitor);
}
void SelectionHandlingApplication::onSelectionModeChanged (const QVariant& theMode)
{
auto aMode = theMode.toInt();
auto aSelectionMode = static_cast<ModelPrs_SelectionMode> (aMode);
myRoot.SetSelectionMode (aSelectionMode);
myScene.Update();
}
void SelectionHandlingApplication::onSelectionFilterChanged (const QVariant& theFilter)
{
auto aFilter = theFilter.toInt();
auto aSelectionFilter = static_cast<ModelPrs_SelectionFilterType> (aFilter);
myScene.SelectionManager().SetFilter (aSelectionFilter);
myScene.Update();
}
void SelectionHandlingApplication::onInitialized()
{
connect (myMainWindow, SIGNAL (selectionModeChanged (const QVariant&)),
this, SLOT (onSelectionModeChanged (const QVariant&)));
connect (myMainWindow, SIGNAL (selectionFilterChanged (const QVariant&)),
this, SLOT (onSelectionFilterChanged (const QVariant&)));
}

SelectionHandlingWindow.qml

import QtQuick.Controls 2.3
import CadEx 1.2
BaseViewerWindow {
signal selectionModeChanged (var index)
signal selectionFilterChanged (var index)
enum SelectionMode {
None = 0x00,
Node = 0x01,
Face = 0x08,
Edge = 0x20
}
enum SelectionFilters {
None = 0x00,
CircleEdge = 0x01,
PlanarFace = 0x02,
RevolFace = 0x04
}
Menu {
id: selectionModeMenu
title: qsTr("&Selection mode")
property var selectionModeMask: SelectionHandlingWindow.SelectionMode.None
onSelectionModeMaskChanged: {
selectionModeChanged (selectionModeMask);
}
function updateMask (theMode, checked)
{
selectionModeMask = checked ? selectionModeMask | theMode
: selectionModeMask & ~theMode;
}
MenuItem {
text: qsTr("&None")
checkable: true
checked: !nodeSelectionModeMenuItem.checked &&
!faceSelectionModeMenuItem.checked &&
!edgeSelectionModeMenuItem.checked
onCheckedChanged: {
if (checked) {
nodeSelectionModeMenuItem.checked = false;
faceSelectionModeMenuItem.checked = false;
edgeSelectionModeMenuItem.checked = false;
}
selectionModeMenu.updateMask (SelectionHandlingWindow.SelectionMode.None, checked);
}
}
MenuItem {
id: nodeSelectionModeMenuItem
text: qsTr("&Node")
checkable: true
onCheckedChanged: {
if (checked) {
faceSelectionModeMenuItem.checked = false;
edgeSelectionModeMenuItem.checked = false;
}
selectionModeMenu.updateMask (SelectionHandlingWindow.SelectionMode.Node, checked)
}
}
MenuItem {
id: faceSelectionModeMenuItem
text: qsTr("&Face")
checkable: true
onCheckedChanged: {
if (checked) {
nodeSelectionModeMenuItem.checked = false;
}
selectionModeMenu.updateMask (SelectionHandlingWindow.SelectionMode.Face, checked);
}
}
MenuItem {
id: edgeSelectionModeMenuItem
text: qsTr("&Edge")
checkable: true
onCheckedChanged: {
if (checked) {
nodeSelectionModeMenuItem.checked = false;
}
selectionModeMenu.updateMask (SelectionHandlingWindow.SelectionMode.Edge, checked);
}
}
}
Menu {
id: selectionFilterMenu
title: qsTr("&Selection Filter")
property int selectionFilterMask: SelectionHandlingWindow.SelectionFilters.None
onSelectionFilterMaskChanged: {
selectionFilterChanged (selectionFilterMask);
}
function updateMask (theFilter, checked)
{
selectionFilterMask = checked ? selectionFilterMask | theFilter
: selectionFilterMask & ~theFilter
}
MenuItem {
text: qsTr("&None")
checkable: true
checked: !circleFilterMenuItem.checked &&
!planarFacesMenuItem.checked &&
!radialSurfacesMenuItem.checked
onCheckedChanged: {
if (checked) {
circleFilterMenuItem.checked = false;
planarFacesMenuItem.checked = false;
radialSurfacesMenuItem.checked = false;
}
selectionFilterMenu.updateMask (SelectionHandlingWindow.SelectionFilters.None, checked);
}
}
MenuItem {
id: circleFilterMenuItem
text: qsTr("&Circle edges only")
checkable: true
onCheckedChanged: {
selectionFilterMenu.updateMask (SelectionHandlingWindow.SelectionFilters.CircleEdge, checked);
}
}
MenuItem {
id: planarFacesMenuItem
text: qsTr("&Planar faces only")
checkable: true
onCheckedChanged: {
selectionFilterMenu.updateMask (SelectionHandlingWindow.SelectionFilters.PlanarFace, checked);
}
}
MenuItem {
id: radialSurfacesMenuItem
text: qsTr("&Revolution faces only")
checkable: true
onCheckedChanged: {
selectionFilterMenu.updateMask (SelectionHandlingWindow.SelectionFilters.RevolFace, checked);
}
}
}
onMenuCompleted: {
menuBarItem.addMenu (selectionModeMenu);
menuBarItem.addMenu (selectionFilterMenu);
}
}

main.cxx

// ****************************************************************************
// $Id$
//
// Copyright (C) 2008-2014, Roman Lygin. All rights reserved.
// Copyright (C) 2014-2022, CADEX. All rights reserved.
//
// This file is part of the CAD Exchanger software.
//
// You may use this file under the terms of the BSD license as follows:
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ****************************************************************************
#include "SelectionHandlingApplication.hxx"
#include <cadex/LicenseManager_Activate.h>
#include <QtCore/QUrl>
#include <QtWidgets/QApplication>
#include "../../../cadex_license.cxx"
using namespace cadex;
int main (int argc, char *argv[])
{
auto aKey = LicenseKey::Value();
// Activate the license (aKey must be defined in cadex_license.cxx)
if (!CADExLicense_Activate (aKey)) {
qCritical ("Failed to activate CAD Exchanger license.");
return 1;
}
// Must set dpi scaling before creating an application.
QCoreApplication::setAttribute (Qt::AA_EnableHighDpiScaling);
// Create QApplication because Qt.labs.platform module requires Qt Widgets library.
// For more information see https://doc.qt.io/qt-5.10/qml-qt-labs-platform-filedialog.html
QApplication app (argc, argv);
SelectionHandlingApplication anApp;
if (anApp.Initialize (QUrl ("qrc:/qml/SelectionHandlingWindow.qml"), "viewPort")) {
return app.exec();
}
return 0;
}
Base class for part, instance and assembly.
Definition: ModelData_SceneGraphElement.hxx:36
Defines an observer on selection events.
Definition: ModelPrs_SelectionChangesObserver.hxx:29
Defines a visitor of the selection object.
Definition: ModelPrs_SelectionVisitor.hxx:33
Defines a Unicode (UTF-16) string wrapping a standard string.
Definition: Base_UTF16String.hxx:33
void Accept(ModelPrs_SelectionVisitor &theVisitor) const
Accepts a visitor.
Definition: ModelPrs_Selection.cxx:197
Encapsulates a container of selected scene nodes.
Definition: ModelPrs_Selection.hxx:39
ModelPrs_SceneNode Parent() const
Returns a parent of this.
Definition: ModelPrs_SceneNode.cxx:758
Represents a node in the visual scene graph.
Definition: ModelPrs_SceneNode.hxx:43
Defines classes, types, and global functions related to CAD Exchanger.
Definition: A3DSTestLib.hxx:22
virtual void SelectionChangedByManager(const ModelPrs_Selection &theCurrent, const ModelPrs_Selection &theSelected, const ModelPrs_Selection &theDeselected)=0
The method is invoked when the source of the selection event is the manager's method call.
Creates a scene nodes and its children from input data model objects.
Definition: ModelPrs_SceneNodeFactory.hxx:47
std::shared_ptr< Data > UserData() const
Returns pointer to user data if exist or nullptr otherwise.
Definition: ModelPrs_SceneNode.cxx:935
Provides combined methods VisitEnter() and VisitLeave() to visit all elements.
Definition: ModelData_Model.hxx:116
bool IsEmpty() const
Returns true if the string is empty.
Definition: Base_UTF16String.cxx:233
ModelData_BRepRepresentation BRepRepresentation() const
Definition: ModelData_Part.cxx:343
Defines a leaf node in the scene graph hiearchy.
Definition: ModelData_Part.hxx:34
virtual void SelectionChangedByScene(const ModelPrs_Selection &theCurrent, const ModelPrs_Selection &theSelected, const ModelPrs_Selection &theDeselected)=0
The method is invoked when the source of the selection event is mouse click on the scene.