ACTUALLY fixed urgent sequence deletion bug
This commit is contained in:
+4
-1
@@ -10,7 +10,7 @@ extern "C" {
|
||||
|
||||
#include "project/clip.h"
|
||||
|
||||
Media::Media() : ready(false), preview_gen(NULL) {
|
||||
Media::Media() : ready(false), preview_gen(NULL), throbber(NULL) {
|
||||
ready_lock.lock();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ void Media::reset() {
|
||||
preview_gen->cancel();
|
||||
preview_gen->wait();
|
||||
}
|
||||
if (throbber != NULL) {
|
||||
delete throbber;
|
||||
}
|
||||
for (int i=0;i<video_tracks.size();i++) {
|
||||
delete video_tracks.at(i);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
struct Sequence;
|
||||
struct Clip;
|
||||
class PreviewGenerator;
|
||||
class MediaThrobber;
|
||||
|
||||
struct MediaStream {
|
||||
int file_index;
|
||||
@@ -53,6 +54,7 @@ struct Media {
|
||||
bool ready;
|
||||
|
||||
PreviewGenerator* preview_gen;
|
||||
MediaThrobber* throbber;
|
||||
QMutex ready_lock;
|
||||
|
||||
bool using_inout;
|
||||
|
||||
+14
-9
@@ -195,21 +195,26 @@ void PreviewGenerator::generate_waveform() {
|
||||
codec_ctx[i] = NULL;
|
||||
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
AVCodec* codec = avcodec_find_decoder(fmt_ctx->streams[i]->codecpar->codec_id);
|
||||
codec_ctx[i] = avcodec_alloc_context3(codec);
|
||||
avcodec_parameters_to_context(codec_ctx[i], fmt_ctx->streams[i]->codecpar);
|
||||
avcodec_open2(codec_ctx[i], codec, NULL);
|
||||
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) {
|
||||
codec_ctx[i]->channel_layout = av_get_default_channel_layout(fmt_ctx->streams[i]->codecpar->channels);
|
||||
}
|
||||
if (codec != NULL) {
|
||||
codec_ctx[i] = avcodec_alloc_context3(codec);
|
||||
avcodec_parameters_to_context(codec_ctx[i], fmt_ctx->streams[i]->codecpar);
|
||||
avcodec_open2(codec_ctx[i], codec, NULL);
|
||||
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) {
|
||||
codec_ctx[i]->channel_layout = av_get_default_channel_layout(fmt_ctx->streams[i]->codecpar->channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AVPacket* packet = av_packet_alloc();
|
||||
bool done = true;
|
||||
|
||||
bool end_of_file = false;
|
||||
|
||||
// get the ball rolling
|
||||
av_read_frame(fmt_ctx, packet);
|
||||
// get the ball rolling
|
||||
do {
|
||||
av_read_frame(fmt_ctx, packet);
|
||||
} while (codec_ctx[packet->stream_index] == NULL);
|
||||
avcodec_send_packet(codec_ctx[packet->stream_index], packet);
|
||||
|
||||
while (!end_of_file) {
|
||||
|
||||
+13
-8
@@ -198,7 +198,8 @@ void Project::new_sequence(ComboAction *ca, Sequence *s, bool open, QTreeWidgetI
|
||||
|
||||
void Project::start_preview_generator(QTreeWidgetItem* item, Media* media, bool replacing) {
|
||||
// set up throbber animation
|
||||
MediaThrobber* throbber = new MediaThrobber(item);
|
||||
MediaThrobber* throbber = new MediaThrobber(item);
|
||||
item->setData(0, Qt::UserRole + 5, reinterpret_cast<quintptr>(throbber));
|
||||
|
||||
PreviewGenerator* pg = new PreviewGenerator(item, media, replacing);
|
||||
media->preview_gen = pg;
|
||||
@@ -212,6 +213,7 @@ QString Project::get_file_name_from_path(const QString& path) {
|
||||
|
||||
QTreeWidgetItem* Project::new_item() {
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setData(0, Qt::UserRole + 5, NULL);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
return item;
|
||||
}
|
||||
@@ -425,7 +427,6 @@ void Project::process_file_list(bool recursive, QStringList& files, QTreeWidgetI
|
||||
// check file extension (assume it's not a
|
||||
|
||||
int lastcharindex = file.lastIndexOf(".");
|
||||
dout << "INFO:" << file << lastcharindex;
|
||||
bool found = true;
|
||||
if (lastcharindex != -1 && lastcharindex > file.lastIndexOf('/')) {
|
||||
// image_sequence_formats
|
||||
@@ -441,6 +442,8 @@ void Project::process_file_list(bool recursive, QStringList& files, QTreeWidgetI
|
||||
lastcharindex = file.length();
|
||||
}
|
||||
|
||||
if (lastcharindex == 0) lastcharindex++;
|
||||
|
||||
if (found && file[lastcharindex-1].isDigit()) {
|
||||
bool is_img_sequence = false;
|
||||
|
||||
@@ -696,6 +699,7 @@ void Project::clear() {
|
||||
while (ui->treeWidget->topLevelItemCount() > 0) {
|
||||
QTreeWidgetItem* item = ui->treeWidget->topLevelItem(0);
|
||||
if (get_type_from_tree(item) != MEDIA_TYPE_SEQUENCE) delete_media(item); // already deleted
|
||||
if (item->data(0, Qt::UserRole + 5) != NULL) delete reinterpret_cast<MediaThrobber*>(item->data(0, Qt::UserRole + 5).value<quintptr>());
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
@@ -1440,7 +1444,7 @@ QVector<Sequence*> Project::list_all_project_sequences() {
|
||||
#define THROBBER_LIMIT 20
|
||||
#define THROBBER_SIZE 50
|
||||
|
||||
MediaThrobber::MediaThrobber(QTreeWidgetItem* i) : pixmap(":/icons/throbber.png"), animation(0), item(i) {
|
||||
MediaThrobber::MediaThrobber(QTreeWidgetItem *i) : pixmap(":/icons/throbber.png"), animation(0), item(i) {
|
||||
// set up throbber
|
||||
animation_update();
|
||||
animator.setInterval(20);
|
||||
@@ -1452,17 +1456,17 @@ void MediaThrobber::animation_update() {
|
||||
if (animation == THROBBER_LIMIT) {
|
||||
animation = 0;
|
||||
}
|
||||
item->setIcon(0, QIcon(pixmap.copy(THROBBER_SIZE*animation, 0, THROBBER_SIZE, THROBBER_SIZE)));
|
||||
animation++;
|
||||
item->setIcon(0, QIcon(pixmap.copy(THROBBER_SIZE*animation, 0, THROBBER_SIZE, THROBBER_SIZE)));
|
||||
animation++;
|
||||
}
|
||||
|
||||
void MediaThrobber::stop(int icon_type, bool replace) {
|
||||
animator.stop();
|
||||
|
||||
switch (icon_type) {
|
||||
case ICON_TYPE_VIDEO: item->setIcon(0, QIcon(":/icons/videosource.png")); break;
|
||||
case ICON_TYPE_AUDIO: item->setIcon(0, QIcon(":/icons/audiosource.png")); break;
|
||||
case ICON_TYPE_ERROR: item->setIcon(0, QIcon::fromTheme("dialog-error")); break;
|
||||
case ICON_TYPE_VIDEO: item->setIcon(0, QIcon(":/icons/videosource.png")); break;
|
||||
case ICON_TYPE_AUDIO: item->setIcon(0, QIcon(":/icons/audiosource.png")); break;
|
||||
case ICON_TYPE_ERROR: item->setIcon(0, QIcon::fromTheme("dialog-error")); break;
|
||||
}
|
||||
|
||||
// refresh all clips
|
||||
@@ -1481,6 +1485,7 @@ void MediaThrobber::stop(int icon_type, bool replace) {
|
||||
update_ui(replace);
|
||||
|
||||
panel_project->source_table->viewport()->update();
|
||||
item->setData(0, Qt::UserRole + 5, NULL);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -108,7 +108,7 @@ private slots:
|
||||
class MediaThrobber : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MediaThrobber(QTreeWidgetItem*);
|
||||
MediaThrobber(QTreeWidgetItem*);
|
||||
public slots:
|
||||
void stop(int, bool replace);
|
||||
private slots:
|
||||
@@ -116,7 +116,7 @@ private slots:
|
||||
private:
|
||||
QPixmap pixmap;
|
||||
int animation;
|
||||
QTreeWidgetItem* item;
|
||||
QTreeWidgetItem* item;
|
||||
QTimer animator;
|
||||
};
|
||||
|
||||
|
||||
@@ -59,9 +59,6 @@
|
||||
<property name="itemsExpandable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
||||
+33
-3
@@ -21,6 +21,7 @@
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "project/marker.h"
|
||||
#include "mainwindow.h"
|
||||
#include "debug.h"
|
||||
|
||||
QUndoStack undo_stack;
|
||||
|
||||
@@ -350,13 +351,24 @@ AddMediaCommand::AddMediaCommand(QTreeWidgetItem* iitem, QTreeWidgetItem* iparen
|
||||
AddMediaCommand::~AddMediaCommand() {
|
||||
if (!done) {
|
||||
panel_project->delete_media(item);
|
||||
if (item->data(0, Qt::UserRole + 5) != NULL) delete reinterpret_cast<MediaThrobber*>(item->data(0, Qt::UserRole + 5).value<quintptr>());
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void AddMediaCommand::undo() {
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item));
|
||||
bool found = false;
|
||||
for (int i=0;i<panel_project->source_table->topLevelItemCount();i++) {
|
||||
if (panel_project->source_table->topLevelItem(i) == item) {
|
||||
dout << "item at index is:" << panel_project->source_table->topLevelItem(i)->text(0);
|
||||
QTreeWidgetItem* deleted_item = panel_project->source_table->takeTopLevelItem(i);
|
||||
dout << "wanted to take" << item->text(0) << "took" << deleted_item->text(0);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dout << "took:" << found;
|
||||
} else {
|
||||
parent->removeChild(item);
|
||||
}
|
||||
@@ -369,8 +381,25 @@ void AddMediaCommand::redo() {
|
||||
panel_project->source_table->addTopLevelItem(item);
|
||||
} else {
|
||||
parent->addChild(item);
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
|
||||
/* Here we force the source_table to sort itself.
|
||||
*
|
||||
* For some reason, sometimes when you add items to the QTreeWidget,
|
||||
* (usually upon first import) they appear at the bottom, regardless
|
||||
* of where they should be placed alphabetically. Then when this
|
||||
* function is "undone", and it tries to remove this item from the
|
||||
* QTreeWidget, it immediately sorts and then removes THE WRONG ONE.
|
||||
* If this happens to be a sequence, the sequence data doesn't save
|
||||
* and is then lost forever (outside of autorecoveries).
|
||||
*
|
||||
* The following 2 lines seem to force the source_table to re-sort
|
||||
* correctly and therefore works around this problem. But holy shit.
|
||||
*/
|
||||
panel_project->source_table->setSortingEnabled(false);
|
||||
panel_project->source_table->setSortingEnabled(true);
|
||||
|
||||
done = true;
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
@@ -382,6 +411,7 @@ DeleteMediaCommand::DeleteMediaCommand(QTreeWidgetItem* i) :
|
||||
DeleteMediaCommand::~DeleteMediaCommand() {
|
||||
if (done) {
|
||||
panel_project->delete_media(item);
|
||||
if (item->data(0, Qt::UserRole + 5) != NULL) delete reinterpret_cast<MediaThrobber*>(item->data(0, Qt::UserRole + 5).value<quintptr>());
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
|
||||
editing_item = NULL;
|
||||
setSortingEnabled(true);
|
||||
sortByColumn(0, Qt::AscendingOrder);
|
||||
rename_timer.setInterval(1000);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
@@ -491,7 +491,7 @@ void TimelineWidget::wheelEvent(QWheelEvent *event) {
|
||||
}
|
||||
|
||||
void TimelineWidget::dragLeaveEvent(QDragLeaveEvent*) {
|
||||
if (sequence != NULL && panel_timeline->importing) {
|
||||
if (panel_timeline->importing) {
|
||||
if (panel_timeline->importing_files) {
|
||||
undo_stack.undo();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user