Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Multimedia
Kdenlive
Commits
ee1d1a97
Commit
ee1d1a97
authored
Dec 11, 2020
by
Jean-Baptiste Mardelle
Browse files
Move timeline tooltips in statusbar.
Fixes
#867
parent
a2cb2600
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/definitions.h
View file @
ee1d1a97
...
...
@@ -142,7 +142,7 @@ enum MonitorSceneType {
MonitorSplitTrack
};
enum
MessageType
{
DefaultMessage
,
ProcessingJobMessage
,
OperationCompletedMessage
,
InformationMessage
,
ErrorMessage
,
MltError
};
enum
MessageType
{
DefaultMessage
,
ProcessingJobMessage
,
OperationCompletedMessage
,
InformationMessage
,
ErrorMessage
,
MltError
,
DirectMessage
};
namespace
BinMessage
{
enum
BinCategory
{
NoMessage
=
0
,
ProfileMessage
,
StreamsMessage
,
InformationMessage
};
...
...
src/statusbarmessagelabel.cpp
View file @
ee1d1a97
...
...
@@ -76,6 +76,7 @@ StatusBarMessageLabel::StatusBarMessageLabel(QWidget *parent)
m_pixmap
->
setAlignment
(
Qt
::
AlignCenter
);
m_label
=
new
QLabel
(
this
);
m_label
->
setAlignment
(
Qt
::
AlignLeft
);
m_label
->
setFont
(
QFontDatabase
::
systemFont
(
QFontDatabase
::
SmallestReadableFont
));
m_progress
=
new
QProgressBar
(
this
);
lay
->
addWidget
(
m_pixmap
);
lay
->
addWidget
(
m_label
);
...
...
@@ -124,7 +125,7 @@ void StatusBarMessageLabel::setMessage(const QString &text, MessageType type, in
m_queueSemaphore
.
acquire
();
if
(
!
m_messageQueue
.
contains
(
item
))
{
if
(
item
.
type
==
ErrorMessage
||
item
.
type
==
MltError
||
item
.
type
==
ProcessingJobMessage
||
item
.
type
==
OperationCompletedMessage
)
{
if
(
item
.
type
==
ErrorMessage
||
item
.
type
==
MltError
||
item
.
type
==
ProcessingJobMessage
||
item
.
type
==
OperationCompletedMessage
||
item
.
type
==
DirectMessage
)
{
qCDebug
(
KDENLIVE_LOG
)
<<
item
.
text
;
// Put the new error message at first place and immediately show it
...
...
src/timeline2/view/qml/Clip.qml
View file @
ee1d1a97
...
...
@@ -98,6 +98,7 @@ Rectangle {
if
(
clipRoot
.
isGrabbed
)
{
grabItem
()
}
else
{
timeline
.
showToolTip
()
mouseArea
.
focus
=
false
}
}
...
...
@@ -118,24 +119,6 @@ Rectangle {
color
:
Qt
.
darker
(
getColor
(),
1.5
)
}
}
ToolTip
{
visible
:
mouseArea
.
containsMouse
&&
!
dragProxyArea
.
pressed
&&
!
trimInMouseArea
.
containsMouse
&&
!
trimOutMouseArea
.
containsMouse
&&
!
fadeInMouseArea
.
containsMouse
&&
!
fadeOutMouseArea
.
containsMouse
&&
!
fadeInMouseArea
.
drag
.
active
&&
!
fadeOutMouseArea
.
drag
.
active
&&
!
trimInMouseArea
.
drag
.
active
&&
!
trimOutMouseArea
.
drag
.
active
delay
:
1000
timeout
:
5000
background
:
Rectangle
{
color
:
activePalette
.
alternateBase
border.color
:
activePalette
.
light
}
contentItem
:
Label
{
color
:
activePalette
.
text
font
:
miniFont
text
:
'
%1 (%2-%3)
\n
%4: %5
'
.
arg
(
label
.
text
)
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
inPoint
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
outPoint
))
.
arg
(
i18n
(
"
Duration
"
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
clipDuration
))
}
}
onKeyframeModelChanged
:
{
if
(
effectRow
.
keyframecanvas
)
{
...
...
@@ -289,11 +272,15 @@ Rectangle {
Keys.onShortcutOverride
:
event
.
accepted
=
clipRoot
.
isGrabbed
&&
(
event
.
key
===
Qt
.
Key_Left
||
event
.
key
===
Qt
.
Key_Right
||
event
.
key
===
Qt
.
Key_Up
||
event
.
key
===
Qt
.
Key_Down
||
event
.
key
===
Qt
.
Key_Escape
)
Keys.onLeftPressed
:
{
var
offset
=
event
.
modifiers
===
Qt
.
ShiftModifier
?
timeline
.
fps
()
:
1
controller
.
requestClipMove
(
clipRoot
.
clipId
,
clipRoot
.
trackId
,
clipRoot
.
modelStart
-
offset
,
true
,
true
,
true
);
if
(
controller
.
requestClipMove
(
clipRoot
.
clipId
,
clipRoot
.
trackId
,
clipRoot
.
modelStart
-
offset
,
true
,
true
,
true
))
{
timeline
.
showToolTip
(
i18n
(
"
Position: %1
"
,
timeline
.
simplifiedTC
(
clipRoot
.
modelStart
)));
}
}
Keys.onRightPressed
:
{
var
offset
=
event
.
modifiers
===
Qt
.
ShiftModifier
?
timeline
.
fps
()
:
1
controller
.
requestClipMove
(
clipRoot
.
clipId
,
clipRoot
.
trackId
,
clipRoot
.
modelStart
+
offset
,
true
,
true
,
true
);
if
(
controller
.
requestClipMove
(
clipRoot
.
clipId
,
clipRoot
.
trackId
,
clipRoot
.
modelStart
+
offset
,
true
,
true
,
true
))
{
timeline
.
showToolTip
(
i18n
(
"
Position: %1
"
,
timeline
.
simplifiedTC
(
clipRoot
.
modelStart
)));
}
}
Keys.onUpPressed
:
{
controller
.
requestClipMove
(
clipRoot
.
clipId
,
controller
.
getNextTrackId
(
clipRoot
.
trackId
),
clipRoot
.
modelStart
,
true
,
true
,
true
);
...
...
@@ -312,10 +299,17 @@ Rectangle {
onEntered
:
{
var
itemPos
=
mapToItem
(
tracksContainerArea
,
0
,
0
,
width
,
height
)
initDrag
(
clipRoot
,
itemPos
,
clipRoot
.
clipId
,
clipRoot
.
modelStart
,
clipRoot
.
trackId
,
false
)
var
text
=
i18n
(
"
%1 (%2-%3), Position: %4, Duration: %5
"
.
arg
(
clipRoot
.
clipName
)
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
inPoint
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
outPoint
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
modelStart
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
clipDuration
)))
timeline
.
showToolTip
(
text
)
}
onExited
:
{
endDrag
()
timeline
.
showToolTip
()
}
onWheel
:
zoomByWheel
(
wheel
)
...
...
@@ -442,11 +436,13 @@ Rectangle {
onEntered
:
{
if
(
!
pressed
)
{
mixOut
.
color
=
'
darkorchid
'
timeline
.
showToolTip
(
i18n
(
"
Mix:%1
"
,
timeline
.
simplifiedTC
(
clipRoot
.
mixDuration
)))
}
}
onExited
:
{
if
(
!
pressed
)
{
mixOut
.
color
=
clipRoot
.
border
.
color
timeline
.
showToolTip
()
}
}
Rectangle
{
...
...
@@ -457,21 +453,6 @@ Rectangle {
Drag.active
:
trimInMixArea
.
drag
.
active
Drag.proposedAction
:
Qt
.
MoveAction
visible
:
trimInMixArea
.
pressed
||
(
root
.
activeTool
===
0
&&
!
mouseArea
.
drag
.
active
&&
parent
.
enabled
)
ToolTip
{
visible
:
trimInMixArea
.
containsMouse
&&
!
trimInMixArea
.
pressed
delay
:
1000
timeout
:
5000
background
:
Rectangle
{
color
:
activePalette
.
alternateBase
border.color
:
activePalette
.
light
}
contentItem
:
Label
{
color
:
activePalette
.
text
font
:
miniFont
text
:
i18n
(
"
Mix:%1
"
,
timeline
.
simplifiedTC
(
clipRoot
.
mixDuration
))
}
}
}
}
}
...
...
@@ -595,10 +576,24 @@ Rectangle {
trimIn
.
opacity
=
1
var
itemPos
=
mapToItem
(
tracksContainerArea
,
0
,
0
,
width
,
height
)
initDrag
(
clipRoot
,
itemPos
,
clipRoot
.
clipId
,
clipRoot
.
modelStart
,
clipRoot
.
trackId
,
false
)
var
s
=
i18n
(
"
In:%1, Position:%2
"
,
timeline
.
simplifiedTC
(
clipRoot
.
inPoint
),
timeline
.
simplifiedTC
(
clipRoot
.
modelStart
))
timeline
.
showToolTip
(
s
)
}
}
onExited
:
{
trimIn
.
opacity
=
0
if
(
!
pressed
)
{
if
(
!
mouseArea
.
containsMouse
)
{
timeline
.
showToolTip
()
}
else
{
var
text
=
i18n
(
"
%1 (%2-%3), Position: %4, Duration: %5
"
.
arg
(
clipRoot
.
clipName
)
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
inPoint
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
outPoint
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
modelStart
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
clipDuration
)))
timeline
.
showToolTip
(
text
)
}
}
}
Rectangle
{
id
:
trimIn
...
...
@@ -611,7 +606,7 @@ Rectangle {
Drag.proposedAction
:
Qt
.
MoveAction
visible
:
trimInMouseArea
.
pressed
||
(
root
.
activeTool
===
0
&&
!
mouseArea
.
drag
.
active
&&
parent
.
enabled
)
ToolTip
{
/*
ToolTip {
visible: trimInMouseArea.containsMouse && !trimInMouseArea.pressed
delay: 1000
timeout: 5000
...
...
@@ -624,7 +619,7 @@ Rectangle {
font: miniFont
text: i18n("In:%1\nPosition:%2", timeline.simplifiedTC(clipRoot.inPoint),timeline.simplifiedTC(clipRoot.modelStart))
}
}
}
*/
}
}
...
...
@@ -687,10 +682,26 @@ Rectangle {
trimOut
.
opacity
=
1
var
itemPos
=
mapToItem
(
tracksContainerArea
,
0
,
0
,
width
,
height
)
initDrag
(
clipRoot
,
itemPos
,
clipRoot
.
clipId
,
clipRoot
.
modelStart
,
clipRoot
.
trackId
,
false
)
var
s
=
i18n
(
"
Out:%1, Position:%2
"
,
timeline
.
simplifiedTC
(
clipRoot
.
outPoint
),
timeline
.
simplifiedTC
(
clipRoot
.
modelStart
+
clipRoot
.
clipDuration
))
timeline
.
showToolTip
(
s
)
}
}
onExited
:
trimOut
.
opacity
=
0
ToolTip
{
onExited
:
{
trimOut
.
opacity
=
0
if
(
!
pressed
)
{
if
(
!
mouseArea
.
containsMouse
)
{
timeline
.
showToolTip
()
}
else
{
var
text
=
i18n
(
"
%1 (%2-%3), Position: %4, Duration: %5
"
.
arg
(
clipRoot
.
clipName
)
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
inPoint
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
outPoint
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
modelStart
))
.
arg
(
timeline
.
simplifiedTC
(
clipRoot
.
clipDuration
)))
timeline
.
showToolTip
(
text
)
}
}
}
/*ToolTip {
visible: trimOutMouseArea.containsMouse && !trimOutMouseArea.pressed
delay: 1000
timeout: 5000
...
...
@@ -703,7 +714,7 @@ Rectangle {
font: miniFont
text: i18n("Out: ") + timeline.simplifiedTC(clipRoot.outPoint)
}
}
}
*/
Rectangle
{
id
:
trimOut
anchors.right
:
parent
.
right
...
...
@@ -789,19 +800,12 @@ Rectangle {
onClicked
:
{
clearAndMove
(
positionOffset
)
}
ToolTip
{
visible
:
offsetArea
.
containsMouse
delay
:
1000
timeout
:
5000
background
:
Rectangle
{
color
:
activePalette
.
alternateBase
border.color
:
activePalette
.
light
}
contentItem
:
Label
{
color
:
activePalette
.
text
font
:
miniFont
text
:
positionOffset
<
0
?
i18n
(
"
Offset: -%1
"
,
timeline
.
simplifiedTC
(
-
positionOffset
))
:
i18n
(
"
Offset: %1
"
,
timeline
.
simplifiedTC
(
positionOffset
))
}
onEntered
:
{
var
text
=
positionOffset
<
0
?
i18n
(
"
Offset: -%1
"
,
timeline
.
simplifiedTC
(
-
positionOffset
))
:
i18n
(
"
Offset: %1
"
,
timeline
.
simplifiedTC
(
positionOffset
))
timeline
.
showToolTip
(
text
)
}
onExited
:
{
timeline
.
showToolTip
()
}
Text
{
id
:
offsetLabel
...
...
@@ -1040,7 +1044,8 @@ Rectangle {
anchors
.
right
=
parent
.
right
var
duration
=
clipRoot
.
fadeOut
timeline
.
adjustFade
(
clipRoot
.
clipId
,
'
fadeout
'
,
duration
,
startFadeOut
)
bubbleHelp
.
hide
()
//bubbleHelp.hide()
timeline
.
showToolTip
()
}
onPositionChanged
:
{
if
(
mouse
.
buttons
===
Qt
.
LeftButton
)
{
...
...
@@ -1052,7 +1057,8 @@ Rectangle {
timeline
.
adjustFade
(
clipRoot
.
clipId
,
'
fadeout
'
,
duration
,
-
1
)
// Show fade duration as time in a "bubble" help.
var
s
=
timeline
.
simplifiedTC
(
clipRoot
.
fadeOut
)
bubbleHelp
.
show
(
clipRoot
.
x
+
x
,
parentTrack
.
y
+
parentTrack
.
height
,
s
)
timeline
.
showToolTip
(
s
)
//bubbleHelp.show(clipRoot.x + x, parentTrack.y + parentTrack.height, s)
}
}
}
...
...
@@ -1130,7 +1136,8 @@ Rectangle {
root
.
autoScrolling
=
timeline
.
autoScroll
fadeInTriangle
.
opacity
=
0.4
timeline
.
adjustFade
(
clipRoot
.
clipId
,
'
fadein
'
,
clipRoot
.
fadeIn
,
startFadeIn
)
bubbleHelp
.
hide
()
//bubbleHelp.hide()
timeline
.
showToolTip
()
anchors
.
left
=
container
.
left
}
onPositionChanged
:
{
...
...
@@ -1142,7 +1149,8 @@ Rectangle {
timeline
.
adjustFade
(
clipRoot
.
clipId
,
'
fadein
'
,
duration
,
-
1
)
// Show fade duration as time in a "bubble" help.
var
s
=
timeline
.
simplifiedTC
(
clipRoot
.
fadeIn
)
bubbleHelp
.
show
(
clipRoot
.
x
+
x
,
parentTrack
.
y
+
parentTrack
.
height
,
s
)
timeline
.
showToolTip
(
s
)
//bubbleHelp.show(clipRoot.x + x, parentTrack.y + parentTrack.height, s)
}
}
}
...
...
src/timeline2/view/qml/Track.qml
View file @
ee1d1a97
...
...
@@ -310,15 +310,17 @@ Item{
// Show amount trimmed as a time in a "bubble" help.
var
delta
=
new_duration
-
clip
.
originalDuration
var
s
=
timeline
.
simplifiedTC
(
Math
.
abs
(
delta
))
s
=
'
%1%2
\n
%3:%4
'
.
arg
((
delta
<=
0
)?
'
+
'
:
'
-
'
)
s
=
'
%1%2
,
%3:%4
'
.
arg
((
delta
<=
0
)?
'
+
'
:
'
-
'
)
.
arg
(
s
)
.
arg
(
i18n
(
"
In
"
))
.
arg
(
timeline
.
simplifiedTC
(
clip
.
inPoint
))
bubbleHelp
.
show
(
clip
.
x
-
20
,
trackRoot
.
y
+
trackRoot
.
height
,
s
)
timeline
.
showToolTip
(
s
)
//bubbleHelp.show(clip.x - 20, trackRoot.y + trackRoot.height, s)
}
}
onTrimmedIn
:
{
bubbleHelp
.
hide
()
//bubbleHelp.hide()
timeline
.
showToolTip
();
if
(
shiftTrim
||
clip
.
groupTrimData
==
undefined
||
controlTrim
)
{
// We only resize one element
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
originalDuration
,
false
,
false
,
0
,
shiftTrim
)
...
...
@@ -357,15 +359,17 @@ Item{
// Show amount trimmed as a time in a "bubble" help.
var
delta
=
clip
.
originalDuration
-
new_duration
var
s
=
timeline
.
simplifiedTC
(
Math
.
abs
(
delta
))
s
=
'
%1%2
\n
%3:%4
'
.
arg
((
delta
<=
0
)?
'
+
'
:
'
-
'
)
s
=
'
%1%2
,
%3:%4
'
.
arg
((
delta
<=
0
)?
'
+
'
:
'
-
'
)
.
arg
(
s
)
.
arg
(
i18n
(
"
Duration
"
))
.
arg
(
timeline
.
simplifiedTC
(
new_duration
))
bubbleHelp
.
show
(
clip
.
x
+
clip
.
width
-
20
,
trackRoot
.
y
+
trackRoot
.
height
,
s
)
timeline
.
showToolTip
(
s
);
//bubbleHelp.show(clip.x + clip.width - 20, trackRoot.y + trackRoot.height, s)
}
}
onTrimmedOut
:
{
bubbleHelp
.
hide
()
timeline
.
showToolTip
();
//bubbleHelp.hide()
if
(
shiftTrim
||
clip
.
groupTrimData
==
undefined
||
controlTrim
)
{
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
originalDuration
,
true
,
false
,
0
,
shiftTrim
)
if
(
controlTrim
)
{
...
...
@@ -401,11 +405,13 @@ Item{
s
=
'
%1%2 = %3
'
.
arg
((
delta
<=
0
)?
'
+
'
:
'
-
'
)
.
arg
(
s
)
.
arg
(
timeline
.
simplifiedTC
(
new_duration
))
bubbleHelp
.
show
(
clip
.
x
+
clip
.
width
,
trackRoot
.
y
+
trackRoot
.
height
,
s
)
timeline
.
showToolTip
(
s
)
//bubbleHelp.show(clip.x + clip.width, trackRoot.y + trackRoot.height, s)
}
}
onTrimmedIn
:
{
bubbleHelp
.
hide
()
timeline
.
showToolTip
()
//bubbleHelp.hide()
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
originalDuration
,
false
,
false
,
root
.
snapping
)
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
lastValidDuration
,
false
,
true
,
root
.
snapping
)
}
...
...
@@ -419,11 +425,13 @@ Item{
s
=
'
%1%2 = %3
'
.
arg
((
delta
<=
0
)?
'
+
'
:
'
-
'
)
.
arg
(
s
)
.
arg
(
timeline
.
simplifiedTC
(
new_duration
))
bubbleHelp
.
show
(
clip
.
x
+
clip
.
width
,
trackRoot
.
y
+
trackRoot
.
height
,
s
)
timeline
.
showToolTip
(
s
)
//bubbleHelp.show(clip.x + clip.width, trackRoot.y + trackRoot.height, s)
}
}
onTrimmedOut
:
{
bubbleHelp
.
hide
()
timeline
.
showToolTip
()
//bubbleHelp.hide()
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
originalDuration
,
true
,
false
,
root
.
snapping
)
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
lastValidDuration
,
true
,
true
,
root
.
snapping
)
}
...
...
src/timeline2/view/qml/timeline.qml
View file @
ee1d1a97
...
...
@@ -1252,7 +1252,7 @@ Rectangle {
anchors.fill
:
parent
acceptedButtons
:
Qt
.
NoButton
onWheel
:
zoomByWheel
(
wheel
)
cursorShape
:
dragProxyArea
.
drag
.
active
?
Qt
.
ClosedHandCursor
:
tracksArea
.
cursorShape
//
cursorShape: dragProxyArea.drag.active ? Qt.ClosedHandCursor : tracksArea.cursorShape
}
Repeater
{
id
:
subtitlesRepeater
;
model
:
subtitleDelegateModel
}
}
...
...
@@ -1405,9 +1405,13 @@ Rectangle {
var
delta
=
dragFrame
-
dragProxy
.
sourceFrame
if
(
delta
!=
0
)
{
var
s
=
timeline
.
simplifiedTC
(
Math
.
abs
(
delta
))
s
=
((
delta
<
0
)?
'
-
'
:
'
+
'
)
+
s
+
i18n
(
"
\n
Position:%1
"
,
timeline
.
simplifiedTC
(
dragFrame
))
bubbleHelp
.
show
(
parent
.
x
+
mouseX
,
Math
.
max
(
ruler
.
height
,
Logic
.
getTrackYFromId
(
timeline
.
activeTrack
)),
s
)
}
else
bubbleHelp
.
hide
()
s
=
i18n
(
"
Offset: %1, Position: %2
"
,
(
delta
<
0
?
'
-
'
:
'
+
'
)
+
s
,
timeline
.
simplifiedTC
(
dragFrame
))
timeline
.
showToolTip
(
s
);
/*bubbleHelp.show(parent.x + mouseX, Math.max(ruler.height, Logic.getTrackYFromId(timeline.activeTrack)), s)*/
}
else
{
timeline
.
showToolTip
()
//bubbleHelp.hide()
}
}
}
onReleased
:
{
...
...
@@ -1432,7 +1436,8 @@ Rectangle {
}
dragProxy
.
x
=
controller
.
getItemPosition
(
dragProxy
.
draggedItem
)
*
timeline
.
scaleFactor
dragProxy
.
sourceFrame
=
dragFrame
bubbleHelp
.
hide
()
timeline
.
showToolTip
()
//bubbleHelp.hide()
}
}
onDoubleClicked
:
{
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
ee1d1a97
...
...
@@ -3979,3 +3979,8 @@ bool TimelineController::subtitlesLocked() const
}
return
false
;
}
void
TimelineController
::
showToolTip
(
const
QString
&
info
)
const
{
pCore
->
displayMessage
(
info
,
DirectMessage
);
}
src/timeline2/view/timelinecontroller.h
View file @
ee1d1a97
...
...
@@ -178,6 +178,7 @@ public:
Q_INVOKABLE
QColor
lockedColor
()
const
;
Q_INVOKABLE
QColor
selectionColor
()
const
;
Q_INVOKABLE
QColor
groupColor
()
const
;
Q_INVOKABLE
void
showToolTip
(
const
QString
&
info
=
QString
())
const
;
void
switchSubtitleDisable
();
bool
subtitlesDisabled
()
const
;
void
switchSubtitleLock
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment