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

Fix marker import, add button for default marker type

parent cd54269b
Pipeline #260478 failed with stage
in 12 minutes and 49 seconds
......@@ -626,16 +626,26 @@ void MarkerListModel::registerSnapModel(const std::weak_ptr<SnapInterface> &snap
}
}
bool MarkerListModel::importFromFile(const QString &fileData, bool ignoreConflicts)
{
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool res = importFromJson(fileData, ignoreConflicts, undo, redo);
if (!res) {
res = importFromTxt(fileData, undo, redo);
}
if (res) {
PUSH_UNDO(undo, redo, m_guide ? i18n("Import guides") : i18n("Import markers"));
}
return res;
}
bool MarkerListModel::importFromJson(const QString &data, bool ignoreConflicts, bool pushUndo)
{
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool result = importFromJson(data, ignoreConflicts, undo, redo);
/*if (!result) {
// Import failed, try to import as txt data
result = importFromTxt(data, ignoreConflicts, undo, redo);
}*/
if (pushUndo) {
if (result && pushUndo) {
PUSH_UNDO(undo, redo, m_guide ? i18n("Import guides") : i18n("Import markers"));
}
return result;
......@@ -684,67 +694,61 @@ bool MarkerListModel::importFromJson(const QString &data, bool ignoreConflicts,
return true;
}
bool MarkerListModel::importFromTxt(const QString &fileName, Fun &undo, Fun &redo)
bool MarkerListModel::importFromTxt(const QString &fileData, Fun &undo, Fun &redo)
{
QWriteLocker locker(&m_lock);
QFile inputFile(fileName);
bool res = true;
bool res = false;
bool lineRead = false;
// TODO: ask for a category
int type = 0;
if (inputFile.open(QIODevice::ReadOnly)) {
QTextStream in(&inputFile);
while (!in.atEnd()) {
QString line = in.readLine().simplified();
if (line.isEmpty()) {
continue;
}
QString pos = line.section(QLatin1Char(' '), 0, 0);
GenTime position;
// Try to read timecode
bool ok = false;
int separatorsCount = pos.count(QLatin1Char(':'));
switch (separatorsCount) {
case 0:
// assume we are dealing with seconds
position = GenTime(pos.toDouble(&ok));
break;
case 1: {
// assume min:sec
QString sec = pos.section(QLatin1Char(':'), 1);
QString min = pos.section(QLatin1Char(':'), 0, 0);
double seconds = sec.toDouble(&ok);
int minutes = ok ? min.toInt(&ok) : 0;
position = GenTime(seconds + 60 * minutes);
break;
}
case 2:
default: {
// assume hh:min:sec
QString sec = pos.section(QLatin1Char(':'), 2);
QString min = pos.section(QLatin1Char(':'), 1, 1);
QString hours = pos.section(QLatin1Char(':'), 0, 0);
double seconds = sec.toDouble(&ok);
int minutes = ok ? min.toInt(&ok) : 0;
int h = ok ? hours.toInt(&ok) : 0;
position = GenTime(seconds + (60 * minutes) + (3600 * h));
break;
}
}
if (!ok) {
// Could not read timecode
qDebug() << "::: Could not read timecode from line: " << line;
continue;
}
QString comment = line.section(QLatin1Char(' '), 1);
bool res = addMarker(position, comment, type, undo, redo);
if (!res) {
break;
} else if (!lineRead) {
lineRead = true;
}
int type = KdenliveSettings::default_marker_type();
const QStringList lines = fileData.split(QLatin1Char('\n'));
for (auto &line : lines) {
if (line.isEmpty()) {
continue;
}
QString pos = line.section(QLatin1Char(' '), 0, 0);
GenTime position;
// Try to read timecode
bool ok = false;
int separatorsCount = pos.count(QLatin1Char(':'));
switch (separatorsCount) {
case 0:
// assume we are dealing with seconds
position = GenTime(pos.toDouble(&ok));
break;
case 1: {
// assume min:sec
QString sec = pos.section(QLatin1Char(':'), 1);
QString min = pos.section(QLatin1Char(':'), 0, 0);
double seconds = sec.toDouble(&ok);
int minutes = ok ? min.toInt(&ok) : 0;
position = GenTime(seconds + 60 * minutes);
break;
}
case 2:
default: {
// assume hh:min:sec
QString sec = pos.section(QLatin1Char(':'), 2);
QString min = pos.section(QLatin1Char(':'), 1, 1);
QString hours = pos.section(QLatin1Char(':'), 0, 0);
double seconds = sec.toDouble(&ok);
int minutes = ok ? min.toInt(&ok) : 0;
int h = ok ? hours.toInt(&ok) : 0;
position = GenTime(seconds + (60 * minutes) + (3600 * h));
break;
}
}
if (!ok) {
// Could not read timecode
qDebug() << "::: Could not read timecode from line: " << line;
continue;
}
QString comment = line.section(QLatin1Char(' '), 1);
res = addMarker(position, comment, type, undo, redo);
if (!res) {
break;
} else if (!lineRead) {
lineRead = true;
}
inputFile.close();
}
return res && lineRead;
}
......@@ -843,6 +847,7 @@ bool MarkerListModel::editMarkerGui(const GenTime &pos, QWidget *parent, bool cr
if (dialog->exec() == QDialog::Accepted) {
marker = dialog->newMarker();
emit pCore->updateDefaultMarkerCategory();
if (exists && !createOnly) {
return editMarker(pos, marker.time(), marker.comment(), marker.markerType());
}
......@@ -869,6 +874,7 @@ bool MarkerListModel::addMultipleMarkersGui(const GenTime &pos, QWidget *parent,
GenTime interval = dialog->getInterval();
KdenliveSettings::setMultipleguidesinterval(interval.seconds());
marker = dialog->newMarker();
emit pCore->updateDefaultMarkerCategory();
GenTime startTime = marker.time();
QWriteLocker locker(&m_lock);
Fun undo = []() { return true; };
......
......@@ -176,6 +176,7 @@ public slots:
bool importFromJson(const QString &data, bool ignoreConflicts, bool pushUndo = true);
bool importFromJson(const QString &data, bool ignoreConflicts, Fun &undo, Fun &redo);
bool importFromTxt(const QString &fileName, Fun &undo, Fun &redo);
bool importFromFile(const QString &fileData, bool ignoreConflicts);
protected:
/** @brief Adds a snap point at marker position in the registered snap models
......
......@@ -409,4 +409,6 @@ signals:
void updateProjectTimecode();
/** @brief Visible guide categories changed, reload snaps in timeline */
void refreshActiveGuides();
/** @brief The default marker category was changed, update guides list button */
void updateDefaultMarkerCategory();
};
......@@ -11,13 +11,17 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include "core.h"
#include "doc/kdenlivedoc.h"
#include "kdenlive_debug.h"
#include "kdenlivesettings.h"
#include "mainwindow.h"
#include "project/projectmanager.h"
#include <KLocalizedString>
#include <KMessageBox>
#include <QButtonGroup>
#include <QCheckBox>
#include <QDialog>
#include <QFileDialog>
#include <QFontDatabase>
#include <QMenu>
#include <QPainter>
......@@ -54,11 +58,12 @@ GuidesList::GuidesList(QWidget *parent)
connect(guide_add, &QToolButton::clicked, this, &GuidesList::addGuide);
connect(guide_edit, &QToolButton::clicked, this, &GuidesList::editGuides);
connect(filter_line, &QLineEdit::textChanged, this, &GuidesList::filterView);
connect(pCore.get(), &Core::updateDefaultMarkerCategory, this, &GuidesList::refreshDefaultCategory);
// Settings menu
QMenu *settingsMenu = new QMenu(this);
QAction *importGuides = new QAction(QIcon::fromTheme(QStringLiteral("document-import")), i18n("Import..."), this);
connect(importGuides, &QAction::triggered, this, &GuidesList::configureGuides);
connect(importGuides, &QAction::triggered, this, &GuidesList::importGuides);
settingsMenu->addAction(importGuides);
QAction *exportGuides = new QAction(QIcon::fromTheme(QStringLiteral("document-export")), i18n("Export..."), this);
connect(exportGuides, &QAction::triggered, this, &GuidesList::saveGuides);
......@@ -105,6 +110,8 @@ GuidesList::GuidesList(QWidget *parent)
show_categories->setToolTip(i18n("Filter guide categories."));
show_categories->setWhatsThis(
xi18nc("@info:whatsthis", "Filter guide categories. This allows you to show or hide selected guide categories in this dialog and in the timeline."));
default_category->setToolTip(i18n("Default guide category."));
default_category->setWhatsThis(xi18nc("@info:whatsthis", "Default guide category. The category used for newly created markers."));
}
void GuidesList::configureGuides()
......@@ -112,6 +119,40 @@ void GuidesList::configureGuides()
pCore->window()->slotEditProjectSettings(2);
}
void GuidesList::importGuides()
{
if (auto markerModel = m_model.lock()) {
QScopedPointer<QFileDialog> fd(
new QFileDialog(this, i18nc("@title:window", "Load Clip Markers"), pCore->projectManager()->current()->projectDataFolder()));
fd->setMimeTypeFilters({QStringLiteral("application/json"), QStringLiteral("text/plain")});
fd->setFileMode(QFileDialog::ExistingFile);
if (fd->exec() != QDialog::Accepted) {
return;
}
QStringList selection = fd->selectedFiles();
QString url;
if (!selection.isEmpty()) {
url = selection.first();
}
if (url.isEmpty()) {
return;
}
QFile file(url);
if (file.size() > 1048576 &&
KMessageBox::warningContinueCancel(this, i18n("Marker file is larger than 1MB, are you sure you want to import ?")) != KMessageBox::Continue) {
// If marker file is larger than 1MB, ask for confirmation
return;
}
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
KMessageBox::error(this, i18n("Cannot read file %1", QUrl::fromLocalFile(url).fileName()));
return;
}
QString fileContent = QString::fromUtf8(file.readAll());
file.close();
markerModel->importFromFile(fileContent, true);
}
}
void GuidesList::saveGuides()
{
if (auto markerModel = m_model.lock()) {
......@@ -251,6 +292,20 @@ void GuidesList::rebuildCategories()
catGroup = new QButtonGroup(this);
catGroup->setExclusive(false);
QPixmap pixmap(32, 32);
// Cleanup default marker category menu
QMenu *markerDefaultMenu = default_category->menu();
if (markerDefaultMenu) {
markerDefaultMenu->clear();
} else {
markerDefaultMenu = new QMenu(this);
connect(markerDefaultMenu, &QMenu::triggered, this, [this](QAction *ac) {
int val = ac->data().toInt();
KdenliveSettings::setDefault_marker_type(val);
default_category->setIcon(ac->icon());
});
default_category->setMenu(markerDefaultMenu);
}
QMapIterator<int, Core::MarkerCategory> i(pCore->markerTypes);
while (i.hasNext()) {
i.next();
......@@ -259,12 +314,33 @@ void GuidesList::rebuildCategories()
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);
if (i.key() == KdenliveSettings::default_marker_type()) {
default_category->setIcon(colorIcon);
}
catGroup->addButton(cb);
m_categoriesLayout.addWidget(cb);
}
connect(catGroup, &QButtonGroup::buttonToggled, this, &GuidesList::updateFilter);
}
void GuidesList::refreshDefaultCategory()
{
int ix = KdenliveSettings::default_marker_type();
QMenu *menu = default_category->menu();
if (menu) {
QList<QAction *> actions = menu->actions();
for (auto *ac : actions) {
if (ac->data() == ix) {
default_category->setIcon(ac->icon());
break;
}
}
}
}
void GuidesList::updateFilter(QAbstractButton *, bool)
{
QList<int> filters;
......
......@@ -32,6 +32,7 @@ public:
private slots:
void saveGuides();
void editGuides();
void importGuides();
void editGuide(const QModelIndex &ix);
void selectionChanged(const QItemSelection &selected, const QItemSelection &);
void removeGuide();
......@@ -42,6 +43,7 @@ private slots:
void filterView(const QString &text);
void sortView(QAction *ac);
void changeSortOrder(bool descending);
void refreshDefaultCategory();
private:
/** @brief Set the marker model that will be displayed. */
......
......@@ -73,7 +73,8 @@
<string>...</string>
</property>
<property name="icon">
<iconset theme="document-edit"/>
<iconset theme="document-edit">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
......@@ -94,6 +95,19 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="default_category">
<property name="text">
<string>...</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
......
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