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
870a07b8
Commit
870a07b8
authored
Mar 16, 2017
by
Nicolas Carion
Browse files
Starting to convert EffectList to a QAbstractItemModel
parent
8aa278e1
Changes
15
Hide whitespace changes
Inline
Side-by-side
src/CMakeLists.txt
View file @
870a07b8
...
...
@@ -92,6 +92,7 @@ install(FILES kdenlivesettings.kcfg DESTINATION ${KCFG_INSTALL_DIR})
kconfig_add_kcfg_files
(
kdenlive_SRCS kdenlivesettings.kcfgc
)
add_subdirectory
(
abstractmodel
)
add_subdirectory
(
effects
)
add_subdirectory
(
doc
)
add_subdirectory
(
project
)
add_subdirectory
(
timeline
)
...
...
src/effects/CMakeLists.txt
0 → 100644
View file @
870a07b8
set
(
kdenlive_SRCS
${
kdenlive_SRCS
}
effects/effectsrepository.cpp
effects/effectlist/view/effectlistwidget.cpp
effects/effectlist/view/qmltypes/effecticonprovider.cpp
effects/effectlist/model/effecttreemodel.cpp
effects/effectlist/model/effectfilter.cpp
PARENT_SCOPE
)
src/effects/effectlist/model/effectfilter.cpp
0 → 100644
View file @
870a07b8
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include
"effectfilter.hpp"
#include
"effecttreemodel.hpp"
#include
"abstractmodel/treeitem.hpp"
EffectFilter
::
EffectFilter
(
QObject
*
parent
)
:
QSortFilterProxyModel
(
parent
)
{
m_name_enabled
=
m_type_enabled
=
false
;
}
void
EffectFilter
::
setFilterName
(
bool
enabled
,
const
QString
&
pattern
)
{
m_name_enabled
=
enabled
;
m_name_value
=
pattern
;
invalidateFilter
();
}
bool
EffectFilter
::
filterName
(
TreeItem
*
item
)
const
{
if
(
!
m_name_enabled
)
{
return
true
;
}
QString
itemText
=
item
->
data
(
EffectTreeModel
::
nameCol
).
toString
();
itemText
=
itemText
.
normalized
(
QString
::
NormalizationForm_D
).
remove
(
QRegExp
(
QStringLiteral
(
"[^a-zA-Z0-9
\\
s]"
)));
QString
patt
=
m_name_value
.
normalized
(
QString
::
NormalizationForm_D
).
remove
(
QRegExp
(
QStringLiteral
(
"[^a-zA-Z0-9
\\
s]"
)));
return
itemText
.
contains
(
patt
,
Qt
::
CaseInsensitive
);
}
void
EffectFilter
::
setFilterType
(
bool
enabled
,
EffectType
type
)
{
m_type_enabled
=
enabled
;
m_type_value
=
type
;
invalidateFilter
();
}
bool
EffectFilter
::
filterType
(
TreeItem
*
item
)
const
{
if
(
!
m_type_enabled
)
{
return
true
;
}
EffectType
itemType
=
item
->
data
(
EffectTreeModel
::
typeCol
).
value
<
EffectType
>
();
return
itemType
==
m_type_value
;
}
bool
EffectFilter
::
filterAcceptsRow
(
int
sourceRow
,
const
QModelIndex
&
sourceParent
)
const
{
if
(
sourceParent
==
QModelIndex
())
{
//In that case, we have a category. We hide it if it does not have children.
QModelIndex
category
=
sourceModel
()
->
index
(
sourceRow
,
0
,
sourceParent
);
bool
accepted
=
false
;
for
(
int
i
=
0
;
i
<
sourceModel
()
->
rowCount
(
category
)
&&
!
accepted
;
++
i
)
{
accepted
=
filterAcceptsRow
(
i
,
category
);
}
return
accepted
;
}
QModelIndex
row
=
sourceModel
()
->
index
(
sourceRow
,
0
,
sourceParent
);
TreeItem
*
item
=
static_cast
<
TreeItem
*>
(
row
.
internalPointer
());
return
filterName
(
item
)
&&
filterType
(
item
);
}
bool
EffectFilter
::
isVisible
(
const
QModelIndex
&
sourceIndex
)
{
auto
parent
=
sourceModel
()
->
parent
(
sourceIndex
);
return
filterAcceptsRow
(
sourceIndex
.
row
(),
parent
);
}
src/effects/effectlist/model/effectfilter.hpp
0 → 100644
View file @
870a07b8
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef EFFECTFILTER_H
#define EFFECTFILTER_H
#include
<QSortFilterProxyModel>
#include
<memory>
#include
"effects/effectsrepository.hpp"
class
TreeItem
;
/* @brief This class is used as a proxy model to filter the effect tree based on given criterion (name, type)
*/
class
EffectFilter
:
public
QSortFilterProxyModel
{
Q_OBJECT
public:
EffectFilter
(
QObject
*
parent
=
nullptr
);
/* @brief Manage the name filter
@param enabled whether to enable this filter
@param pattern to match against effects' names
*/
void
setFilterName
(
bool
enabled
,
const
QString
&
pattern
);
/* @brief Manage the type filter
@param enabled whether to enable this filter
@param type Effect type to display
*/
void
setFilterType
(
bool
enabled
,
EffectType
type
);
/** @brief Returns true if the ModelIndex in the source model is visible after filtering
*/
bool
isVisible
(
const
QModelIndex
&
sourceIndex
);
protected:
bool
filterAcceptsRow
(
int
sourceRow
,
const
QModelIndex
&
sourceParent
)
const
override
;
private:
bool
filterName
(
TreeItem
*
item
)
const
;
bool
filterType
(
TreeItem
*
item
)
const
;
bool
m_name_enabled
;
QString
m_name_value
;
bool
m_type_enabled
;
EffectType
m_type_value
;
};
#endif
src/effects/effectlist/model/effecttreemodel.cpp
0 → 100644
View file @
870a07b8
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include
"effecttreemodel.hpp"
#include
"effects/effectsrepository.hpp"
#include
"abstractmodel/treeitem.hpp"
#include
<vector>
#include
<QVector>
#include
<array>
#include
<KLocalizedString>
#include
<QDomDocument>
#include
<QFile>
#include
<QDebug>
int
EffectTreeModel
::
nameCol
=
0
;
int
EffectTreeModel
::
idCol
=
1
;
int
EffectTreeModel
::
typeCol
=
2
;
int
EffectTreeModel
::
favCol
=
3
;
EffectTreeModel
::
EffectTreeModel
(
const
QString
&
categoryFile
,
QObject
*
parent
)
:
AbstractTreeModel
(
parent
)
{
QList
<
QVariant
>
rootData
;
rootData
<<
"Name"
<<
"ID"
<<
"Type"
<<
"isFav"
;
rootItem
=
new
TreeItem
(
rootData
);
QHash
<
QString
,
TreeItem
*>
effectCategory
;
//category in which each effect should land.
//We parse category file
if
(
!
categoryFile
.
isEmpty
())
{
QDomDocument
doc
;
QFile
file
(
categoryFile
);
doc
.
setContent
(
&
file
,
false
);
file
.
close
();
QDomNodeList
groups
=
doc
.
documentElement
().
elementsByTagName
(
QStringLiteral
(
"group"
));
for
(
int
i
=
0
;
i
<
groups
.
count
();
i
++
)
{
QString
groupName
=
i18n
(
groups
.
at
(
i
).
firstChild
().
firstChild
().
nodeValue
().
toUtf8
().
constData
());
QStringList
list
=
groups
.
at
(
i
).
toElement
().
attribute
(
QStringLiteral
(
"list"
)).
split
(
QLatin1Char
(
','
),
QString
::
SkipEmptyParts
);
TreeItem
*
groupItem
=
rootItem
->
appendChild
(
QList
<
QVariant
>
{
groupName
});
for
(
const
QString
&
effect
:
list
){
effectCategory
[
effect
]
=
groupItem
;
}
}
}
//We also create "Misc" and "Custom" categories
TreeItem
*
miscCategory
=
rootItem
->
appendChild
(
QList
<
QVariant
>
{
i18n
(
"Misc"
)});
TreeItem
*
customCategory
=
rootItem
->
appendChild
(
QList
<
QVariant
>
{
i18n
(
"Custom"
)});
//We parse effects
auto
allEffects
=
EffectsRepository
::
get
()
->
getEffectsNames
();
for
(
const
auto
&
effect
:
allEffects
)
{
TreeItem
*
targetCategory
=
miscCategory
;
EffectType
type
=
EffectsRepository
::
get
()
->
getEffectType
(
effect
.
first
);
if
(
effectCategory
.
contains
(
effect
.
first
))
{
targetCategory
=
effectCategory
[
effect
.
first
];
}
if
(
type
==
EffectType
::
Custom
)
{
targetCategory
=
customCategory
;
}
// we create the data list corresponding to this profile
QList
<
QVariant
>
data
;
bool
isFav
=
EffectsRepository
::
get
()
->
isFavorite
(
effect
.
first
);
qDebug
()
<<
effect
.
second
<<
effect
.
first
<<
"in "
<<
targetCategory
->
data
(
0
).
toString
();
data
<<
effect
.
second
<<
effect
.
first
<<
QVariant
::
fromValue
(
type
)
<<
isFav
;
targetCategory
->
appendChild
(
data
);
}
}
QHash
<
int
,
QByteArray
>
EffectTreeModel
::
roleNames
()
const
{
QHash
<
int
,
QByteArray
>
roles
;
roles
[
IdRole
]
=
"id"
;
roles
[
NameRole
]
=
"name"
;
return
roles
;
}
QString
EffectTreeModel
::
getName
(
const
QModelIndex
&
index
)
const
{
if
(
!
index
.
isValid
())
{
return
QString
();
}
TreeItem
*
item
=
static_cast
<
TreeItem
*>
(
index
.
internalPointer
());
if
(
item
->
depth
()
==
1
)
{
return
item
->
data
(
0
).
toString
();
}
else
{
return
item
->
data
(
EffectTreeModel
::
nameCol
).
toString
();
}
}
QVariant
EffectTreeModel
::
data
(
const
QModelIndex
&
index
,
int
role
)
const
{
if
(
!
index
.
isValid
())
{
return
QVariant
();
}
TreeItem
*
item
=
static_cast
<
TreeItem
*>
(
index
.
internalPointer
());
if
(
role
==
IdRole
)
{
if
(
item
->
depth
()
==
1
)
{
return
"root"
;
}
else
{
return
item
->
data
(
EffectTreeModel
::
idCol
);
}
}
if
(
role
!=
NameRole
)
{
return
QVariant
();
}
return
item
->
data
(
index
.
column
());
}
src/effects/effectlist/model/effecttreemodel.hpp
0 → 100644
View file @
870a07b8
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef EFFECTTREEMODEL_H
#define EFFECTTREEMODEL_H
#include
"abstractmodel/abstracttreemodel.hpp"
#include
<QHash>
#include
<QIcon>
/* @brief This class represents an effect hierarchy to be displayed as a tree
*/
class
TreeItem
;
class
EffectTreeModel
:
public
AbstractTreeModel
{
Q_OBJECT
public:
explicit
EffectTreeModel
(
const
QString
&
categoryFile
,
QObject
*
parent
=
0
);
enum
{
IdRole
=
Qt
::
UserRole
+
1
,
NameRole
};
//Helper function to retrieve name
QString
getName
(
const
QModelIndex
&
index
)
const
;
QHash
<
int
,
QByteArray
>
roleNames
()
const
override
;
QVariant
data
(
const
QModelIndex
&
index
,
int
role
)
const
override
;
// for convenience, we store the column of each data field
static
int
nameCol
,
idCol
,
favCol
,
typeCol
;
protected:
};
#endif
src/effects/effectlist/view/effectlistwidget.cpp
0 → 100644
View file @
870a07b8
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include
"effectlistwidget.hpp"
#include
"../model/effecttreemodel.hpp"
#include
"../model/effectfilter.hpp"
#include
"effects/effectsrepository.hpp"
#include
<QStandardPaths>
#include
<QQmlContext>
EffectListWidget
::
EffectListWidget
(
QWidget
*
parent
)
:
QQuickWidget
(
parent
)
{
QString
effectCategory
=
QStandardPaths
::
locate
(
QStandardPaths
::
AppDataLocation
,
QStringLiteral
(
"kdenliveeffectscategory.rc"
));
m_model
.
reset
(
new
EffectTreeModel
(
effectCategory
,
this
));
m_proxyModel
=
new
EffectFilter
(
this
);
m_proxyModel
->
setSourceModel
(
m_model
.
get
());
setResizeMode
(
QQuickWidget
::
SizeRootObjectToView
);
rootContext
()
->
setContextProperty
(
"effectlist"
,
this
);
rootContext
()
->
setContextProperty
(
"effectListModel"
,
m_proxyModel
);
m_effectIconProvider
.
reset
(
new
EffectIconProvider
);
engine
()
->
addImageProvider
(
QStringLiteral
(
"effecticon"
),
m_effectIconProvider
.
get
());
setSource
(
QUrl
(
QStringLiteral
(
"qrc:/qml/effectList.qml"
)));
setFocusPolicy
(
Qt
::
StrongFocus
);
}
QString
EffectListWidget
::
getName
(
const
QModelIndex
&
index
)
const
{
return
m_model
->
getName
(
m_proxyModel
->
mapToSource
(
index
));
}
src/effects/effectlist/view/effectlistwidget.hpp
0 → 100644
View file @
870a07b8
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef EFFECTLISTWIDGET_H
#define EFFECTLISTWIDGET_H
#include
<QQuickWidget>
#include
<memory>
#include
"qmltypes/effecticonprovider.hpp"
/* @brief This class is a widget that display the list of available effects
*/
class
EffectFilter
;
class
EffectTreeModel
;
class
EffectListWidget
:
public
QQuickWidget
{
Q_OBJECT
public:
EffectListWidget
(
QWidget
*
parent
=
Q_NULLPTR
);
Q_INVOKABLE
QString
getName
(
const
QModelIndex
&
index
)
const
;
private:
std
::
unique_ptr
<
EffectTreeModel
>
m_model
;
EffectFilter
*
m_proxyModel
;
std
::
unique_ptr
<
EffectIconProvider
>
m_effectIconProvider
;
signals:
};
#endif
src/effects/effectlist/view/qml/effectList.qml
0 → 100644
View file @
870a07b8
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
import
QtQuick
2.4
import
QtQuick
.
Controls
1.4
import
QtQuick
.
Controls
.
Styles
1.4
import
QtQuick
.
Window
2.2
Rectangle
{
id
:
listRoot
TreeView
{
anchors.fill
:
parent
alternatingRowColors
:
false
headerVisible
:
false
itemDelegate
:
Row
{
Image
{
visible
:
styleData
.
value
!=
"
root
"
source
:
'
image://effecticon/
'
+
styleData
.
value
}
Text
{
text
:
effectlist
.
getName
(
styleData
.
index
)
}
}
TableViewColumn
{
role
:
"
id
"
;
title
:
"
Name
"
;
width
:
200
}
model
:
effectListModel
}
}
src/effects/effectlist/view/qmltypes/effecticonprovider.cpp
0 → 100644
View file @
870a07b8
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include
"effecticonprovider.hpp"
#include
"effects/effectsrepository.hpp"
#include
<QDebug>
#include
<QIcon>
#include
<QPainter>
#include
<QFont>
EffectIconProvider
::
EffectIconProvider
()
:
QQuickImageProvider
(
QQmlImageProviderBase
::
Image
,
QQmlImageProviderBase
::
ForceAsynchronousImageLoading
)
{
}
QImage
EffectIconProvider
::
requestImage
(
const
QString
&
id
,
QSize
*
size
,
const
QSize
&
requestedSize
)
{
QImage
result
;
// id is [hash]/mlt_service/resource#frameNumber
if
(
EffectsRepository
::
get
()
->
hasEffect
(
id
))
{
QString
name
=
EffectsRepository
::
get
()
->
getEffectName
(
id
);
result
=
makeIcon
(
id
,
name
,
requestedSize
);
if
(
size
)
{
*
size
=
result
.
size
();
}
}
else
{
qDebug
()
<<
"Effect not found "
<<
id
;
}
return
result
;
}
QImage
EffectIconProvider
::
makeIcon
(
const
QString
&
effectId
,
const
QString
&
effectName
,
const
QSize
&
size
)
{
qDebug
()
<<
"Painting"
<<
effectName
<<
"size"
<<
size
;
QPixmap
pix
(
30
,
30
);
if
(
effectName
.
isEmpty
())
{
pix
.
fill
(
Qt
::
red
);
return
pix
.
toImage
();
}
QFont
ft
=
QFont
();
ft
.
setBold
(
true
);
uint
hex
=
qHash
(
effectName
);
QString
t
=
"#"
+
QString
::
number
(
hex
,
16
).
toUpper
().
left
(
6
);
QColor
col
(
t
);
bool
isAudio
=
EffectsRepository
::
get
()
->
getEffectType
(
effectId
)
==
EffectType
::
Audio
;