<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Ubuntu;
        panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        mso-ligatures:standardcontextual;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:Consolas;}
span.EmailStyle21
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal">So it seems that when I select all the features, triggering the rotation action deselects them all when I click the left mouse button to rotate and so I am left again with just rotating the center feature.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I thought well maybe select the features after triggering the rotation and that somewhat works in that the features are all still selected when the rotation is triggered, but the rotation then appear not to be centered around the object
 because when I move the mouse all of the features move across the map and the rotation just changes by hundreds of degrees.  Its like the rotation is happening around some far object rather than the center point.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="mso-ligatures:none">From:</span></b><span style="mso-ligatures:none"> Jacky Volpes <jacky.volpes@oslandia.com>
<br>
<b>Sent:</b> Tuesday, August 6, 2024 10:06 AM<br>
<b>To:</b> Catania, Luke A ERDC-RDE-GRL-VA CIV <Luke.A.Catania@erdc.dren.mil>; 'qgis-developer' <qgis-developer@lists.osgeo.org><br>
<b>Subject:</b> Re: [QGIS-Developer] Rotating selected features programmatically<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="font-family:"Ubuntu",serif">Hi Luke,<br>
<br>
>  and only rotates the inner most one.<br>
<br>
Like I guessed, it's because element_layer_rotated() commits and ends the edition of the layer (and disconnects signal) as soon as the first feature geometry has been changed, so all other change won't follow.<br>
<br>
Here is a way to wait for every selected feature to be rotated (feel free to adapt):<br>
<br>
<br>
 <br>
def element_layer_rotated(self):<br>
        """When the rotate action is triggered it seems to ignore the ElementPlacementTool events, so in order to end the edit session<br>
        we need to detect a geometryChanged event after the rotation is complete.<br>
        """<br>
<br>
        # Do nothing if all the selected features have not been rotated</span><br>
<span style="font-family:"Ubuntu",serif">        if set(self.vector_layer.selectedFeatureIds()) != set(self.vector_layer.editBuffer().changedGeometries().keys()):<br>
                return<br>
<br>
        QgsMessageLog.logMessage(f"Element Layer Rotated: {self.vector_layer.name()}", "ElementPlacementTool", Qgis.Info)<br>
 <br>
        # Disconnect from the signal so we can just commit the changes.<br>
        self.vector_layer.editBuffer().geometryChanged.disconnect(</span>self.element_layer_rotated<span style="font-family:"Ubuntu",serif">)<br>
 <br>
        # Save changes and end edit mode<br>
        self.vector_layer.commitChanges()<br>
        self.vector_layer.endEditCommand()<br>
        self.deactivate()<br>
<br>
<br>
Regards,<br>
<br>
</span><span style="mso-ligatures:none"><o:p></o:p></span></p>
<pre>--<o:p></o:p></pre>
<pre>Jacky Volpes<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>Ingénieur développeur SIG - Oslandia<o:p></o:p></pre>
<div>
<p class="MsoNormal">Le 05/08/2024 à 19:44, Catania, Luke A ERDC-RDE-GRL-VA CIV a écrit :<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal">So I found that I could use a selectAll() method on the layer directly rather than use the processing tool, but when I call the trigger on the rotate action it unselects all the features and only rotates the inner most one.<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="mso-ligatures:none">From:</span></b><span style="mso-ligatures:none"> QGIS-Developer
<a href="mailto:qgis-developer-bounces@lists.osgeo.org"><qgis-developer-bounces@lists.osgeo.org></a>
<b>On Behalf Of </b>Catania, Luke A ERDC-RDE-GRL-VA CIV via QGIS-Developer<br>
<b>Sent:</b> Monday, August 5, 2024 1:22 PM<br>
<b>To:</b> Jacky Volpes <a href="mailto:jacky.volpes@oslandia.com"><jacky.volpes@oslandia.com></a>; 'qgis-developer'
<a href="mailto:qgis-developer@lists.osgeo.org"><qgis-developer@lists.osgeo.org></a><br>
<b>Subject:</b> Re: [QGIS-Developer] Rotating selected features programmatically</span><o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">Well.  Now for some reason my select by expression tool is not selecting any features, so need to figure out why that is happening before implementing this change. I did not make any changes that I can see that would have caused this.<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="mso-ligatures:none">From:</span></b><span style="mso-ligatures:none"> Jacky Volpes <<a href="mailto:jacky.volpes@oslandia.com">jacky.volpes@oslandia.com</a>>
<br>
<b>Sent:</b> Monday, August 5, 2024 5:14 AM<br>
<b>To:</b> Catania, Luke A ERDC-RDE-GRL-VA CIV <<a href="mailto:Luke.A.Catania@erdc.dren.mil">Luke.A.Catania@erdc.dren.mil</a>>; 'qgis-developer' <<a href="mailto:qgis-developer@lists.osgeo.org">qgis-developer@lists.osgeo.org</a>><br>
<b>Subject:</b> Re: [QGIS-Developer] Rotating selected features programmatically</span><o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-family:"Ubuntu",serif">Hi Luke,<br>
<br>
My guess is that when more than one feature is selected, and the rotation is ended, geometryChanged signal is emitted for each rotated feature.<br>
<br>
element_layer_rotated() is run when the first geometryChanged signal is emitted, and is disconnected, and the layer is saved, and the other geometryChanged signals don't trigger anything.<br>
<br>
NB: self.vector_layer.editBuffer().geometryChanged.disconnect()       is risky, if other slots are connected, prefer      self.vector_layer.editBuffer().geometryChanged.disconnect(self.element_layer_rotated)</span><br>
<span style="font-family:"Ubuntu",serif"><br>
Regards,</span><o:p></o:p></p>
<pre>--<o:p></o:p></pre>
<pre>Jacky Volpes<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>Ingénieur développeur SIG - Oslandia<o:p></o:p></pre>
<div>
<p class="MsoNormal">Le 01/08/2024 à 20:29, Catania, Luke A ERDC-RDE-GRL-VA CIV a écrit :<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal">def rotateFeature(self):<o:p></o:p></p>
<p class="MsoNormal">        """Find the rotate feature action in QGIS toolbar and trigger it so the user can rotate the element.<o:p></o:p></p>
<p class="MsoNormal">        """<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">        # We want to detect when the rotation is complete with a geometryChanged signal so we can commit the changes and<o:p></o:p></p>
<p class="MsoNormal">        # end the edit session.<o:p></o:p></p>
<p class="MsoNormal">        self.vector_layer.editBuffer().geometryChanged.connect(self.element_layer_rotated)<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">        # Get all actions so we can search for the mActionRotateFeature action.<o:p></o:p></p>
<p class="MsoNormal">        actions = iface.mainWindow().findChildren(QAction)<o:p></o:p></p>
<p class="MsoNormal">        action = [x for x in actions if x.objectName()=='mActionRotateFeature'][0]<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">        expression = '"Element_Nb" = '<o:p></o:p></p>
<p class="MsoNormal">        expression = expression + "\'" + f'{self.element_number}' + "\'"<o:p></o:p></p>
<p class="MsoNormal">        QgsMessageLog.logMessage(f"expression: {expression}", "StandoffLayers", Qgis.Info)<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">        processing.run("qgis:selectbyexpression", <o:p></o:p></p>
<p class="MsoNormal">                       {'INPUT':self.vector_layer,<o:p></o:p></p>
<p class="MsoNormal">                        'EXPRESSION': expression,<o:p></o:p></p>
<p class="MsoNormal">                        'METHOD':0<o:p></o:p></p>
<p class="MsoNormal">                        }<o:p></o:p></p>
<p class="MsoNormal">        )<o:p></o:p></p>
<p class="MsoNormal">        # Inititates rotate feature action allowing to select a snap to value.<o:p></o:p></p>
<p class="MsoNormal">        action.trigger()<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">        QgsMessageLog.logMessage(f"Rotate Feature Action Triggered", "ElementPlacementTool", Qgis.Info)<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">def element_layer_rotated(self):<o:p></o:p></p>
<p class="MsoNormal">        """When the rotate action is triggered it seems to ignore the ElementPlacementTool events, so in order to end the edit session<o:p></o:p></p>
<p class="MsoNormal">        we need to detect a geometryChanged event after the rotation is complete.<o:p></o:p></p>
<p class="MsoNormal">        """<o:p></o:p></p>
<p class="MsoNormal">        QgsMessageLog.logMessage(f"Element Layer Rotated: {self.vector_layer.name()}", "ElementPlacementTool", Qgis.Info)<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">        # Disconnect from the signal so we can just commit the changes.<o:p></o:p></p>
<p class="MsoNormal">        self.vector_layer.editBuffer().geometryChanged.disconnect()<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">        # Save changes and end edit mode<o:p></o:p></p>
<p class="MsoNormal">        self.vector_layer.commitChanges()<o:p></o:p></p>
<p class="MsoNormal">        self.vector_layer.endEditCommand()<o:p></o:p></p>
<p class="MsoNormal">        self.deactivate()<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="mso-ligatures:none">From:</span></b><span style="mso-ligatures:none"> Jacky Volpes
<a href="mailto:jacky.volpes@oslandia.com"><jacky.volpes@oslandia.com></a> <br>
<b>Sent:</b> Thursday, August 1, 2024 8:26 AM<br>
<b>To:</b> Catania, Luke A ERDC-RDE-GRL-VA CIV <a href="mailto:Luke.A.Catania@erdc.dren.mil">
<Luke.A.Catania@erdc.dren.mil></a>; 'qgis-developer' <a href="mailto:qgis-developer@lists.osgeo.org">
<qgis-developer@lists.osgeo.org></a><br>
<b>Subject:</b> Re: [QGIS-Developer] Rotating selected features programmatically</span><o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-family:"Ubuntu",serif">Hi Luke,<br>
<br>
Please provide a PyQGIS code snippet to reproduce. It will be more convenient to comment and suggest modifications.<br>
Thanks,<br>
<br>
<br>
</span><o:p></o:p></p>
<pre>--<o:p></o:p></pre>
<pre>Jacky Volpes<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>Ingénieur développeur SIG - Oslandia<o:p></o:p></pre>
<div>
<p class="MsoNormal"><br>
Le 26/07/2024 à 22:06, Catania, Luke A ERDC-RDE-GRL-VA CIV via QGIS-Developer a écrit :<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal">I am using the select by expression tool through python to select my features and then I trigger rotation through python I see both selected features rotating, but when I click to end the rotation, it only rotated one of the features and
 left the other one as is.  If I do this through the QGIS using the selection by expression in the selection toolbar and the rotate in the advanced digitizing tool bar rotating both features works fine.<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">Any Ideas?<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">Luke<o:p></o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="mso-ligatures:none"><br>
<br>
<br>
</span><o:p></o:p></p>
<pre>_______________________________________________<o:p></o:p></pre>
<pre>QGIS-Developer mailing list<o:p></o:p></pre>
<pre><a href="mailto:QGIS-Developer@lists.osgeo.org">QGIS-Developer@lists.osgeo.org</a><o:p></o:p></pre>
<pre>List info: <a href="Blockedhttps://lists.osgeo.org/mailman/listinfo/qgis-developerBlocked">Blockedhttps://lists.osgeo.org/mailman/listinfo/qgis-developerBlocked</a><o:p></o:p></pre>
<pre>Unsubscribe: <a href="Blockedhttps://lists.osgeo.org/mailman/listinfo/qgis-developerBlocked">Blockedhttps://lists.osgeo.org/mailman/listinfo/qgis-developerBlocked</a><o:p></o:p></pre>
</blockquote>
<p class="MsoNormal"><span style="mso-ligatures:none"> </span><o:p></o:p></p>
</blockquote>
<p class="MsoNormal"><span style="mso-ligatures:none"> </span><o:p></o:p></p>
</blockquote>
<p class="MsoNormal"><span style="mso-ligatures:none"><o:p> </o:p></span></p>
</div>
</body>
</html>