Skip to content
GitLab
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
89c51c8b
Commit
89c51c8b
authored
Jan 10, 2020
by
Jean-Baptiste Mardelle
Browse files
Update bin filtering to use more standard button, allow filtering on multiple criterias
parent
6f221df9
Pipeline
#13048
passed with stage
in 13 minutes and 52 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/bin/bin.cpp
View file @
89c51c8b
...
...
@@ -783,6 +783,8 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
,
m_propertiesPanel
(
nullptr
)
,
m_blankThumb
()
,
m_filterGroup
(
this
)
,
m_filterRateGroup
(
this
)
,
m_filterTypeGroup
(
this
)
,
m_invalidClipDialog
(
nullptr
)
,
m_gainedFocus
(
false
)
,
m_audioDuration
(
0
)
...
...
@@ -989,29 +991,98 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
});
// Filter menu
m_filterGroup
.
setExclusive
(
false
);
m_filterMenu
=
new
QMenu
(
i18n
(
"Filter"
),
this
);
m_filterButton
=
new
QToolButton
;
m_filterButton
->
setPopupMode
(
QToolButton
::
MenuButtonPopup
);
m_filterButton
->
setCheckable
(
true
);
m_filterButton
->
setPopupMode
(
QToolButton
::
MenuButtonPopup
);
m_filterButton
->
setIcon
(
QIcon
::
fromTheme
(
QStringLiteral
(
"view-filter"
)));
m_filterButton
->
setToolTip
(
i18n
(
"Filter"
));
m_filterButton
->
setStyleSheet
(
QString
(
"QToolButton:checked{ background-color: %1;border: none; border-radius: 2px;padding-right: 20px;}"
).
arg
(
palette
().
highlight
().
color
().
name
()));
m_filterButton
->
setFont
(
QFontDatabase
::
systemFont
(
QFontDatabase
::
SmallestReadableFont
));
m_filterButton
->
setMenu
(
m_filterMenu
);
connect
(
m_filterButton
,
&
QToolButton
::
toggled
,
[
&
](
bool
toggled
)
{
if
(
toggled
)
{
processBinFiltering
();
connect
(
m_filterButton
,
&
QToolButton
::
toggled
,
[
this
]
(
bool
toggle
)
{
if
(
!
toggle
)
{
m_proxyModel
->
slotClearSearchFilters
();
return
;
}
QList
<
QAction
*>
list
=
m_filterMenu
->
actions
();
int
rateFilters
=
0
;
int
typeFilters
=
0
;
QStringList
tagFilters
;
for
(
QAction
*
ac
:
list
)
{
if
(
ac
->
isChecked
())
{
QString
actionData
=
ac
->
data
().
toString
();
if
(
actionData
.
startsWith
(
QLatin1Char
(
'#'
)))
{
// Filter by tag
tagFilters
<<
actionData
;
}
else
if
(
actionData
.
startsWith
(
QLatin1Char
(
'.'
)))
{
// Filter by rating
rateFilters
=
actionData
.
remove
(
0
,
1
).
toInt
();
}
}
}
// Type actions
list
=
m_filterTypeGroup
.
actions
();
for
(
QAction
*
ac
:
list
)
{
if
(
ac
->
isChecked
())
{
typeFilters
=
ac
->
data
().
toInt
();
break
;
}
}
QSignalBlocker
bkt
(
m_filterButton
);
if
(
rateFilters
>
0
||
!
tagFilters
.
isEmpty
()
||
typeFilters
>
0
)
{
m_filterButton
->
setChecked
(
true
);
}
else
{
// Reset filter
m_proxyModel
->
slotClearSearchType
();
m_filterButton
->
setChecked
(
false
);
}
m_proxyModel
->
slotSetFilters
(
tagFilters
,
rateFilters
,
typeFilters
);
});
connect
(
m_filterMenu
,
&
QMenu
::
triggered
,
[
&
]
()
{
if
(
m_filterButton
->
isChecked
())
{
processBinFiltering
();
}
else
{
connect
(
m_filterMenu
,
&
QMenu
::
triggered
,
[
this
](
QAction
*
action
)
{
if
(
action
->
data
().
toString
().
isEmpty
())
{
// Clear filters action
QSignalBlocker
bk
(
m_filterMenu
);
QList
<
QAction
*>
list
=
m_filterMenu
->
actions
();
list
<<
m_filterTypeGroup
.
actions
();
for
(
QAction
*
ac
:
list
)
{
ac
->
setChecked
(
false
);
}
m_proxyModel
->
slotClearSearchFilters
();
m_filterButton
->
setChecked
(
false
);
return
;
}
QList
<
QAction
*>
list
=
m_filterMenu
->
actions
();
int
rateFilters
=
0
;
int
typeFilters
=
0
;
QStringList
tagFilters
;
for
(
QAction
*
ac
:
list
)
{
if
(
ac
->
isChecked
())
{
QString
actionData
=
ac
->
data
().
toString
();
if
(
actionData
.
startsWith
(
QLatin1Char
(
'#'
)))
{
// Filter by tag
tagFilters
<<
actionData
;
}
else
if
(
actionData
.
startsWith
(
QLatin1Char
(
'.'
)))
{
// Filter by rating
rateFilters
=
actionData
.
remove
(
0
,
1
).
toInt
();
}
}
}
// Type actions
list
=
m_filterTypeGroup
.
actions
();
for
(
QAction
*
ac
:
list
)
{
if
(
ac
->
isChecked
())
{
typeFilters
=
ac
->
data
().
toInt
();
break
;
}
}
QSignalBlocker
bkt
(
m_filterButton
);
if
(
rateFilters
>
0
||
!
tagFilters
.
isEmpty
()
||
typeFilters
>
0
)
{
m_filterButton
->
setChecked
(
true
);
}
else
{
m_filterButton
->
setChecked
(
false
);
}
m_proxyModel
->
slotSetFilters
(
tagFilters
,
rateFilters
,
typeFilters
);
});
m_tagAction
->
setCheckable
(
true
);
...
...
@@ -1116,28 +1187,6 @@ void Bin::abortOperations()
blockSignals
(
false
);
}
void
Bin
::
processBinFiltering
()
{
if
(
m_filterGroup
.
checkedAction
())
{
QString
actionData
=
m_filterGroup
.
checkedAction
()
->
data
().
toString
();
if
(
actionData
.
startsWith
(
QLatin1Char
(
'#'
)))
{
// Filter by tag
m_proxyModel
->
slotSetSearchTag
(
actionData
);
}
else
if
(
actionData
.
startsWith
(
QLatin1Char
(
'.'
)))
{
// Filter by rating
int
type
=
actionData
.
remove
(
0
,
1
).
toInt
();
m_proxyModel
->
slotSetSearchRating
(
type
);
}
else
{
// Filter by type
int
type
=
actionData
.
toInt
();
m_proxyModel
->
slotSetSearchType
(
type
);
}
m_filterButton
->
setToolTip
(
i18n
(
"Filter by %1"
,
m_filterGroup
.
checkedAction
()
->
text
().
remove
(
QLatin1Char
(
'&'
))));
}
else
{
emit
displayBinMessage
(
i18n
(
"Select a filter to apply in filter menu"
),
KMessageWidget
::
Information
);
}
}
bool
Bin
::
eventFilter
(
QObject
*
obj
,
QEvent
*
event
)
{
if
(
event
->
type
()
==
QEvent
::
MouseButtonRelease
)
{
...
...
@@ -1486,6 +1535,8 @@ void Bin::rebuildFilters(QMap <QString, QString> tags)
{
m_filterMenu
->
clear
();
// Add tag filters
QAction
*
clearFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"edit-clear"
)),
i18n
(
"Clear filters"
),
this
);
m_filterMenu
->
addAction
(
clearFilter
);
int
tagsCount
=
tags
.
size
();
for
(
int
i
=
1
;
i
<=
tagsCount
;
i
++
)
{
QAction
*
tag
=
pCore
->
window
()
->
actionCollection
()
->
action
(
QString
(
"tag_%1"
).
arg
(
i
));
...
...
@@ -1500,7 +1551,7 @@ void Bin::rebuildFilters(QMap <QString, QString> tags)
m_filterMenu
->
addSeparator
();
QAction
*
rateFilter
;
for
(
int
i
=
1
;
i
<
6
;
++
i
)
{
rateFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"favorite"
)),
i18np
(
"%1 star"
,
"%1 stars"
,
i
),
&
m_filterGroup
);
rateFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"favorite"
)),
i18np
(
"%1 star"
,
"%1 stars"
,
i
),
&
m_filter
Rate
Group
);
rateFilter
->
setData
(
QString
(
".%1"
).
arg
(
2
*
i
));
rateFilter
->
setCheckable
(
true
);
m_filterMenu
->
addAction
(
rateFilter
);
...
...
@@ -1508,42 +1559,42 @@ void Bin::rebuildFilters(QMap <QString, QString> tags)
// Add type filters
m_filterMenu
->
addSeparator
();
QMenu
*
typeMenu
=
new
QMenu
(
i18n
(
"
Sort
by type"
),
m_filterMenu
);
QMenu
*
typeMenu
=
new
QMenu
(
i18n
(
"
Filter
by type"
),
m_filterMenu
);
m_filterMenu
->
addMenu
(
typeMenu
);
m_filterMenu
->
addSeparator
();
QAction
*
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"video-x-generic"
)),
i18n
(
"AV Clip"
),
&
m_filterGroup
);
QAction
*
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"video-x-generic"
)),
i18n
(
"AV Clip"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
AV
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"video-x-matroska"
)),
i18n
(
"Mute Video"
),
&
m_filterGroup
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"video-x-matroska"
)),
i18n
(
"Mute Video"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
Video
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"audio-x-generic"
)),
i18n
(
"Audio"
),
&
m_filterGroup
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"audio-x-generic"
)),
i18n
(
"Audio"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
Audio
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"image-jpeg"
)),
i18n
(
"Image"
),
&
m_filterGroup
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"image-jpeg"
)),
i18n
(
"Image"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
Image
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"kdenlive-add-slide-clip"
)),
i18n
(
"Slideshow"
),
&
m_filterGroup
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"kdenlive-add-slide-clip"
)),
i18n
(
"Slideshow"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
SlideShow
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"video-mlt-playlist"
)),
i18n
(
"Playlist"
),
&
m_filterGroup
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"video-mlt-playlist"
)),
i18n
(
"Playlist"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
Playlist
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"draw-text"
)),
i18n
(
"Title"
),
&
m_filterGroup
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"draw-text"
)),
i18n
(
"Title"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
Text
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"draw-text"
)),
i18n
(
"Title Template"
),
&
m_filterGroup
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"draw-text"
)),
i18n
(
"Title Template"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
TextTemplate
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"kdenlive-add-color-clip"
)),
i18n
(
"Color"
),
&
m_filterGroup
);
typeFilter
=
new
QAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"kdenlive-add-color-clip"
)),
i18n
(
"Color"
),
&
m_filter
Type
Group
);
typeFilter
->
setData
(
ClipType
::
Color
);
typeFilter
->
setCheckable
(
true
);
typeMenu
->
addAction
(
typeFilter
);
...
...
src/bin/bin.h
View file @
89c51c8b
...
...
@@ -436,6 +436,8 @@ private:
TagWidget
*
m_tagsWidget
;
QMenu
*
m_filterMenu
;
QActionGroup
m_filterGroup
;
QActionGroup
m_filterRateGroup
;
QActionGroup
m_filterTypeGroup
;
QToolButton
*
m_filterButton
;
/** @brief The info widget for failed jobs. */
KMessageWidget
*
m_infoMessage
;
...
...
@@ -463,8 +465,6 @@ private:
void
showSlideshowWidget
(
const
std
::
shared_ptr
<
ProjectClip
>
&
clip
);
void
processAudioThumbs
();
void
updateSortingAction
(
int
ix
);
/** @brief Apply Bin filtering. */
void
processBinFiltering
();
int
wheelAccumulatedDelta
;
signals:
...
...
src/bin/projectsortproxymodel.cpp
View file @
89c51c8b
...
...
@@ -73,8 +73,10 @@ bool ProjectSortProxyModel::filterAcceptsRowItself(int sourceRow, const QModelIn
// Column 4 contains the item tag data
QModelIndex
indexTag
=
sourceModel
()
->
index
(
sourceRow
,
4
,
sourceParent
);
auto
tagData
=
sourceModel
()
->
data
(
indexTag
);
if
(
!
tagData
.
toString
().
contains
(
m_searchTag
,
Qt
::
CaseInsensitive
))
{
return
false
;
for
(
const
QString
&
tag
:
m_searchTag
)
{
if
(
!
tagData
.
toString
().
contains
(
tag
,
Qt
::
CaseInsensitive
))
{
return
false
;
}
}
}
if
(
data
.
toString
().
contains
(
m_searchString
,
Qt
::
CaseInsensitive
))
{
...
...
@@ -140,31 +142,15 @@ void ProjectSortProxyModel::slotSetSearchString(const QString &str)
invalidateFilter
();
}
void
ProjectSortProxyModel
::
slotSetSearchRating
(
const
int
type
)
{
m_searchTag
.
clear
();
m_searchType
=
0
;
m_searchRating
=
type
;
invalidateFilter
();
}
void
ProjectSortProxyModel
::
slotSetSearchTag
(
const
QString
&
str
)
void
ProjectSortProxyModel
::
slotSetFilters
(
const
QStringList
tagFilters
,
const
int
rateFilters
,
const
int
typeFilters
)
{
m_searchType
=
0
;
m_searchRating
=
0
;
m_searchTag
=
str
;
invalidateFilter
();
}
void
ProjectSortProxyModel
::
slotSetSearchType
(
const
int
type
)
{
m_searchTag
.
clear
();
m_searchRating
=
0
;
m_searchType
=
type
;
m_searchType
=
typeFilters
;
m_searchRating
=
rateFilters
;
m_searchTag
=
tagFilters
;
invalidateFilter
();
}
void
ProjectSortProxyModel
::
slotClearSearch
Type
()
void
ProjectSortProxyModel
::
slotClearSearch
Filters
()
{
m_searchTag
.
clear
();
m_searchRating
=
0
;
...
...
src/bin/projectsortproxymodel.h
View file @
89c51c8b
...
...
@@ -44,13 +44,9 @@ public slots:
/** @brief Set search string that will filter the view */
void
slotSetSearchString
(
const
QString
&
str
);
/** @brief Set search tag that will filter the view */
void
slotSetSearchTag
(
const
QString
&
str
);
/** @brief Set search rating that will filter the view */
void
slotSetSearchRating
(
const
int
type
);
/** @brief Set search type that will filter the view */
void
slotSetSearchType
(
const
int
type
);
void
slotSetFilters
(
const
QStringList
tagFilters
,
int
rateFilters
,
int
typeFilters
);
/** @brief Reset search filters */
void
slotClearSearch
Type
();
void
slotClearSearch
Filters
();
/** @brief Relay datachanged signal from view's model */
void
slotDataChanged
(
const
QModelIndex
&
ix1
,
const
QModelIndex
&
ix2
,
const
QVector
<
int
>
&
roles
);
/** @brief Select all items in model */
...
...
@@ -72,7 +68,7 @@ protected:
private:
QItemSelectionModel
*
m_selection
;
QString
m_searchString
;
QString
m_searchTag
;
QString
List
m_searchTag
;
int
m_searchType
;
int
m_searchRating
;
QCollator
m_collator
;
...
...
Eugen Mohr
@emohr
mentioned in issue
#287
·
Jan 11, 2020
mentioned in issue
#287
mentioned in issue #287
Toggle commit list
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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