Seek in bin thumbnails on mouse hover, disabled by default (setting in Bin menu)

parent f241d191
Pipeline #26360 failed with stage
in 5 minutes and 56 seconds
......@@ -559,7 +559,7 @@ void MyListView::mousePressEvent(QMouseEvent *event)
void MyListView::mouseMoveEvent(QMouseEvent *event)
{
if (event->modifiers() == Qt::ShiftModifier) {
if (KdenliveSettings::hoverPreview()) {
QModelIndex index = indexAt(event->pos());
if (index.isValid()) {
QAbstractItemDelegate *del = itemDelegate(index);
......@@ -614,7 +614,7 @@ void MyTreeView::mouseMoveEvent(QMouseEvent *event)
if (distance >= QApplication::startDragDistance()) {
dragged = performDrag();
}
} else if (event->modifiers() == Qt::ShiftModifier) {
} else if (KdenliveSettings::hoverPreview()) {
QModelIndex index = indexAt(event->pos());
if (index.isValid()) {
QAbstractItemDelegate *del = itemDelegate(index);
......@@ -1009,6 +1009,15 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
disableEffects->setCheckable(true);
disableEffects->setChecked(false);
pCore->window()->actionCollection()->addAction(QStringLiteral("disable_bin_effects"), disableEffects);
QAction *hoverPreview = new QAction(i18n("Show video preview in thumbnails"), this);
hoverPreview->setCheckable(true);
hoverPreview->setChecked(KdenliveSettings::hoverPreview());
connect(hoverPreview, &QAction::triggered, [] (bool checked) {
KdenliveSettings::setHoverPreview(checked);
});
connect(disableEffects, &QAction::triggered, [this](bool disable) { this->setBinEffectsEnabled(!disable); });
disableEffects->setIcon(QIcon::fromTheme(QStringLiteral("favorite")));
listType->setToolBarMode(KSelectAction::MenuMode);
connect(listType, static_cast<void (KSelectAction::*)(QAction *)>(&KSelectAction::triggered), this, &Bin::slotInitView);
......@@ -1039,6 +1048,7 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
settingsMenu->addAction(m_showDesc);
settingsMenu->addAction(m_showRating);
settingsMenu->addAction(disableEffects);
settingsMenu->addAction(hoverPreview);
// Show tags panel
m_tagAction = new QAction(QIcon::fromTheme(QStringLiteral("tag")), i18n("Tags Panel"), this);
......
......@@ -511,7 +511,7 @@ bool ProjectClip::setProducer(std::shared_ptr<Mlt::Producer> producer, bool repl
m_videoProducers.clear();
m_timewarpProducers.clear();
emit refreshPropertiesPanel();
if (m_clipType == ClipType::AV || m_clipType == ClipType::Video || m_clipType == ClipType::Playlist) {
if (KdenliveSettings::hoverPreview() && (m_clipType == ClipType::AV || m_clipType == ClipType::Video || m_clipType == ClipType::Playlist)) {
QTimer::singleShot(1000, this, [this]() {
int loadjobId;
if (!pCore->jobManager()->hasPendingJob(m_binId, AbstractClipJob::CACHEJOB, &loadjobId)) {
......@@ -1534,17 +1534,18 @@ void ProjectClip::updateZones()
void ProjectClip::getThumbFromPercent(int percent)
{
// extract a maximum of 50 frames for bin preview
percent += percent%2;
// extract a maximum of 30 frames for bin preview
int duration = getFramePlaytime();
int steps = qCeil(qMax(pCore->getCurrentFps(), (double)duration / 30));
int framePos = duration * percent / 100;
framePos -= framePos%steps;
if (ThumbnailCache::get()->hasThumbnail(m_binId, framePos)) {
setThumbnail(ThumbnailCache::get()->getThumbnail(m_binId, framePos));
} else {
// Generate percent thumbs
int id;
if (!pCore->jobManager()->hasPendingJob(m_binId, AbstractClipJob::CACHEJOB, &id)) {
pCore->jobManager()->startJob<CacheJob>({m_binId}, -1, QString(), 50);
pCore->jobManager()->startJob<CacheJob>({m_binId}, -1, QString());
}
}
}
......
......@@ -200,16 +200,18 @@ bool ProjectSubClip::hasAudioAndVideo() const
void ProjectSubClip::getThumbFromPercent(int percent)
{
// extract a maximum of 50 frames for bin preview
percent += percent%2;
int framePos = (m_outPoint - m_inPoint) * percent / 100;
// extract a maximum of 30 frames for bin preview
int duration = m_outPoint - m_inPoint;
int steps = qCeil(qMax(pCore->getCurrentFps(), (double)duration / 30));
int framePos = duration * percent / 100;
framePos -= framePos%steps;
if (ThumbnailCache::get()->hasThumbnail(m_parentClipId, m_inPoint + framePos)) {
setThumbnail(ThumbnailCache::get()->getThumbnail(m_parentClipId, m_inPoint + framePos));
} else {
// Generate percent thumbs
int id;
if (!pCore->jobManager()->hasPendingJob(m_parentClipId, AbstractClipJob::CACHEJOB, &id)) {
pCore->jobManager()->startJob<CacheJob>({m_parentClipId}, -1, QString(), 25, m_inPoint, m_outPoint);
pCore->jobManager()->startJob<CacheJob>({m_parentClipId}, -1, QString(), 30, m_inPoint, m_outPoint);
}
}
}
......
......@@ -28,13 +28,15 @@
#include "klocalizedstring.h"
#include "macros.hpp"
#include "utils/thumbnailcache.hpp"
#include <QImage>
#include <QScopedPointer>
#include <QThread>
#include <mlt++/MltProducer.h>
#include <set>
#include <QImage>
#include <QScopedPointer>
#include <QThread>
#include <QtConcurrent>
CacheJob::CacheJob(const QString &binId, int thumbsCount, int inPoint, int outPoint)
: AbstractClipJob(CACHEJOB, binId)
, m_fullWidth(qFuzzyCompare(pCore->getCurrentSar(), 1.0) ? 0 : pCore->thumbProfile()->height() * pCore->getCurrentDar() + 0.5)
......@@ -86,13 +88,10 @@ bool CacheJob::startJob()
return false;
}
int duration = m_outPoint > 0 ? m_outPoint - m_inPoint : (int)m_binClip->frameDuration();
if (m_thumbsCount * 5 > duration) {
m_thumbsCount = duration / 10;
}
std::set<int> frames;
double steps = qMax(pCore->getCurrentFps(), (double)duration / m_thumbsCount);
int steps = qCeil(qMax(pCore->getCurrentFps(), (double)duration / m_thumbsCount));
int pos = m_inPoint;
for (int i = 1; i <= m_thumbsCount && pos <= duration; ++i) {
for (int i = 1; i <= m_thumbsCount && pos <= m_inPoint + duration; ++i) {
frames.insert(pos);
pos = m_inPoint + (steps * i);
}
......@@ -115,7 +114,7 @@ bool CacheJob::startJob()
frame->set("rescale.interp", "nearest");
if (frame != nullptr && frame->is_valid()) {
QImage result = KThumb::getFrame(frame.data(), 0, 0, m_fullWidth);
ThumbnailCache::get()->storeThumbnail(m_clipId, i, result, true);
QtConcurrent::run(ThumbnailCache::get().get(), &ThumbnailCache::storeThumbnail, m_clipId, i, result, true);
}
m_semaphore.release(1);
}
......
......@@ -43,7 +43,7 @@ public:
@param frameNumber is the frame to extract. Leave to -1 for default
@param persistent: if true, we will use the persistent cache (for query and saving)
*/
CacheJob(const QString &binId, int thumbsCount = 10, int inPoint = 0, int outPoint = 0);
CacheJob(const QString &binId, int thumbsCount = 30, int inPoint = 0, int outPoint = 0);
const QString getDescription() const override;
......
......@@ -25,6 +25,10 @@
<label>User added clip file extensions.</label>
<default></default>
</entry>
<entry name="hoverPreview" type="Bool">
<label>Generate and show video preview when moving mouse over clip thumbnail.</label>
<default>false</default>
</entry>
</group>
<group name="misc">
......
......@@ -280,7 +280,7 @@ QString ThumbnailCache::getKey(const QString &binId, int pos, bool *ok)
}
auto binClip = pCore->projectItemModel()->getClipByBinID(binId);
*ok = binClip != nullptr;
return *ok ? binClip->hash() + QLatin1Char('#') + QString::number(pos) + QStringLiteral(".png") : QString();
return *ok ? binClip->hash() + QLatin1Char('#') + QString::number(pos) + QStringLiteral(".jpg") : QString();
}
// static
......
Markdown is supported
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