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
36ea3371
Commit
36ea3371
authored
Jun 03, 2020
by
Jean-Baptiste Mardelle
Browse files
Project notes: allow creating markers from timestamps and assign timestamps to current bin clip
CCBUG: 420843
parent
e892a7a2
Pipeline
#22403
passed with stage
in 9 minutes and 37 seconds
Changes
11
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/bin/bin.cpp
View file @
36ea3371
...
...
@@ -4156,3 +4156,18 @@ void Bin::checkProjectAudioTracks(QString clipId, int minimumTracksCount)
m_infoMessage
->
animatedHide
();
}
}
void
Bin
::
addClipMarker
(
const
QString
binId
,
QList
<
int
>
positions
)
{
std
::
shared_ptr
<
ProjectClip
>
clip
=
getBinClip
(
binId
);
if
(
!
clip
)
{
pCore
->
displayMessage
(
i18n
(
"Cannot find clip to add marker"
),
ErrorMessage
);
return
;
}
QMap
<
GenTime
,
QString
>
markers
;
for
(
int
pos
:
positions
)
{
GenTime
p
(
pos
,
pCore
->
getCurrentFps
());
markers
.
insert
(
p
,
pCore
->
currentDoc
()
->
timecode
().
getDisplayTimecode
(
p
,
false
));
}
clip
->
getMarkerModel
()
->
addMarkers
(
markers
,
KdenliveSettings
::
default_marker_type
());
}
src/bin/bin.h
View file @
36ea3371
...
...
@@ -199,6 +199,9 @@ public:
/** @brief Get a clip's name from it's id */
const
QString
getBinClipName
(
const
QString
&
id
)
const
;
/** @brief Add markers on clip @param binId at @param positions */
void
addClipMarker
(
const
QString
binId
,
QList
<
int
>
positions
);
/** @brief Returns a list of selected clip ids.
* @param allowSubClips: if true, will include subclip ids in the form: "master clip id/in/out"
*/
...
...
src/bin/model/markerlistmodel.cpp
View file @
36ea3371
...
...
@@ -95,6 +95,32 @@ bool MarkerListModel::addMarker(GenTime pos, const QString &comment, int type, F
return
false
;
}
bool
MarkerListModel
::
addMarkers
(
QMap
<
GenTime
,
QString
>
markers
,
int
type
)
{
QWriteLocker
locker
(
&
m_lock
);
Fun
undo
=
[]()
{
return
true
;
};
Fun
redo
=
[]()
{
return
true
;
};
QMapIterator
<
GenTime
,
QString
>
i
(
markers
);
bool
rename
=
false
;
bool
res
=
true
;
while
(
i
.
hasNext
()
&&
res
)
{
i
.
next
();
if
(
m_markerList
.
count
(
i
.
key
())
>
0
)
{
rename
=
true
;
}
res
=
addMarker
(
i
.
key
(),
i
.
value
(),
type
,
undo
,
redo
);
}
if
(
res
)
{
if
(
rename
)
{
PUSH_UNDO
(
undo
,
redo
,
m_guide
?
i18n
(
"Rename guide"
)
:
i18n
(
"Rename marker"
));
}
else
{
PUSH_UNDO
(
undo
,
redo
,
m_guide
?
i18n
(
"Add guide"
)
:
i18n
(
"Add marker"
));
}
}
return
res
;
}
bool
MarkerListModel
::
addMarker
(
GenTime
pos
,
const
QString
&
comment
,
int
type
)
{
QWriteLocker
locker
(
&
m_lock
);
...
...
src/bin/model/markerlistmodel.hpp
View file @
36ea3371
...
...
@@ -64,6 +64,7 @@ public:
@param type is the type (color) associated with the marker. If -1 is passed, then the value is pulled from kdenlive's defaults
*/
bool
addMarker
(
GenTime
pos
,
const
QString
&
comment
,
int
type
=
-
1
);
bool
addMarkers
(
QMap
<
GenTime
,
QString
>
markers
,
int
type
=
-
1
);
protected:
/* @brief Same function but accumulates undo/redo */
...
...
src/core.cpp
View file @
36ea3371
...
...
@@ -928,3 +928,13 @@ int Core::audioChannels()
}
return
2
;
}
void
Core
::
addGuides
(
QList
<
int
>
guides
)
{
QMap
<
GenTime
,
QString
>
markers
;
for
(
int
pos
:
guides
)
{
GenTime
p
(
pos
,
pCore
->
getCurrentFps
());
markers
.
insert
(
p
,
pCore
->
currentDoc
()
->
timecode
().
getDisplayTimecode
(
p
,
false
));
}
pCore
->
currentDoc
()
->
getGuideModel
()
->
addMarkers
(
markers
);
}
src/core.h
View file @
36ea3371
...
...
@@ -224,6 +224,8 @@ public:
bool
enableMultiTrack
(
bool
enable
);
/** @brief Returns number of audio channels for this project. */
int
audioChannels
();
/** @brief Add guides in the project. */
void
addGuides
(
QList
<
int
>
guides
);
private:
explicit
Core
();
...
...
src/mainwindow.cpp
View file @
36ea3371
...
...
@@ -1637,7 +1637,7 @@ void MainWindow::setupActions()
connect
(
switchTrackTarget
,
&
QAction
::
triggered
,
this
,
&
MainWindow
::
slotSwitchTrackAudioStream
);
timelineActions
->
addAction
(
QStringLiteral
(
"switch_target_stream"
),
switchTrackTarget
);
actionCollection
()
->
setDefaultShortcut
(
switchTrackTarget
,
Qt
::
Key_Apostrophe
);
QAction
*
deleteTrack
=
new
QAction
(
QIcon
(),
i18n
(
"Delete Track"
),
this
);
connect
(
deleteTrack
,
&
QAction
::
triggered
,
this
,
&
MainWindow
::
slotDeleteTrack
);
timelineActions
->
addAction
(
QStringLiteral
(
"delete_track"
),
deleteTrack
);
...
...
@@ -1737,7 +1737,7 @@ void MainWindow::setupActions()
addAction
(
QStringLiteral
(
"activate_all_targets"
),
i18n
(
"Switch All Tracks Active"
),
pCore
->
projectManager
(),
SLOT
(
slotMakeAllTrackActive
()),
QIcon
(),
Qt
::
SHIFT
+
Qt
::
ALT
+
Qt
::
Key_A
);
addAction
(
QStringLiteral
(
"add_project_note"
),
i18n
(
"Add Project Note"
),
pCore
->
projectManager
(),
SLOT
(
slotAddProjectNote
()),
QIcon
::
fromTheme
(
QStringLiteral
(
"bookmark"
)));
QIcon
::
fromTheme
(
QStringLiteral
(
"bookmark
-new
"
)));
pCore
->
bin
()
->
setupMenu
();
...
...
@@ -2559,15 +2559,7 @@ void MainWindow::slotAddMarkerGuideQuickly()
}
if
(
m_clipMonitor
->
isActive
())
{
std
::
shared_ptr
<
ProjectClip
>
clip
(
m_clipMonitor
->
currentController
());
GenTime
pos
(
m_clipMonitor
->
position
(),
pCore
->
getCurrentFps
());
if
(
!
clip
)
{
m_messageLabel
->
setMessage
(
i18n
(
"Cannot find clip to add marker"
),
ErrorMessage
);
return
;
}
CommentedTime
marker
(
pos
,
pCore
->
currentDoc
()
->
timecode
().
getDisplayTimecode
(
pos
,
false
),
KdenliveSettings
::
default_marker_type
());
clip
->
getMarkerModel
()
->
addMarker
(
marker
.
time
(),
marker
.
comment
(),
marker
.
markerType
());
pCore
->
bin
()
->
addClipMarker
(
m_clipMonitor
->
activeClipId
(),
{
m_clipMonitor
->
position
()});
}
else
{
int
selectedClip
=
getMainTimeline
()
->
controller
()
->
getMainSelectedItem
();
if
(
selectedClip
==
-
1
)
{
...
...
src/project/dialogs/noteswidget.cpp
View file @
36ea3371
...
...
@@ -20,6 +20,7 @@
#include "noteswidget.h"
#include "kdenlive_debug.h"
#include "core.h"
#include "bin/bin.h"
#include <QMenu>
#include <QMouseEvent>
...
...
@@ -29,21 +30,79 @@
NotesWidget
::
NotesWidget
(
QWidget
*
parent
)
:
QTextEdit
(
parent
)
{
setContextMenuPolicy
(
Qt
::
CustomContextMenu
);
connect
(
this
,
&
NotesWidget
::
customContextMenuRequested
,
this
,
&
NotesWidget
::
slotFillNotesMenu
);
setMouseTracking
(
true
);
}
NotesWidget
::~
NotesWidget
()
=
default
;
void
NotesWidget
::
slotFillNotesMenu
(
const
QPoint
&
pos
)
void
NotesWidget
::
contextMenuEvent
(
QContextMenuEvent
*
event
)
{
QMenu
*
menu
=
createStandardContextMenu
();
if
(
menu
)
{
QAction
*
a
=
new
QAction
(
i18n
(
"Insert current timecode"
),
menu
);
connect
(
a
,
&
QAction
::
triggered
,
this
,
&
NotesWidget
::
insertNotesTimecode
);
menu
->
insertAction
(
menu
->
actions
().
at
(
0
),
a
);
menu
->
exec
(
viewport
()
->
mapToGlobal
(
pos
));
QPair
<
QStringList
,
QList
<
QPoint
>
>
result
=
getSelectedAnchors
();
QStringList
anchors
=
result
.
first
;
QList
<
QPoint
>
anchorPoints
=
result
.
second
;
if
(
anchors
.
isEmpty
())
{
const
QString
anchor
=
anchorAt
(
event
->
pos
());
if
(
!
anchor
.
isEmpty
())
{
anchors
<<
anchor
;
}
}
if
(
!
anchors
.
isEmpty
())
{
a
=
new
QAction
(
i18np
(
"Create marker"
,
"create markers"
,
anchors
.
count
()),
menu
);
connect
(
a
,
&
QAction
::
triggered
,
[
this
,
anchors
]
()
{
createMarker
(
anchors
);
});
menu
->
insertAction
(
menu
->
actions
().
at
(
1
),
a
);
if
(
!
anchorPoints
.
isEmpty
())
{
a
=
new
QAction
(
i18n
(
"Assign timestamps to current Bin Clip"
),
menu
);
connect
(
a
,
&
QAction
::
triggered
,
[
this
,
anchors
,
anchorPoints
]
()
{
emit
reAssign
(
anchors
,
anchorPoints
);
});
menu
->
insertAction
(
menu
->
actions
().
at
(
2
),
a
);
}
}
menu
->
exec
(
event
->
globalPos
());
delete
menu
;
}
}
void
NotesWidget
::
createMarker
(
QStringList
anchors
)
{
QMap
<
QString
,
QList
<
int
>>
clipMarkers
;
QList
<
int
>
guides
;
for
(
const
QString
&
anchor
:
anchors
)
{
if
(
anchor
.
contains
(
QLatin1Char
(
'#'
)))
{
// That's a Bin Clip reference.
const
QString
binId
=
anchor
.
section
(
QLatin1Char
(
'#'
),
0
,
0
);
QList
<
int
>
timecodes
;
if
(
clipMarkers
.
contains
(
binId
))
{
timecodes
=
clipMarkers
.
value
(
binId
);
timecodes
<<
anchor
.
section
(
QLatin1Char
(
'#'
),
1
).
toInt
();
}
else
{
timecodes
=
{
anchor
.
section
(
QLatin1Char
(
'#'
),
1
).
toInt
()};
}
clipMarkers
.
insert
(
binId
,
timecodes
);
}
else
{
// That is a guide
guides
<<
anchor
.
toInt
();
}
}
QMapIterator
<
QString
,
QList
<
int
>>
i
(
clipMarkers
);
while
(
i
.
hasNext
())
{
i
.
next
();
// That's a Bin Clip reference.
pCore
->
bin
()
->
addClipMarker
(
i
.
key
(),
i
.
value
());
}
if
(
!
clipMarkers
.
isEmpty
())
{
const
QString
&
binId
=
clipMarkers
.
firstKey
();
pCore
->
selectBinClip
(
binId
,
clipMarkers
.
value
(
binId
).
constFirst
(),
QPoint
());
}
if
(
!
guides
.
isEmpty
())
{
pCore
->
addGuides
(
guides
);
}
}
...
...
@@ -61,7 +120,7 @@ void NotesWidget::mouseMoveEvent(QMouseEvent *e)
void
NotesWidget
::
mousePressEvent
(
QMouseEvent
*
e
)
{
QString
anchor
=
anchorAt
(
e
->
pos
());
if
(
anchor
.
isEmpty
())
{
if
(
anchor
.
isEmpty
()
||
e
->
button
()
!=
Qt
::
LeftButton
)
{
QTextEdit
::
mousePressEvent
(
e
);
return
;
}
...
...
@@ -74,6 +133,79 @@ void NotesWidget::mousePressEvent(QMouseEvent *e)
e
->
setAccepted
(
true
);
}
QPair
<
QStringList
,
QList
<
QPoint
>
>
NotesWidget
::
getSelectedAnchors
()
{
int
startPos
=
textCursor
().
selectionStart
();
int
endPos
=
textCursor
().
selectionEnd
();
QStringList
anchors
;
QList
<
QPoint
>
anchorPoints
;
if
(
endPos
>
startPos
)
{
textCursor
().
clearSelection
();
QTextCursor
cur
(
textCursor
());
// Ensure we are at the start of current selection
if
(
!
cur
.
atBlockStart
())
{
cur
.
setPosition
(
startPos
,
QTextCursor
::
MoveAnchor
);
int
pos
=
startPos
;
const
QString
an
=
anchorAt
(
cursorRect
(
cur
).
center
());
while
(
!
cur
.
atBlockStart
())
{
pos
--
;
cur
.
setPosition
(
pos
,
QTextCursor
::
MoveAnchor
);
if
(
anchorAt
(
cursorRect
(
cur
).
center
())
==
an
)
{
startPos
=
pos
;
}
else
{
break
;
}
}
}
bool
isInAnchor
=
false
;
QPoint
anchorPoint
;
for
(
int
p
=
startPos
;
p
<=
endPos
;
++
p
)
{
cur
.
setPosition
(
p
,
QTextCursor
::
MoveAnchor
);
const
QString
anchor
=
anchorAt
(
cursorRect
(
cur
).
center
());
if
(
isInAnchor
&&
!
anchor
.
isEmpty
()
&&
p
==
endPos
)
{
endPos
++
;
}
if
(
isInAnchor
&&
(
anchor
.
isEmpty
()
||
!
anchors
.
contains
(
anchor
)
||
cur
.
atEnd
()))
{
// End of current anchor
anchorPoint
.
setY
(
p
);
anchorPoints
.
prepend
(
anchorPoint
);
isInAnchor
=
false
;
}
if
(
!
anchor
.
isEmpty
()
&&
!
anchors
.
contains
(
anchor
))
{
anchors
.
prepend
(
anchor
);
if
(
!
isInAnchor
)
{
isInAnchor
=
true
;
anchorPoint
.
setX
(
p
);
}
}
}
}
return
{
anchors
,
anchorPoints
};
}
void
NotesWidget
::
assignProjectNote
()
{
QPair
<
QStringList
,
QList
<
QPoint
>
>
result
=
getSelectedAnchors
();
QStringList
anchors
=
result
.
first
;
QList
<
QPoint
>
anchorPoints
=
result
.
second
;
if
(
!
anchors
.
isEmpty
())
{
emit
reAssign
(
anchors
,
anchorPoints
);
}
else
{
pCore
->
displayMessage
(
i18n
(
"Select some timecodes to reassign"
),
InformationMessage
);
}
}
void
NotesWidget
::
createMarkers
()
{
QPair
<
QStringList
,
QList
<
QPoint
>
>
result
=
getSelectedAnchors
();
QStringList
anchors
=
result
.
first
;
if
(
!
anchors
.
isEmpty
())
{
createMarker
(
anchors
);
}
else
{
pCore
->
displayMessage
(
i18n
(
"Select some timecodes to create markers"
),
InformationMessage
);
}
}
void
NotesWidget
::
addProjectNote
()
{
if
(
!
textCursor
().
atBlockStart
())
{
...
...
src/project/dialogs/noteswidget.h
View file @
36ea3371
...
...
@@ -41,13 +41,21 @@ protected:
void
mouseMoveEvent
(
QMouseEvent
*
e
)
override
;
void
mousePressEvent
(
QMouseEvent
*
e
)
override
;
void
insertFromMimeData
(
const
QMimeData
*
source
)
override
;
void
contextMenuEvent
(
QContextMenuEvent
*
event
)
override
;
private
slots
:
void
slotFillNotesMenu
(
const
QPoint
&
pos
);
public
slots
:
void
createMarkers
();
void
assignProjectNote
();
private:
QAction
*
m_markerAction
;
void
createMarker
(
QStringList
anchors
);
QPair
<
QStringList
,
QList
<
QPoint
>
>
getSelectedAnchors
();
signals:
void
insertNotesTimecode
();
void
seekProject
(
int
);
void
reAssign
(
QStringList
anchors
,
QList
<
QPoint
>
points
);
};
#endif
src/project/notesplugin.cpp
View file @
36ea3371
...
...
@@ -20,11 +20,19 @@ the Free Software Foundation, either version 3 of the License, or
NotesPlugin
::
NotesPlugin
(
ProjectManager
*
projectManager
)
:
QObject
(
projectManager
)
{
QWidget
*
container
=
new
QWidget
();
auto
*
lay
=
new
QVBoxLayout
();
m_tb
=
new
QToolBar
();
m_tb
->
setToolButtonStyle
(
Qt
::
ToolButtonIconOnly
);
lay
->
addWidget
(
m_tb
);
m_widget
=
new
NotesWidget
();
lay
->
addWidget
(
m_widget
);
container
->
setLayout
(
lay
);
connect
(
m_widget
,
&
NotesWidget
::
insertNotesTimecode
,
this
,
&
NotesPlugin
::
slotInsertTimecode
);
connect
(
m_widget
,
&
NotesWidget
::
reAssign
,
this
,
&
NotesPlugin
::
slotReAssign
);
m_widget
->
setTabChangesFocus
(
true
);
m_widget
->
setPlaceholderText
(
i18n
(
"Enter your project notes here ..."
));
m_notesDock
=
pCore
->
window
()
->
addDock
(
i18n
(
"Project Notes"
),
QStringLiteral
(
"notes_widget"
),
m_widget
);
m_notesDock
=
pCore
->
window
()
->
addDock
(
i18n
(
"Project Notes"
),
QStringLiteral
(
"notes_widget"
),
container
);
m_notesDock
->
close
();
connect
(
projectManager
,
&
ProjectManager
::
docOpened
,
this
,
&
NotesPlugin
::
setProject
);
}
...
...
@@ -33,6 +41,16 @@ void NotesPlugin::setProject(KdenliveDoc *document)
{
connect
(
m_widget
,
&
NotesWidget
::
seekProject
,
pCore
->
monitorManager
()
->
projectMonitor
(),
&
Monitor
::
requestSeek
);
connect
(
m_widget
,
SIGNAL
(
textChanged
()),
document
,
SLOT
(
setModified
()));
if
(
m_tb
->
actions
().
isEmpty
())
{
// initialize toolbar
m_tb
->
addAction
(
pCore
->
window
()
->
action
(
"add_project_note"
));
QAction
*
a
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"edit-find-replace"
)),
i18n
(
"Reassign selected timecodes to current Bin clip"
));
connect
(
a
,
&
QAction
::
triggered
,
m_widget
,
&
NotesWidget
::
assignProjectNote
);
m_tb
->
addAction
(
a
);
a
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"list-add"
)),
i18n
(
"Create markers from selected timecodes"
));
connect
(
a
,
&
QAction
::
triggered
,
m_widget
,
&
NotesWidget
::
createMarkers
);
m_tb
->
addAction
(
a
);
}
}
void
NotesPlugin
::
showDock
()
...
...
@@ -46,17 +64,59 @@ void NotesPlugin::slotInsertTimecode()
// Add a note on the current bin clip
int
frames
=
pCore
->
monitorManager
()
->
clipMonitor
()
->
position
();
QString
position
=
pCore
->
timecode
().
getTimecodeFromFrames
(
frames
);
QString
binId
=
pCore
->
monitorManager
()
->
clipMonitor
()
->
activeClipId
();
const
QString
binId
=
pCore
->
monitorManager
()
->
clipMonitor
()
->
activeClipId
();
if
(
binId
.
isEmpty
())
{
pCore
->
displayMessage
(
i18n
(
"Cannot add note, no clip selected in project bin"
),
InformationMessage
);
return
;
}
QString
clipName
=
pCore
->
bin
()
->
getBinClipName
(
binId
);
m_widget
->
insertHtml
(
QString
(
"<a href=
\"
%1#%2
\"
>%3
(
%4
)
</a> "
).
arg
(
binId
).
arg
(
frames
).
arg
(
clipName
).
arg
(
position
));
m_widget
->
insertHtml
(
QString
(
"<a href=
\"
%1#%2
\"
>%3
:
%4</a> "
).
arg
(
binId
).
arg
(
frames
).
arg
(
clipName
).
arg
(
position
));
}
else
{
int
frames
=
pCore
->
monitorManager
()
->
projectMonitor
()
->
position
();
QString
position
=
pCore
->
timecode
().
getTimecodeFromFrames
(
frames
);
m_widget
->
insertHtml
(
QStringLiteral
(
"<a href=
\"
"
)
+
QString
::
number
(
frames
)
+
QStringLiteral
(
"
\"
>"
)
+
position
+
QStringLiteral
(
"</a> "
));
m_widget
->
insertHtml
(
QString
(
"<a href=
\"
%1
\"
>%2</a> "
).
arg
(
frames
).
arg
(
position
));
}
}
void
NotesPlugin
::
slotReAssign
(
QStringList
anchors
,
QList
<
QPoint
>
points
)
{
const
QString
binId
=
pCore
->
monitorManager
()
->
clipMonitor
()
->
activeClipId
();
int
ix
=
0
;
if
(
points
.
count
()
!=
anchors
.
count
())
{
// Something is wrong, abort
pCore
->
displayMessage
(
i18n
(
"Cannot perform assign"
),
InformationMessage
);
return
;
}
for
(
const
QString
&
a
:
anchors
)
{
QPoint
pt
=
points
.
at
(
ix
);
QString
updatedLink
=
a
;
int
position
=
0
;
if
(
a
.
contains
(
QLatin1Char
(
'#'
)))
{
// Link was previously attached to another clip
updatedLink
=
a
.
section
(
QLatin1Char
(
'#'
),
1
);
position
=
updatedLink
.
toInt
();
if
(
!
binId
.
isEmpty
())
{
updatedLink
.
prepend
(
QString
(
"%1#"
).
arg
(
binId
));
}
}
else
{
updatedLink
=
a
;
position
=
a
.
toInt
();
if
(
!
binId
.
isEmpty
())
{
updatedLink
.
prepend
(
QString
(
"%1#"
).
arg
(
binId
));
}
}
QTextCursor
cur
(
m_widget
->
textCursor
());
cur
.
setPosition
(
pt
.
x
());
cur
.
setPosition
(
pt
.
y
(),
QTextCursor
::
KeepAnchor
);
QString
pos
=
pCore
->
timecode
().
getTimecodeFromFrames
(
position
);
if
(
!
binId
.
isEmpty
())
{
QString
clipName
=
pCore
->
bin
()
->
getBinClipName
(
binId
);
cur
.
insertHtml
(
QString
(
"<a href=
\"
%1
\"
>%2:%3</a> "
).
arg
(
updatedLink
).
arg
(
clipName
).
arg
(
pos
));
}
else
{
// Timestamp relative to project timeline
cur
.
insertHtml
(
QString
(
"<a href=
\"
%1
\"
>%2</a> "
).
arg
(
updatedLink
).
arg
(
pos
));
}
ix
++
;
}
}
...
...
src/project/notesplugin.h
View file @
36ea3371
...
...
@@ -17,6 +17,7 @@ class NotesWidget;
class
KdenliveDoc
;
class
ProjectManager
;
class
QDockWidget
;
class
QToolBar
;
/**
* @class NotesPlugin
...
...
@@ -39,10 +40,13 @@ private slots:
void
setProject
(
KdenliveDoc
*
document
);
/** @brief Insert current timecode/cursor position into the widget. */
void
slotInsertTimecode
();
/** @brief Re-assign timestamps to current Bin Clip. */
void
slotReAssign
(
QStringList
anchors
,
QList
<
QPoint
>
points
);
private:
NotesWidget
*
m_widget
;
QDockWidget
*
m_notesDock
;
QToolBar
*
m_tb
;
};
#endif
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