Commit 35a4d73f authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Add new marker multi category selection button (MarkerCategoryButton), used in guides list

parent a7999056
Pipeline #260982 passed with stage
in 5 minutes and 19 seconds
......@@ -49,9 +49,6 @@ GuidesList::GuidesList(QWidget *parent)
{
setupUi(this);
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
categoryContent->setLayout(&m_categoriesLayout);
category_frame->setVisible(false);
connect(show_categories, &QToolButton::toggled, category_frame, &QFrame::setVisible);
m_proxy = new GuidesProxyModel(this);
connect(guides_list, &QListView::doubleClicked, this, &GuidesList::editGuide);
connect(guide_delete, &QToolButton::clicked, this, &GuidesList::removeGuide);
......@@ -76,7 +73,7 @@ GuidesList::GuidesList(QWidget *parent)
guides_settings->setMenu(settingsMenu);
// Sort menu
m_filterGroup = new QActionGroup(this);
m_sortGroup = new QActionGroup(this);
QMenu *sortMenu = new QMenu(this);
QAction *sort1 = new QAction(i18n("Sort by Category"), this);
sort1->setCheckable(true);
......@@ -90,9 +87,9 @@ GuidesList::GuidesList(QWidget *parent)
sort1->setData(0);
sort2->setData(1);
sort3->setData(2);
m_filterGroup->addAction(sort1);
m_filterGroup->addAction(sort2);
m_filterGroup->addAction(sort3);
m_sortGroup->addAction(sort1);
m_sortGroup->addAction(sort2);
m_sortGroup->addAction(sort3);
sortMenu->addAction(sort1);
sortMenu->addAction(sort2);
sortMenu->addAction(sort3);
......@@ -100,9 +97,15 @@ GuidesList::GuidesList(QWidget *parent)
sortMenu->addAction(sortDescending);
sort2->setChecked(true);
sort_guides->setMenu(sortMenu);
connect(m_filterGroup, &QActionGroup::triggered, this, &GuidesList::sortView);
connect(m_sortGroup, &QActionGroup::triggered, this, &GuidesList::sortView);
connect(sortDescending, &QAction::triggered, this, &GuidesList::changeSortOrder);
// Filtering
show_categories->enableFilterMode();
show_categories->setAllowAll(true);
connect(show_categories, &QToolButton::toggled, this, &GuidesList::switchFilter);
connect(show_categories, &MarkerCategoryButton::categoriesChanged, this, &GuidesList::updateFilter);
guide_add->setToolTip(i18n("Add new guide."));
guide_add->setWhatsThis(xi18nc("@info:whatsthis", "Add new guide. This will add a guide at the current frame position."));
guide_delete->setToolTip(i18n("Delete guide."));
......@@ -269,6 +272,7 @@ void GuidesList::setClipMarkerModel(std::shared_ptr<ProjectClip> clip)
guides_list->setSelectionMode(QAbstractItemView::ExtendedSelection);
connect(guides_list->selectionModel(), &QItemSelectionModel::selectionChanged, this, &GuidesList::selectionChanged);
if (auto markerModel = m_model.lock()) {
show_categories->setMarkerModel(markerModel.get());
connect(markerModel.get(), &MarkerListModel::categoriesChanged, this, &GuidesList::rebuildCategories);
}
rebuildCategories();
......@@ -286,6 +290,7 @@ void GuidesList::setModel(std::weak_ptr<MarkerListModel> model, std::shared_ptr<
setEnabled(true);
guideslist_label->setText(i18n("Timeline Guides"));
if (auto markerModel = m_model.lock()) {
show_categories->setMarkerModel(markerModel.get());
m_sortModel = viewModel.get();
m_proxy->setSourceModel(m_sortModel);
guides_list->setModel(m_proxy);
......@@ -298,15 +303,6 @@ void GuidesList::setModel(std::weak_ptr<MarkerListModel> model, std::shared_ptr<
void GuidesList::rebuildCategories()
{
// Clean up categories
QLayoutItem *item;
while ((item = m_categoriesLayout.takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
delete catGroup;
catGroup = new QButtonGroup(this);
catGroup->setExclusive(false);
QPixmap pixmap(32, 32);
// Cleanup default marker category menu
QMenu *markerDefaultMenu = default_category->menu();
......@@ -328,9 +324,6 @@ void GuidesList::rebuildCategories()
i.next();
pixmap.fill(i.value().color);
QIcon colorIcon(pixmap);
QCheckBox *cb = new QCheckBox(i.value().displayName, this);
cb->setProperty("index", i.key());
cb->setIcon(colorIcon);
QAction *ac = new QAction(colorIcon, i.value().displayName);
ac->setData(i.key());
markerDefaultMenu->addAction(ac);
......@@ -338,8 +331,6 @@ void GuidesList::rebuildCategories()
default_category->setIcon(colorIcon);
defaultCategoryFound = true;
}
catGroup->addButton(cb);
m_categoriesLayout.addWidget(cb);
}
if (!defaultCategoryFound) {
// Default marker category not found. set it to first one
......@@ -349,7 +340,6 @@ void GuidesList::rebuildCategories()
KdenliveSettings::setDefault_marker_type(ac->data().toInt());
}
}
connect(catGroup, &QButtonGroup::buttonToggled, this, &GuidesList::updateFilter);
}
void GuidesList::refreshDefaultCategory()
......@@ -367,16 +357,20 @@ void GuidesList::refreshDefaultCategory()
}
}
void GuidesList::updateFilter(QAbstractButton *, bool)
void GuidesList::switchFilter(bool enable)
{
QList<int> filters;
QList<QAbstractButton *> buttons = catGroup->buttons();
for (auto &b : buttons) {
if (b->isChecked()) {
filters << b->property("index").toInt();
}
if (enable) {
QList<int> cats = show_categories->currentCategories();
cats.removeAll(-1);
updateFilter(cats);
} else {
updateFilter({});
}
pCore->currentDoc()->setGuidesFilter(filters);
}
void GuidesList::updateFilter(QList<int> categories)
{
pCore->currentDoc()->setGuidesFilter(categories);
emit pCore->refreshActiveGuides();
}
......
......@@ -42,11 +42,12 @@ private slots:
void addGuide();
void configureGuides();
void rebuildCategories();
void updateFilter(QAbstractButton *, bool);
void updateFilter(QList<int> categories);
void filterView(const QString &text);
void sortView(QAction *ac);
void changeSortOrder(bool descending);
void refreshDefaultCategory();
void switchFilter(bool enable);
private:
/** @brief Set the marker model that will be displayed. */
......@@ -54,9 +55,8 @@ private:
QIdentityProxyModel *m_proxy{nullptr};
MarkerSortModel *m_sortModel{nullptr};
std::shared_ptr<ProjectClip> m_clip;
QVBoxLayout m_categoriesLayout;
QButtonGroup *catGroup{nullptr};
QActionGroup *m_filterGroup;
QActionGroup *m_sortGroup;
bool m_markerMode;
signals:
......
......@@ -6,49 +6,15 @@
<rect>
<x>0</x>
<y>0</y>
<width>227</width>
<height>296</height>
<width>263</width>
<height>288</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="3">
<widget class="KSqueezedTextLabel" name="guideslist_label">
<property name="text">
<string>KSqueezedTextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="filter_line">
<property name="placeholderText">
<string>Search</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="sort_guides">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="view-sort">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<item row="4" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="guide_add">
......@@ -140,59 +106,58 @@
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="show_categories">
<item row="0" column="0" colspan="3">
<widget class="KSqueezedTextLabel" name="guideslist_label">
<property name="text">
<string>KSqueezedTextLabel</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="sort_guides">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="view-filter">
<normaloff>../../../../.designer/backup</normaloff>../../../../.designer/backup</iconset>
<iconset theme="view-sort">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="checkable">
<bool>true</bool>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<item row="2" column="0" colspan="3">
<widget class="QListView" name="guides_list">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QScrollArea" name="category_frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<item row="1" column="0">
<widget class="QLineEdit" name="filter_line">
<property name="placeholderText">
<string>Search</string>
</property>
<property name="widgetResizable">
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
<widget class="QWidget" name="categoryContent">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>215</width>
<height>83</height>
</rect>
</property>
</widget>
</widget>
</item>
<item row="1" column="1">
<widget class="MarkerCategoryButton" name="show_categories"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MarkerCategoryButton</class>
<extends>QToolButton</extends>
<header>widgets/markercategorybutton.h</header>
</customwidget>
<customwidget>
<class>KSqueezedTextLabel</class>
<extends>QLabel</extends>
......
......@@ -6,6 +6,7 @@ set(kdenlive_SRCS
widgets/dragvalue.cpp
widgets/geometrywidget.cpp
widgets/markercategorychooser.cpp
widgets/markercategorybutton.cpp
widgets/positionwidget.cpp
widgets/progressbutton.cpp
widgets/timecodedisplay.cpp
......@@ -39,6 +40,12 @@ if (BUILD_DESIGNERPLUGIN)
GROUP "Kdenlive Widgets"
)
ecm_qtdesignerplugin_widget(MarkerCategoryButton
INCLUDE_FILE widgets/markercategorybutton.h
TOOLTIP "A QToolButton that can be used to select one or several marker categories (Kdenlive)"
GROUP "Kdenlive Widgets"
)
ecm_add_qtdesignerplugin(kdenlivewidgets
NAME KdenliveWidgets
WIDGETS
......@@ -46,6 +53,7 @@ if (BUILD_DESIGNERPLUGIN)
ColorPickerWidget
ChooseColorWidget
MarkerCategoryChooser
MarkerCategoryButton
LINK_LIBRARIES
kdenliveLib
INSTALL_DESTINATION "${KDE_INSTALL_QTPLUGINDIR}/designer"
......
/*
* SPDX-FileCopyrightText: 2022 Jean-Baptiste Mardelle <jb.kdenlive@org>
* SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "markercategorybutton.h"
#include "../bin/model/markerlistmodel.hpp"
#include "core.h"
#include <KLocalizedString>
#include <QMenu>
MarkerCategoryButton::MarkerCategoryButton(QWidget *parent)
: QToolButton(parent)
, m_markerListModel(nullptr)
, m_allowAll(true)
, m_onlyUsed(false)
{
setCheckable(false);
setIcon(QIcon::fromTheme(QLatin1String("view-filter")));
setPopupMode(QToolButton::InstantPopup);
m_menu = new QMenu(this);
setMenu(m_menu);
if (pCore) {
refresh();
}
connect(m_menu, &QMenu::triggered, this, &MarkerCategoryButton::categorySelected);
connect(this, &MarkerCategoryButton::changed, this, &MarkerCategoryButton::refresh);
}
void MarkerCategoryButton::enableFilterMode()
{
setCheckable(true);
setPopupMode(QToolButton::MenuButtonPopup);
}
void MarkerCategoryButton::categorySelected(QAction *ac)
{
int index = ac->data().toInt();
QList<QAction *> actions = m_menu->actions();
if (index == -1) {
if (!ac->isChecked()) {
// Don't allow unselecting all categories
ac->setChecked(true);
if (isCheckable()) {
setChecked(false);
}
return;
}
// All categories selected, unselect any other
for (auto &action : actions) {
if (action != ac && action->isChecked()) {
action->setChecked(false);
}
}
emit categoriesChanged({-1});
if (isCheckable()) {
setChecked(false);
}
return;
} else {
// If a category is selected, ensure "all categories" is unchecked
if (!ac->isChecked()) {
bool categorySelected = false;
for (auto &action : actions) {
if (action->data().toInt() != -1 && action->isChecked()) {
categorySelected = true;
break;
}
}
if (!categorySelected) {
for (auto &action : actions) {
if (action->data().toInt() == -1) {
action->setChecked(true);
break;
}
}
}
} else {
// A category is checked, ensure "all categories is unchecked
for (auto &action : actions) {
if (action->data().toInt() == -1) {
action->setChecked(false);
break;
}
}
}
}
QList<int> selection;
for (auto &action : actions) {
if (action->isChecked()) {
selection << action->data().toInt();
}
}
emit categoriesChanged(selection);
if (isCheckable()) {
setChecked(selection != (QList<int>() << -1));
}
}
void MarkerCategoryButton::refresh()
{
QList<int> selected;
// remember selected categories
QList<QAction *> actions = m_menu->actions();
for (auto &ac : actions) {
if (ac->isChecked()) {
selected << ac->data().toInt();
}
}
m_menu->clear();
// Set up guide categories
QPixmap pixmap(32, 32);
QMapIterator<int, Core::MarkerCategory> i(pCore->markerTypes);
while (i.hasNext()) {
i.next();
if (m_onlyUsed && m_markerListModel && m_markerListModel->getAllMarkers(i.key()).isEmpty()) {
continue;
}
pixmap.fill(i.value().color);
QIcon colorIcon(pixmap);
QAction *ac = new QAction(colorIcon, i.value().displayName, m_menu);
ac->setData(i.key());
ac->setCheckable(true);
ac->setChecked(selected.contains(i.key()));
m_menu->addAction(ac);
}
if (m_menu->actions().count() == 0) {
setEnabled(false);
setText(i18n("Nothing to select"));
return;
}
setEnabled(true);
if (m_allowAll) {
QAction *ac = new QAction(i18n("All Categories"), m_menu);
ac->setData(-1);
ac->setCheckable(true);
m_menu->insertAction(m_menu->actions().first(), ac);
if (selected.isEmpty() || selected.contains(-1)) {
ac->setChecked(true);
}
}
}
void MarkerCategoryButton::setCurrentCategories(QList<int> categories)
{
QList<QAction *> actions = m_menu->actions();
if (categories.contains(-1)) {
for (auto &ac : actions) {
if (ac->data().toInt() == -1) {
ac->setChecked(true);
} else {
ac->setChecked(false);
}
}
} else {
for (auto &ac : actions) {
int categoryIndex = ac->data().toInt();
if (categoryIndex == -1) {
ac->setChecked(false);
} else {
ac->setChecked(categories.contains(categoryIndex));
}
}
}
}
QList<int> MarkerCategoryButton::currentCategories()
{
QList<int> selected;
QList<QAction *> actions = m_menu->actions();
for (auto &ac : actions) {
if (ac->isChecked()) {
selected << ac->data().toInt();
}
}
if (selected.contains(-1)) {
return {-1};
}
return selected;
}
void MarkerCategoryButton::setMarkerModel(const MarkerListModel *model)
{
m_markerListModel = model;
connect(m_markerListModel, &MarkerListModel::categoriesChanged, this, &MarkerCategoryButton::changed);
emit changed();
}
void MarkerCategoryButton::setAllowAll(bool allowAll)
{
m_allowAll = allowAll;
emit changed();
}
void MarkerCategoryButton::setOnlyUsed(bool onlyUsed)
{
m_onlyUsed = onlyUsed;
emit changed();
}
/*
* SPDX-FileCopyrightText: 2022 Jean-Baptiste Mardelle <jb.kdenlive@org>
* SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef MARKERCATEGORYBUTTON_H
#define MARKERCATEGORYBUTTON_H
#include <QToolButton>
#include <QWidget>
class MarkerListModel;
class QMenu;
class MarkerCategoryButton : public QToolButton
{
Q_OBJECT
Q_PROPERTY(bool allowAll READ allowAll WRITE setAllowAll NOTIFY changed)
Q_PROPERTY(bool onlyUsed READ onlyUsed WRITE setOnlyUsed NOTIFY changed)
public:
MarkerCategoryButton(QWidget *parent = nullptr);
/** @brief Set currently selected category by its number. */
void setCurrentCategories(QList<int> categories);
/** @brief get the number of the currently selected category. */
QList<int> currentCategories();
/** @brief Set the marker model of the chooser. Only needed if @property onlyUsed is true.*/
void setMarkerModel(const MarkerListModel *model);
/** @brief Whether the user should be able to select "All Categories" */
void setAllowAll(bool allowAll);
/** @brief Show only categories that are used by markers in the model.
* If no model is set, all categories will be show. @see setMarkerModel
*/
void setOnlyUsed(bool onlyUsed);
/** @brief Calling this will make the button checkable and have a default action on its own (for example enable/disable filtering) */
void enableFilterMode();
private slots:
void categorySelected(QAction *ac);
private:
const MarkerListModel *m_markerListModel;
bool m_allowAll;
bool m_onlyUsed;
QMenu *m_menu;
void refresh();
bool allowAll() { return m_allowAll; };
bool onlyUsed() { return m_onlyUsed; };
signals:
void changed();
void categoriesChanged(const QList<int> categories);
};
#endif // MARKERCATEGORYBUTTON_H
......@@ -14,7 +14,9 @@ MarkerCategoryChooser::MarkerCategoryChooser(QWidget *parent)
, m_allowAll(true)
, m_onlyUsed(false)
{
refresh();
if (pCore) {
refresh();
}
connect(this, &MarkerCategoryChooser::changed, this, &MarkerCategoryChooser::refresh);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment