Repository: biolab/orange3

Issue:
Orange3 widgets move around
##### Orange version 3.16.0 (as it was with the previous version) on Anaconda 5.2 (Windows 10 Pro workstation)


##### Expected behavior
When double-clicking on the widget it opens as expected. 
When doing it via contextual menu it opens as expected and remains as expected on its place.

##### Actual behavior
The widget moves to another place when double-clicked. With a few widget someone can manage well, but with complex systems it is quite chaotic.


##### Steps to reproduce the behavior
Just add some widgets and double-click on them.


##### Additional info (worksheets, data, screenshots, ...)
![widgtes_not_ok](https://user-images.githubusercontent.com/29803730/46560483-3dd8e480-c8f4-11e8-949c-ed16a1bdd66e.jpg)
![widgtes_ok](https://user-images.githubusercontent.com/29803730/46560484-3e717b00-c8f4-11e8-9d68-166ffdf2d36e.jpg)





Discussion:
Dude, I have the exact same version and have no problem like this.
Apparently the problem is only on Windows version 10. Tried on another machine, it does exactly the same.
Tried it on a Windows 7 machine, it works.
Tried it on a Linux Debian system, it works. 
I tried on a fresh Windows 10 VM and cannot reproduce it either.

Closing until someone finds a way to reproduce it.
I have these a similar problem on Linux with dwm in tiling mode and can reproduce it at will. 

If I double click, a new windows appears. And in tiling mode, this means that windows are rearranged/resized. The canvas therefore thinks that the widget was dragged because the position of the mouse cursor relative to canvas changed and the widget is moved.
@ajdapretnar 
@enjoysmath

I would like to come back to my original post (#3294).

Generally, I reformat the disks of my workstation every year, but this time I kept it about 3 years. Finally, I did one – reformatted the disks and installed a fresh copy of Windows 10 Pro.

So, left the Anaconda and installed Miniconda – believe or not, it became worse, now when clicking one widget, the two widgets move around (before only one).

On the virtual machine (VirtualBox), it works like a charm – no issues.

Addendum (02/02/2019):
---------------------------
The versions 3.16, 3.17 (never used) 3.18, 3.19 (version that I use now) – all do the same problem.




![or_2019-02-01](https://user-images.githubusercontent.com/29803730/52132672-f3683a00-263f-11e9-9310-3f25b1c96b64.jpg)

@ajdapretnar
@enjoysmath

Update on Orange 3 - widgets moving around:
---------------------------------------------------

I uninstalled everything and did a new installation (first Miniconda then Orange3).
This time I installed Orange3.20.

1. No errors were reported - not so with the previous versions.
(except for the add-ons with the openTSNE, patsy, cv2, which I installed separately)
2. The widgets continue to "dance", but this time only one and curiously it sets itself behind the window - see picture.
(tried a few ones - always the same)

I intend to keep this so-called "beta" version.

![pr-2019-02-02](https://user-images.githubusercontent.com/29803730/52169088-1b849580-2733-11e9-945b-8ad18c7d7919.png)

The behaviour where canvas is behind the widget window is expected/intentional. Go to View and uncheck _Display widgets on top_ to turn off this feature.
@ajdapretnar 
Checked or unchecked the behavior is the same.
Which behaviour?
I was referring to 
> curiously it sets itself behind the window
The dancing around is another issue.
In #3598 someone was kind enough to trace it (on Windows) to a feature called "Smart move".
@thocevar, this looks like a job for somebody with Windows. (= You. :)) See #3598 for the explanation of why this happens.

Resolving patch:
diff --git a/Orange/canvas/canvas/items/nodeitem.py b/Orange/canvas/canvas/items/nodeitem.py
--- a/Orange/canvas/canvas/items/nodeitem.py
+++ b/Orange/canvas/canvas/items/nodeitem.py
@@ -17,7 +17,7 @@
     QPainterPathStroker
 )
 from AnyQt.QtCore import (
-    Qt, QEvent, QPointF, QRectF, QRect, QSize, QTimer, QPropertyAnimation
+    Qt, QEvent, QPointF, QRectF, QRect, QSize, QTime, QTimer, QPropertyAnimation
 )
 from AnyQt.QtCore import pyqtSignal as Signal, pyqtProperty as Property
 
@@ -77,7 +77,7 @@ class NodeBodyItem(GraphicsPathObject):
     """
     def __init__(self, parent=None):
         GraphicsPathObject.__init__(self, parent)
-        assert(isinstance(parent, NodeItem))
+        assert isinstance(parent, NodeItem)
 
         self.__processingState = 0
         self.__progress = -1
@@ -799,6 +799,9 @@ def __init__(self, widget_description=None, parent=None, **kwargs):
         self.warningItem = None
         self.infoItem = None
 
+        self.mousePressTime = QTime()
+        self.mousePressTime.start()
+
         self.__title = ""
         self.__processingState = 0
         self.__progress = -1
@@ -1189,7 +1192,7 @@ def __updateTitleText(self):
             if "progress" in format_fields and len(format_fields) == 1:
                 # Insert progress into the status text format string.
                 spec, _ = format_fields["progress"]
-                if spec != None:
+                if spec is not None:
                     progress_included = True
                     progress_str = "{0:.0f}%".format(self.progress())
                     status_text.append(msg.format(progress=progress_str))
@@ -1241,10 +1244,17 @@ def __updateMessages(self):
                 origin = origin + QPointF(rect.width() + spacing, 0)
 
     def mousePressEvent(self, event):
-        if self.shapeItem.path().contains(event.pos()):
-            return super().mousePressEvent(event)
-        else:
+        if self.mousePressTime.elapsed() < QApplication.doubleClickInterval():
+            # Double-click triggers two mouse press events and a double-click event.
+            # Ignore the second mouse press event (causes widget's node relocation with
+            # Logitech's Smart Move).
             event.ignore()
+        else:
+            self.mousePressTime.restart()
+            if self.shapeItem.path().contains(event.pos()):
+                super().mousePressEvent(event)
+            else:
+                event.ignore()
 
     def mouseDoubleClickEvent(self, event):
         if self.shapeItem.path().contains(event.pos()):
@@ -1255,17 +1265,17 @@ def mouseDoubleClickEvent(self, event):
 
     def contextMenuEvent(self, event):
         if self.shapeItem.path().contains(event.pos()):
-            return super().contextMenuEvent(event)
+            super().contextMenuEvent(event)
         else:
             event.ignore()
 
     def focusInEvent(self, event):
         self.shapeItem.setHasFocus(True)
-        return super().focusInEvent(event)
+        super().focusInEvent(event)
 
     def focusOutEvent(self, event):
         self.shapeItem.setHasFocus(False)
-        return super().focusOutEvent(event)
+        super().focusOutEvent(event)
 
     def changeEvent(self, event):
         if event.type() == QEvent.PaletteChange:
@@ -1332,13 +1342,13 @@ def NodeItem_toolTipHelper(node, links_in=[], links_out=[]):
         inputs = [channel_fmt.format(inp.name) for inp in desc.inputs]
         inputs = inputs_list_fmt.format(inputs="".join(inputs))
     else:
-        inputs = "No inputs<hr/>" 
+        inputs = "No inputs<hr/>"
 
     if desc.outputs:
         outputs = [channel_fmt.format(out.name) for out in desc.outputs]
         outputs = outputs_list_fmt.format(outputs="".join(outputs))
     else:
-        outputs = "No outputs" 
+        outputs = "No outputs"
 
     tooltip = title + inputs + outputs
     style = "ul { margin-top: 1px; margin-bottom: 1px; }"


Test patch: