Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Display Widgets on Top option #3038

Merged
merged 6 commits into from
Jun 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Orange/canvas/application/canvasmain.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,13 @@ def setup_actions(self):
QAction(self.tr("Reset Widget Settings..."), self,
triggered=self.reset_widget_settings)

self.float_widgets_on_top_action = \
QAction(self.tr("Display Widgets on Top"), self,
checkable=True,
toolTip=self.tr("Widgets are always displayed above other windows."))
self.float_widgets_on_top_action.toggled.connect(
self.set_float_widgets_on_top_enabled)

def setup_menu(self):
if sys.platform == "darwin" and QT_VERSION >= 0x50000:
self.__menu_glob = QMenuBar(None)
Expand Down Expand Up @@ -694,6 +701,7 @@ def setup_menu(self):
self.view_menu.addSeparator()

self.view_menu.addAction(self.toogle_margins_action)
self.view_menu.addAction(self.float_widgets_on_top_action)
menu_bar.addMenu(self.view_menu)

# Options menu
Expand Down Expand Up @@ -760,6 +768,10 @@ def restore(self):
settings.value("quick-help/visible", True, type=bool)
)

self.float_widgets_on_top_action.setChecked(
settings.value("widgets-float-on-top", False, type=bool)
)

self.__update_from_settings()

def set_document_title(self, title):
Expand Down Expand Up @@ -925,6 +937,7 @@ def create_new_window(self):
window.restoreState(self.saveState(self.SETTINGS_VERSION),
self.SETTINGS_VERSION)
window.set_tool_dock_expanded(self.dock_widget.expanded())
window.set_float_widgets_on_top_enabled(self.float_widgets_on_top_action.isChecked())

logview = window.log_view() # type: OutputView
te = logview.findChild(QPlainTextEdit)
Expand Down Expand Up @@ -1655,6 +1668,13 @@ def reset_widget_settings(self):
"Settings will still be reset at next application start",
parent=self)

def set_float_widgets_on_top_enabled(self, enabled):
if self.float_widgets_on_top_action.isChecked() != enabled:
self.float_widgets_on_top_action.setChecked(enabled)

wm = self.current_document().scheme().widget_manager
wm.set_float_widgets_on_top(enabled)

def show_report_view(self):
from Orange.canvas.report.owreport import OWReport
doc = self.current_document()
Expand Down Expand Up @@ -1822,6 +1842,8 @@ def closeEvent(self, event):

settings.setValue("quick-help/visible",
self.canvas_tool_dock.quickHelpVisible())
settings.setValue("widgets-float-on-top",
self.float_widgets_on_top_action.isChecked())

settings.endGroup()
self.help_dock.close()
Expand Down Expand Up @@ -1974,6 +1996,11 @@ def __update_from_settings(self):
defaultValue=15,
type=int)

float_widgets_on_top = settings.value("widgets-float-on-top",
defaultValue=False,
type=bool)
self.set_float_widgets_on_top_enabled(float_widgets_on_top)

settings.endGroup()
settings.beginGroup("quickmenu")

Expand Down
3 changes: 3 additions & 0 deletions Orange/canvas/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ def init():
"Use a popover menu to select a widget when clicking on a category "
"button"),

("mainwindow/widgets-float-on-top", bool, False,
"Float widgets on top of other windows"),

("mainwindow/number-of-recent-schemes", int, 15,
"Number of recent workflows to keep in history"),

Expand Down
47 changes: 45 additions & 2 deletions Orange/canvas/scheme/widgetsscheme.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@

import sip

from AnyQt.QtWidgets import QWidget, QShortcut, QLabel, QSizePolicy, QAction
from AnyQt.QtWidgets import QWidget, QShortcut, QLabel, QSizePolicy, QAction, qApp
from AnyQt.QtGui import QKeySequence, QWhatsThisClickedEvent

from AnyQt.QtCore import Qt, QObject, QCoreApplication, QTimer, QEvent
from AnyQt.QtCore import pyqtSignal as Signal

from .signalmanager import SignalManager, compress_signals, can_enable_dynamic
from .scheme import Scheme, SchemeNode, SchemeLink
from .scheme import Scheme, SchemeNode
from .node import UserMessage
from ..utils import name_lookup
from ..resources import icon_loader
Expand Down Expand Up @@ -258,6 +258,15 @@ def __init__(self, parent=None):
# Tracks the widget in the update loop by the SignalManager
self.__updating_widget = None

# Widgets float above other windows
self.__float_widgets_on_top = False
if hasattr(qApp, "applicationStateChanged"):
# disables/enables widget floating when app (de)activates
# available in Qt >= 5.2
def reapply_float_on_top():
self.set_float_widgets_on_top(self.__float_widgets_on_top)
qApp.applicationStateChanged.connect(reapply_float_on_top)

def set_scheme(self, scheme):
"""
Set the :class:`WidgetsScheme` instance to manage.
Expand Down Expand Up @@ -597,6 +606,9 @@ def create_widget_instance(self, node):
widget.setCaption(node.title)
# befriend class Report
widget._Report__report_view = self.scheme().report_view

self.__set_float_on_top_flag(widget)

# Schedule an update with the signal manager, due to the cleared
# implicit Initializing flag
self.signal_manager()._update()
Expand Down Expand Up @@ -627,6 +639,15 @@ def widget_processing_state(self, widget):
"""
return self.__widget_processing_state[widget]

def set_float_widgets_on_top(self, float_on_top):
"""
Set `Float Widgets on Top` flag on all widgets.
"""
self.__float_widgets_on_top = float_on_top

for widget in self.__widget_for_node.values():
self.__set_float_on_top_flag(widget)

def __create_delayed(self):
if self.__init_queue:
state = self.__init_queue.popleft()
Expand Down Expand Up @@ -790,6 +811,28 @@ def __on_env_changed(self, key, newvalue, oldvalue):
for widget in self.__widget_for_node.values():
widget.workflowEnvChanged(key, newvalue, oldvalue)

def __set_float_on_top_flag(self, widget):
"""Set or unset widget's float on top flag"""
should_float_on_top = self.__float_widgets_on_top
if hasattr(qApp, "applicationState"):
# only float on top when the application is active
# available in Qt >= 5.2
should_float_on_top &= qApp.applicationState() == Qt.ApplicationActive
float_on_top = widget.windowFlags() & Qt.WindowStaysOnTopHint

if float_on_top == should_float_on_top:
return

widget_was_visible = widget.isVisible()
if should_float_on_top:
widget.setWindowFlags(Qt.WindowStaysOnTopHint)
else:
widget.setWindowFlags(widget.windowFlags() & ~Qt.WindowStaysOnTopHint)

# Changing window flags hid the widget
if widget_was_visible:
widget.show()


def user_message_from_state(message_group):
return UserMessage(
Expand Down