replaced mediathrobber with mediaiconservice

This commit is contained in:
itsmattkc
2019-02-16 22:22:43 -08:00
parent 5207a0511f
commit f14b0cef7d
17 changed files with 213 additions and 142 deletions
+1 -1
View File
@@ -67,7 +67,7 @@ ReplaceClipMediaDialog::ReplaceClipMediaDialog(QWidget *parent, Media* old_media
layout->addLayout(buttons);
tree->setModel(&project_model);
tree->setModel(&olive::project_model);
}
void ReplaceClipMediaDialog::replace() {
+2 -2
View File
@@ -288,7 +288,7 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
item->set_footage(f);
if (folder == 0) {
project_model.appendChild(nullptr, item);
olive::project_model.appendChild(nullptr, item);
} else {
find_loaded_folder_by_id(folder)->appendChild(item);
}
@@ -645,7 +645,7 @@ void LoadThread::run() {
Media* folder = loaded_folders.at(i);
int parent = folder->temp_id2;
if (folder->temp_id2 == 0) {
project_model.appendChild(nullptr, folder);
olive::project_model.appendChild(nullptr, folder);
} else {
find_loaded_folder_by_id(parent)->appendChild(folder);
}
+6 -5
View File
@@ -20,6 +20,7 @@
#include "previewgenerator.h"
#include "ui/mediaiconservice.h"
#include "project/media.h"
#include "project/footage.h"
#include "panels/viewer.h"
@@ -189,12 +190,12 @@ void PreviewGenerator::finalize_media() {
footage->ready = true;
if (!cancelled) {
if (footage->video_tracks.size() == 0) {
emit set_icon(ICON_TYPE_AUDIO, replace);
if (footage->video_tracks.size() == 0) {
olive::media_icon_service->SetMediaIcon(media, ICON_TYPE_AUDIO);
} else if (contains_still_image) {
emit set_icon(ICON_TYPE_IMAGE, replace);
olive::media_icon_service->SetMediaIcon(media, ICON_TYPE_IMAGE);
} else {
emit set_icon(ICON_TYPE_VIDEO, replace);
olive::media_icon_service->SetMediaIcon(media, ICON_TYPE_VIDEO);
}
/*if (!contains_still_image || media->audio_tracks.size() > 0) {
@@ -575,7 +576,7 @@ void PreviewGenerator::run() {
if (!cancelled) {
if (error) {
media->update_tooltip(errorStr);
emit set_icon(ICON_TYPE_ERROR, replace);
olive::media_icon_service->SetMediaIcon(media, ICON_TYPE_ERROR);
footage->invalid = true;
footage->ready_lock.unlock();
} else {
+1 -10
View File
@@ -25,13 +25,6 @@
#include <QSemaphore>
#include <QDir>
enum IconType {
ICON_TYPE_VIDEO,
ICON_TYPE_AUDIO,
ICON_TYPE_IMAGE,
ICON_TYPE_ERROR
};
#include "project/footage.h"
#include "project/media.h"
@@ -48,9 +41,7 @@ class PreviewGenerator : public QThread
public:
PreviewGenerator(Media*, FootagePtr, bool);
void run();
void cancel();
signals:
void set_icon(int, bool);
void cancel();
private:
void parse_media();
bool retrieve_preview(const QString &hash);
+3
View File
@@ -24,6 +24,7 @@
#include "debug.h"
#include "oliveglobal.h"
#include "ui/mediaiconservice.h"
#include "io/config.h"
@@ -109,6 +110,8 @@ int main(int argc, char *argv[]) {
QApplication a(argc, argv);
a.setWindowIcon(QIcon(":/icons/olive64.png"));
olive::media_icon_service = std::unique_ptr<MediaIconService>(new MediaIconService());
QCoreApplication::setOrganizationName("olivevideoeditor.org");
QCoreApplication::setOrganizationDomain("olivevideoeditor.org");
QCoreApplication::setApplicationName("Olive");
+4 -2
View File
@@ -149,7 +149,8 @@ SOURCES += \
ui/menuhelper.cpp \
oliveglobal.cpp \
ui/focusfilter.cpp \
project/comboaction.cpp
project/comboaction.cpp \
ui/mediaiconservice.cpp
HEADERS += \
mainwindow.h \
@@ -256,7 +257,8 @@ HEADERS += \
oliveglobal.h \
project/projectelements.h \
ui/focusfilter.h \
project/comboaction.h
project/comboaction.h \
ui/mediaiconservice.h
FORMS +=
+26 -86
View File
@@ -38,6 +38,7 @@
#include "ui/sourcetable.h"
#include "ui/sourceiconview.h"
#include "ui/menuhelper.h"
#include "ui/mediaiconservice.h"
#include "project/sourcescommon.h"
#include "project/projectfilter.h"
#include "debug.h"
@@ -63,9 +64,7 @@ extern "C" {
#include <libavcodec/avcodec.h>
}
#define MAXIMUM_RECENT_PROJECTS 10
ProjectModel project_model;
#define MAXIMUM_RECENT_PROJECTS 10 // FIXME: should be configurable
QString autorecovery_filename;
QStringList recent_projects;
@@ -86,7 +85,7 @@ Project::Project(QWidget *parent) :
sources_common = new SourcesCommon(this);
sorter = new ProjectFilter(this);
sorter->setSourceModel(&project_model);
sorter->setSourceModel(&olive::project_model);
// optional toolbar
toolbar_widget = new QWidget();
@@ -223,7 +222,7 @@ Project::Project(QWidget *parent) :
verticalLayout->addWidget(icon_view_container);
connect(directory_up, SIGNAL(clicked(bool)), this, SLOT(go_up_dir()));
connect(icon_view, SIGNAL(changed_root()), this, SLOT(set_up_dir_enabled()));
connect(icon_view, SIGNAL(changed_root()), this, SLOT(set_up_dir_enabled()));
setWindowTitle(tr("Project"));
@@ -247,8 +246,8 @@ QString Project::get_next_sequence_name(QString start) {
name += "0";
}
name += QString::number(n);
for (int i=0;i<project_model.childCount();i++) {
if (QString::compare(project_model.child(i)->get_name(), name, Qt::CaseInsensitive) == 0) {
for (int i=0;i<olive::project_model.childCount();i++) {
if (QString::compare(olive::project_model.child(i)->get_name(), name, Qt::CaseInsensitive) == 0) {
found = true;
n++;
break;
@@ -426,7 +425,7 @@ void Project::new_folder() {
Media* m = create_folder_internal(nullptr);
olive::UndoStack.push(new AddMediaCommand(m, get_selected_folder()));
QModelIndex index = project_model.create_index(m->row(), 0, m);
QModelIndex index = olive::project_model.create_index(m->row(), 0, m);
switch (olive::CurrentConfig.project_view_type) {
case PROJECT_VIEW_TREE:
tree_view->edit(sorter->mapFromSource(index));
@@ -445,7 +444,7 @@ void Project::new_sequence() {
Media* Project::create_sequence_internal(ComboAction *ca, SequencePtr s, bool open, Media* parent) {
if (parent == nullptr) {
parent = project_model.get_root();
parent = olive::project_model.get_root();
}
Media* item(new Media(parent));
@@ -455,8 +454,8 @@ Media* Project::create_sequence_internal(ComboAction *ca, SequencePtr s, bool op
ca->append(new NewSequenceCommand(item, parent));
if (open) ca->append(new ChangeSequenceAction(s));
} else {
if (parent == project_model.get_root()) {
project_model.appendChild(parent, item);
if (parent == olive::project_model.get_root()) {
olive::project_model.appendChild(parent, item);
} else {
parent->appendChild(item);
}
@@ -534,8 +533,8 @@ void Project::delete_selected_media() {
QVector<Media*> parents;
QList<Media*> sequence_items;
QList<Media*> all_top_level_items;
for (int i=0;i<project_model.childCount();i++) {
all_top_level_items.append(project_model.child(i));
for (int i=0;i<olive::project_model.childCount();i++) {
all_top_level_items.append(olive::project_model.child(i));
}
get_all_media_from_table(all_top_level_items, sequence_items, MEDIA_TYPE_SEQUENCE); // find all sequences in project
if (sequence_items.size() > 0) {
@@ -665,15 +664,11 @@ void Project::delete_selected_media() {
}
void Project::start_preview_generator(Media* item, bool replacing) {
// set up throbber animation
MediaThrobber* throbber = new MediaThrobber(item);
throbber->moveToThread(QApplication::instance()->thread());
item->throbber = throbber;
QMetaObject::invokeMethod(throbber, "start", Qt::QueuedConnection);
// set up throbber animation
olive::media_icon_service->SetMediaIcon(item, ICON_TYPE_LOADING);
PreviewGenerator* pg = new PreviewGenerator(item, item->to_footage(), replacing);
item->to_footage()->preview_gen = pg;
connect(pg, SIGNAL(set_icon(int, bool)), throbber, SLOT(stop(int, bool)));
item->to_footage()->preview_gen = pg;
pg->start(QThread::LowPriority);
}
@@ -710,7 +705,7 @@ void Project::process_file_list(QStringList& files, bool recursive, Media* repla
if (create_undo_action) {
ca->append(new AddMediaCommand(folder, parent));
} else {
project_model.appendChild(parent, folder);
olive::project_model.appendChild(parent, folder);
}
imported = true;
@@ -853,9 +848,9 @@ Media* Project::get_selected_folder() {
}
bool Project::reveal_media(Media *media, QModelIndex parent) {
for (int i=0;i<project_model.rowCount(parent);i++) {
const QModelIndex& item = project_model.index(i, 0, parent);
Media* m = project_model.getItem(item);
for (int i=0;i<olive::project_model.rowCount(parent);i++) {
const QModelIndex& item = olive::project_model.index(i, 0, parent);
Media* m = olive::project_model.getItem(item);
if (m->get_type() == MEDIA_TYPE_FOLDER) {
@@ -963,7 +958,7 @@ void Project::clear() {
}
// delete everything else
project_model.clear();
olive::project_model.clear();
// update tree view (sometimes this doesn't seem to update reliably)
tree_view->update();
@@ -992,9 +987,9 @@ void save_marker(QXmlStreamWriter& stream, const Marker& m) {
}
void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex& parent) {
for (int i=0;i<project_model.rowCount(parent);i++) {
const QModelIndex& item = project_model.index(i, 0, parent);
Media* m = project_model.getItem(item);
for (int i=0;i<olive::project_model.rowCount(parent);i++) {
const QModelIndex& item = olive::project_model.index(i, 0, parent);
Media* m = olive::project_model.getItem(item);
if (type == m->get_type()) {
if (m->get_type() == MEDIA_TYPE_FOLDER) {
@@ -1009,7 +1004,7 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only,
if (!item.parent().isValid()) {
stream.writeAttribute("parent", "0");
} else {
stream.writeAttribute("parent", QString::number(project_model.getItem(item.parent())->temp_id));
stream.writeAttribute("parent", QString::number(olive::project_model.getItem(item.parent())->temp_id));
}
stream.writeEndElement();
}
@@ -1308,8 +1303,8 @@ void Project::add_recent_project(QString url) {
}
void Project::list_all_sequences_worker(QVector<Media*>* list, Media* parent) {
for (int i=0;i<project_model.childCount(parent);i++) {
Media* item = project_model.child(i, parent);
for (int i=0;i<olive::project_model.childCount(parent);i++) {
Media* item = olive::project_model.child(i, parent);
switch (item->get_type()) {
case MEDIA_TYPE_SEQUENCE:
list->append(item);
@@ -1333,58 +1328,3 @@ QModelIndexList Project::get_current_selected() {
}
return icon_view->selectionModel()->selectedIndexes();
}
#define THROBBER_LIMIT 20
#define THROBBER_SIZE 50
MediaThrobber::MediaThrobber(Media *i) : pixmap(":/icons/throbber.png"), animation(0), item(i), animator(nullptr) {}
void MediaThrobber::start() {
// set up throbber
animation_update();
animator = new QTimer(this);
animator->setInterval(20);
connect(animator, SIGNAL(timeout()), this, SLOT(animation_update()));
animator->start();
}
void MediaThrobber::animation_update() {
if (animation == THROBBER_LIMIT) {
animation = 0;
}
project_model.set_icon(item, QIcon(pixmap.copy(THROBBER_SIZE*animation, 0, THROBBER_SIZE, THROBBER_SIZE)));
animation++;
}
void MediaThrobber::stop(int icon_type, bool replace) {
if (animator != nullptr) {
animator->stop();
delete animator;
}
switch (icon_type) {
case ICON_TYPE_VIDEO: project_model.set_icon(item, QIcon(":/icons/videosource.png")); break;
case ICON_TYPE_AUDIO: project_model.set_icon(item, QIcon(":/icons/audiosource.png")); break;
case ICON_TYPE_IMAGE: project_model.set_icon(item, QIcon(":/icons/imagesource.png")); break;
case ICON_TYPE_ERROR: project_model.set_icon(item, QIcon(":/icons/error.png")); break;
}
// refresh all clips
QVector<Media*> sequences = panel_project->list_all_project_sequences();
for (int i=0;i<sequences.size();i++) {
SequencePtr s = sequences.at(i)->to_sequence();
for (int j=0;j<s->clips.size();j++) {
const ClipPtr& c = s->clips.at(j);
if (c != nullptr) {
c->refresh();
}
}
}
// redraw clips
update_ui(replace);
panel_project->tree_view->viewport()->update();
item->throbber = nullptr;
deleteLater();
}
-17
View File
@@ -44,7 +44,6 @@
extern QString autorecovery_filename;
extern QStringList recent_projects;
extern ProjectModel project_model;
SequencePtr create_sequence_from_media(QVector<Media *> &media_list);
@@ -122,20 +121,4 @@ private slots:
void make_new_menu();
};
class MediaThrobber : public QObject {
Q_OBJECT
public:
MediaThrobber(Media*);
public slots:
void start();
void stop(int, bool replace);
private slots:
void animation_update();
private:
QPixmap pixmap;
int animation;
Media* item;
QTimer* animator;
};
#endif // PROJECT_H
-1
View File
@@ -40,7 +40,6 @@ enum VideoInterlacingMode {
class Sequence;
class Clip;
class PreviewGenerator;
class MediaThrobber;
struct FootageStream {
int file_index;
+1 -3
View File
@@ -61,8 +61,7 @@ QString get_channel_layout_name(int channels, uint64_t layout) {
}
Media::Media(Media* iparent) :
parent(iparent),
throbber(nullptr),
parent(iparent),
root(false),
type(-1)
{}
@@ -71,7 +70,6 @@ Media::~Media() {
for (int i=0;i<children.size();i++) {
delete children.at(i);
}
delete throbber;
}
FootagePtr Media::to_footage() {
-3
View File
@@ -39,8 +39,6 @@ using SequencePtr = std::shared_ptr<Sequence>;
using VoidPtr = std::shared_ptr<void>;
class MediaThrobber;
class Media
{
public:
@@ -58,7 +56,6 @@ public:
int get_type();
const QString& get_name();
void set_name(const QString& n);
MediaThrobber* throbber;
double get_frame_rate(int stream = -1);
int get_sampling_rate(int stream = -1);
+2
View File
@@ -26,6 +26,8 @@
#include "project/media.h"
#include "debug.h"
ProjectModel olive::project_model;
ProjectModel::ProjectModel(QObject *parent) : QAbstractItemModel(parent), root_item(nullptr) {
make_root();
}
+4
View File
@@ -60,4 +60,8 @@ private:
Media* root_item;
};
namespace olive {
extern ProjectModel project_model;
}
#endif // PROJECTMODEL_H
+10 -10
View File
@@ -357,7 +357,7 @@ NewSequenceCommand::NewSequenceCommand(Media *s, Media* iparent) {
parent = iparent;
done = false;
if (parent == nullptr) parent = project_model.get_root();
if (parent == nullptr) parent = olive::project_model.get_root();
}
NewSequenceCommand::~NewSequenceCommand() {
@@ -365,13 +365,13 @@ NewSequenceCommand::~NewSequenceCommand() {
}
void NewSequenceCommand::doUndo() {
project_model.removeChild(parent, seq);
olive::project_model.removeChild(parent, seq);
done = false;
}
void NewSequenceCommand::doRedo() {
project_model.appendChild(parent, seq);
olive::project_model.appendChild(parent, seq);
done = true;
}
@@ -389,13 +389,13 @@ AddMediaCommand::~AddMediaCommand() {
}
void AddMediaCommand::doUndo() {
project_model.removeChild(parent, item);
olive::project_model.removeChild(parent, item);
done = false;
}
void AddMediaCommand::doRedo() {
project_model.appendChild(parent, item);
olive::project_model.appendChild(parent, item);
done = true;
}
@@ -412,14 +412,14 @@ DeleteMediaCommand::~DeleteMediaCommand() {
}
void DeleteMediaCommand::doUndo() {
project_model.appendChild(parent, item);
olive::project_model.appendChild(parent, item);
done = false;
}
void DeleteMediaCommand::doRedo() {
project_model.removeChild(parent, item);
olive::project_model.removeChild(parent, item);
done = true;
}
@@ -641,18 +641,18 @@ MediaMove::MediaMove() {}
void MediaMove::doUndo() {
for (int i=0;i<items.size();i++) {
project_model.moveChild(items.at(i), froms.at(i));
olive::project_model.moveChild(items.at(i), froms.at(i));
}
}
void MediaMove::doRedo() {
if (to == nullptr) to = project_model.get_root();
if (to == nullptr) to = olive::project_model.get_root();
froms.resize(items.size());
for (int i=0;i<items.size();i++) {
Media* parent = items.at(i)->parentItem();
froms[i] = parent;
project_model.moveChild(items.at(i), to);
olive::project_model.moveChild(items.at(i), to);
}
}
+93
View File
@@ -0,0 +1,93 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
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 3 of the License, or
(at your option) any later version.
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 "mediaiconservice.h"
const int kThrobberLimit = 20;
const int kThrobberSize = 50;
#include "project/projectmodel.h"
std::unique_ptr<MediaIconService> olive::media_icon_service;
MediaIconService::MediaIconService() {
// set up animation timer
throbber_animator_.setInterval(20);
connect(&throbber_animator_, SIGNAL(timeout()), this, SLOT(AnimationUpdate()));
// set up pixmap
throbber_pixmap_ = QPixmap(":/icons/throbber.png");
}
void MediaIconService::SetMediaIcon(Media *media, int icon_type) {
// if this icon is already part of the throbber animation loop, remove it
if (throbber_items_.contains(media)) {
throbber_items_.removeAll(media);
// if we aren't animating anything, no need to run the timer for now
if (throbber_items_.empty()) {
// ensure timer function is called in its own thread
QMetaObject::invokeMethod(&throbber_animator_, "stop", Qt::QueuedConnection);
}
}
switch (icon_type) {
case ICON_TYPE_VIDEO:
olive::project_model.set_icon(media, QIcon(":/icons/videosource.png"));
break;
case ICON_TYPE_AUDIO:
olive::project_model.set_icon(media, QIcon(":/icons/audiosource.png"));
break;
case ICON_TYPE_IMAGE:
olive::project_model.set_icon(media, QIcon(":/icons/imagesource.png"));
break;
case ICON_TYPE_LOADING:
throbber_items_.append(media);
// if the animation timer isn't running, start it
if (!throbber_animator_.isActive()) {
// set starting frame to 0
throbber_animation_frame_ = 0;
// ensure timer function is called in its own thread
QMetaObject::invokeMethod(&throbber_animator_, "start", Qt::QueuedConnection);
}
break;
case ICON_TYPE_ERROR:
olive::project_model.set_icon(media, QIcon(":/icons/error.png"));
break;
}
emit IconChanged();
}
void MediaIconService::AnimationUpdate() {
if (throbber_animation_frame_ == kThrobberLimit) {
throbber_animation_frame_ = 0;
}
QIcon throbber_ico = QIcon(throbber_pixmap_.copy(kThrobberSize*throbber_animation_frame_, 0, kThrobberSize, kThrobberSize));
for (int i=0;i<throbber_items_.size();i++) {
olive::project_model.set_icon(throbber_items_.at(i), throbber_ico);
}
throbber_animation_frame_++;
}
+58
View File
@@ -0,0 +1,58 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
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 3 of the License, or
(at your option) any later version.
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 MEDIAICONSERVICE_H
#define MEDIAICONSERVICE_H
#include <QObject>
#include <QTimer>
#include "project/media.h"
enum IconType {
ICON_TYPE_VIDEO,
ICON_TYPE_AUDIO,
ICON_TYPE_IMAGE,
ICON_TYPE_LOADING,
ICON_TYPE_ERROR
};
class MediaIconService : public QObject {
Q_OBJECT
public:
MediaIconService();
public slots:
void SetMediaIcon(Media* media, int icon_type);
signals:
void IconChanged();
private slots:
void AnimationUpdate();
private:
int throbber_animation_frame_;
QVector<Media*> throbber_items_;
QTimer throbber_animator_;
QPixmap throbber_pixmap_;
};
namespace olive {
extern std::unique_ptr<MediaIconService> media_icon_service;
}
#endif // MEDIAICONSERVICE_H
+2 -2
View File
@@ -244,8 +244,8 @@ void TimelineWidget::rename_clip() {
void TimelineWidget::open_sequence_properties() {
QList<Media*> sequence_items;
QList<Media*> all_top_level_items;
for (int i=0;i<project_model.childCount();i++) {
all_top_level_items.append(project_model.child(i));
for (int i=0;i<olive::project_model.childCount();i++) {
all_top_level_items.append(olive::project_model.child(i));
}
panel_project->get_all_media_from_table(all_top_level_items, sequence_items, MEDIA_TYPE_SEQUENCE); // find all sequences in project
for (int i=0;i<sequence_items.size();i++) {