Skip to content

Commit d783de3

Browse files
authored
Merge pull request #3517 from OpenShot/tutorial-positioning
Adjust position of tutorial message (for smaller screens)
2 parents a45a82d + f6ff0c9 commit d783de3

File tree

1 file changed

+81
-27
lines changed

1 file changed

+81
-27
lines changed

src/windows/views/tutorial.py

+81-27
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,30 @@ def checkbox_metrics_callback(self, state):
7777
# Disable metric sending
7878
s.set("send_metrics", False)
7979

80-
def __init__(self, id, text, arrow, *args):
80+
def keyPressEvent(self, event):
81+
""" Process key press events and match with known shortcuts"""
82+
# Detect the current KeySequence pressed (including modifier keys)
83+
key_value = event.key()
84+
modifiers = int(event.modifiers())
85+
86+
# Abort handling if the key sequence is invalid
87+
if (key_value <= 0 or key_value in
88+
[Qt.Key_Shift, Qt.Key_Alt, Qt.Key_Control, Qt.Key_Meta]):
89+
return
90+
91+
# A valid keysequence was detected
92+
key = QKeySequence(modifiers + key_value)
93+
if key == Qt.Key_Escape:
94+
# User hit Escape key, hide tutorial permanently
95+
self.manager.hide_tips(self.id, True)
96+
97+
def mouseReleaseEvent(self, event):
98+
"""Process click events on tutorial. Especially useful when tutorial messages are partially
99+
obscured or offscreen (i.e. on small screens). Just click any part of the tutorial, and it will
100+
move on to the next one."""
101+
self.manager.next_tip(self.id)
102+
103+
def __init__(self, id, text, arrow, manager, *args):
81104
# Invoke parent init
82105
QWidget.__init__(self, *args)
83106

@@ -88,6 +111,7 @@ def __init__(self, id, text, arrow, *args):
88111
# Keep track of widget to position next to
89112
self.id = id
90113
self.arrow = arrow
114+
self.manager = manager
91115

92116
# Create vertical box
93117
vbox = QVBoxLayout()
@@ -99,6 +123,7 @@ def __init__(self, id, text, arrow, *args):
99123
self.label.setTextFormat(Qt.RichText)
100124
self.label.setWordWrap(True)
101125
self.label.setStyleSheet("margin-left: 20px;")
126+
self.label.setAttribute(Qt.WA_TransparentForMouseEvents)
102127
vbox.addWidget(self.label)
103128

104129
# Add error and anonymous metrics checkbox (for ID=0) tooltip
@@ -138,12 +163,11 @@ def __init__(self, id, text, arrow, *args):
138163
self.setCursor(Qt.ArrowCursor)
139164
self.setMinimumWidth(350)
140165
self.setMinimumHeight(100)
166+
self.setFocusPolicy(Qt.ClickFocus)
141167

142168
# Make transparent
143169
self.setAttribute(Qt.WA_NoSystemBackground, True)
144170
self.setAttribute(Qt.WA_TranslucentBackground, True)
145-
# self.setWindowFlags(Qt.FramelessWindowHint)
146-
147171
self.setAttribute(Qt.WA_DeleteOnClose, True)
148172

149173

@@ -176,7 +200,7 @@ def process(self, parent_name=None):
176200
self.position_widget = tutorial_object
177201
self.x_offset = tutorial_details["x"]
178202
self.y_offset = tutorial_details["y"]
179-
tutorial_dialog = TutorialDialog(tutorial_id, tutorial_details["text"], tutorial_details["arrow"])
203+
tutorial_dialog = TutorialDialog(tutorial_id, tutorial_details["text"], tutorial_details["arrow"], self)
180204

181205
# Connect signals
182206
tutorial_dialog.btn_next_tip.clicked.connect(functools.partial(self.next_tip, tutorial_id))
@@ -207,14 +231,21 @@ def get_object(self, object_id):
207231
return self.win.filesView
208232
elif object_id == "timeline":
209233
return self.win.timeline
210-
elif object_id == "dockVideoContents":
211-
return self.win.dockVideoContents
234+
elif object_id == "dockVideo":
235+
return self.win.dockVideo
212236
elif object_id == "propertyTableView":
213237
return self.win.propertyTableView
214238
elif object_id == "transitionsView":
215239
return self.win.transitionsView
216240
elif object_id == "effectsView":
217241
return self.win.effectsView
242+
elif object_id == "emojisView":
243+
return self.win.emojiListView
244+
elif object_id == "actionPlay":
245+
play_button = None
246+
for w in self.win.actionPlay.associatedWidgets():
247+
if type(w) == QToolButton:
248+
return w
218249
elif object_id == "export_button":
219250
# Find export toolbar button on main window
220251
export_button = None
@@ -252,6 +283,9 @@ def hide_tips(self, tid, user_clicked=False):
252283
self.tutorial_enabled = False
253284
s.set("tutorial_enabled", False)
254285

286+
# Forgot current tutorial
287+
self.current_dialog = None
288+
255289
def close_dialogs(self):
256290
""" Close any open tutorial dialogs """
257291
if self.current_dialog:
@@ -288,10 +322,23 @@ def hide_dialog(self):
288322
def re_position_dialog(self):
289323
""" Reposition a tutorial dialog next to another widget """
290324
if self.current_dialog:
291-
""" Move widget next to its position widget """
292-
x = self.position_widget.mapToGlobal(self.position_widget.pos()).x()
293-
y = self.position_widget.mapToGlobal(self.position_widget.pos()).y()
294-
self.dock.move(QPoint(x + self.x_offset, y + self.y_offset))
325+
""" Move widget next to its position widget. Padd with 1/4 width of widget, so the tutorial dialog
326+
floats a bit, and add custom offets for certain widgets, such as the Export button.
327+
"""
328+
x = self.position_widget.mapToGlobal(self.position_widget.rect().topLeft()).x() + \
329+
(self.position_widget.width() / 4) + self.x_offset
330+
y = self.position_widget.mapToGlobal(self.position_widget.rect().topLeft()).y() + \
331+
(self.position_widget.height() / 4) + self.y_offset
332+
333+
# Hide / Show tutorial dialog based on if the position widget has valid coordinates
334+
# When a dock is invisible, the widgets inside are located in negative coordinate space.
335+
if x < 0 or y < 0:
336+
self.hide_dialog()
337+
else:
338+
self.re_show_dialog()
339+
340+
# Move tutorial widget to the correct position
341+
self.dock.move(QPoint(x, y))
295342

296343
def __init__(self, win):
297344
""" Constructor """
@@ -311,56 +358,63 @@ def __init__(self, win):
311358
# Add all possible tutorials
312359
self.tutorial_objects = [
313360
{"id": "0",
314-
"x": 400,
361+
"x": 0,
315362
"y": 0,
316-
"object_id": "filesView",
363+
"object_id": "dockVideo",
317364
"text": _("<b>Welcome!</b> OpenShot Video Editor is an award-winning, open-source video editing application! This tutorial will walk you through the basics.<br><br>Would you like to automatically send errors and metrics to help improve OpenShot?"),
318365
"arrow": False
319366
},
320367
{"id": "1",
321-
"x": 20,
368+
"x": 0,
322369
"y": 0,
323370
"object_id": "filesView",
324371
"text": _("<b>Project Files:</b> Get started with your project by adding video, audio, and image files here. Drag and drop files from your file system."),
325372
"arrow": True
326373
},
327374
{"id": "2",
328-
"x": 200,
329-
"y": -15,
375+
"x": 0,
376+
"y": 0,
330377
"object_id": "timeline",
331378
"text": _("<b>Timeline:</b> Arrange your clips on the timeline here. Overlap clips to create automatic transitions. Access lots of fun presets and options by right-clicking on clips."),
332379
"arrow": True
333380
},
334381
{"id": "3",
335-
"x": 200,
336-
"y": 100,
337-
"object_id": "dockVideoContents",
382+
"x": 10,
383+
"y": -27,
384+
"object_id": "actionPlay",
338385
"text": _("<b>Video Preview:</b> Watch your timeline video preview here. Use the buttons (play, rewind, fast-forward) to control the video playback."),
339386
"arrow": True},
340387
{"id": "4",
341-
"x": 20,
342-
"y": -35,
388+
"x": 0,
389+
"y": 0,
343390
"object_id": "propertyTableView",
344391
"text": _("<b>Properties:</b> View and change advanced properties of clips and effects here. Right-clicking on clips is usually faster than manually changing properties."),
345392
"arrow": True
346393
},
347394
{"id": "5",
348-
"x": 20,
349-
"y": 10,
395+
"x": 0,
396+
"y": 0,
350397
"object_id": "transitionsView",
351398
"text": _("<b>Transitions:</b> Create a gradual fade from one clip to another. Drag and drop a transition onto the timeline and position it on top of a clip (usually at the beginning or ending)."),
352399
"arrow": True
353400
},
354401
{"id": "6",
355-
"x": 20,
356-
"y": 20,
402+
"x": 0,
403+
"y": 0,
357404
"object_id": "effectsView",
358405
"text": _("<b>Effects:</b> Adjust brightness, contrast, saturation, and add exciting special effects. Drag and drop an effect onto the timeline and position it on top of a clip (or track)"),
359406
"arrow": True
360407
},
408+
{"id": "8",
409+
"x": 0,
410+
"y": 0,
411+
"object_id": "emojisView",
412+
"text": _("<b>Emojis:</b> Add exciting and colorful emojis to your project! Drag and drop an emoji onto the timeline. The emoji will become a new Clip when dropped on the Timeline."),
413+
"arrow": True
414+
},
361415
{"id": "7",
362-
"x": -265,
363-
"y": -22,
416+
"x": 10,
417+
"y": -27,
364418
"object_id": "export_button",
365419
"text": _("<b>Export Video:</b> When you are ready to create your finished video, click this button to export your timeline as a single video file."),
366420
"arrow": True
@@ -374,13 +428,13 @@ def __init__(self, win):
374428
self.dock.setWindowFlags(Qt.FramelessWindowHint)
375429
self.dock.setFloating(True)
376430

377-
378431
# Connect to interface dock widgets
379432
self.win.dockFiles.visibilityChanged.connect(functools.partial(self.process, "dockFiles"))
380433
self.win.dockTransitions.visibilityChanged.connect(functools.partial(self.process, "dockTransitions"))
381434
self.win.dockEffects.visibilityChanged.connect(functools.partial(self.process, "dockEffects"))
382435
self.win.dockProperties.visibilityChanged.connect(functools.partial(self.process, "dockProperties"))
383436
self.win.dockVideo.visibilityChanged.connect(functools.partial(self.process, "dockVideo"))
437+
self.win.dockEmojis.visibilityChanged.connect(functools.partial(self.process, "dockEmojis"))
384438

385439
# Process tutorials (1 by 1)
386440
if self.tutorial_enabled:

0 commit comments

Comments
 (0)