<div dir="ltr">Thanks a lot Nathan !<br></div><div class="gmail_extra"><br><div class="gmail_quote">2015-04-17 14:40 GMT+02:00 Nathan Woodrow <span dir="ltr"><<a href="mailto:madmanwoo@gmail.com" target="_blank">madmanwoo@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">And here is a different way using just functions:<div><br></div><div>(<a href="https://gist.github.com/mdouchin/72a09b629a5557c1dc1c#comment-1435388" target="_blank">https://gist.github.com/mdouchin/72a09b629a5557c1dc1c#comment-1435388</a>)<br><br><div>def forcedScale(*scales):</div><div>    replayed = False</div><div>    </div><div>    def setScale(scale ):</div><div>        iface.mapCanvas().scaleChanged.disconnect(setScale)</div><div>        </div><div>        print "initial scale: %s" % scale</div><div>        </div><div>        targetScale = min(</div><div>            scales, </div><div>            key=lambda x:abs(x-scale)</div><div>        )</div><div>        if targetScale == scale:</div><div>            return</div><div>        </div><div>        print "zoom to %s" % targetScale</div><div>        iface.mapCanvas().zoomScale( targetScale )</div><div>        iface.mapCanvas().scaleChanged.connect(setScale)</div><div>        </div><div>    # pre-defined scales</div><div>    predefinedScales = [</div><div>        5000,</div><div>        10000,</div><div>        25000,</div><div>        50000,</div><div>        100000,</div><div>        250000,</div><div>        500000</div><div>    ]</div><div>    </div><div>    # avoid loop</div><div><br></div><div>    iface.mapCanvas().scaleChanged.connect(setScale)</div><div>    </div><div>    if not scales:</div><div>        scales = predefinedScales</div></div></div><div class="HOEnZb"><div class="h5"><br><div class="gmail_quote">On Fri, 17 Apr 2015 at 22:34 kimaidou <<a href="mailto:kimaidou@gmail.com" target="_blank">kimaidou@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">More pythonesque Nathan, thanks !<br></div><div class="gmail_extra"><br><div class="gmail_quote">2015-04-17 14:32 GMT+02:00 Nathan Woodrow <span dir="ltr"><<a href="mailto:madmanwoo@gmail.com" target="_blank">madmanwoo@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><span style="color:rgb(167,29,93);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap">def</span><span style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap"> </span><span style="color:rgb(121,93,163);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap"><span style="color:rgb(0,134,179)">__init__</span></span><span style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap">( </span><span style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap">self</span><span style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap">, </span><span style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap">*</span><span style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap">predefinedScales</span><span style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:16.7999992370605px;white-space:pre-wrap"> ):
</span><br><div>and you can do this</div><div><br></div><div><span style="font-size:13.1999998092651px;line-height:19.7999992370605px">forcedScale(25000, 50000, 100000)</span><br></div></div><div><div><br><div class="gmail_quote">On Fri, 17 Apr 2015 at 22:30 kimaidou <<a href="mailto:kimaidou@gmail.com" target="_blank">kimaidou@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div><div>Hi all,<br><br></div>Improve version here:<br><a href="https://gist.github.com/mdouchin/72a09b629a5557c1dc1c" target="_blank">https://gist.github.com/mdouchin/72a09b629a5557c1dc1c</a> <br><br>with:<br></div><br>* "replayed" variable to avoid probable infinite loop, thanks to Hugo's proposal<br></div><br>* you can now initialize the method with a python list of scales you want to force canvas to:  <br><br>fs =  fs = forcedScale( [25000, 50000, 100000 ] )<br><br></div>Cheers,<br></div>Michaël<br></div><div class="gmail_extra"><br><div class="gmail_quote">2015-04-17 12:27 GMT+02:00 kimaidou <span dir="ltr"><<a href="mailto:kimaidou@gmail.com" target="_blank">kimaidou@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div>Hi Hugo,<br><br></div>Thanks for the anwser. I used some "print scale" and "print targetScale" in my script to check the behavious, and I did not have any "infinite loop" or strange behaviour with it. It seems the related QGIS code is armed against this risks.<br></div><div><br>This python script was only a prototype, and I will surely have a look at the cpp classes and propose a PR to add this option in QGIS core.<br></div><br></div>Michaël<br></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">2015-04-17 11:26 GMT+02:00 Hugo Mercier <span dir="ltr"><<a href="mailto:hugo.mercier@oslandia.com" target="_blank">hugo.mercier@oslandia.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<span><br>
Le 17/04/2015 10:46, kimaidou a écrit :<br>
> Hi QGIS !<br>
><br>
> I would like to be able in QGIS to force the canvas scales to some<br>
> predefined ones. Since we now have project scales (and QGIS pre-defined<br>
> scales) in the scale selector, we could use them, and add a simple<br>
> checkbox near the combobox "Stick to predefined scales".<br>
><br>
> The aim is to force the canvas to render only at these scales. For<br>
> example, if I use the rectangle zoom tool, and I should go toe 1/56003,<br>
> I would instead land on 1/50000 , the closest pre-defined scale.<br>
<br>
</span>That would be nice to have it in the core. I already had to do something<br>
similar with a plugin.<br>
<span><br>
><br>
> I made a little python script as a proof of concept to illustrate it :<br>
> <a href="http://paste.debian.net/167247/" target="_blank">http://paste.debian.net/167247/</a><br>
><br>
> In this script, I hard coded the scales, but oviously we should get them<br>
> from the project properties.<br>
><br>
> I have a question regarding my script. Since I use the<br>
> QgsMapCanvas::scaleChanged signal, I assume the rendering is done twice<br>
> ? Once the "normal" way, and once again after I use the<br>
> QgsMapCanvas::zoomScale method after calculating the new target scale.<br>
><br>
> Any idea for improving it ? I assume I would have to disconnect one (not<br>
> found yet) signal/slot, then set the scale and reconnect this<br>
> signal/slot afterwards ?<br>
<br>
</span>QObject::blockSignals might be of help here. But in this case, you don't<br>
want to block all signals, only yours.<br>
<br>
I guess your solution would work.<br>
You can also use a flag in your callback, something like :<br>
<br>
    def setScale( self, scale ):<br>
        if self.reentrant:<br>
                return<br>
<br>
        targetScale = min(<br>
            self.predefinedScales,<br>
            key=lambda x:abs(x-scale)<br>
        )<br>
        self.reentrant = True<br>
        self.mc.zoomScale( targetScale )<br>
        self.reentrant = False<br>
<br>
_______________________________________________<br>
Qgis-developer mailing list<br>
<a href="mailto:Qgis-developer@lists.osgeo.org" target="_blank">Qgis-developer@lists.osgeo.org</a><br>
<a href="http://lists.osgeo.org/mailman/listinfo/qgis-developer" target="_blank">http://lists.osgeo.org/mailman/listinfo/qgis-developer</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
_______________________________________________<br>
Qgis-developer mailing list<br>
<a href="mailto:Qgis-developer@lists.osgeo.org" target="_blank">Qgis-developer@lists.osgeo.org</a><br>
<a href="http://lists.osgeo.org/mailman/listinfo/qgis-developer" target="_blank">http://lists.osgeo.org/mailman/listinfo/qgis-developer</a></blockquote></div>
</div></div></blockquote></div><br></div>
</blockquote></div>
</div></div></blockquote></div><br></div>