Salome HOME
Second integration of PV3D viewer: duc/Viewerunique_integre1 master
authorDUC ANH HOANG <dh77501n@dsp1043837>
Tue, 4 Jun 2024 12:08:35 +0000 (14:08 +0200)
committerDUC ANH HOANG <dh77501n@dsp1043837>
Thu, 20 Jun 2024 15:02:42 +0000 (17:02 +0200)
   Correction of the Presentation pipeline updating
   Correction of the CAD selection(setup solid_id with entry)
   Get preselect solidID (entry) from client

60 files changed:
CMakeLists.txt
SalomeGUIConfig.cmake.in
src/CMakeLists.txt
src/LightApp/CMakeLists.txt
src/LightApp/LightApp_Application.cxx
src/LightApp/LightApp_Application.h
src/LightApp/LightApp_QTVSelector.cxx [new file with mode: 0644]
src/LightApp/LightApp_QTVSelector.h [new file with mode: 0644]
src/LightApp/resources/LightApp.xml
src/LightApp/resources/LightApp_msg_en.ts
src/LightApp/resources/LightApp_msg_fr.ts
src/OCCViewer/OCCViewer_ViewPort3d.cxx
src/OCCViewer/OCCViewer_ViewSketcher.cxx
src/OCCViewer/OCCViewer_ViewWindow.cxx
src/QtViewer/CMakeLists.txt [new file with mode: 0644]
src/QtViewer/QtViewer.h [new file with mode: 0644]
src/QtViewer/QtViewer_Object.cxx [new file with mode: 0644]
src/QtViewer/QtViewer_Object.h [new file with mode: 0644]
src/QtViewer/QtViewer_PainterObject.cxx [new file with mode: 0644]
src/QtViewer/QtViewer_PainterObject.h [new file with mode: 0644]
src/QtViewer/QtViewer_Scene.cxx [new file with mode: 0644]
src/QtViewer/QtViewer_Scene.h [new file with mode: 0644]
src/QtViewer/QtViewer_Selector.cxx [new file with mode: 0644]
src/QtViewer/QtViewer_Selector.h [new file with mode: 0644]
src/QtViewer/QtViewer_ViewFrame.cxx [new file with mode: 0644]
src/QtViewer/QtViewer_ViewFrame.h [new file with mode: 0644]
src/QtViewer/QtViewer_ViewManager.cxx [new file with mode: 0644]
src/QtViewer/QtViewer_ViewManager.h [new file with mode: 0644]
src/QtViewer/QtViewer_ViewPort.cxx [new file with mode: 0644]
src/QtViewer/QtViewer_ViewPort.h [new file with mode: 0644]
src/QtViewer/QtViewer_Viewer.cxx [new file with mode: 0644]
src/QtViewer/QtViewer_Viewer.h [new file with mode: 0644]
src/QtViewer/resources/QtViewer_images.ts [new file with mode: 0644]
src/QtViewer/resources/QtViewer_msg_en.ts [new file with mode: 0644]
src/QtViewer/resources/QtViewer_msg_fr.ts [new file with mode: 0644]
src/QtViewer/resources/QtViewer_msg_ja.ts [new file with mode: 0644]
src/QtViewer/resources/qtviewer_cursor_zoom.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_dump.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_fitall.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_fitarea.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_fitselect.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_glpan.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_pan.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_reset.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_rotate.png [new file with mode: 0644]
src/QtViewer/resources/qtviewer_zoom.png [new file with mode: 0644]
src/SPV3D/SPV3D_CADSelection.cxx
src/SPV3D/SPV3D_Prs.cxx
src/SPV3D/SPV3D_Prs.h
src/SPV3D/SPV3D_ViewModel.cxx
src/SPV3D/SPV3D_ViewModel.h
src/SPV3D/SPV3D_ViewWindow.cxx
src/SPV3D/SPV3D_ViewWindow.h
src/SUIT/resources/action_assets.json
src/SVTK/SVTK_InteractorStyle.cxx
src/SVTK/SVTK_RenderWindowInteractor.cxx
src/Session/SALOME_Session_Server.cxx
src/ViewerTools/CMakeLists.txt
src/ViewerTools/ViewerTools_ScreenScaling.cxx [new file with mode: 0644]
src/ViewerTools/ViewerTools_ScreenScaling.h [new file with mode: 0644]

index 4819eebbdbe523df05046e599eb9515b89c2e513..76b0251ee99977cc3ab34cf9088c9f038b48d50d 100644 (file)
@@ -78,6 +78,7 @@ OPTION(SALOME_USE_OCCVIEWER "Enable OCC visualization (Mandatory in classic conf
 OPTION(SALOME_USE_PV3DVIEWER "Enable ParaView3D visualization (Optionally in classic configurations)" ON)
 OPTION(SALOME_USE_GLVIEWER "Enable OpenGL visualization (Mandatory in classic configurations)" ON)
 OPTION(SALOME_USE_GRAPHICSVIEW "Enable GraphicsView visualization (Mandatory in classic configurations)" ON)
+OPTION(SALOME_USE_QTVIEWER "Enable Qt viewer visualization (Mandatory in classic configurations)" ON)
 OPTION(SALOME_USE_PYVIEWER "Enable Python viewer (Mandatory in classic configurations)" ON)
 OPTION(SALOME_USE_PLOT2DVIEWER "Enable Plot2D visualization (Mandatory in classic configurations)" ON)
 OPTION(SALOME_USE_PYCONSOLE "Enable Python GUI interface (Mandatory in classic configurations)" ON)
@@ -87,7 +88,7 @@ OPTION(SALOME_USE_PVVIEWER "Enable ParaView visualization (Mandatory in classic
 CMAKE_DEPENDENT_OPTION(SALOME_USE_SALOMEOBJECT "Enable Salome Object (Mandatory in classic configurations)" ON
                        "SALOME_LIGHT_ONLY" ON)
 
-MARK_AS_ADVANCED(SALOME_LIGHT_ONLY SALOME_USE_VTKVIEWER SALOME_USE_GRAPHICSVIEW SALOME_USE_PVVIEWER)
+MARK_AS_ADVANCED(SALOME_LIGHT_ONLY SALOME_USE_VTKVIEWER SALOME_USE_GRAPHICSVIEW SALOME_USE_QTVIEWER SALOME_USE_PVVIEWER)
 MARK_AS_ADVANCED(SALOME_USE_SALOMEOBJECT SALOME_USE_OCCVIEWER SALOME_USE_GLVIEWER SALOME_USE_PLOT2DVIEWER)
 MARK_AS_ADVANCED(SALOME_USE_PYCONSOLE SALOME_USE_QXGRAPHVIEWER SALOME_USE_PYVIEWER SALOME_USE_PV3DVIEWER)
 
@@ -231,6 +232,11 @@ IF (NOT SALOME_USE_GRAPHICSVIEW)
   ADD_DEFINITIONS("-DDISABLE_GRAPHICSVIEW")
 ENDIF()
 
+# - Qt viewer: no prereqs
+IF (NOT SALOME_USE_QTVIEWER)
+  ADD_DEFINITIONS("-DDISABLE_QTVIEWER")
+ENDIF()
+
 # - Python editor: no prereqs
 IF (NOT SALOME_USE_PYVIEWER)
   ADD_DEFINITIONS("-DDISABLE_PYVIEWER")
@@ -409,6 +415,12 @@ IF(SALOME_USE_GRAPHICSVIEW)
        GraphicsView)
 ENDIF(SALOME_USE_GRAPHICSVIEW)
 
+# QtViewer specific targets:
+IF(SALOME_USE_QTVIEWER)
+  LIST(APPEND _${PROJECT_NAME}_exposed_targets
+       QtViewer)
+ENDIF(SALOME_USE_QTVIEWER)
+
 # PyEditor/Viewer specific targets:
 IF(SALOME_USE_PYVIEWER)
   LIST(APPEND _${PROJECT_NAME}_exposed_targets
index 85008e92a4242b4e82577eefa4afe4ee7dc80a9b..58b1d2714e0fcaaf3173d158e194f846359c33d0 100644 (file)
@@ -58,6 +58,7 @@ SET(SALOME_USE_VTKVIEWER      @SALOME_USE_VTKVIEWER@)
 SET(SALOME_USE_PV3DVIEWER     @SALOME_USE_PV3DVIEWER@)
 SET(SALOME_USE_PLOT2DVIEWER   @SALOME_USE_PLOT2DVIEWER@)
 SET(SALOME_USE_GRAPHICSVIEW   @SALOME_USE_GRAPHICSVIEW@)
+SET(SALOME_USE_QTVIEWER       @SALOME_USE_QTVIEWER@)
 SET(SALOME_USE_QXGRAPHVIEWER  @SALOME_USE_QXGRAPHVIEWER@)
 SET(SALOME_USE_PVVIEWER       @SALOME_USE_PVVIEWER@)
 SET(SALOME_USE_PYVIEWER       @SALOME_USE_PYVIEWER@)
@@ -99,6 +100,9 @@ ENDIF()
 IF (NOT SALOME_USE_GRAPHICSVIEW)
   LIST(APPEND GUI_DEFINITIONS "-DDISABLE_GRAPHICSVIEW")
 ENDIF()
+IF (NOT SALOME_USE_QTVIEWER)
+  LIST(APPEND GUI_DEFINITIONS "-DDISABLE_QTVIEWER")
+ENDIF()
 IF (NOT SALOME_USE_PVVIEWER)
   LIST(APPEND GUI_DEFINITIONS "-DDISABLE_PVVIEWER")
 ENDIF()
index 2143144f1c2ce4a00d8adca2f479d671cf9c71dc..ab7b75a4a381c6a34d3582476b35a200be4d28cc 100644 (file)
@@ -118,6 +118,12 @@ IF(SALOME_USE_GRAPHICSVIEW)
   ADD_SUBDIRECTORY(GraphicsView)
 ENDIF(SALOME_USE_GRAPHICSVIEW)
 
+# Qt viewer
+##
+IF(SALOME_USE_QTVIEWER)
+  ADD_SUBDIRECTORY(QtViewer)
+ENDIF(SALOME_USE_QTVIEWER)
+
 # ParaView Viewer
 IF(SALOME_USE_PVVIEWER)
   ADD_SUBDIRECTORY(PVViewer)
index bcc0372895727f26d25ed150763d301b1df4a121..f37dfae1a0f852548d3c66b4a46456624c87fd65 100644 (file)
@@ -50,6 +50,9 @@ ENDIF()
 IF(SALOME_USE_GRAPHICSVIEW)
   INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/GraphicsView)
 ENDIF()
+IF(SALOME_USE_QTVIEWER)
+  INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/QtViewer)
+ENDIF()
 IF(SALOME_USE_PYVIEWER)
   INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/PyEditor)
   INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/PyViewer)
@@ -122,6 +125,9 @@ ENDIF()
 IF(SALOME_USE_GRAPHICSVIEW)
   LIST(APPEND _link_LIBRARIES GraphicsView)
 ENDIF()
+IF(SALOME_USE_QTVIEWER)
+  LIST(APPEND _link_LIBRARIES QtViewer)
+ENDIF()
 IF(SALOME_USE_PYVIEWER)
   LIST(APPEND _link_LIBRARIES PyEditor PyViewer)
 ENDIF()
@@ -188,6 +194,9 @@ ENDIF()
 IF(SALOME_USE_GRAPHICSVIEW)
   LIST(APPEND _moc_HEADERS LightApp_GVSelector.h)
 ENDIF()
+IF(SALOME_USE_QTVIEWER)
+  LIST(APPEND _moc_HEADERS LightApp_QTVSelector.h)
+ENDIF()
 IF(SALOME_USE_OCCVIEWER)
   LIST(APPEND _moc_HEADERS LightApp_OCCSelector.h)
 ENDIF()
@@ -314,6 +323,9 @@ ENDIF()
 IF(SALOME_USE_GRAPHICSVIEW)
   LIST(APPEND _other_SOURCES LightApp_GVSelector.cxx)
 ENDIF()
+IF(SALOME_USE_QTVIEWER)
+  LIST(APPEND _other_SOURCES LightApp_QTVSelector.cxx)
+ENDIF()
 IF(SALOME_USE_OCCVIEWER)
   LIST(APPEND _other_SOURCES LightApp_OCCSelector.cxx)
 ENDIF()
index fcd338411b1849f6ae760452fb45d303ce83b19c..a83faafc4d04fff81308ba8d08fcc9b1935b9868 100644 (file)
   #include "LightApp_GVSelector.h"
 #endif
 
+#ifndef DISABLE_QTVIEWER
+  #include "QtViewer_Viewer.h"
+  #include "QtViewer_ViewManager.h"
+  #include "LightApp_QTVSelector.h"
+#endif
+
 #ifndef DISABLE_PVVIEWER
   #include "PVViewer_ViewManager.h"
   #include "PVViewer_ViewWindow.h"
@@ -829,6 +835,9 @@ void LightApp_Application::createActions()
 #ifndef DISABLE_PV3DVIEWER
   createActionForViewer( NewPV3DViewId, newWinMenu, QString::number( 8 ) );
 #endif
+#ifndef DISABLE_QTVIEWER
+  createActionForViewer( NewQtViewId, newWinMenu, QString::number( 9 ) );
+#endif
 
   createAction( RenameId, desk, false /*toggle*/, "/PRP_RENAME",
                 tr( "TOT_RENAME" ), tr( "MEN_DESK_RENAME" ), tr( "PRP_RENAME" ), QIcon(),
@@ -1346,6 +1355,11 @@ void LightApp_Application::onNewWindow()
     type = GraphicsView_Viewer::Type();
     break;
 #endif
+#ifndef DISABLE_QTVIEWER
+  case NewQtViewId:
+    type = QtViewer_Viewer::Type();
+    break;
+#endif
 #ifndef DISABLE_PVVIEWER
   case NewPVViewId:
     type = PVViewer_Viewer::Type();
@@ -1523,6 +1537,12 @@ void LightApp_Application::updateCommandsStatus()
     a->setEnabled( activeStudy() );
 #endif
 
+#ifndef DISABLE_QTVIEWER
+  a = action( NewQtViewId );
+  if( a )
+    a->setEnabled( activeStudy() );
+#endif
+
 #ifndef DISABLE_PVVIEWER
   a = action( NewPVViewId );
   if( a )
@@ -2000,6 +2020,13 @@ SUIT_ViewManager* LightApp_Application::createViewManager( const QString& vmType
     new LightApp_GVSelector( (GraphicsView_Viewer*)viewMgr->getViewModel(), mySelMgr );
   }
 #endif
+#ifndef DISABLE_QTVIEWER
+  if( vmType == QtViewer_Viewer::Type() )
+  {
+    viewMgr = new QtViewer_ViewManager( activeStudy(), desktop() );
+    new LightApp_QTVSelector( (QtViewer_Viewer*)viewMgr->getViewModel(), mySelMgr );
+  }
+#endif
 #ifndef DISABLE_PVVIEWER
   if( vmType == PVViewer_Viewer::Type() )
   {
index 3a0b70ad311c9da565869fd5d32b0a662556a0a4..3b02baca1e278acd0ee6d46c51fc83df547c9072 100644 (file)
@@ -92,7 +92,7 @@ public:
          CloseId, CloseAllId, GroupAllId,
          PreferencesId, MRUId, ModulesListId,
          NewGLViewId, NewPlot2dId, NewOCCViewId, NewVTKViewId,
-         NewQxSceneViewId, NewGraphicsViewId, NewPVViewId, NewPyViewerId, NewPV3DViewId, StyleId, FullScreenId,
+         NewQxSceneViewId, NewGraphicsViewId, NewQtViewId, NewPVViewId, NewPyViewerId, NewPV3DViewId, StyleId, FullScreenId,
          WebSiteId, ForumId, VideosId, TutorialsId,
          UserID };
 
diff --git a/src/LightApp/LightApp_QTVSelector.cxx b/src/LightApp/LightApp_QTVSelector.cxx
new file mode 100644 (file)
index 0000000..f6f54e4
--- /dev/null
@@ -0,0 +1,97 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "LightApp_QTVSelector.h"
+
+#include "LightApp_DataOwner.h"
+
+#include <QtViewer_Object.h>
+#include <QtViewer_ViewPort.h>
+#include <QtViewer_Viewer.h>
+
+LightApp_QTVSelector::LightApp_QTVSelector( QtViewer_Viewer* theViewer,
+                                          SUIT_SelectionMgr* theSelMgr )
+: SUIT_Selector( theSelMgr, theViewer ),
+  myViewer( theViewer )
+{
+  connect( theViewer, SIGNAL( selectionChanged() ),
+          this, SLOT( onSelectionChanged() ) );
+}
+
+LightApp_QTVSelector::~LightApp_QTVSelector()
+{
+}
+
+QString LightApp_QTVSelector::type() const
+{
+  return QtViewer_Viewer::Type();
+}
+
+void LightApp_QTVSelector::getSelection( SUIT_DataOwnerPtrList& theList ) const
+{
+  if ( !myViewer )
+    return;
+
+  if( QtViewer_ViewPort* aViewport = myViewer->getActiveViewPort() )
+    {
+      foreach (QGraphicsItem *item, aViewport->scene()->selectedItems()) 
+        {
+         if (QtViewer_Object* obj = dynamic_cast<QtViewer_Object*>(item))
+           {
+             LightApp_DataOwner* owner = dynamic_cast<LightApp_DataOwner*>( obj->owner() );
+             if ( owner )
+               theList.append( SUIT_DataOwnerPtr( new LightApp_DataOwner( owner->entry() ) ) );
+           }
+        }
+    } 
+}
+
+void LightApp_QTVSelector::setSelection( const SUIT_DataOwnerPtrList& theList)
+{ 
+ if ( !myViewer )
+    return;
+
+  QMap<QString, int> aSelected;
+  for ( SUIT_DataOwnerPtrList::const_iterator itr = theList.begin(); itr != theList.end(); ++itr )
+  {
+    const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr).operator->() );
+
+    if ( owner )
+      aSelected.insert( owner->entry(), 0 );
+  }
+  
+  if( QtViewer_ViewPort* aViewport = myViewer->getActiveViewPort() )
+    {
+      aViewport->scene()->clearSelection();
+      foreach (QGraphicsItem *item, aViewport->items())
+        {
+          if (QtViewer_Object* obj = dynamic_cast<QtViewer_Object*>(item))
+            {
+              LightApp_DataOwner* owner = dynamic_cast<LightApp_DataOwner*>( obj->owner() );
+              bool sel = owner && aSelected.contains(owner->entry());
+              obj->setSelected(sel);
+            }
+       }
+   }
+}
+
+void LightApp_QTVSelector::onSelectionChanged()
+{
+  selectionChanged();
+}
diff --git a/src/LightApp/LightApp_QTVSelector.h b/src/LightApp/LightApp_QTVSelector.h
new file mode 100644 (file)
index 0000000..0d7e67c
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef LIGHTAPP_QTVSELECTOR_H
+#define LIGHTAPP_QTVSELECTOR_H
+
+#include "LightApp.h"
+
+#include <QObject>
+#include <SUIT_Selector.h>
+#include <SUIT_DataOwner.h>
+
+class QtViewer_Viewer;
+
+class LIGHTAPP_EXPORT LightApp_QTVSelector : public QObject, public SUIT_Selector
+{
+  Q_OBJECT
+
+public:
+  LightApp_QTVSelector( QtViewer_Viewer*, SUIT_SelectionMgr* );
+  virtual ~LightApp_QTVSelector();
+
+  virtual QString type() const;
+
+protected:
+  virtual void getSelection( SUIT_DataOwnerPtrList& ) const;
+  virtual void setSelection( const SUIT_DataOwnerPtrList& );
+
+protected slots:
+  void onSelectionChanged();
+
+protected:
+  QtViewer_Viewer* myViewer;
+};
+
+#endif
index b7d00fb800b709815061ed3945136d112c6f187d..3ba6a36e54719bda11cf5cf5db4d59a03c612bf1 100644 (file)
@@ -43,6 +43,7 @@
     <parameter name="SPlot2d"       value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="GLViewer"      value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="GraphicsView"  value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
+    <parameter name="QtViewer"      value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="OCCViewer"     value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="VTKViewer"     value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="PVViewer"      value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="PRP_CREATE_NEW_WINDOW_FOR_VIEWER_7" value="Alt+Y"/>
     <parameter name="PRP_DESK_FIND_ACTION" value="Ctrl+Shift+Space"/>
     <parameter name="PRP_CREATE_NEW_WINDOW_FOR_VIEWER_8" value="Alt+3"/>
+    <parameter name="PRP_CREATE_NEW_WINDOW_FOR_VIEWER_9" value="Alt+Q"/>
     <parameter name="#General/Object(s)/Show" value="Ctrl+Alt+S"/>
     <parameter name="#General/Object(s)/Hide" value="Ctrl+Alt+H"/>
     <parameter name="#Viewers/View/Set X+" value="Ctrl+Alt+B"/>
index 38550acb5ea0b00246662eced648fb393eaf342f..90c371e2479a3b00244c90405d45dd205f59b4b0 100644 (file)
@@ -568,6 +568,10 @@ The changes will be applied on the next application session.</translation>
         <source>NEW_WINDOW_8</source>
         <translation>ParaView&amp;3D view</translation>
     </message>
+    <message>
+        <source>NEW_WINDOW_9</source>
+        <translation>Q&amp;t view</translation>
+    </message>
     <message>
         <source>CREATING_NEW_WINDOW</source>
         <translation>Create new %1</translation>
index 826114cf7eb1df2cba26daa5f428299facfb9003..d5981a7e1cb78613fa9f4a48b9524398156f45e7 100644 (file)
@@ -564,6 +564,14 @@ Les modifications seront appliquées à la prochaine session.</translation>
         <source>NEW_WINDOW_7</source>
         <translation>Vue P&amp;ython</translation>
     </message>
+    <message>
+        <source>NEW_WINDOW_8</source>
+        <translation>ParaView&amp;3D view</translation>
+    </message>
+    <message>
+        <source>NEW_WINDOW_9</source>
+        <translation>Q&amp;t view</translation>
+    </message>
     <message>
         <source>CREATING_NEW_WINDOW</source>
         <translation>Créer une nouvelle %1</translation>
index 7e7b26c13ed1edfb8f7dd308528b4954d7839ea1..3a64aa21056f35d2768f04f2199d648d0ead132f 100644 (file)
@@ -322,6 +322,7 @@ void OCCViewer_ViewPort3d::updateBackground()
        Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
        Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
        activeView()->SetBgImageStyle( Aspect_FM_NONE );    // cancel texture background
+#if OCC_VERSION_LARGE > 0x07070000
        switch ( type ) {
        case OCCViewer_Viewer::HorizontalGradient:
          activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GradientFillMethod_Horizontal, Standard_True );
@@ -350,6 +351,36 @@ void OCCViewer_ViewPort3d::updateBackground()
        default:
          break;
        }
+#else
+       switch ( type ) {
+       case OCCViewer_Viewer::HorizontalGradient:
+         activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
+         break;
+       case OCCViewer_Viewer::VerticalGradient:
+         activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
+         break;
+       case OCCViewer_Viewer::Diagonal1Gradient:
+         activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
+         break;
+       case OCCViewer_Viewer::Diagonal2Gradient:
+         activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
+         break;
+       case OCCViewer_Viewer::Corner1Gradient:
+         activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
+         break;
+       case OCCViewer_Viewer::Corner2Gradient:
+         activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
+         break;
+       case OCCViewer_Viewer::Corner3Gradient:
+         activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
+         break;
+       case OCCViewer_Viewer::Corner4Gradient:
+         activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
+         break;
+       default:
+         break;
+       }
+#endif
       }
       break;
     }
index b4621257770aa28042ead568820e370958916f94..d59345aa78a1fefaf1b3c476426a442c45b5d153 100644 (file)
@@ -20,6 +20,7 @@
 #include "OCCViewer_ViewSketcher.h"
 #include "OCCViewer_ViewWindow.h"
 #include "OCCViewer_ViewPort3d.h"
+#include "ViewerTools_ScreenScaling.h"
 
 #include "QtxRubberBand.h"
 
@@ -122,6 +123,13 @@ bool OCCViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
 {
   OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
 
+  // We need to downscale only non-system events here
+  if (!e->spontaneous())
+  {
+    // Make a copy event with updated coordinates
+    e = ViewerTools_ScreenScaling::getDpiAwareEvent(e, false);
+  }
+
   QMouseEvent* me = (QMouseEvent*)e;
   SketchState state = EnTrain;
   bool ignore = false;
index 3a5336beeaf12e47f767a5c3a12bbfb15fda09d4..372b9145a350e7a8c5cad6968e0844d4067a689f 100644 (file)
@@ -40,6 +40,7 @@
 #include "OCCViewer_EnvTextureDlg.h"
 #include "OCCViewer_LightSourceDlg.h"
 #include "OCCViewer_Utilities.h"
+#include "ViewerTools_ScreenScaling.h"
 
 #include <SUIT_Desktop.h>
 #include <SUIT_Session.h>
@@ -373,6 +374,9 @@ OCCViewer_ViewWindow::getButtonState( QMouseEvent* theEvent, int theInteractionS
 bool OCCViewer_ViewWindow::eventFilter( QObject* watched, QEvent* e )
 {
   if ( watched == myViewPort ) {
+    // Makes a copy event with updated coordinates if we need so
+    e = ViewerTools_ScreenScaling::getDpiAwareEvent(e);
+
     int aType = e->type();
     switch(aType) {
     case QEvent::MouseButtonPress:
@@ -1080,8 +1084,10 @@ void OCCViewer_ViewWindow::vpMouseReleaseEvent(QMouseEvent* theEvent)
       emit mouseReleased(this, theEvent);
       if(theEvent->button() == Qt::RightButton && prevState == -1)
       {
+        // We need to pass unscaled coordinates to get a menu painted in a right place.
+        const double pixelRatio = ViewerTools_ScreenScaling::getPR();
         QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
-                                  theEvent->pos(), theEvent->globalPos() );
+                                  theEvent->pos() / pixelRatio, theEvent->globalPos() / pixelRatio );
         emit contextMenuRequested( &aEvent );
       }
     }
@@ -3153,6 +3159,11 @@ void OCCViewer_ViewWindow::onSketchingFinished()
   {
     Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
     bool append = mypSketcher->isHasShift();
+
+    // Sketcher uses unscaled coordinates to draw a rubber band,
+    // then we need to scale them here for proper selection.
+    const double pixelRatio = ViewerTools_ScreenScaling::getPR();
+
     switch( mypSketcher->type() )
     {
     case Rect:
@@ -3160,10 +3171,10 @@ void OCCViewer_ViewWindow::onSketchingFinished()
         QRect* aRect = (QRect*)mypSketcher->data();
         if ( aRect )
         {
-          int aLeft = aRect->left();
-          int aRight = aRect->right();
-          int aTop = aRect->top();
-          int aBottom = aRect->bottom();
+          int aLeft = aRect->left() * pixelRatio;
+          int aRight = aRect->right() * pixelRatio;
+          int aTop = aRect->top() * pixelRatio;
+          int aBottom = aRect->bottom() * pixelRatio;
 //           myRect = aRect;
 
           if( append )
@@ -3186,7 +3197,7 @@ void OCCViewer_ViewWindow::onSketchingFinished()
           for (int index = 1; it != itEnd; ++it, index++)
           {
             QPoint aPoint = *it;
-            anArray.SetValue(index, gp_Pnt2d(aPoint.x(), aPoint.y()));
+            anArray.SetValue(index, gp_Pnt2d(aPoint.x() * pixelRatio, aPoint.y() * pixelRatio));
           }
 
           if (append)
diff --git a/src/QtViewer/CMakeLists.txt b/src/QtViewer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2d688c2
--- /dev/null
@@ -0,0 +1,113 @@
+# Copyright (C) 2012-2023  CEA, EDF, OPEN CASCADE
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+INCLUDE(UseQtExt)
+
+# --- options ---
+
+# additional include directories
+INCLUDE_DIRECTORIES(
+  ${QT_INCLUDES}
+  ${PROJECT_SOURCE_DIR}/src/Qtx
+  ${PROJECT_SOURCE_DIR}/src/SUIT
+  ${PROJECT_SOURCE_DIR}/src/ImageComposer
+)
+
+# additional preprocessor / compiler flags
+ADD_DEFINITIONS(${QT_DEFINITIONS})
+
+# libraries to link to
+SET(_link_LIBRARIES ${QT_LIBRARIES} qtx suit ImageComposer)
+
+# --- headers ---
+
+# header files / to be processed by moc
+SET(_moc_HEADERS   
+  QtViewer_Scene.h
+  QtViewer_Selector.h
+  QtViewer_ViewFrame.h
+  QtViewer_ViewManager.h
+  QtViewer_ViewPort.h
+  QtViewer_Viewer.h
+)
+
+# header files / no moc processing
+SET(_other_HEADERS
+  QtViewer.h
+  QtViewer_Object.h
+  QtViewer_PainterObject.h
+)
+
+# header files / to install
+SET(QtViewer_HEADERS ${_moc_HEADERS} ${_other_HEADERS})
+
+# --- resources ---
+
+# resource files / to be processed by lrelease
+SET(_ts_RESOURCES
+  resources/QtViewer_images.ts
+  resources/QtViewer_msg_en.ts
+  resources/QtViewer_msg_fr.ts
+  resources/QtViewer_msg_ja.ts
+)
+
+# resource files / static
+SET(_other_RESOURCES
+  resources/qtviewer_cursor_zoom.png
+  resources/qtviewer_dump.png
+  resources/qtviewer_fitall.png
+  resources/qtviewer_fitarea.png
+  resources/qtviewer_fitselect.png
+  resources/qtviewer_glpan.png
+  resources/qtviewer_pan.png
+  resources/qtviewer_reset.png
+  resources/qtviewer_rotate.png
+  resources/qtviewer_zoom.png
+)
+
+# --- sources ---
+
+# sources / moc wrappings
+QT_WRAP_MOC(_moc_SOURCES ${_moc_HEADERS})
+
+# sources / static
+SET(_other_SOURCES
+  QtViewer_Object.cxx
+  QtViewer_PainterObject.cxx
+  QtViewer_Scene.cxx
+  QtViewer_Selector.cxx
+  QtViewer_ViewFrame.cxx
+  QtViewer_ViewManager.cxx
+  QtViewer_ViewPort.cxx
+  QtViewer_Viewer.cxx
+)
+
+# sources / to compile
+SET(QtViewer_SOURCES ${_other_SOURCES} ${_moc_SOURCES})
+
+# --- rules ---
+
+ADD_LIBRARY(QtViewer ${QtViewer_SOURCES})
+TARGET_LINK_LIBRARIES(QtViewer ${_link_LIBRARIES})
+INSTALL(TARGETS QtViewer EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
+
+INSTALL(FILES ${QtViewer_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
+QT_INSTALL_TS_RESOURCES("${_ts_RESOURCES}" "${SALOME_GUI_INSTALL_RES_DATA}")
+
+INSTALL(FILES ${_other_RESOURCES} DESTINATION ${SALOME_GUI_INSTALL_RES_DATA})
diff --git a/src/QtViewer/QtViewer.h b/src/QtViewer/QtViewer.h
new file mode 100644 (file)
index 0000000..b605fd4
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifdef WIN32
+
+#if defined QTVIEWER_EXPORTS || defined QtViewer_EXPORTS
+#define QTVIEWER_API __declspec(dllexport)
+#else
+#define QTVIEWER_API __declspec(dllimport)
+#endif
+
+#else
+#define QTVIEWER_API
+#endif // WIN32
+
diff --git a/src/QtViewer/QtViewer_Object.cxx b/src/QtViewer/QtViewer_Object.cxx
new file mode 100644 (file)
index 0000000..18fb3a3
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "QtViewer_Object.h"
+
+//=======================================================================
+// Name    : QtViewer_Object
+// Purpose : Constructor
+//=======================================================================
+QtViewer_Object::QtViewer_Object( QGraphicsItem* theParent ) 
+: QGraphicsItem( theParent )
+{
+}
+
+//=======================================================================
+// Name    : QtViewer_Object
+// Purpose : Destructor
+//=======================================================================
+QtViewer_Object::~QtViewer_Object()
+{
+}
diff --git a/src/QtViewer/QtViewer_Object.h b/src/QtViewer/QtViewer_Object.h
new file mode 100644 (file)
index 0000000..7e69f1a
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef QTVIEWER_OBJECT_H
+#define QTVIEWER_OBJECT_H
+
+#include "QtViewer.h"
+#include <QGraphicsItem>
+
+class SUIT_DataOwner;
+/*
+  Class       : QtViewer_Object
+  Description : Base class for all objects displayed at the scene
+*/
+class QTVIEWER_API QtViewer_Object : public QGraphicsItem
+{
+public:
+  QtViewer_Object( QGraphicsItem* theParent = nullptr );
+  ~QtViewer_Object();
+
+  const QString& getName() const { return myName; }
+  virtual void setName( const QString& theName ) { myName = theName; }
+
+  SUIT_DataOwner* owner() const { return myOwner; }
+  void setOwner( SUIT_DataOwner* owner ) { myOwner = owner; }
+
+protected:
+  SUIT_DataOwner* myOwner;
+  QString myName;
+};
+
+#endif
diff --git a/src/QtViewer/QtViewer_PainterObject.cxx b/src/QtViewer/QtViewer_PainterObject.cxx
new file mode 100644 (file)
index 0000000..aad7cbb
--- /dev/null
@@ -0,0 +1,14 @@
+#include "QtViewer_PainterObject.h"
+  
+
+QtViewer_PainterObject::QtViewer_PainterObject()
+{
+}
+
+QtViewer_PainterObject::~QtViewer_PainterObject()
+{
+}
+
+void QtViewer_PainterObject::draw(QPainter* painter)
+{
+}
diff --git a/src/QtViewer/QtViewer_PainterObject.h b/src/QtViewer/QtViewer_PainterObject.h
new file mode 100644 (file)
index 0000000..6f4a692
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef QTVIEWER_PAINTEROBJECT_H
+#define QTVIEWER_PAINTEROBJECT_H
+
+#include "QtViewer.h"
+#include <QPainter>
+
+class QTVIEWER_API QtViewer_PainterObject 
+{
+public:
+
+  QtViewer_PainterObject();
+  ~QtViewer_PainterObject();
+
+  virtual void draw(QPainter* painter); 
+};
+#endif
diff --git a/src/QtViewer/QtViewer_Scene.cxx b/src/QtViewer/QtViewer_Scene.cxx
new file mode 100644 (file)
index 0000000..29675ff
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "QtViewer_Scene.h"
+
+//=======================================================================
+// Name    : QtViewer_Scene
+// Purpose : Constructor
+//=======================================================================
+QtViewer_Scene::QtViewer_Scene( QObject* theParent )
+: QGraphicsScene( theParent )
+{
+}
+
+//=======================================================================
+// Name    : QtViewer_Scene
+// Purpose : Destructor
+//=======================================================================
+QtViewer_Scene::~QtViewer_Scene()
+{
+}
+
diff --git a/src/QtViewer/QtViewer_Scene.h b/src/QtViewer/QtViewer_Scene.h
new file mode 100644 (file)
index 0000000..47c1702
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef QTVIEWER_SCENE_H
+#define QTVIEWER_SCENE_H
+
+#include "QtViewer.h"
+#include <QGraphicsScene>
+
+class QGraphicsRectItem;
+
+/*
+  Class       : QtViewer_Scene
+  Description : Scene of the graphics view
+*/
+class QTVIEWER_API QtViewer_Scene : public QGraphicsScene
+{
+  Q_OBJECT
+
+public:
+  QtViewer_Scene( QObject* theParent = 0 );
+  ~QtViewer_Scene();
+};
+#endif
diff --git a/src/QtViewer/QtViewer_Selector.cxx b/src/QtViewer/QtViewer_Selector.cxx
new file mode 100644 (file)
index 0000000..79aa12c
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "QtViewer_Selector.h"
+#include "QtViewer_Viewer.h"
+
+//=======================================================================
+// Name    : QtViewer_Selector
+// Purpose : Constructor
+//=======================================================================
+QtViewer_Selector::QtViewer_Selector(QtViewer_Viewer* theViewer)
+: QObject( nullptr ),
+  myViewer(theViewer)
+{   
+}
+
+//=======================================================================
+// Name    : QtViewer_Selector
+// Purpose : Destructor
+//=======================================================================
+QtViewer_Selector::~QtViewer_Selector()
+{
+}
+
+//================================================================
+// Function : select
+// Purpose  : 
+//================================================================
+void QtViewer_Selector::select( const QRectF& selRect)
+{
+  emit selSelectionDone();
+}
diff --git a/src/QtViewer/QtViewer_Selector.h b/src/QtViewer/QtViewer_Selector.h
new file mode 100644 (file)
index 0000000..7720b86
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef QTVIEWER_SELECTOR_H
+#define QTVIEWER_SELECTOR_H
+
+#include "QtViewer.h"
+
+#include <QObject>
+#include <QRectF>
+
+class QtViewer_Viewer;
+
+/*
+  Class       : QtViewer_Selector
+  Description : Selector of the graphics view
+*/
+class QTVIEWER_API QtViewer_Selector : public QObject
+{
+  Q_OBJECT
+
+public:
+  QtViewer_Selector(QtViewer_Viewer*);
+  ~QtViewer_Selector();
+
+public:
+
+  virtual void  select(const QRectF&);    
+
+signals:
+  void selSelectionDone();
+
+protected:
+  QtViewer_Viewer* myViewer;
+};
+
+#endif
diff --git a/src/QtViewer/QtViewer_ViewFrame.cxx b/src/QtViewer/QtViewer_ViewFrame.cxx
new file mode 100644 (file)
index 0000000..8014160
--- /dev/null
@@ -0,0 +1,406 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "QtViewer_ViewFrame.h"
+
+#include "QtViewer_Viewer.h"
+#include "QtViewer_ViewPort.h"
+
+#include <QtxAction.h>
+#include <QtxActionToolMgr.h>
+#include <QtxMultiAction.h>
+#include <QtxToolBar.h>
+
+#include <SUIT_Desktop.h>
+#include <SUIT_MessageBox.h>
+#include <SUIT_Session.h>
+#include <SUIT_ResourceMgr.h>
+
+#include <QColor>
+#include <QFrame>
+#include <QFileDialog>
+
+#include <QWheelEvent>
+#include <QHBoxLayout>
+#include <QImage>
+#include <QMouseEvent>
+#include <QString>
+#include <QWheelEvent>
+
+//=======================================================================
+// Name    : QtViewer_ViewFrame
+// Purpose : Constructor
+//=======================================================================
+QtViewer_ViewFrame::QtViewer_ViewFrame( SUIT_Desktop* d, QtViewer_Viewer* vw, QWidget* w )
+: SUIT_ViewWindow( d ),
+  myViewer( vw )
+{
+  QFrame* aFrame = new QFrame( this );
+  setCentralWidget( aFrame );
+
+  QBoxLayout* aLayout = new QHBoxLayout( aFrame );
+  aLayout->setMargin( 0 );
+  aLayout->setSpacing( 0 );
+
+  if( w )
+    myViewPort = dynamic_cast<QtViewer_ViewPort*>(w);
+  else
+    myViewPort = new QtViewer_ViewPort( aFrame );
+
+  aLayout->addWidget( myViewPort );
+  createActions();
+  createToolBar();
+
+  connect( myViewPort, SIGNAL( vpKeyEvent( QKeyEvent* ) ),
+           this, SLOT( keyEvent( QKeyEvent* ) ) );
+  connect( myViewPort, SIGNAL( vpMouseEvent( QMouseEvent* ) ),
+           this, SLOT( mouseEvent( QMouseEvent* ) ) );
+  connect( myViewPort, SIGNAL( vpWheelEvent( QWheelEvent* ) ),
+           this, SLOT( wheelEvent( QWheelEvent* ) ) );
+  connect( myViewPort, SIGNAL( vpContextMenuEvent( QContextMenuEvent* ) ),
+           this, SLOT( contextMenuEvent( QContextMenuEvent* ) ) );
+}
+
+//=======================================================================
+// Name    : QtViewer_ViewFrame
+// Purpose : Destructor
+//=======================================================================
+QtViewer_ViewFrame::~QtViewer_ViewFrame()
+{
+}
+
+//================================================================
+// Function : createActions
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::createActions()
+{
+  SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+  QtxAction* anAction;
+
+  // Dump view
+  anAction = new QtxAction( tr( "MNU_DUMP_VIEW" ),
+                           aResMgr->loadPixmap( "QtViewer", tr( "ICON_QTV_DUMP" ) ),
+                           tr( "MNU_DUMP_VIEW" ), 0, this );
+  anAction->setStatusTip( tr( "DSC_DUMP_VIEW" ) );
+  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onDumpView() ) );
+  toolMgr()->registerAction( anAction, DumpId );
+
+  // FitAll
+  anAction = new QtxAction( tr( "MNU_FITALL" ),
+                           aResMgr->loadPixmap( "QtViewer", tr( "ICON_QTV_FITALL" ) ),
+                           tr( "MNU_FITALL" ), 0, this );
+  anAction->setStatusTip( tr( "DSC_FITALL" ) );
+  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onViewFitAll() ) );
+  toolMgr()->registerAction( anAction, FitAllId );
+
+  // FitRect
+  anAction = new QtxAction( tr( "MNU_FITRECT" ),
+                           aResMgr->loadPixmap( "QtViewer", tr( "ICON_QTV_FITAREA" ) ),
+                           tr( "MNU_FITRECT" ), 0, this );
+  anAction->setStatusTip( tr( "DSC_FITRECT" ) );
+  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onViewFitArea() ) );
+  toolMgr()->registerAction( anAction, FitRectId );
+
+  // FitSelect
+  anAction = new QtxAction( tr( "MNU_FITSELECT" ),
+                           aResMgr->loadPixmap( "QtViewer", tr( "ICON_QTV_FITSELECT" ) ),
+                           tr( "MNU_FITSELECT" ), 0, this );
+  anAction->setStatusTip( tr( "DSC_FITSELECT" ) );
+  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onViewFitSelect() ) );
+  toolMgr()->registerAction( anAction, FitSelectId );
+
+  // Zoom
+  anAction = new QtxAction( tr( "MNU_ZOOM_VIEW" ),
+                           aResMgr->loadPixmap( "QtViewer", tr( "ICON_QTV_ZOOM" ) ),
+                           tr( "MNU_ZOOM_VIEW" ), 0, this );
+  anAction->setStatusTip( tr( "DSC_ZOOM_VIEW" ) );
+  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onViewZoom() ) );
+  toolMgr()->registerAction( anAction, ZoomId );
+
+  // Panning
+  anAction = new QtxAction( tr( "MNU_PAN_VIEW" ),
+                           aResMgr->loadPixmap( "QtViewer", tr( "ICON_QTV_PAN" ) ),
+                           tr( "MNU_PAN_VIEW" ), 0, this );
+  anAction->setStatusTip( tr( "DSC_PAN_VIEW" ) );
+  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onViewPan() ) );
+  toolMgr()->registerAction( anAction, PanId );
+
+  // Global Panning
+  anAction = new QtxAction( tr( "MNU_GLOBALPAN_VIEW" ),
+                           aResMgr->loadPixmap( "QtViewer", tr( "ICON_QTV_GLOBALPAN" ) ),
+                           tr( "MNU_GLOBALPAN_VIEW" ), 0, this );
+  anAction->setStatusTip( tr( "DSC_GLOBALPAN_VIEW" ) );
+  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onViewGlobalPan() ) );
+  toolMgr()->registerAction( anAction, GlobalPanId );
+}
+
+//================================================================
+// Function : createToolBar
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::createToolBar()
+{
+  int tid = toolMgr()->createToolBar( tr("LBL_TOOLBAR_LABEL"),                 // title (language-dependant)
+                                     QString( "QtViewerViewOperations" ), // name (language-independant)
+                                     false );                                 // disable floatable toolbar
+  toolMgr()->append( DumpId, tid );
+
+  QtxMultiAction* aScaleAction = new QtxMultiAction( this );
+  aScaleAction->insertAction( toolMgr()->action( FitAllId ) );
+  aScaleAction->insertAction( toolMgr()->action( FitRectId ) );
+  aScaleAction->insertAction( toolMgr()->action( FitSelectId ) );
+  aScaleAction->insertAction( toolMgr()->action( ZoomId ) );
+  toolMgr()->append( aScaleAction, tid );
+
+  QtxMultiAction* aPanAction = new QtxMultiAction( this );
+  aPanAction->insertAction( toolMgr()->action( PanId ) );
+  aPanAction->insertAction( toolMgr()->action( GlobalPanId ) );
+  toolMgr()->append( aPanAction, tid );
+
+  toolMgr()->append( toolMgr()->action( ResetId ), tid );
+}
+
+//================================================================
+// Function : dumpView
+// Purpose  : 
+//================================================================
+QImage QtViewer_ViewFrame::dumpView()
+{
+  return myViewPort->dumpView();
+}
+
+//================================================================
+// Function : dumpViewToFormat
+// Purpose  : 
+//================================================================
+bool QtViewer_ViewFrame::dumpViewToFormat( const QImage& image, const QString& fileName, const QString& format )
+{
+  bool isOK = myViewPort->dumpViewToFormat(fileName, format);
+  if( !isOK )
+    isOK = SUIT_ViewWindow::dumpViewToFormat( image, fileName, format );
+  return isOK;
+}
+
+//================================================================
+// Function : getVisualParameters
+// Purpose  : 
+//================================================================
+QString QtViewer_ViewFrame::getVisualParameters()
+{
+  QTransform aTransform = myViewPort->transform();
+
+  QString aString;
+  aString.asprintf( "%.3f*%.3f*%.3f*%.3f*%.3f*%.3f*%.3f*%.3f*%.3f",
+    aTransform.m11(), aTransform.m12(), aTransform.m13(),
+    aTransform.m21(), aTransform.m22(), aTransform.m23(),
+    aTransform.m31(), aTransform.m32(), aTransform.m33() );
+  return aString;
+}
+
+//================================================================
+// Function : setVisualParameters
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::setVisualParameters( const QString& theParameters )
+{
+  QStringList aList = theParameters.split( '*' );
+  if( aList.size() < 9 )
+    return;
+
+  bool anIsOk[9];
+  QTransform aTransform( aList[0].toDouble( &anIsOk[0] ),
+                         aList[1].toDouble( &anIsOk[1] ),
+                         aList[2].toDouble( &anIsOk[2] ),
+                         aList[3].toDouble( &anIsOk[3] ),
+                         aList[4].toDouble( &anIsOk[4] ),
+                         aList[5].toDouble( &anIsOk[5] ),
+                         aList[6].toDouble( &anIsOk[6] ),
+                         aList[7].toDouble( &anIsOk[7] ),
+                         aList[8].toDouble( &anIsOk[8] ) );
+  for( int i = 0; i < 9; i++ )
+    if( !anIsOk[ i ] )
+      return;
+
+  myViewPort->setTransform(aTransform);
+}
+
+//================================================================
+// Function : onViewPan
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::onViewPan()
+{
+  myViewer->pan();
+}
+
+//================================================================
+// Function : onViewZoom
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::onViewZoom()
+{
+  myViewer->zoom();
+}
+
+//================================================================
+// Function : onViewFitAll
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::onViewFitAll()
+{
+    myViewer->fitAll();
+}
+
+//================================================================
+// Function : onViewFitArea
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::onViewFitArea()
+{
+    myViewer->fitArea();
+}
+
+//================================================================
+// Function : onViewFitSelect
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::onViewFitSelect()
+{
+    myViewer->fitSelect();
+}
+
+//================================================================
+// Function : onViewGlobalPan
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::onViewGlobalPan()
+{
+  myViewer->globalPan();
+}
+
+//================================================================
+// Function : onViewReset
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::onViewReset()
+{
+}
+
+//================================================================
+// Function : keyEvent
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::keyEvent( QKeyEvent* e )
+{
+  switch ( e->type() )
+  {
+    case QEvent::KeyPress:
+      emit keyPressed( e );
+      break;
+    case QEvent::KeyRelease:
+      emit keyReleased( e );
+      break;
+    default:
+      break;
+  }
+}
+
+//================================================================
+// Function : mouseEvent
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::mouseEvent( QMouseEvent* e )
+{
+  switch ( e->type() )
+  {
+    case QEvent::MouseButtonPress:
+      emit mousePressed( e );
+      break;
+    case QEvent::MouseMove:
+      emit mouseMoving( e );
+      break;
+    case QEvent::MouseButtonRelease:
+      emit mouseReleased( e );
+      break;
+    case QEvent::MouseButtonDblClick:
+      emit mouseDoubleClicked( e );
+      break;
+    default:
+      break;
+  }
+}
+//================================================================
+// Function : wheelEvent
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::wheelEvent( QWheelEvent* e )
+{
+  switch ( e->type() )
+  {
+    case QEvent::Wheel:
+      emit wheeling( e );
+      break;
+    default:
+      break;
+  }
+}
+
+//================================================================
+// Function : contextMenuEvent
+// Purpose  : 
+//================================================================
+void QtViewer_ViewFrame::contextMenuEvent( QContextMenuEvent* e )
+{
+  emit contextMenuRequested(e);
+}
+
+/*!
+  \brief Handle show event.
+
+  Emits Show() signal.
+
+  \param theEvent show event
+*/
+void QtViewer_ViewFrame::showEvent( QShowEvent* theEvent )
+{
+  emit Show( theEvent );
+}
+
+/*!
+  \brief Handle hide event.
+
+  Emits Hide() signal.
+
+  \param theEvent hide event
+*/
+void QtViewer_ViewFrame::hideEvent( QHideEvent* theEvent )
+{
+  emit Hide( theEvent );
+}
+
+/*!
+  \return filters for image files
+*/
+QString QtViewer_ViewFrame::filter() const
+{
+  QStringList filters = SUIT_ViewWindow::filter().split( ";;", QString::SkipEmptyParts );
+  filters << tr("POSTSCRIPT_FILES");
+  return filters.join( ";;" );
+}
diff --git a/src/QtViewer/QtViewer_ViewFrame.h b/src/QtViewer/QtViewer_ViewFrame.h
new file mode 100644 (file)
index 0000000..7367742
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef QTVIEWER_VIEWFRAME_H
+#define QTVIEWER_VIEWFRAME_H
+
+#include "QtViewer.h"
+
+#include <SUIT_ViewWindow.h>
+#include <QPainterPath>
+
+class QContextMenuEvent;
+
+class QAction;
+
+class SUIT_Desktop;
+
+class QtViewer_Viewer;
+class QtViewer_ViewPort;
+
+/*
+  Class       : QtViewer_ViewFrame
+  Description : View frame of the graphics view
+*/
+class QTVIEWER_API QtViewer_ViewFrame : public SUIT_ViewWindow
+{
+  Q_OBJECT
+
+public:
+  enum { DumpId, FitAllId, FitRectId, FitSelectId, ZoomId, PanId, GlobalPanId, ResetId };
+
+public:
+  QtViewer_ViewFrame( SUIT_Desktop*, QtViewer_Viewer*, QWidget* w = nullptr );
+  ~QtViewer_ViewFrame();
+
+  QtViewer_Viewer*    getViewer() const { return myViewer; }
+  QtViewer_ViewPort*  getViewPort() const  { return myViewPort; }
+
+  virtual QImage          dumpView();
+  
+  virtual QString         getVisualParameters();
+  virtual void            setVisualParameters( const QString& theParameters );
+
+public slots:
+  virtual void showEvent( QShowEvent* );
+  virtual void hideEvent( QHideEvent* );
+
+protected slots:
+  void                    onViewPan();
+  void                    onViewZoom();
+  void                    onViewFitAll();
+  void                    onViewFitArea();
+  void                    onViewFitSelect();
+  void                    onViewGlobalPan();
+  void                    onViewReset();
+
+private slots:
+  void                    keyEvent( QKeyEvent* );
+  void                    mouseEvent( QMouseEvent* );
+  void                    wheelEvent( QWheelEvent* );
+  void                    contextMenuEvent( QContextMenuEvent* );
+
+signals:
+  void                    keyPressed( QKeyEvent* );
+  void                    keyReleased( QKeyEvent* );
+  void                    mousePressed( QMouseEvent* );
+  void                    mouseMoving( QMouseEvent* );
+  void                    mouseReleased( QMouseEvent* );
+  void                    mouseDoubleClicked( QMouseEvent* );
+  void                    wheeling( QWheelEvent* );
+
+  void                    sketchingFinished( QPainterPath );
+
+  void Show( QShowEvent* );
+  void Hide( QHideEvent* );
+
+protected:
+  virtual void            createActions();
+  virtual void            createToolBar();
+  virtual QString         filter() const;
+  virtual bool            dumpViewToFormat( const QImage&, const QString& fileName, const QString& format );
+
+private:
+  QtViewer_Viewer*    myViewer;
+  QtViewer_ViewPort*  myViewPort;
+};
+
+#endif
diff --git a/src/QtViewer/QtViewer_ViewManager.cxx b/src/QtViewer/QtViewer_ViewManager.cxx
new file mode 100644 (file)
index 0000000..bd5c0dd
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "QtViewer_ViewManager.h"
+#include "QtViewer_Viewer.h"
+
+//=======================================================================
+// Name    : QtViewer_ViewManager
+// Purpose : Constructor
+//=======================================================================
+QtViewer_ViewManager::QtViewer_ViewManager( SUIT_Study* theStudy,
+                                                    SUIT_Desktop* theDesktop,
+                                                    SUIT_ViewModel* theModel )
+: SUIT_ViewManager( theStudy, theDesktop, 
+    theModel ? theModel : new QtViewer_Viewer("QtViewer") )
+{
+  setTitle( tr( "QTVIEWER_TITLE" ) );
+}
+
+//=======================================================================
+// Name    : QtViewer_ViewManager
+// Purpose : Destructor
+//=======================================================================
+QtViewer_ViewManager::~QtViewer_ViewManager()
+{
+}
+
+//================================================================
+// Function : getViewer
+// Purpose  : 
+//================================================================
+QtViewer_Viewer* QtViewer_ViewManager::getViewer()
+{
+  return dynamic_cast<QtViewer_Viewer*>( getViewModel() );
+}
diff --git a/src/QtViewer/QtViewer_ViewManager.h b/src/QtViewer/QtViewer_ViewManager.h
new file mode 100644 (file)
index 0000000..b7cd022
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef QTVIEWER_VIEWMANAGER_H
+#define QTVIEWER_VIEWMANAGER_H
+
+#include "QtViewer.h"
+#include <SUIT_ViewManager.h>
+
+class QtViewer_Viewer;
+
+/*
+  Class       : QtViewer_ViewManager
+  Description : View manager of the graphics view
+*/
+class QTVIEWER_API QtViewer_ViewManager : public SUIT_ViewManager
+{
+  Q_OBJECT
+
+public:
+  QtViewer_ViewManager( SUIT_Study* theStudy,
+                            SUIT_Desktop* theDesktop,
+                            SUIT_ViewModel* theModel = 0 );
+  virtual ~QtViewer_ViewManager();
+
+  QtViewer_Viewer* getViewer();
+};
+#endif
diff --git a/src/QtViewer/QtViewer_ViewPort.cxx b/src/QtViewer/QtViewer_ViewPort.cxx
new file mode 100644 (file)
index 0000000..44402b4
--- /dev/null
@@ -0,0 +1,396 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "QtViewer_ViewPort.h"
+#include "QtViewer_Scene.h"
+#include <QGraphicsItem>
+#include <QRubberBand>
+#include <QMouseEvent>
+#include <QCursor>
+#include <QScrollBar>
+#include <QPainter>
+#include <QPrinter>
+
+#include "SUIT_ResourceMgr.h"
+#include "SUIT_Session.h"
+
+#include "QtViewer_PainterObject.h"
+
+//=======================================================================
+// Name    : QtViewer_ViewPort
+// Purpose : Constructor
+//=======================================================================
+QtViewer_ViewPort::QtViewer_ViewPort( QWidget* theParent )
+: QGraphicsView( theParent )
+{
+  setScene(new QtViewer_Scene(this));
+
+  setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+  setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+  
+  setMouseTracking( true );
+  setFocusPolicy( Qt::StrongFocus );
+
+  myFitAllGap = 40;
+
+  myRectBand = nullptr;
+  myRectBandStart = QPoint();
+  myRectBandEnd = QPoint();
+  fittingArea = false;
+
+  zooming = false;
+  previousPos = QPoint();
+
+  panning = false;
+  globalPanning = false;
+  
+  SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
+  zoomCursor = new QCursor( rmgr->loadPixmap( "QtViewer", tr( "ICON_QTV_CURSOR_ZOOM" ) ) );
+}
+
+//=======================================================================
+// Name    : QtViewer_ViewPort
+// Purpose : Destructor
+//=======================================================================
+QtViewer_ViewPort::~QtViewer_ViewPort()
+{
+  delete zoomCursor;
+  zoomCursor = nullptr;
+}
+
+void QtViewer_ViewPort::resetForeground()
+{
+  for (QSharedPointer<QtViewer_PainterObject> obj : foregroundObjects)
+    obj.reset();
+
+  foregroundObjects.clear();
+}
+
+void QtViewer_ViewPort::drawForeground(QPainter *painter, const QRectF &rect)
+{
+  Q_UNUSED(rect);
+
+  for (QSharedPointer<QtViewer_PainterObject> obj : foregroundObjects)
+    obj->draw(painter);
+}
+
+void QtViewer_ViewPort::addItem( QGraphicsItem* theItem )
+{
+  scene()->addItem(theItem);
+}
+
+void QtViewer_ViewPort::fitAll()
+{
+  QRectF aRect;
+  foreach (QGraphicsItem* item, scene()->items())
+    { 
+      if (item->isVisible())
+        aRect = aRect.united(item->boundingRect());
+    }
+  fitInView( aRect.adjusted(-myFitAllGap, -myFitAllGap, myFitAllGap, myFitAllGap), Qt::KeepAspectRatio);
+}
+
+void QtViewer_ViewPort::fitSelect() 
+{
+  if (scene()->selectedItems().isEmpty())
+      return;
+
+  QRectF selectionRect;
+  foreach (QGraphicsItem *item, scene()->selectedItems()) 
+    selectionRect = selectionRect.united(item->sceneBoundingRect());
+
+  if(!selectionRect.isNull())
+    fitInView(selectionRect.adjusted(-myFitAllGap, -myFitAllGap, myFitAllGap, myFitAllGap), Qt::KeepAspectRatio); 
+}
+
+void QtViewer_ViewPort::fitRect(const QRectF& theRect)
+{
+  fitInView(theRect, Qt::KeepAspectRatio);
+}
+
+QRect QtViewer_ViewPort::selectionRect()
+{
+  if (myRectBand)
+    {
+      QRect aRect;
+      aRect.setLeft(qMin( myRectBandStart.x(), myRectBandEnd.x()));
+      aRect.setTop(qMin( myRectBandStart.y(), myRectBandEnd.y()));
+      aRect.setRight(qMax( myRectBandStart.x(), myRectBandEnd.x()));
+      aRect.setBottom(qMax( myRectBandStart.y(), myRectBandEnd.y()));
+      return aRect;
+    }
+  return QRect();
+}
+
+void QtViewer_ViewPort::startDrawingRect( int x, int y )
+{
+  myRectBandStart = QPoint(x,y);
+
+  if (!myRectBand) 
+    {
+      myRectBand = new QRubberBand(QRubberBand::Rectangle, this);
+      myRectBand->setGeometry(QRect(myRectBandStart, QSize()));
+      myRectBand->show();
+    }
+}
+
+void QtViewer_ViewPort::drawingRect( int x, int y )
+{
+  myRectBandEnd = QPoint(x,y);
+  myRectBand->setGeometry(QRect(myRectBandStart, myRectBandEnd).normalized());
+}
+
+void QtViewer_ViewPort::finishDrawingRect()
+{
+  myRectBand->hide();
+
+  QRectF selectionRect = mapToScene(myRectBand->geometry()).boundingRect();
+
+  if (fittingArea)
+    fitInView(selectionRect, Qt::KeepAspectRatio);
+  else
+    {
+      QList<QGraphicsItem *> selectedItems = scene()->items(selectionRect, Qt::IntersectsItemShape);
+      for (QGraphicsItem *item : selectedItems) 
+        item->setSelected(true);
+    }
+  
+  myRectBandStart = QPoint();
+  myRectBandEnd = QPoint();
+  delete myRectBand;
+  myRectBand = nullptr;
+}
+
+void QtViewer_ViewPort::updateSceneRect(const QRectF &rect)
+{
+}
+
+void QtViewer_ViewPort::mousePressEvent(QMouseEvent *event)
+{ 
+  if (!zooming && !panning && !globalPanning && items(event->pos()).count()==0 && (event->buttons() & Qt::LeftButton))
+    {
+      startDrawingRect(event->pos().x(), event->pos().y());
+    }
+
+  if (globalPanning)
+    {
+      QPoint p0 = viewport()->rect().center();
+      QPoint p1 = event->pos();
+      double deltaX = p0.x() - p1.x();
+      double deltaY = p0.y() - p1.y();
+
+      pan(deltaX, -deltaY);
+    }
+  QGraphicsView::mousePressEvent(event);
+  emit vpMouseEvent(event);
+}
+
+
+void QtViewer_ViewPort::mouseMoveEvent(QMouseEvent *event)
+{    
+  if ((event->modifiers() & Qt::ShiftModifier) && (event->buttons() & Qt::LeftButton))
+    activateZoomAction();
+
+  if (event->buttons() & Qt::MiddleButton)
+    activatePanAction();
+    
+  if (panning && event->buttons() & (Qt::LeftButton | Qt::MiddleButton))
+    {
+    QPoint currentPos = event->pos();
+
+    if (!previousPos.isNull())
+    {
+      double deltaX = currentPos.x() - previousPos.x();
+      double deltaY = currentPos.y() - previousPos.y();
+
+      pan(deltaX, -deltaY);
+
+    }
+    previousPos = currentPos;  
+    viewport()->update();
+    }
+  else if (zooming && (event->buttons() & Qt::LeftButton))
+  {
+    QPoint currentPos = event->pos();
+    if (!previousPos.isNull())
+    {
+      int deltaX = currentPos.x() - previousPos.x();
+      double scaleFactor = deltaX>0 ? 1.1 : 0.9;
+      scale(scaleFactor, scaleFactor);
+    }
+    previousPos = currentPos;
+  }
+  else if (myRectBand)
+    drawingRect(event->pos().x(), event->pos().y());
+
+  QGraphicsView::mouseMoveEvent(event);
+  emit vpMouseEvent(event);
+}
+
+void QtViewer_ViewPort::mouseReleaseEvent(QMouseEvent *event)
+{
+  if (myRectBand)
+    finishDrawingRect(); 
+
+  clearActions();
+  QGraphicsView::mouseReleaseEvent(event);
+  emit vpMouseEvent(event);
+}
+
+void QtViewer_ViewPort::resizeEvent(QResizeEvent *event)
+{
+  QSize oldSize = event->oldSize();
+  QSize newSize = event->size();
+
+  qreal w = static_cast<qreal>(newSize.width());
+  qreal h = static_cast<qreal>(newSize.height());
+
+  qreal w0 = static_cast<qreal>(oldSize.width());
+  qreal h0 = static_cast<qreal>(oldSize.height());
+
+  qreal widthRatio = w/w0;
+  qreal heightRatio = h/h0;
+   
+  if (widthRatio>0 && heightRatio>0)
+    {
+      qreal scaleFactor = w<h ? widthRatio : heightRatio;
+      scale(scaleFactor, scaleFactor);
+    }
+
+  QGraphicsView::resizeEvent(event);
+}
+
+void QtViewer_ViewPort::wheelEvent(QWheelEvent *event)
+{
+  int delta = event->angleDelta().y();
+  double scaleFactor = delta>0 ? 1.1 : 0.9;
+  scale(scaleFactor, scaleFactor);
+}
+
+void QtViewer_ViewPort::keyPressEvent(QKeyEvent *event)
+{
+  if (event->key() == Qt::Key_Escape)
+    clearActions();
+
+  QGraphicsView::keyPressEvent(event);
+}
+
+void QtViewer_ViewPort::clearActions()
+{
+  setCursor(Qt::ArrowCursor);
+  fittingArea = false;
+  zooming = false;
+  panning  = false;
+  globalPanning = false;
+  previousPos = QPoint();
+}
+  
+void QtViewer_ViewPort::activateZoomAction() 
+{ 
+  zooming = true;
+  fittingArea = false;
+  panning  = false;
+  globalPanning = false;
+  setCursor(*zoomCursor); 
+}
+
+void QtViewer_ViewPort::activateFitAreaAction() 
+{ 
+  fittingArea = true;
+  zooming = false;
+  panning  = false;
+  globalPanning = false;
+  setCursor(Qt::PointingHandCursor);
+}
+
+void QtViewer_ViewPort::activatePanAction() 
+{
+  panning = true; 
+  fittingArea = false;
+  zooming = false;
+  globalPanning = false;
+  setCursor(Qt::SizeAllCursor);
+  viewport()->update();
+}
+
+void QtViewer_ViewPort::activateGlobalPanAction() 
+{
+  globalPanning = true;
+  panning = false; 
+  fittingArea = false;
+  zooming = false;
+  setCursor(Qt::CrossCursor);
+}
+
+void QtViewer_ViewPort::pan( double theDX, double theDY )
+{
+  if( QScrollBar* aHBar = horizontalScrollBar() )
+  {
+      int aNewValue = aHBar->value() - theDX;
+      if( aNewValue < aHBar->minimum() )
+        aHBar->setMinimum( aNewValue );
+      if( aNewValue > aHBar->maximum() )
+        aHBar->setMaximum( aNewValue );
+    
+      aHBar->setValue( aHBar->value() - theDX );
+  }
+  if( QScrollBar* aVBar = verticalScrollBar() )
+  {
+      int aNewValue = aVBar->value() + theDY;
+      if( aNewValue < aVBar->minimum() )
+        aVBar->setMinimum( aNewValue );
+      if( aNewValue > aVBar->maximum() )
+        aVBar->setMaximum( aNewValue );
+    aVBar->setValue( aVBar->value() + theDY );
+  }
+}
+
+//================================================================
+// Function : dumpView
+// Purpose  : 
+//================================================================
+QImage QtViewer_ViewPort::dumpView( bool theWholeScene,
+                                        QSizeF theSize )
+{
+   QPixmap screenshot = viewport()->grab();
+   return screenshot.toImage();
+}
+
+bool QtViewer_ViewPort::dumpViewToFormat(const QString& fileName, const QString& format)
+{
+  if( format!="PS" && format!="EPS" )
+    return false;
+
+  QPrinter printer(QPrinter::ScreenResolution);
+  printer.setOutputFormat(QPrinter::NativeFormat); 
+  printer.setOutputFileName(fileName); 
+
+  QPainter painter;
+  if (!painter.begin(&printer))
+    return false;
+
+  render(&painter);
+  if (!painter.end())
+    return false;
+
+  return true;
+} 
diff --git a/src/QtViewer/QtViewer_ViewPort.h b/src/QtViewer/QtViewer_ViewPort.h
new file mode 100644 (file)
index 0000000..2749f9d
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef QTVIEWER_VIEWPORT_H
+#define QTVIEWER_VIEWPORT_H
+
+#include "QtViewer.h"
+#include <QGraphicsView>
+
+class QtViewer_PainterObject;
+class QRubberBand;
+
+/*
+  Class       : QtViewer_ViewPort
+  Description : View port of the graphics view
+*/
+class QTVIEWER_API QtViewer_ViewPort : public QGraphicsView
+{
+  Q_OBJECT
+
+public:
+  QtViewer_ViewPort(QWidget* theParent);
+  ~QtViewer_ViewPort();
+
+  void addItem(QGraphicsItem* theItem);
+
+  void fitAll();
+  void fitSelect();
+  void fitRect(const QRectF& theRect);
+  void pan(double theDX, double theDY);
+
+  // rectangle selection
+  void startDrawingRect(int x, int y);
+  void drawingRect(int x, int y);
+  void finishDrawingRect();
+  QRect selectionRect();
+
+  void activateZoomAction();
+  void activateFitAreaAction(); 
+  void activatePanAction(); 
+  void activateGlobalPanAction();
+
+  QImage dumpView(bool theWholeScene = false, QSizeF theSize = QSizeF());
+  bool dumpViewToFormat(const QString& fileName, const QString& format);
+
+  void addForegroundObject( QSharedPointer<QtViewer_PainterObject> obj) { foregroundObjects.append(obj); }
+  void resetForeground();
+
+signals:
+  void vpMouseEvent(QMouseEvent*);
+
+
+public slots:
+   virtual void updateSceneRect(const QRectF &rect);
+
+protected:
+
+  virtual void mousePressEvent(QMouseEvent *event);
+  virtual void mouseMoveEvent(QMouseEvent *event);
+  virtual void mouseReleaseEvent(QMouseEvent *event);
+  virtual void resizeEvent(QResizeEvent *event);
+  virtual void wheelEvent(QWheelEvent *event);
+  virtual void keyPressEvent(QKeyEvent *event);
+
+  virtual void drawForeground(QPainter *painter, const QRectF &rect);
+
+  void clearActions();
+private:
+
+  double myFitAllGap;
+  QRubberBand* myRectBand;
+  QPoint myRectBandStart;
+  QPoint myRectBandEnd;
+
+  bool fittingArea;
+  bool zooming;
+  bool panning;
+  bool globalPanning;
+  QPoint previousPos;
+  QCursor* zoomCursor;
+
+  QList<QSharedPointer<QtViewer_PainterObject> > foregroundObjects;
+};
+
+#endif
diff --git a/src/QtViewer/QtViewer_Viewer.cxx b/src/QtViewer/QtViewer_Viewer.cxx
new file mode 100644 (file)
index 0000000..bf5db2e
--- /dev/null
@@ -0,0 +1,336 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "QtViewer_Viewer.h"
+
+#include "QtViewer_Selector.h"
+#include "QtViewer_Scene.h"
+#include "QtViewer_ViewFrame.h"
+#include "QtViewer_ViewPort.h"
+
+#include <SUIT_ViewManager.h>
+
+#include <QColorDialog>
+#include <QWheelEvent>
+#include <QKeyEvent>
+#include <QMenu>
+
+
+//=======================================================================
+// Name    : QtViewer_Viewer
+// Purpose : Constructor
+//=======================================================================
+QtViewer_Viewer::QtViewer_Viewer( const QString& /*title*/, QWidget* widget )
+: SUIT_ViewModel(),
+  mySelector( 0 ),
+  myWidget( widget )
+{
+}
+
+//=======================================================================
+// Name    : QtViewer_Viewer
+// Purpose : Destructor
+//=======================================================================
+QtViewer_Viewer::~QtViewer_Viewer()
+{
+  delete mySelector;
+}
+
+QtViewer_ViewFrame* QtViewer_Viewer::createViewFrame( SUIT_Desktop* theDesktop, QWidget* theWidget )
+{
+  return new QtViewer_ViewFrame( theDesktop, this, theWidget );
+}
+
+//================================================================
+// Function : createView
+// Purpose  : 
+//================================================================
+SUIT_ViewWindow* QtViewer_Viewer::createView( SUIT_Desktop* theDesktop )
+{
+  QtViewer_ViewFrame* aViewFrame = createViewFrame( theDesktop, myWidget );
+
+  connect( aViewFrame, SIGNAL( keyPressed( QKeyEvent* ) ),
+           this, SLOT( onKeyEvent( QKeyEvent* ) ) );
+
+  connect( aViewFrame, SIGNAL( keyReleased( QKeyEvent* ) ),
+           this, SLOT( onKeyEvent( QKeyEvent* ) ) );
+
+  connect( aViewFrame, SIGNAL( mousePressed( QMouseEvent* ) ),
+           this, SLOT( onMouseEvent( QMouseEvent* ) ) );
+
+  connect( aViewFrame, SIGNAL( mouseMoving( QMouseEvent* ) ),
+           this, SLOT( onMouseEvent( QMouseEvent* ) ) );
+
+  connect( aViewFrame, SIGNAL( mouseReleased( QMouseEvent* ) ),
+           this, SLOT( onMouseEvent( QMouseEvent* ) ) );
+  return aViewFrame;
+}
+
+//================================================================
+// Function : contextMenuPopup
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::contextMenuPopup( QMenu* thePopup )
+{
+  if( thePopup->actions().count() > 0 )
+    thePopup->addSeparator();
+
+  thePopup->addAction(tr("CHANGE_BGCOLOR"), this, SLOT(onChangeBgColor()));
+}
+
+//================================================================
+// Function : getSelector
+// Purpose  : 
+//================================================================
+QtViewer_Selector* QtViewer_Viewer::getSelector()
+{
+  if( !mySelector )
+  {
+    mySelector = new QtViewer_Selector( this );
+    if( mySelector )
+      connect( mySelector, SIGNAL(selSelectionDone()), this, SLOT( onSelectionDone()));
+  }
+  return mySelector;
+}
+
+//================================================================
+// Function : getActiveView
+// Purpose  : 
+//================================================================
+QtViewer_ViewFrame* QtViewer_Viewer::getActiveView() const
+{
+  if( SUIT_ViewManager* aViewManager = getViewManager() )
+    return dynamic_cast<QtViewer_ViewFrame*>( aViewManager->getActiveView() );
+  return nullptr;
+}
+
+//================================================================
+// Function : getActiveViewPort
+// Purpose  : 
+//================================================================
+QtViewer_ViewPort* QtViewer_Viewer::getActiveViewPort() const
+{
+  if( QtViewer_ViewFrame* aViewFrame = getActiveView() )
+    return aViewFrame->getViewPort();
+  return nullptr;
+}
+
+//================================================================
+// Function : getActiveScene
+// Purpose  : 
+//================================================================
+QtViewer_Scene* QtViewer_Viewer::getActiveScene() const
+{
+  if( QtViewer_ViewPort* aViewPort = getActiveViewPort() )
+    return dynamic_cast<QtViewer_Scene*>( aViewPort->scene() );
+  return nullptr;
+}
+
+//================================================================
+// Function : onKeyEvent
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::onKeyEvent( QKeyEvent* e )
+{
+  switch( e->type() )
+  {
+    case QEvent::KeyPress:
+      handleKeyPress( e );
+      break;
+    case QEvent::KeyRelease:
+      handleKeyRelease( e );
+      break;
+    default: break;
+  }
+}
+
+//================================================================
+// Function : onMouseEvent
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::onMouseEvent(QMouseEvent* e)
+{
+  switch( e->type() )
+  {
+    case QEvent::MouseButtonPress:
+      handleMousePress(e);
+      break;
+    case QEvent::MouseMove:
+      handleMouseMove(e);
+      break;
+    case QEvent::MouseButtonRelease:
+      handleMouseRelease(e);
+      break;
+    default: break;
+  }
+}
+//================================================================
+// Function : onWheelEvent
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::onWheelEvent(QWheelEvent* e)
+{
+  switch(e->type())
+  {
+    case QEvent::Wheel:
+      handleWheel(e);
+      break;
+    default: break;
+  }
+}
+
+//================================================================
+// Function : handleKeyPress
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::handleKeyPress( QKeyEvent* e )
+{ 
+  Q_UNUSED(e);
+}
+
+//================================================================
+// Function : handleKeyRelease
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::handleKeyRelease(QKeyEvent* e)
+{
+  Q_UNUSED(e);
+}
+
+//================================================================
+// Function : handleMousePress
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::handleMousePress(QMouseEvent* e)
+{
+  Q_UNUSED(e);
+}
+
+void QtViewer_Viewer::handleWheel(QWheelEvent* e)
+{
+  Q_UNUSED(e);
+}
+
+//================================================================
+// Function : handleMouseMove
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::handleMouseMove(QMouseEvent* e)
+{
+  Q_UNUSED(e);
+}
+
+//================================================================
+// Function : handleMouseRelease
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::handleMouseRelease(QMouseEvent* e)
+{
+  QtViewer_ViewPort* aViewPort = getActiveViewPort();
+  if ( getSelector() )
+    getSelector()->select(aViewPort->selectionRect());
+}
+
+//================================================================
+// Function : onChangeBgColor
+// Purpose  : 
+//================================================================
+
+void QtViewer_Viewer::onChangeBgColor()
+{
+  if( QtViewer_ViewPort* aViewPort = getActiveViewPort() )
+  {
+    QColor aColor = QColorDialog::getColor( aColor, aViewPort );
+
+    if (aColor.isValid())
+      aViewPort->setBackgroundBrush(QBrush(aColor));
+ }
+}
+
+//================================================================
+// Function : onSelectionDone
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::onSelectionDone()
+{
+  emit selectionChanged();
+}
+
+//================================================================
+// Function : fitAll 
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::fitAll()
+{
+  if (QtViewer_ViewPort* aViewPort = getActiveViewPort())
+    aViewPort->fitAll();
+}
+
+//================================================================
+// Function : fitSelect
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::fitSelect()
+{
+  if (QtViewer_ViewPort* aViewPort = getActiveViewPort())
+    aViewPort->fitSelect();
+}
+
+//================================================================
+// Function : fitArea
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::fitArea()
+{
+  if (QtViewer_ViewPort* aViewPort = getActiveViewPort())
+    aViewPort->activateFitAreaAction();
+}
+
+//================================================================
+// Function : zoom
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::zoom()
+{
+  if (QtViewer_ViewPort* aViewPort = getActiveViewPort())
+    aViewPort->activateZoomAction();
+}
+
+//================================================================
+// Function : pan 
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::pan()
+{
+  if (QtViewer_ViewPort* aViewPort = getActiveViewPort())
+    aViewPort->activatePanAction();
+}
+
+//================================================================
+// Function : globalPan 
+// Purpose  : 
+//================================================================
+void QtViewer_Viewer::globalPan()
+{
+  if (QtViewer_ViewPort* aViewPort = getActiveViewPort())
+    {
+      aViewPort->fitAll();
+      aViewPort->activateGlobalPanAction();
+    }
+}
diff --git a/src/QtViewer/QtViewer_Viewer.h b/src/QtViewer/QtViewer_Viewer.h
new file mode 100644 (file)
index 0000000..71c41a4
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright (C) 2013-2023  CEA, EDF, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef QTVIEWER_VIEWER_H
+#define QTVIEWER_VIEWER_H
+
+#include "QtViewer.h"
+#include <SUIT_ViewModel.h>
+
+class QKeyEvent;
+class QMouseEvent;
+class QWheelEvent;
+
+class SUIT_ViewWindow;
+
+class QtViewer_Selector;
+class QtViewer_Scene;
+class QtViewer_ViewFrame;
+class QtViewer_ViewPort;
+
+/*
+  Class       : QtViewer_Viewer
+  Description : View model of the graphics view
+*/
+class QTVIEWER_API QtViewer_Viewer: public SUIT_ViewModel
+{
+  Q_OBJECT
+
+public:
+  QtViewer_Viewer(const QString& title, QWidget* widget = nullptr);
+  ~QtViewer_Viewer();
+
+public:
+  virtual SUIT_ViewWindow*      createView(SUIT_Desktop*);
+
+  virtual QString getType() const { return Type(); }
+  static QString Type() { return "QtViewer"; }
+
+  virtual void contextMenuPopup(QMenu*);
+
+public:
+  QtViewer_Selector* getSelector();
+
+  QtViewer_ViewFrame* getActiveView() const;
+  QtViewer_ViewPort* getActiveViewPort() const;
+  QtViewer_Scene* getActiveScene() const;
+
+  void fitAll();
+  void fitSelect();
+  void fitArea();
+  void zoom();
+  void pan();
+  void globalPan();
+
+signals:
+  void selectionChanged();
+
+protected:
+
+  virtual QtViewer_ViewFrame* createViewFrame(SUIT_Desktop* theDesktop, QWidget* theWidget);
+
+protected slots:
+  virtual void onKeyEvent(QKeyEvent*);
+  virtual void onMouseEvent(QMouseEvent*);
+  virtual void onWheelEvent(QWheelEvent*);
+
+  virtual void onSelectionDone();
+  virtual void onChangeBgColor();
+
+protected:
+  virtual void handleKeyPress(QKeyEvent*);
+  virtual void handleKeyRelease(QKeyEvent*);
+  virtual void handleMouseMove(QMouseEvent*);
+  virtual void handleMousePress(QMouseEvent*);
+  virtual void handleMouseRelease(QMouseEvent*);
+  virtual void handleWheel(QWheelEvent*);
+
+protected:
+  QtViewer_Selector*        mySelector;
+  QWidget*                      myWidget;
+};
+
+#endif
diff --git a/src/QtViewer/resources/QtViewer_images.ts b/src/QtViewer/resources/QtViewer_images.ts
new file mode 100644 (file)
index 0000000..b52e211
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE TS><TS>
+<context>
+    <name>QtViewer_ViewFrame</name>
+    <message>
+        <source>ICON_QTV_DUMP</source>
+        <translation>qtviewer_dump.png</translation>
+    </message>
+    <message>
+        <source>ICON_QTV_ZOOM</source>
+        <translation>qtviewer_zoom.png</translation>
+    </message>
+    <message>
+        <source>ICON_QTV_PAN</source>
+        <translation>qtviewer_pan.png</translation>
+    </message>
+    <message>
+        <source>ICON_QTV_GLOBALPAN</source>
+        <translation>qtviewer_glpan.png</translation>
+    </message>
+    <message>
+        <source>ICON_QTV_FITALL</source>
+        <translation>qtviewer_fitall.png</translation>
+    </message>
+    <message>
+        <source>ICON_QTV_FITSELECT</source>
+        <translation>qtviewer_fitselect.png</translation>
+    </message>
+    <message>
+        <source>ICON_QTV_RESET</source>
+        <translation>qtviewer_reset.png</translation>
+    </message>
+    <message>
+        <source>ICON_QTV_FITAREA</source>
+        <translation>qtviewer_fitarea.png</translation>
+    </message>
+    <message>
+        <source>ICON_QTV_ROTATE</source>
+        <translation>qtviewer_rotate.png</translation>
+    </message>
+</context>
+<context>
+    <name>QtViewer_ViewPort</name>
+    <message>
+        <source>ICON_QTV_CURSOR_ZOOM</source>
+        <translation>qtviewer_cursor_zoom.png</translation>
+    </message>
+</context>
+</TS>
diff --git a/src/QtViewer/resources/QtViewer_msg_en.ts b/src/QtViewer/resources/QtViewer_msg_en.ts
new file mode 100644 (file)
index 0000000..7898ce4
--- /dev/null
@@ -0,0 +1,128 @@
+<!DOCTYPE TS>
+<TS>
+  <context>
+    <name>QtViewer_ViewFrame</name>
+    <message>
+      <source>DSC_DUMP_VIEW</source>
+      <translation>Saves the active view in the image file</translation>
+    </message>
+    <message>
+      <source>DSC_FITALL</source>
+      <translation>Fit all objects inside the view frame</translation>
+    </message>
+    <message>
+      <source>DSC_FITRECT</source>
+      <translation>Fit area within the view frame</translation>
+    </message>
+    <message>
+      <source>DSC_FITSELECT</source>
+      <translation>Fit area of selection within the view frame</translation>
+    </message>
+    <message>
+      <source>DSC_GLOBALPAN_VIEW</source>
+      <translation>Selection of a new center of the view</translation>
+    </message>
+    <message>
+      <source>DSC_PAN_VIEW</source>
+      <translation>Pan the view</translation>
+    </message>
+    <message>
+      <source>DSC_RESET_VIEW</source>
+      <translation>Reset view point</translation>
+    </message>
+    <message>
+      <source>DSC_ZOOM_VIEW</source>
+      <translation>Zoom the view</translation>
+    </message>
+    <message>
+      <source>LBL_TOOLBAR_LABEL</source>
+      <translation>View Operations</translation>
+    </message>
+    <message>
+      <source>MNU_DUMP_VIEW</source>
+      <translation>Dump</translation>
+    </message>
+    <message>
+      <source>MNU_FITALL</source>
+      <translation>Fit All</translation>
+    </message>
+    <message>
+      <source>MNU_FITRECT</source>
+      <translation>Fit Area</translation>
+    </message>
+    <message>
+      <source>MNU_FITSELECT</source>
+      <translation>Fit Selection</translation>
+    </message>
+    <message>
+      <source>MNU_GLOBALPAN_VIEW</source>
+      <translation>Global Pan</translation>
+    </message>
+    <message>
+      <source>MNU_PAN_VIEW</source>
+      <translation>Pan</translation>
+    </message>
+    <message>
+      <source>MNU_RESET_VIEW</source>
+      <translation>Reset</translation>
+    </message>
+    <message>
+      <source>MNU_ZOOM_VIEW</source>
+      <translation>Zoom</translation>
+    </message>
+    <message>
+        <source>POSTSCRIPT_FILES</source>
+        <translation>PostScript files (*.ps *.eps)</translation>
+    </message>
+  </context>
+  <context>
+    <name>QtViewer_Viewer</name>
+    <message>
+      <source>CHANGE_BGCOLOR</source>
+      <translation>Change background...</translation>
+    </message>
+    <message>
+      <source>ADD_IMAGE</source>
+      <translation>Add image</translation>
+    </message>
+    <message>
+      <source>REMOVE_IMAGES</source>
+      <translation>Remove image(s)</translation>
+    </message>
+    <message>
+      <source>BRING_TO_FRONT</source>
+      <translation>Bring to front</translation>
+    </message>
+    <message>
+      <source>SEND_TO_BACK</source>
+      <translation>Send to back</translation>
+    </message>
+    <message>
+      <source>BRING_FORWARD</source>
+      <translation>Bring forward</translation>
+    </message>
+    <message>
+      <source>SEND_BACKWARD</source>
+      <translation>Send backward</translation>
+    </message>
+    <message>
+      <source>PROPERTIES</source>
+      <translation>Properties</translation>
+    </message>
+    <message>
+      <source>TEST_FUSE_OPERATOR</source>
+      <translation>Test Fuse operator</translation>
+    </message>
+    <message>
+      <source>TEST_CROP_OPERATOR</source>
+      <translation>Test Crop operator</translation>
+    </message>
+  </context>
+  <context>
+    <name>QtViewer_ViewManager</name>
+    <message>
+      <source>QTVIEWER_TITLE</source>
+      <translation>Qt scene:%M - viewer:%V</translation>
+    </message>
+  </context>
+</TS>
diff --git a/src/QtViewer/resources/QtViewer_msg_fr.ts b/src/QtViewer/resources/QtViewer_msg_fr.ts
new file mode 100644 (file)
index 0000000..7675789
--- /dev/null
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr" sourcelanguage="en">
+<context>
+    <name>QtViewer_ViewFrame</name>
+    <message>
+        <source>DSC_DUMP_VIEW</source>
+        <translation>Sauver la scène actuelle au fichier image</translation>
+    </message>
+    <message>
+        <source>DSC_FITALL</source>
+        <translation>Redimensionner la scène pour montrer tous les objets </translation>
+    </message>
+    <message>
+        <source>DSC_FITRECT</source>
+        <translation>Redimensionner la scène pour ne montrer que sa partie choisie par l&apos;encadré</translation>
+    </message>
+    <message>
+        <source>DSC_FITSELECT</source>
+        <translation>Redimensionner la scène pour montrer la sélection.</translation>
+    </message>
+    <message>
+        <source>DSC_GLOBALPAN_VIEW</source>
+        <translation>Sélection d&apos;un nouveau centre de la vue</translation>
+    </message>
+    <message>
+        <source>DSC_PAN_VIEW</source>
+        <translation>Redimensionner la vue</translation>
+    </message>
+    <message>
+        <source>DSC_RESET_VIEW</source>
+        <translation>Restaurer le point de vue</translation>
+    </message>
+    <message>
+        <source>DSC_ZOOM_VIEW</source>
+        <translation>Zoom</translation>
+    </message>
+    <message>
+        <source>LBL_TOOLBAR_LABEL</source>
+        <translation>Opérations de visualisation</translation>
+    </message>
+    <message>
+        <source>MNU_DUMP_VIEW</source>
+        <translation>Sauver la scène</translation>
+    </message>
+    <message>
+        <source>MNU_FITALL</source>
+        <translation>Montrer tout</translation>
+    </message>
+    <message>
+        <source>MNU_FITRECT</source>
+        <translation>Montrer l&apos;encadré</translation>
+    </message>
+    <message>
+        <source>MNU_FITSELECT</source>
+        <translation>Ajuster la sélection</translation>
+    </message>
+    <message>
+        <source>MNU_GLOBALPAN_VIEW</source>
+        <translation>Panoramique Globale</translation>
+    </message>
+    <message>
+        <source>MNU_PAN_VIEW</source>
+        <translation>Redimensionner la vue</translation>
+    </message>
+    <message>
+        <source>MNU_RESET_VIEW</source>
+        <translation>Restaurer</translation>
+    </message>
+    <message>
+        <source>MNU_ZOOM_VIEW</source>
+        <translation>Zoom</translation>
+    </message>
+    <message>
+        <source>POSTSCRIPT_FILES</source>
+        <translation>Fichiers PostScript (*.ps *.eps)</translation>
+    </message>
+</context>
+<context>
+    <name>QtViewer_Viewer</name>
+    <message>
+        <source>TEST_CROP_OPERATOR</source>
+        <translation>Test Crop operator</translation>
+    </message>
+    <message>
+        <source>TEST_FUSE_OPERATOR</source>
+        <translation>Test Fuse operator</translation>
+    </message>
+    <message>
+        <source>PROPERTIES</source>
+        <translation>Propriétés</translation>
+    </message>
+    <message>
+        <source>SEND_BACKWARD</source>
+        <translation>Afficher derrière</translation>
+    </message>
+    <message>
+        <source>BRING_FORWARD</source>
+        <translation>Afficher devant</translation>
+    </message>
+    <message>
+        <source>SEND_TO_BACK</source>
+        <translation>Afficher au fond</translation>
+    </message>
+    <message>
+        <source>BRING_TO_FRONT</source>
+        <translation>Afficher au premier plan</translation>
+    </message>
+    <message>
+        <source>REMOVE_IMAGES</source>
+        <translation>Supprimer image(s)</translation>
+    </message>
+    <message>
+        <source>ADD_IMAGE</source>
+        <translation>Ajouter une image</translation>
+    </message>
+    <message>
+        <source>CHANGE_BGCOLOR</source>
+        <translation>Changer l&apos;arrière-plan...</translation>
+    </message>
+</context>
+<context>
+    <name>QtViewer_ViewManager</name>
+    <message>
+        <source>QTVIEWER_TITLE</source>
+        <translation> Scène Qt:%M - visualisation:%V</translation>
+    </message>
+</context>
+</TS>
diff --git a/src/QtViewer/resources/QtViewer_msg_ja.ts b/src/QtViewer/resources/QtViewer_msg_ja.ts
new file mode 100644 (file)
index 0000000..262e904
--- /dev/null
@@ -0,0 +1,129 @@
+<?xml version="1.0"?>
+<!DOCTYPE TS>
+<TS language="ja" sourcelanguage="en">
+  <context>
+    <name>QtViewer_ViewFrame</name>
+    <message>
+      <source>DSC_DUMP_VIEW</source>
+      <translation>&#x30A2;&#x30AF;&#x30C6;&#x30A3;&#x30D6;&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x753B;&#x50CF;&#x3092;&#x4FDD;&#x5B58;</translation>
+    </message>
+    <message>
+      <source>DSC_FITALL</source>
+      <translation>&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x67A0;&#x5185;&#x306B;&#x3059;&#x3079;&#x3066;&#x306E;&#x30AA;&#x30D6;&#x30B8;&#x30A7;&#x30AF;&#x30C8;&#x3092;&#x30D5;&#x30A3;&#x30C3;&#x30C8;&#x3059;&#x308B;</translation>
+    </message>
+    <message>
+      <source>DSC_FITRECT</source>
+      <translation>&#x9818;&#x57DF;&#x3092;&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x67A0;&#x5185;&#x306B;&#x30D5;&#x30A3;&#x30C3;&#x30C8;&#x3059;&#x308B;</translation>
+    </message>
+    <message>
+      <source>DSC_FITSELECT</source>
+      <translation>&#x9078;&#x629E;&#x9818;&#x57DF;&#x3092;&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x67A0;&#x5185;&#x306B;&#x30D5;&#x30A3;&#x30C3;&#x30C8;&#x3059;&#x308B;</translation>
+    </message>
+    <message>
+      <source>DSC_GLOBALPAN_VIEW</source>
+      <translation>&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x65B0;&#x3057;&#x3044;&#x4E2D;&#x5FC3;&#x306E;&#x9078;&#x629E;</translation>
+    </message>
+    <message>
+      <source>DSC_PAN_VIEW</source>
+      <translation>&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x56DE;&#x8EE2;</translation>
+    </message>
+    <message>
+      <source>DSC_RESET_VIEW</source>
+      <translation>&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x30EA;&#x30BB;&#x30C3;&#x30C8;</translation>
+    </message>
+    <message>
+      <source>DSC_ZOOM_VIEW</source>
+      <translation>&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x62E1;&#x5927;</translation>
+    </message>
+    <message>
+      <source>LBL_TOOLBAR_LABEL</source>
+      <translation>&#x30D3;&#x30E5;&#x30FC;&#x306E;&#x64CD;&#x4F5C;</translation>
+    </message>
+    <message>
+      <source>MNU_DUMP_VIEW</source>
+      <translation>&#x8868;&#x793A;&#x72B6;&#x614B;&#x306E;&#x4FDD;&#x5B58;</translation>
+    </message>
+    <message>
+      <source>MNU_FITALL</source>
+      <translation>&#x5168;&#x8868;&#x793A;</translation>
+    </message>
+    <message>
+      <source>MNU_FITRECT</source>
+      <translation>&#x9818;&#x57DF;&#x306B;&#x30D5;&#x30A3;&#x30C3;&#x30C8;</translation>
+    </message>
+    <message>
+      <source>MNU_FITSELECT</source>
+      <translation>&#x9078;&#x629E;&#x7BC4;&#x56F2;&#x3092;&#x30BA;&#x30FC;&#x30E0;</translation>
+    </message>
+    <message>
+      <source>MNU_GLOBALPAN_VIEW</source>
+      <translation>&#x30B0;&#x30ED;&#x30FC;&#x30D0;&#x30EB;&#x56DE;&#x8EE2;</translation>
+    </message>
+    <message>
+      <source>MNU_PAN_VIEW</source>
+      <translation>&#x56DE;&#x8EE2;</translation>
+    </message>
+    <message>
+      <source>MNU_RESET_VIEW</source>
+      <translation>&#x30EA;&#x30BB;&#x30C3;&#x30C8;</translation>
+    </message>
+    <message>
+      <source>MNU_ZOOM_VIEW</source>
+      <translation>&#x30BA;&#x30FC;&#x30E0;</translation>
+    </message>
+    <message>
+        <source>POSTSCRIPT_FILES</source>
+        <translation>PostScript files (*.ps *.eps)</translation>
+    </message>
+  </context>
+  <context>
+    <name>QtViewer_Viewer</name>
+    <message>
+      <source>CHANGE_BGCOLOR</source>
+      <translation>&#x80CC;&#x666F;&#x306E;&#x5909;&#x66F4;.</translation>
+    </message>
+    <message>
+      <source>ADD_IMAGE</source>
+      <translation>&#x753B;&#x50CF;&#x306E;&#x8FFD;&#x52A0;</translation>
+    </message>
+    <message>
+      <source>REMOVE_IMAGES</source>
+      <translation>&#x753B;&#x50CF;&#x306E;&#x524A;&#x9664;</translation>
+    </message>
+    <message>
+      <source>BRING_TO_FRONT</source>
+      <translation>&#x6700;&#x524D;&#x9762;&#x3078;&#x79FB;&#x52D5;</translation>
+    </message>
+    <message>
+      <source>SEND_TO_BACK</source>
+      <translation>&#x6700;&#x80CC;&#x9762;&#x3078;&#x79FB;&#x52D5;</translation>
+    </message>
+    <message>
+      <source>BRING_FORWARD</source>
+      <translation>&#x524D;&#x9762;&#x3078;&#x79FB;&#x52D5;</translation>
+    </message>
+    <message>
+      <source>SEND_BACKWARD</source>
+      <translation>&#x80CC;&#x9762;&#x3078;&#x79FB;&#x52D5;</translation>
+    </message>
+    <message>
+      <source>PROPERTIES</source>
+      <translation>&#x30D7;&#x30ED;&#x30D1;&#x30C6;&#x30A3;</translation>
+    </message>
+    <message>
+      <source>TEST_FUSE_OPERATOR</source>
+      <translation>&#x7D50;&#x5408;&#x306E;&#x30C6;&#x30B9;&#x30C8;</translation>
+    </message>
+    <message>
+      <source>TEST_CROP_OPERATOR</source>
+      <translation>&#x30C8;&#x30EA;&#x30E0;&#x306E;&#x30C6;&#x30B9;&#x30C8;</translation>
+    </message>
+  </context>
+  <context>
+    <name>QtViewer_ViewManager</name>
+    <message>
+      <source>QTVIEWER_TITLE</source>
+      <translation>&#x30B0;&#x30E9;&#x30D5;&#x30A3;&#x30C3;&#x30AF;&#x30B7;&#x30FC;&#x30F3;:%M - &#x30D3;&#x30E5;&#x30FC;&#x30EF;:%V</translation>
+    </message>
+  </context>
+</TS>
diff --git a/src/QtViewer/resources/qtviewer_cursor_zoom.png b/src/QtViewer/resources/qtviewer_cursor_zoom.png
new file mode 100644 (file)
index 0000000..0020fea
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_cursor_zoom.png differ
diff --git a/src/QtViewer/resources/qtviewer_dump.png b/src/QtViewer/resources/qtviewer_dump.png
new file mode 100644 (file)
index 0000000..b02616f
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_dump.png differ
diff --git a/src/QtViewer/resources/qtviewer_fitall.png b/src/QtViewer/resources/qtviewer_fitall.png
new file mode 100644 (file)
index 0000000..87e001d
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_fitall.png differ
diff --git a/src/QtViewer/resources/qtviewer_fitarea.png b/src/QtViewer/resources/qtviewer_fitarea.png
new file mode 100644 (file)
index 0000000..e83d023
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_fitarea.png differ
diff --git a/src/QtViewer/resources/qtviewer_fitselect.png b/src/QtViewer/resources/qtviewer_fitselect.png
new file mode 100644 (file)
index 0000000..e52598d
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_fitselect.png differ
diff --git a/src/QtViewer/resources/qtviewer_glpan.png b/src/QtViewer/resources/qtviewer_glpan.png
new file mode 100644 (file)
index 0000000..28ab547
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_glpan.png differ
diff --git a/src/QtViewer/resources/qtviewer_pan.png b/src/QtViewer/resources/qtviewer_pan.png
new file mode 100644 (file)
index 0000000..ec56cac
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_pan.png differ
diff --git a/src/QtViewer/resources/qtviewer_reset.png b/src/QtViewer/resources/qtviewer_reset.png
new file mode 100644 (file)
index 0000000..66f81e6
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_reset.png differ
diff --git a/src/QtViewer/resources/qtviewer_rotate.png b/src/QtViewer/resources/qtviewer_rotate.png
new file mode 100644 (file)
index 0000000..3f180b4
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_rotate.png differ
diff --git a/src/QtViewer/resources/qtviewer_zoom.png b/src/QtViewer/resources/qtviewer_zoom.png
new file mode 100644 (file)
index 0000000..386c966
Binary files /dev/null and b/src/QtViewer/resources/qtviewer_zoom.png differ
index cd7820cf90d17cc61375b08258e7f25ca775c3d2..2cf4d17515a86eaaf3c751bc9f1988c34a0904b1 100644 (file)
 #include <vtkSMRepresentationProxy.h>
 #include <vtkPVDataSetAttributesInformation.h>
 
+#include <QDebug>
+
+#include "SPV3D_Prs.h"
+
+
+
 //-----------------------------------------------------------------------------
 SPV3D_CADSelection::SPV3D_CADSelection(QObject *parent,
   pqRenderView* view, SelectionMode mode):QObject(parent)
@@ -275,6 +281,32 @@ void SPV3D_CADSelection::onMouseMove()
   {
     this->fastSelection(true);
   }
+
+  // get preselected id here
+  vtkSMProxy* proxyRepresentation = this->Representation->getProxy();
+  if (!proxyRepresentation)
+  {
+    qWarning()<< "There is no representation in the active view for the Geometry Source.";
+    return;
+  }
+
+
+  // Retrieve the wanted information property
+  vtkSMProperty* PreselectedIDProperty =
+    proxyRepresentation->GetProperty("PreSelectedID");
+  if (!PreselectedIDProperty)
+  {
+    qWarning()<< "The representation named '" << proxyRepresentation->GetXMLName()<< "' didn't have a property named 'SelectedIDInfo'.";
+    return;
+  }
+
+  // Force to update the information property
+  proxyRepresentation->UpdatePropertyInformation(PreselectedIDProperty);
+
+  vtkIdType PreSelectedID =
+    vtkSMPropertyHelper(proxyRepresentation,"PreSelectedID").GetAsInt(0);
+  qInfo() << "entry from client: "<< SPV3D_Prs::FromVtkIdToEntry(PreSelectedID);
+  
 }
 
 //-----------------------------------------------------------------------------
index 8e8637cc5d9a03a2e370ffe6652aa68305e7d37b..210d89a502095f868d4fd2e8f3ccb5d22b4f505b 100644 (file)
@@ -23,6 +23,7 @@
 #include "SPV3D_Prs.h"
 #include "SPV3D_ViewWindow.h"
 
+#include <vtkAppendPolyData.h>
 #include "vtkActor.h"
 #include "vtkPolyData.h"
 #include "vtkCellData.h"
 #include "vtkPVTrivialProducer.h"
 #include <pqDataRepresentation.h>
 
+#include <QDebug>
+
+vtkIdType SPV3D_Prs::cellid = 0;
+vtkIdType SPV3D_Prs::nbsolid = 0;
+
+SPV3D_EXPORTSPV3DData::SPV3D_EXPORTSPV3DData()
+{
+  nbsolid = 0;
+  _multiGEOMData = vtkSmartPointer<vtkMultiBlockDataSet>::New();
+  pqServer *serv(pqApplicationCore::instance()->getServerManagerModel()->findServer(pqServerResource("builtin:")));
+  pqObjectBuilder *builder(pqApplicationCore::instance()->getObjectBuilder());
+  _sourceProducer = builder->createSource("sources","PVTrivialProducer",serv);
+}
+void SPV3D_EXPORTSPV3DData::SetPolyData(vtkPolyData* ds)
+{
+  _multiGEOMData->SetBlock(nbsolid , ds);
+  nbsolid++;
+}
+
+void SPV3D_EXPORTSPV3DData::SetPrs(vtkPolyData* ds, const char* entry)
+{
+  unsigned int id;
+  if (havePrs(entry, id))
+    return;
+  auto nbCells( ds->GetNumberOfCells() );
+
+  vtkNew<vtkIdTypeArray> solidIdArray;
+  qInfo() << "nb of cells: " << nbCells;
+  solidIdArray->SetNumberOfComponents(1);
+  solidIdArray->SetNumberOfTuples( nbCells );
+  solidIdArray->SetName("Solid id");
+
+//  vtkNew<vtkIdTypeArray> cellIdArray;
+//  cellIdArray->SetNumberOfComponents(1);
+//  cellIdArray->SetNumberOfTuples( nbCells );
+//  cellIdArray->SetName("Edge id");
+
+  vtkIdType *pt( solidIdArray->GetPointer(0) );
+  vtkIdType solidid = SPV3D_Prs::FromEntryToVtkId(entry);
+  std::for_each(pt,pt+nbCells,[solidid](vtkIdType& elt) { elt = solidid;});
+// pt = cellIdArray->GetPointer(0);
+// std::for_each(pt,pt+nbCells,[](vtkIdType& elt) { elt = SPV3D_Prs::cellid;SPV3D_Prs::cellid++; });
+
+  ds->GetCellData()->AddArray( solidIdArray );
+// ->GetCellData()->AddArray( cellIdArray );
+  SetPolyData(ds);
+  updateSource_for_display();
+}
+
+void SPV3D_EXPORTSPV3DData::RemovePrs(const char* entry)
+{
+  unsigned int id;
+  if (!havePrs(entry, id))
+  {
+    qWarning() << "Can not find solid with entry: " << entry;
+    return;
+  }
+  _multiGEOMData->RemoveBlock(id);
+  updateSource_for_display();
+}
+
+void SPV3D_EXPORTSPV3DData::updateSource_for_display()
+{
+  vtkNew<vtkAppendPolyData> appendFilter;
+  nbsolid = _multiGEOMData->GetNumberOfBlocks();
+  qInfo() <<"number of block: " << nbsolid;
+  for (unsigned int i = 0; i < nbsolid; ++i)
+  {
+      vtkPolyData* polyData = vtkPolyData::SafeDownCast(_multiGEOMData->GetBlock(i));
+      if (polyData)
+      {
+        vtkIdTypeArray* retrievedArray = vtkIdTypeArray::SafeDownCast(polyData->GetCellData()->GetArray("Solid id"));
+        if (retrievedArray)
+          appendFilter->AddInputData(polyData);
+      }
+  }
+  appendFilter->Update();
+  vtkNew<vtkPolyData> ds;
+  ds->ShallowCopy(appendFilter->GetOutput());
+
+  vtkSMProxy* producerBase = _sourceProducer->getProxy();
+  vtkSMSourceProxy *producer(vtkSMSourceProxy::SafeDownCast(producerBase));
+  vtkObjectBase *clientSideObject(producer->GetClientSideObject());
+  vtkPVTrivialProducer *clientSideObjectCast = vtkPVTrivialProducer::SafeDownCast(clientSideObject);
+  clientSideObjectCast->SetOutput(ds);
+  _sourceProducer->updatePipeline();
+
+  //pqServerManagerModel* smmodel = pqApplicationCore::instance()->getServerManagerModel();
+  //pqProxy *producerBase2( smmodel->findItem<pqProxy*>(producerBase) );
+  //if(producerBase2 && !_name.empty())
+  //  producerBase2->rename( _name.c_str() );
+}
+
 bool SPV3D_EXPORTSPV3DData::IsVisible() const
 {
   if( IsNull() )
@@ -43,6 +137,25 @@ bool SPV3D_EXPORTSPV3DData::IsVisible() const
   return GetRepresentation()->isVisible();
 }
 
+bool SPV3D_EXPORTSPV3DData::havePrs(const char* entry, unsigned int & id)
+{
+  vtkIdType solid_id = SPV3D_Prs::FromEntryToVtkId(entry);
+  id = 0;
+  while (id < _multiGEOMData->GetNumberOfBlocks())
+  {
+      vtkPolyData* polyData = vtkPolyData::SafeDownCast(_multiGEOMData->GetBlock(id));
+      if (polyData)
+      {
+        vtkIdTypeArray* retrievedArray = vtkIdTypeArray::SafeDownCast(polyData->GetCellData()->GetArray("Solid id"));
+        if (retrievedArray && retrievedArray->GetValue(0) == solid_id)
+          break;
+      }
+    id++;
+  }
+
+  return id < _multiGEOMData->GetNumberOfBlocks();
+}
+
 void SPV3D_EXPORTSPV3DData::Hide() const
 {
   if( GetRepresentation() )
@@ -53,6 +166,38 @@ SPV3D_Prs::SPV3D_Prs( const char* entry , SPV3D_ViewWindow *view) : SALOME_PV3DP
 {
 }
 
+vtkIdType SPV3D_Prs::FromEntryToVtkId (const char* entry)
+{
+  char *str = new char[strlen(entry)+1];
+  strcpy(str, entry);
+
+  const char delimiter[2] = ":";
+
+  char* token;
+  token = strtok(str, delimiter);
+
+  std::uint32_t ret(atoi(token));
+  token = strtok(NULL, delimiter);
+
+  while (token != NULL) {
+      ret <<=8;
+      ret |= atoi(token);
+      token = strtok(NULL, delimiter);
+  }
+
+  return static_cast<vtkIdType> (ret);
+}
+
+const char* SPV3D_Prs::FromVtkIdToEntry(vtkIdType id)
+{
+  int d = id & 0xFF;
+  std::uint32_t c_work = ( id & 0xFF00 ); int c = c_work >> 8;
+  std::uint32_t b_work = ( id & 0xFF0000 ); int b = b_work >> 16;
+  std::uint32_t a_work = ( id & 0xFF000000 ); int a = a_work >> 24;
+  std::string ret = std::to_string(a) + ":" + std::to_string(b) + ":" + std::to_string(c)+ ":" + std::to_string(d);
+  return ret.c_str();
+}
+
 SPV3D_Prs *SPV3D_Prs::deepCopy() const
 {
   SPV3D_Prs *ret = new SPV3D_Prs( *this );
@@ -65,49 +210,6 @@ pqProxy *getPQProxy(vtkSMProxy *proxy)
   return smmodel->findItem<pqProxy*>(proxy);
 }
 
-void SPV3D_Prs::FillUsingActor(vtkActor *actor) const
-{
-  SPV3D_EXPORTSPV3DData *alreadyExistingSrc = nullptr;
-  alreadyExistingSrc = _view->isEntryAlreadyExist( GetEntry() );
-  if(alreadyExistingSrc && !alreadyExistingSrc->GetSourceProducer())
-  {
-    actor->GetMapper()->Update();
-    vtkDataObject *ds = actor->GetMapper()->GetInput();
-    vtkPolyData *ds3 = vtkPolyData::SafeDownCast(ds);
-    vtkNew<vtkPolyData> ds4;
-    if(ds3)
-    {
-      ds4->ShallowCopy( ds3 );
-      vtkNew<vtkIdTypeArray> solidIdArray;
-      auto nbCells( ds4->GetNumberOfCells() );
-      solidIdArray->SetNumberOfComponents(1);
-      solidIdArray->SetNumberOfTuples( nbCells );
-      solidIdArray->SetName("Solid id");
-      vtkIdType *pt( solidIdArray->GetPointer(0) );
-      std::for_each(pt,pt+nbCells,[](vtkIdType& elt) { elt = 0; });
-      ds4->GetCellData()->AddArray( solidIdArray );
-    }
-    //
-    pqServer *serv(pqApplicationCore::instance()->getServerManagerModel()->findServer(pqServerResource("builtin:")));
-    pqObjectBuilder *builder(pqApplicationCore::instance()->getObjectBuilder());
-    pqPipelineSource *mySourceProducer(builder->createSource("sources","PVTrivialProducer",serv));
-    vtkSMProxy *producerBase = mySourceProducer->getProxy();
-    vtkSMSourceProxy *producer(vtkSMSourceProxy::SafeDownCast(producerBase));
-    vtkObjectBase *clientSideObject(producer->GetClientSideObject());
-    vtkPVTrivialProducer *clientSideObjectCast = vtkPVTrivialProducer::SafeDownCast(clientSideObject);
-    clientSideObjectCast->SetOutput(ds4);
-    mySourceProducer->updatePipeline();
-    pqProxy *producerBase2( getPQProxy(producerBase) );
-    if(producerBase2 && !_name.empty())
-      producerBase2->rename( _name.c_str() );
-    this->SetSourceProducer( mySourceProducer );
-  }
-  else
-  {
-    this->CopyInfo( alreadyExistingSrc );
-  }
-}
-
 SPV3D_Prs:: ~SPV3D_Prs() 
 {
 }
@@ -117,20 +219,33 @@ void SPV3D_Prs::DisplayIn( SALOME_View* v ) const
   SALOME_PV3DPrs::DisplayIn(v);
 }
 
-void SPV3D_Prs::CopyInfo(SPV3D_EXPORTSPV3DData *info) const
-{
-  if(!_pvRendInfo || !info)
-    return ;
-  if(_pvRendInfo == info)
-    return ;
-  *_pvRendInfo = *info;
-}
-
 bool SPV3D_Prs::IsNull() const
 {
   if(_pvRendInfo)
-    return _pvRendInfo->IsNull();
+  {
+    unsigned int id;
+    return !_pvRendInfo->havePrs(GetEntry(),id);
+  }
   return true;
 }
 
+void SPV3D_Prs::FillUsingActor(vtkActor *actor) const
+{
+  std::cout << "Hello FillUsingActor"<<std::endl;
+  int id = _view->isEntryAlreadyExist( GetEntry() );
 
+  if(id == -1) // not exist
+  {
+    actor->GetMapper()->Update();
+    vtkDataObject *ds = actor->GetMapper()->GetInput();
+    vtkPolyData *ds2 = vtkPolyData::SafeDownCast(ds);
+    if(ds2)
+    {
+      _view->ExportToSPV3D(ds2, GetEntry());
+    }
+  }
+  else
+  {
+    qWarning() << "Geometry Object is already in viewer window";
+  }
+}
index 2cba496a03867a265d3316c5a1044fe3f4806f94..191fd556b839e2e69c38b8308ab46476db00f79e 100644 (file)
 #include "SPV3D.h"
 #include "SALOME_Prs.h"
 
+#include "vtkPolyData.h"
+#include "vtkCellData.h"
+#include <vtkMultiBlockDataSet.h>
+#include <vtkSmartPointer.h>
+
+#include <set>
 class vtkActor;
 class pqPipelineSource;
 class pqDataRepresentation;
@@ -29,21 +35,32 @@ class pqDataRepresentation;
 class SPV3D_EXPORTSPV3DData
 {
 public:
-  SPV3D_EXPORTSPV3DData() = default;
+  SPV3D_EXPORTSPV3DData();
   SPV3D_EXPORTSPV3DData *deepCopy() { return new SPV3D_EXPORTSPV3DData(*this); }
-  void SetSourceProducer(pqPipelineSource *sourceProducer) const { _sourceProducer = sourceProducer; }
+  void SetPrs(vtkPolyData* ds, const char* entry);
+  void SetPolyData(vtkPolyData* ds);
+  void RemovePrs(const char* entry);
+
+  // the source producer is initialized in the instantiation of SPV3D_EXPORTSPV3DData
+  // Normaly, we shouldn't copy another src in SPV3D_EXPORTSPV3DData
+  //void SetSourceProducer(pqPipelineSource *sourceProducer) const { _sourceProducer = sourceProducer; }
   pqPipelineSource *GetSourceProducer() const { return _sourceProducer; }
   
   void SetRepresentation(pqDataRepresentation *repr) const { _repr = repr; }
   pqDataRepresentation *GetRepresentation() const { return _repr; }
   
+  void updateSource_for_display();
   bool IsNull() const { return !_sourceProducer && !_repr; }
 
   bool IsVisible() const;
+  bool havePrs(const char* entry, unsigned int & id);
   void Hide() const;
+
 private:
   SPV3D_EXPORTSPV3DData(const SPV3D_EXPORTSPV3DData& other) = default;
 private:
+  vtkSmartPointer<vtkMultiBlockDataSet> _multiGEOMData;
+  vtkIdType nbsolid;
   mutable pqPipelineSource *_sourceProducer = nullptr;
   mutable pqDataRepresentation *_repr = nullptr;
 };
@@ -64,24 +81,26 @@ public:
 
   void DisplayIn( SALOME_View* v ) const override;
 
-  void CopyInfo(SPV3D_EXPORTSPV3DData *info) const;
-
   void SetPVRenderInfo(SPV3D_EXPORTSPV3DData *pvRendInfo) { _pvRendInfo = pvRendInfo; }
 
-  void SetSourceProducer(pqPipelineSource *sourceProducer) const { if(_pvRendInfo) _pvRendInfo->SetSourceProducer(sourceProducer); }
+  // the source producer is initialized in the instantiation of SPV3D_EXPORTSPV3DData
+  // Normaly, we shouldn't copy another src in SPV3D_EXPORTSPV3DData
+  //void SetSourceProducer(pqPipelineSource *sourceProducer) const { if(_pvRendInfo) _pvRendInfo->SetSourceProducer(sourceProducer); }
   pqPipelineSource *GetSourceProducer() const { if(_pvRendInfo) return _pvRendInfo->GetSourceProducer(); return nullptr; }
   
   void SetRepresentation(pqDataRepresentation *repr) const { if(_pvRendInfo) _pvRendInfo->SetRepresentation(repr); }
   pqDataRepresentation *GetRepresentation() const { if(_pvRendInfo) return _pvRendInfo->GetRepresentation(); return nullptr; }
 
   bool IsNull() const override;
+  static vtkIdType FromEntryToVtkId (const char*);
+  static const char* FromVtkIdToEntry (vtkIdType);
 
 private:
 
   SPV3D_Prs(const SPV3D_Prs& other) = default;
 
 public:
-  void hide() const { if(_pvRendInfo) return _pvRendInfo->Hide(); }
+  void hide() const { if(_pvRendInfo) return _pvRendInfo->RemovePrs(GetEntry()); }
   bool isVisible() const { if(_pvRendInfo) return _pvRendInfo->IsVisible(); return false; }
 
 private:
@@ -90,4 +109,7 @@ private:
   SPV3D_ViewWindow *_view = nullptr;
   //! Name attached to the displayable object in the study
   std::string _name;
+  static vtkIdType cellid;
+  static vtkIdType nbsolid;
+
 };
index 30b4f1e2e87920270ec9efb5682979ecde6e76e5..90cae0b6a96f122486d227e3fde2391db441121b 100644 (file)
 #include <QColorDialog>
 #include <QToolBar>
 #include <QTimer>
+#include <QDebug>
 
 #include <vtkActorCollection.h>
 
 #include "SPV3D_ViewModel.h"
 #include "SPV3D_ViewWindow.h"
-#include "SPV3D_Prs.h"
 #include "PVViewer_Core.h"
 
 #include <pqActiveObjects.h>
@@ -196,6 +196,28 @@ pqView *SPV3D_ViewModel::getView() const
   return _view;
 }
 
+void SPV3D_ViewModel::updatePVPrsPipeline(const SPV3D_Prs* aPrs)
+{
+  if (aPrs->GetRepresentation())
+  {
+    aPrs->GetRepresentation()->setVisible(0);
+    delete(aPrs->GetRepresentation());
+  }
+  pqObjectBuilder *builder(pqApplicationCore::instance()->getObjectBuilder());
+  pqActiveObjects::instance().setActiveView(getView());
+  pqPipelineSource *mySourceProducer = aPrs->GetSourceProducer();
+  pqDataRepresentation* myRepr(builder->createDataRepresentation(mySourceProducer->getOutputPort(0),getView(),"CADRepresentation"));//"GeometryRepresentation"
+  vtkSMViewProxy::RepresentationVisibilityChanged(myRepr->getViewProxy(), myRepr->getProxy(), true);
+  aPrs->SetRepresentation(myRepr);
+  myRepr->setVisible(1);
+  vtkSMPVRepresentationProxy* proxy(dynamic_cast<vtkSMPVRepresentationProxy*>(myRepr->getProxy()));
+  if(proxy)
+  {
+    vtkSMPropertyHelper inputHelper(proxy, "Input");
+    vtkSMSourceProxy* input = vtkSMSourceProxy::SafeDownCast(inputHelper.GetAsProxy());
+    input->UpdatePipeline();
+  }
+}
 /*!
   Display presentation
   \param prs - presentation
@@ -204,28 +226,14 @@ void SPV3D_ViewModel::Display( const SALOME_PV3DPrs* prs )
 {
   if(const SPV3D_Prs* aPrs = dynamic_cast<const SPV3D_Prs*>( prs ))
   {
-    if( !aPrs->GetRepresentation() )
-    {
-      pqObjectBuilder *builder(pqApplicationCore::instance()->getObjectBuilder());
-      pqActiveObjects::instance().setActiveView(getView());
-      pqPipelineSource *mySourceProducer = aPrs->GetSourceProducer();
-      aPrs->SetSourceProducer( mySourceProducer );
-      pqDataRepresentation* myRepr(builder->createDataRepresentation(mySourceProducer->getOutputPort(0),getView(),"CADRepresentation"));//"GeometryRepresentation"
-      vtkSMViewProxy::RepresentationVisibilityChanged(myRepr->getViewProxy(), myRepr->getProxy(), true);
-      aPrs->SetRepresentation(myRepr);
-    }
-    pqDataRepresentation* myRepr = aPrs->GetRepresentation();
-    myRepr->setVisible(1);
-    vtkSMPVRepresentationProxy* proxy(dynamic_cast<vtkSMPVRepresentationProxy*>(myRepr->getProxy()));
-    if(proxy)
-    {
-      vtkSMPropertyHelper inputHelper(proxy, "Input");
-      vtkSMSourceProxy* input = vtkSMSourceProxy::SafeDownCast(inputHelper.GetAsProxy());
-      input->UpdatePipeline();
-    }
+    updatePVPrsPipeline(aPrs);
     getView()->resetDisplay();
     getView()->render();
   }
+  else
+  {
+    qWarning()<< "SPV3D_ViewModel::Display: Something wrong";
+  }
 }
 
 /*!
@@ -239,11 +247,10 @@ void SPV3D_ViewModel::Erase( const SALOME_PV3DPrs* prs, const bool /*forced*/ )
   if(const SPV3D_Prs* aPrs = dynamic_cast<const SPV3D_Prs*>( prs )){
     if(aPrs->IsNull())
       return;
-    aPrs->GetRepresentation()->setVisible(0);
+    aPrs->hide();
+    updatePVPrsPipeline(aPrs);
+    getView()->resetDisplay();
     getView()->render();
-    //pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder();
-    //pqServer* activeServer = pqActiveObjects::instance().activeServer();
-    //builder->destroySources(activeServer);
   }
 }
 
index dc982345e58fa6c12c6b44ab6b2cb534b645f5d8..3daf72d7ee320a4ee23b66f2a8e53ceccdb69ce4 100644 (file)
@@ -26,6 +26,9 @@
 #include <SALOME_InteractiveObject.hxx>
 #include <SALOME_ListIO.hxx>
 
+#include "SPV3D_Prs.h"
+
+
 class QMouseEvent;
 class pqPipelineSource;
 class pqView;
@@ -62,7 +65,7 @@ public:
 public:
   void enableSelection(bool isEnabled);
   bool isSelectionEnabled() const { return mySelectionEnabled; }
-
+  void updatePVPrsPipeline( const SPV3D_Prs* aPrs);
   /* Reimplemented from SALOME_View */
 
   //! See #SALOME_View::Display( const SALOME_Prs* )
index 5837461f2335ae716143a140118b7a41f0e4a28a..b4e04f9b55f94597d70517340a9bfa8670c6b71c 100644 (file)
@@ -114,6 +114,9 @@ void SPV3D_ViewWindow::init()
   QAction *selectionAction =  toolMgr()->toolBar(myToolBar)->addAction(SUIT_Session::session()->resourceMgr()->loadPixmap( "VTKViewer", tr( "ICON_SVTK_PRESELECTION_STANDARD" ) ), tr( "MNU_SVTK_PRESELECTION_STANDARD" ) );
   selectionAction->setCheckable(true);
   QObject::connect(selectionAction, &QAction::toggled, this, &SPV3D_ViewWindow::goSelect);
+  
+  SPV3D_EXPORTSPV3DData* rawPtr = new SPV3D_EXPORTSPV3DData();
+  myPrs.reset(rawPtr);
 }
 
 void SPV3D_ViewWindow::goSelect(bool val)
@@ -125,15 +128,12 @@ void SPV3D_ViewWindow::goSelect(bool val)
       {
         return;
       }
-      for(const auto& elt : myPrs)
+      pqPipelineSource *geometrySource = myPrs->GetSourceProducer();
+      if(geometrySource)
       {
-        pqPipelineSource *geometrySource = elt.second->GetSourceProducer();
-        if(geometrySource)
-        {
-          vtkSMProxy* repr = activeView->getViewProxy()->FindRepresentation(
-            geometrySource->getSourceProxy(), 0);
-          repr->InvokeCommand("Reset");
-        }
+        vtkSMProxy* repr = activeView->getViewProxy()->FindRepresentation(
+          geometrySource->getSourceProxy(), 0);
+        repr->InvokeCommand("Reset");
       }
       activeView->forceRender();
       activeView->render();
@@ -234,34 +234,26 @@ void SPV3D_ViewWindow::showCenterAxes(bool show_axes)
   renderView->render();
 }
 
+
 SPV3D_Prs *SPV3D_ViewWindow::findOrCreatePrs( const char* entry )
-{
-  std::string entryCpp( entry );
+{//en cours
   SPV3D_Prs *prsOut( new SPV3D_Prs( entry, this ) );
-  for(auto& prs : myPrs)
-  {
-    if(entryCpp == prs.first)
-    {
-      prsOut->SetPVRenderInfo( prs.second.get() );
-      return prsOut;
-    }
-  }
-  std::unique_ptr<SPV3D_EXPORTSPV3DData> data(new SPV3D_EXPORTSPV3DData);
-  prsOut->SetPVRenderInfo( data.get() );
-  std::pair<std::string, std::unique_ptr<SPV3D_EXPORTSPV3DData> > p(entryCpp,std::move(data));
-  myPrs.emplace_back( std::move(p) );
+  prsOut->SetPVRenderInfo( myPrs.get() );
   return prsOut;
 }
 
-SPV3D_EXPORTSPV3DData *SPV3D_ViewWindow::isEntryAlreadyExist( const char* entry ) const
+unsigned int SPV3D_ViewWindow::isEntryAlreadyExist( const char* entry ) const
 {
-  std::string entryCpp( entry );
-  for(const auto& prs : myPrs)
-  {
-    if(entryCpp == prs.first)
-      return prs.second.get();
-  }
-  return nullptr;
+  unsigned int id;
+  if(myPrs->havePrs(entry, id))
+    return id;
+  else
+    return -1;
+}
+
+void SPV3D_ViewWindow::ExportToSPV3D(vtkPolyData* ds, const char* entry)
+{
+  myPrs->SetPrs(ds, entry);
 }
 
 /*!
@@ -273,11 +265,11 @@ SPV3D_ViewWindow::~SPV3D_ViewWindow()
 
 bool SPV3D_ViewWindow::isVisible(const Handle(SALOME_InteractiveObject)& theIObject)
 {
-  std::string entryCpp( theIObject->getEntry() );
-  for(auto& prs : myPrs)
+  auto entry =  theIObject->getEntry();
+  unsigned int id;
+  if (myPrs->havePrs(entry, id))
   {
-    if(entryCpp == prs.first )
-      return prs.second->IsVisible();
+    return true;
   }
   return false;
 }
@@ -323,10 +315,7 @@ void SPV3D_ViewWindow::DisplayAll()
 */
 void SPV3D_ViewWindow::EraseAll() 
 {
-  for(auto& prs : myPrs)
-  {
-    prs.second->Hide();
-  }
+  myPrs->Hide();
   if(myModel)
     myModel->render();
 }
index 084d4268b2134cca52ff18232b2f70ae9dc08f9a..fb546dc784a0e4bf644d93b4b7b6ba12532bd975 100644 (file)
@@ -48,7 +48,9 @@ class SPV3D_EXPORT SPV3D_ViewWindow : public PV3DViewer_ViewWindow
 
   SPV3D_Prs *findOrCreatePrs( const char* entry );
 
-  SPV3D_EXPORTSPV3DData *isEntryAlreadyExist( const char* entry ) const;
+  unsigned int isEntryAlreadyExist( const char* entry ) const;
+
+  void ExportToSPV3D(vtkPolyData* ds, const char*);
 
   void init();
 
@@ -104,7 +106,9 @@ protected:
   SPV3D_CADSelection *mySelection = nullptr;
   int myToolBar = -1;
   SPV3D_ViewModel* myModel;
-  std::list< std::pair<std::string, std::unique_ptr<SPV3D_EXPORTSPV3DData> > > myPrs;
+  //std::list< std::pair<std::string, std::unique_ptr<SPV3D_EXPORTSPV3DData> > > myPrs;
+  std::list< std::pair<std::string, SPV3D_Prs* > > Prs;
+  std::unique_ptr<SPV3D_EXPORTSPV3DData> myPrs;
 };
 
 #ifdef WIN32
index 70952aaecb9e263aa39d6dd4ffbf94dba774d00d..14bbfeff2a8e7e8099af9f0139af03a881f772f6 100644 (file)
             }
         }
     },
+    "/PRP_CREATE_NEW_WINDOW_FOR_VIEWER_9": {
+        "iconPath": "",
+        "langDependentAssets": {
+            "en": {
+                "name": "QtView view",
+                "tooltip": "Create new QtView view"
+            },
+            "fr": {
+                "name": "QtView view",
+                "tooltip": "Créer une nouvelle QtView view"
+            },
+            "ja": {
+                "name": "QtView view",
+                "tooltip": "新しい QtView view を作成します。"
+            }
+        }
+    },
     "/PRP_DESK_CATALOG_GENERATOR": {
         "iconPath": "",
         "langDependentAssets": {
             }
         }
     }
-}
\ No newline at end of file
+}
index 1701d907e825839b032da7150a0318bfe4c9ca64..57da3e4fdb9f137f0634a5297cf4f1bc04f1b514 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "SUIT_Tools.h"
 #include "SALOME_Actor.h"
+#include "ViewerTools_ScreenScaling.h"
 
 #include <vtkObjectFactory.h>
 #include <vtkMath.h>
@@ -646,7 +647,12 @@ void SVTK_InteractorStyle::OnLeftButtonUp(int vtkNotUsed(ctrl),
 {
   myShiftState = shift;
   if( myPoligonState == InProcess ) { // add a new point of polygon
-    myPolygonPoints.append( QPoint( x, y ) );
+    // The mouse events were already scaled up with a pixel ratio for a proper selection,
+    // but rubber band's implemented with QPainter scales them on its own.
+    // So, we need to pass unscaled coordinates to get a polygon painted in a right place.
+    const double pixelRatio = ViewerTools_ScreenScaling::getPR();
+
+    myPolygonPoints.append(QPoint(x / pixelRatio, y / pixelRatio));
     this->Interactor->GetEventPosition( mySelectionEvent->myX, mySelectionEvent->myY );
     mySelectionEvent->myPolygonPoints.append( QPoint( mySelectionEvent->myX, mySelectionEvent->myY ) );
     return;
@@ -1672,7 +1678,17 @@ void SVTK_InteractorStyle::drawRect()
     myRectBand = new QtxRectRubberBand( GetRenderWidget() );
 
   myRectBand->setUpdatesEnabled ( false );
-  QRect aRect = SUIT_Tools::makeRect(myPoint.x(), myPoint.y(), myOtherPoint.x(), myOtherPoint.y());
+
+  // The mouse events were already scaled up with a pixel ratio for a proper selection,
+  // but rubber band's implemented with QPainter scales them on its own.
+  // So, we need to pass unscaled coordinates to get a rectangle painted in a right place.
+  const double pixelRatio = ViewerTools_ScreenScaling::getPR();
+  QRect aRect = SUIT_Tools::makeRect(
+    myPoint.x() / pixelRatio,
+    myPoint.y() / pixelRatio,
+    myOtherPoint.x() / pixelRatio,
+    myOtherPoint.y() / pixelRatio);
+
   myRectBand->initGeometry( aRect );
 
   if ( !myRectBand->isVisible() )
@@ -1771,27 +1787,34 @@ bool isValid( const QPolygon* thePoints, const QPoint& theCurrent )
 */
 void SVTK_InteractorStyle::drawPolygon()
 {
+  // The mouse events were already scaled up with a pixel ratio for a proper selection,
+  // but rubber band's implemented with QPainter scales them on its own.
+  // So, we need to pass unscaled coordinates to get a polygon painted in a right place.
+  const double pixelRatio = ViewerTools_ScreenScaling::getPR();
+  const QPoint myPointCopy(myPoint.x() / pixelRatio, myPoint.y() / pixelRatio);
+  const QPoint myOtherPointCopy(myOtherPoint.x() / pixelRatio, myOtherPoint.y() / pixelRatio);
+
   QSize aToler( 5, 5 );
   if ( !myPolygonBand ) {
     myPolygonBand = new QtxPolyRubberBand( GetRenderWidget() );
     QPalette palette;
     palette.setColor( myPolygonBand->foregroundRole(), Qt::white );
     myPolygonBand->setPalette( palette );
-    myPolygonPoints.append( QPoint( myPoint.x(), myPoint.y() ) );
+    myPolygonPoints.append(myPointCopy);
   }
   myPolygonBand->hide();
 
   bool closed = false;
-  bool valid = GetRenderWidget()->rect().contains( QPoint( myOtherPoint.x(), myOtherPoint.y() ) );
+  bool valid = GetRenderWidget()->rect().contains(myOtherPointCopy);
   if ( !myPolygonPoints.at(0).isNull() )
   {
     QRect aRect( myPolygonPoints.at(0).x() - aToler.width(), myPolygonPoints.at(0).y() - aToler.height(),
                  2 * aToler.width(), 2 * aToler.height() );
-    closed = aRect.contains( QPoint( myOtherPoint.x(), myOtherPoint.y() ) );
+    closed = aRect.contains(myOtherPointCopy);
   }
 
   QPolygon* points = new QPolygon( myPolygonPoints );
-  valid = valid && isValid( points, QPoint( myOtherPoint.x(), myOtherPoint.y() ) );
+  valid = valid && isValid(points, myOtherPointCopy);
   myPoligonState = valid ? InProcess : NotValid;
   delete points;
   if ( closed && !valid )
@@ -1806,7 +1829,7 @@ void SVTK_InteractorStyle::drawPolygon()
   else
     GetRenderWidget()->setCursor( Qt::ForbiddenCursor );
 
-  myPolygonPoints.append( QPoint( myOtherPoint.x(), myOtherPoint.y() ) );
+  myPolygonPoints.append(myOtherPointCopy);
 
   QPolygon aPolygon( myPolygonPoints );
   myPolygonBand->initGeometry( aPolygon );
index c24945c22445e0db9d388a94c080aaad16b4e37b..4ac4dea5f21a8796034d230b637b7c7ea9aa6685 100644 (file)
@@ -30,6 +30,7 @@
 #include "SVTK_Renderer.h"
 #include "SVTK_Functor.h"
 #include "SALOME_Actor.h"
+#include "ViewerTools_ScreenScaling.h"
 
 // QT Includes
 // Put Qt includes before the X11 includes which #define the symbol None
@@ -175,7 +176,8 @@ QVTK_RenderWindowInteractor
 ::polish()
 {
   // Final initialization just before the widget is displayed
-  GetDevice()->SetSize(width(),height());
+  const double pixelRatio = ViewerTools_ScreenScaling::getPR();
+  GetDevice()->SetSize(width() * pixelRatio, height() * pixelRatio);
   if(!GetDevice()->GetInitialized() && GetDevice()->GetRenderWindow()){
     GetDevice()->Initialize();
     GetDevice()->ConfigureEvent();
@@ -208,13 +210,15 @@ QVTK_RenderWindowInteractor
 */
 void
 QVTK_RenderWindowInteractor
-::resizeEvent( QResizeEvent* /*theEvent*/ )
+::resizeEvent( QResizeEvent* /* theEvent */ )
 {
+
   int* aSize = getRenderWindow()->GetSize();
   int aWidth = aSize[0];
   int aHeight = aSize[1];
 
-  GetDevice()->UpdateSize(width(),height());
+  const double pixelRatio = ViewerTools_ScreenScaling::getPR();
+  GetDevice()->UpdateSize(width() * pixelRatio, height() * pixelRatio);
 
   if(isVisible() && aWidth && aHeight){
     if( aWidth != width() || aHeight != height() ) {
@@ -695,6 +699,7 @@ void
 SVTK_RenderWindowInteractor
 ::mouseMoveEvent( QMouseEvent* event ) 
 {
+  event = static_cast<QMouseEvent*>(ViewerTools_ScreenScaling::getDpiAwareEvent(event));
   QVTK_RenderWindowInteractor::mouseMoveEvent(event);
 
   if(GENERATE_SUIT_EVENTS)
@@ -709,6 +714,7 @@ void
 SVTK_RenderWindowInteractor
 ::mousePressEvent( QMouseEvent* event ) 
 {
+  event = static_cast<QMouseEvent*>(ViewerTools_ScreenScaling::getDpiAwareEvent(event));
   QVTK_RenderWindowInteractor::mousePressEvent(event);
 
   if(GENERATE_SUIT_EVENTS)
@@ -733,6 +739,7 @@ SVTK_RenderWindowInteractor
       isOperation = style->CurrentState() != VTK_INTERACTOR_STYLE_CAMERA_NONE;
   }
 
+  event = static_cast<QMouseEvent*>(ViewerTools_ScreenScaling::getDpiAwareEvent(event));
   QVTK_RenderWindowInteractor::mouseReleaseEvent(event);
 
   if ( style ) {
@@ -743,8 +750,10 @@ SVTK_RenderWindowInteractor
   if ( aRightBtn && !isOperation && !isPolygonalSelection &&
        !( event->modifiers() & Qt::ControlModifier ) &&
        !( event->modifiers() & Qt::ShiftModifier ) ) {
+    // We need to pass unscaled coordinates to get a menu painted in a right place.
+    const double pixelRatio = ViewerTools_ScreenScaling::getPR();
     QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
-                              event->pos(), event->globalPos() );
+                              event->pos() / pixelRatio, event->globalPos() / pixelRatio);
     emit contextMenuRequested( &aEvent );
   }
   if(GENERATE_SUIT_EVENTS)
@@ -759,6 +768,8 @@ void
 SVTK_RenderWindowInteractor
 ::mouseDoubleClickEvent( QMouseEvent* event )
 {
+  event = static_cast<QMouseEvent*>(ViewerTools_ScreenScaling::getDpiAwareEvent(event));
+
   if( GetInteractorStyle() && event->button() == Qt::LeftButton ) {
     SVTK_InteractorStyle* style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
     if ( style )
@@ -779,6 +790,8 @@ void
 SVTK_RenderWindowInteractor
 ::wheelEvent( QWheelEvent* event )
 {
+  event = static_cast<QWheelEvent*>(ViewerTools_ScreenScaling::getDpiAwareEvent(event));
+
   QVTK_RenderWindowInteractor::wheelEvent(event);
 
   if(event->delta() > 0)
index b4bd5c6116f9d9207e3cf77581dc7db8152c0dd6..b291e1070405cec17322668750c4c6ed5d7b80d5 100644 (file)
@@ -477,6 +477,25 @@ int AbstractGUIAppMain(int argc, char **argv)
   QApplication::setApplicationName("salome");
   QApplication::setApplicationVersion(salomeVersion());
 
+  // supports HDPI
+  MESSAGE("Set QApplication attributes to supports HDPI...");
+
+  // Make QIcon::pixmap() generate high-dpi pixmaps that can be larger than the requested size.
+  // Such pixmaps will have devicePixelRatio() set to a value higher than 1.
+  // After setting this attribute, application code that uses pixmap sizes in layout geometry calculations
+  // should typically divide by devicePixelRatio() to get device-independent layout geometry.
+  QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+
+  // The lines below do the same - enables automatic scaling, based on the monitor's pixel density.
+  // This won't change the size of point-sized fonts, since point is a physical measurement unit.
+  // Using them can make an impression of large icons among small fonts.
+  // qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
+  // QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // Doesn't scale fonts
+
+  // Keep this line as an example of using explicit scale factor.
+  // Defines a global scale factor for the whole application, including point-sized fonts.
+  // qputenv("QT_SCALE_FACTOR", "1.5"); // Scales everything
+
   // Install Qt debug messages handler
   MsgHandler msgHandler;
   qInstallMessageHandler(QtxMsgHandler);
index 44792cd1154868552a80bd1161d7e37de7c31e43..fa3791cc85ede57957fb3606cb059d4d553a5ee7 100644 (file)
@@ -31,7 +31,10 @@ INCLUDE_DIRECTORIES(
 ADD_DEFINITIONS(${QT_DEFINITIONS})
 
 # libraries to link to
-SET(_link_LIBRARIES ${QT_LIBRARIES} qtx)
+SET(_link_LIBRARIES
+  ${QT_LIBRARIES}
+  ${KERNEL_SALOMELocalTrace}
+  qtx)
 
 # --- headers ---
 
@@ -40,6 +43,7 @@ SET(_moc_HEADERS
   ViewerTools_CubeAxesDlgBase.h
   ViewerTools_DialogBase.h
   ViewerTools_FontWidgetBase.h
+  ViewerTools_ScreenScaling.h
 )
 
 # header files / no moc processing
@@ -67,6 +71,7 @@ SET(_other_SOURCES
   ViewerTools_CubeAxesDlgBase.cxx
   ViewerTools_DialogBase.cxx
   ViewerTools_FontWidgetBase.cxx
+  ViewerTools_ScreenScaling.cxx
 )
 
 # sources / to compile
diff --git a/src/ViewerTools/ViewerTools_ScreenScaling.cxx b/src/ViewerTools/ViewerTools_ScreenScaling.cxx
new file mode 100644 (file)
index 0000000..e4dd6d9
--- /dev/null
@@ -0,0 +1,167 @@
+// Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "ViewerTools_ScreenScaling.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QEvent>
+#include <QMouseEvent>
+#include <QWheelEvent>
+
+#include "utilities.h"
+
+/*!
+ * Namespace   : ViewerTools_ScreenScaling
+ * Description : Tools for handle UI on screens with different scaling
+ */
+namespace ViewerTools_ScreenScaling
+{
+  // Returns pixel ratio for the current screen
+  double getPR()
+  {
+    auto getPixelRatio = []() -> double
+    {
+      // Returns the device pixel ratio for the device as a floating point number.
+      // Common values are 1 for normal-dpi displays and 2 for high-dpi "retina" displays.
+      // Returns QT_SCALE_FACTOR if QT_SCALE_FACTOR was set.
+      // Returns 2 on HDPI if QApplication::setAttribute(Qt::AA_EnableHighDpiScaling) was set.
+      // Returns 2 * QT_SCALE_FACTOR if both of the features above were set.
+      // NOTE. QT_SCALE_FACTOR breaks UI in a set (-1.0, 0.0) and (0.0, 1.0).
+      // Negative values don't scale or break UI down, but end up with 1.0 pixel ratio.
+      const double pixelRatio = QApplication::desktop()->devicePixelRatioF();
+      MESSAGE("pixelRatio: " << pixelRatio);
+
+      // Keep commented block here for a test case where we use QT_SCALE_FACTOR value instead.
+      // QByteArray scaleFactorArr = qgetenv("QT_SCALE_FACTOR");
+      // const QString scaleFactorStr = QString::fromLocal8Bit(scaleFactorArr);
+
+      // bool isScale = false;
+      // const double scaleFactor = scaleFactorStr.toDouble(&isScale);
+      // if (isScale)
+      // {
+      //   MESSAGE("scaleFactor: " << scaleFactor);
+      //   return scaleFactor;
+      // }
+
+      return pixelRatio;
+    };
+
+    // TODO: check if we need to get it out of static to handle moving to another screen
+    static const double pixelRatio = getPixelRatio();
+    return pixelRatio;
+  }
+
+  // Check if we have pixel ratio != 1.0
+  bool isScaledPixelRatio()
+  {
+    auto isScaledPR = []() -> bool
+    {
+      // This an arbitrary value that seems to be meaningful for UI scaling.
+      // It's not clear if we need smaller values.
+      const double epsilon = 0.01;
+      const double pixelRatio = ViewerTools_ScreenScaling::getPR();
+
+      const bool isScaled = std::abs(pixelRatio - 1.0) > epsilon;
+      MESSAGE("isScaled: " << isScaled);
+
+      return isScaled;
+    };
+
+    static const bool isScaled = isScaledPR();
+    return isScaled;
+  }
+
+
+  // Returns a copy of the given event with the local coordinates
+  // updated with the current pixel ratio.
+  QEvent* getDpiAwareEvent(QEvent* e, bool toMultiply/*  = true */)
+  {
+    // Calculate a new position
+    auto getNewPos = [toMultiply](const QPointF& pos) -> QPointF
+    {
+      double pixelRatio = ViewerTools_ScreenScaling::getPR();
+      if (!toMultiply)
+      {
+        pixelRatio = 1.0 / pixelRatio;
+      }
+
+      const double x = pos.x() * pixelRatio;
+      const double y = pos.y() * pixelRatio;
+
+      // Commented because of bloated output for casual debug
+      // MESSAGE("New pos: " << x << ", " << y);
+
+      return QPointF(x, y);
+    };
+
+    // Scales mouse event
+    auto makeMouseEvent = [&getNewPos](QMouseEvent* e) -> QEvent*
+    {
+      const QPointF pos = e->localPos();
+      const QPointF newPos = getNewPos(pos);
+
+      const QPointF globalPos = e->globalPos();
+      const QPointF globalNewPos = getNewPos(globalPos);
+
+      // Commented because of bloated output for casual debug
+      // MESSAGE("type: " << e->type() << "; old: " << pos.x() << ", " << pos.y() << "; new: " << newPos.x() << ", " << newPos.y());
+
+      return new QMouseEvent(e->type(), newPos, globalNewPos, e->button(), e->buttons(), e->modifiers());
+    };
+
+    // Scales wheel event
+    auto makeWheelEvent = [&getNewPos](QWheelEvent* e) -> QEvent*
+    {
+      const QPointF pos = e->posF();
+
+      // Commented because of bloated output for casual debug
+      // MESSAGE("Old pos: " << pos.x() << ", " << pos.y());
+
+      return new QWheelEvent(
+        getNewPos(pos), e->globalPosF(), e->pixelDelta(), e->angleDelta(), e->buttons(), e->modifiers(), e->phase(), e->inverted(), e->source());
+    };
+
+    // Return on start if we don't have any scaling
+    if (!isScaledPixelRatio())
+      return e;
+
+    // Make a copy of the event with the new position
+    const int aType = e->type();
+    switch(aType)
+    {
+      case QEvent::MouseButtonPress:
+      case QEvent::MouseButtonRelease:
+      case QEvent::MouseMove:
+      case QEvent::MouseButtonDblClick:
+        return makeMouseEvent((QMouseEvent*)e);
+
+      case QEvent::Wheel:
+        return makeWheelEvent((QWheelEvent*)e);
+
+      default:
+        break;
+    }
+
+    return e;
+  }
+};
diff --git a/src/ViewerTools/ViewerTools_ScreenScaling.h b/src/ViewerTools/ViewerTools_ScreenScaling.h
new file mode 100644 (file)
index 0000000..12e70fb
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef VIEWERTOOLS_SCREENSCALING_H
+#define VIEWERTOOLS_SCREENSCALING_H
+
+#include "ViewerTools.h"
+
+class QEvent;
+
+/*!
+ * Namespace   : ViewerTools_ScreenScaling
+ * Description : Tools for handle UI on screens with different scaling
+ */
+namespace ViewerTools_ScreenScaling
+{
+  // Returns pixel ratio for the current screen
+  VIEWERTOOLS_EXPORT double getPR();
+
+  // Check if we have pixel ratio != 1.0
+  VIEWERTOOLS_EXPORT bool isScaledPixelRatio();
+
+  // Returns a copy of the given event with the local coordinates
+  // updated with the current pixel ratio.
+  VIEWERTOOLS_EXPORT QEvent* getDpiAwareEvent(QEvent* e, bool toMultiply = true);
+}
+
+#endif