| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 | /******************************************************************************    Copyright (C) 2014 by Ruwen Hahn <[email protected]>    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 2 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 "RemuxQueueModel.hpp"#include <OBSApp.hpp>#include <QDir>#include <QStyle>#include "moc_RemuxQueueModel.cpp"int RemuxQueueModel::rowCount(const QModelIndex &) const{	return queue.length() + (isProcessing ? 0 : 1);}int RemuxQueueModel::columnCount(const QModelIndex &) const{	return RemuxEntryColumn::Count;}QVariant RemuxQueueModel::data(const QModelIndex &index, int role) const{	QVariant result = QVariant();	if (index.row() >= queue.length()) {		return QVariant();	} else if (role == Qt::DisplayRole) {		switch (index.column()) {		case RemuxEntryColumn::InputPath:			result = queue[index.row()].sourcePath;			break;		case RemuxEntryColumn::OutputPath:			result = queue[index.row()].targetPath;			break;		}	} else if (role == Qt::DecorationRole && index.column() == RemuxEntryColumn::State) {		result = getIcon(queue[index.row()].state);	} else if (role == RemuxEntryRole::EntryStateRole) {		result = queue[index.row()].state;	}	return result;}QVariant RemuxQueueModel::headerData(int section, Qt::Orientation orientation, int role) const{	QVariant result = QVariant();	if (role == Qt::DisplayRole && orientation == Qt::Orientation::Horizontal) {		switch (section) {		case RemuxEntryColumn::State:			result = QString();			break;		case RemuxEntryColumn::InputPath:			result = QTStr("Remux.SourceFile");			break;		case RemuxEntryColumn::OutputPath:			result = QTStr("Remux.TargetFile");			break;		}	}	return result;}Qt::ItemFlags RemuxQueueModel::flags(const QModelIndex &index) const{	Qt::ItemFlags flags = QAbstractTableModel::flags(index);	if (index.column() == RemuxEntryColumn::InputPath) {		flags |= Qt::ItemIsEditable;	} else if (index.column() == RemuxEntryColumn::OutputPath && index.row() != queue.length()) {		flags |= Qt::ItemIsEditable;	}	return flags;}bool RemuxQueueModel::setData(const QModelIndex &index, const QVariant &value, int role){	bool success = false;	if (role == RemuxEntryRole::NewPathsToProcessRole) {		QStringList pathList = value.toStringList();		if (pathList.size() == 0) {			if (index.row() < queue.size()) {				beginRemoveRows(QModelIndex(), index.row(), index.row());				queue.removeAt(index.row());				endRemoveRows();			}		} else {			if (pathList.size() >= 1 && index.row() < queue.length()) {				queue[index.row()].sourcePath = pathList[0];				checkInputPath(index.row());				pathList.removeAt(0);				success = true;			}			if (pathList.size() > 0) {				int row = index.row();				int lastRow = row + pathList.size() - 1;				beginInsertRows(QModelIndex(), row, lastRow);				for (QString path : pathList) {					RemuxQueueEntry entry;					entry.sourcePath = path;					entry.state = RemuxEntryState::Empty;					queue.insert(row, entry);					row++;				}				endInsertRows();				for (row = index.row(); row <= lastRow; row++) {					checkInputPath(row);				}				success = true;			}		}	} else if (index.row() == queue.length()) {		QString path = value.toString();		if (!path.isEmpty()) {			RemuxQueueEntry entry;			entry.sourcePath = path;			entry.state = RemuxEntryState::Empty;			beginInsertRows(QModelIndex(), queue.length() + 1, queue.length() + 1);			queue.append(entry);			endInsertRows();			checkInputPath(index.row());			success = true;		}	} else {		QString path = value.toString();		if (path.isEmpty()) {			if (index.column() == RemuxEntryColumn::InputPath) {				beginRemoveRows(QModelIndex(), index.row(), index.row());				queue.removeAt(index.row());				endRemoveRows();			}		} else {			switch (index.column()) {			case RemuxEntryColumn::InputPath:				queue[index.row()].sourcePath = value.toString();				checkInputPath(index.row());				success = true;				break;			case RemuxEntryColumn::OutputPath:				queue[index.row()].targetPath = value.toString();				emit dataChanged(index, index);				success = true;				break;			}		}	}	return success;}QVariant RemuxQueueModel::getIcon(RemuxEntryState state){	QVariant icon;	QStyle *style = QApplication::style();	switch (state) {	case RemuxEntryState::Complete:		icon = style->standardIcon(QStyle::SP_DialogApplyButton);		break;	case RemuxEntryState::InProgress:		icon = style->standardIcon(QStyle::SP_ArrowRight);		break;	case RemuxEntryState::Error:		icon = style->standardIcon(QStyle::SP_DialogCancelButton);		break;	case RemuxEntryState::InvalidPath:		icon = style->standardIcon(QStyle::SP_MessageBoxWarning);		break;	default:		break;	}	return icon;}void RemuxQueueModel::checkInputPath(int row){	RemuxQueueEntry &entry = queue[row];	if (entry.sourcePath.isEmpty()) {		entry.state = RemuxEntryState::Empty;	} else {		entry.sourcePath = QDir::toNativeSeparators(entry.sourcePath);		QFileInfo fileInfo(entry.sourcePath);		if (fileInfo.exists())			entry.state = RemuxEntryState::Ready;		else			entry.state = RemuxEntryState::InvalidPath;		QString newExt = ".mp4";		QString suffix = fileInfo.suffix();		if (suffix.contains("mov", Qt::CaseInsensitive) || suffix.contains("mp4", Qt::CaseInsensitive)) {			newExt = ".remuxed." + suffix;		}		if (entry.state == RemuxEntryState::Ready)			entry.targetPath = QDir::toNativeSeparators(fileInfo.path() + QDir::separator() +								    fileInfo.completeBaseName() + newExt);	}	if (entry.state == RemuxEntryState::Ready && isProcessing)		entry.state = RemuxEntryState::Pending;	emit dataChanged(index(row, 0), index(row, RemuxEntryColumn::Count));}QFileInfoList RemuxQueueModel::checkForOverwrites() const{	QFileInfoList list;	for (const RemuxQueueEntry &entry : queue) {		if (entry.state == RemuxEntryState::Ready) {			QFileInfo fileInfo(entry.targetPath);			if (fileInfo.exists()) {				list.append(fileInfo);			}		}	}	return list;}bool RemuxQueueModel::checkForErrors() const{	bool hasErrors = false;	for (const RemuxQueueEntry &entry : queue) {		if (entry.state == RemuxEntryState::Error) {			hasErrors = true;			break;		}	}	return hasErrors;}void RemuxQueueModel::clearAll(){	beginRemoveRows(QModelIndex(), 0, queue.size() - 1);	queue.clear();	endRemoveRows();}void RemuxQueueModel::clearFinished(){	int index = 0;	for (index = 0; index < queue.size(); index++) {		const RemuxQueueEntry &entry = queue[index];		if (entry.state == RemuxEntryState::Complete) {			beginRemoveRows(QModelIndex(), index, index);			queue.removeAt(index);			endRemoveRows();			index--;		}	}}bool RemuxQueueModel::canClearFinished() const{	bool canClearFinished = false;	for (const RemuxQueueEntry &entry : queue)		if (entry.state == RemuxEntryState::Complete) {			canClearFinished = true;			break;		}	return canClearFinished;}void RemuxQueueModel::beginProcessing(){	for (RemuxQueueEntry &entry : queue)		if (entry.state == RemuxEntryState::Ready)			entry.state = RemuxEntryState::Pending;	// Signal that the insertion point no longer exists.	beginRemoveRows(QModelIndex(), queue.length(), queue.length());	endRemoveRows();	isProcessing = true;	emit dataChanged(index(0, RemuxEntryColumn::State), index(queue.length(), RemuxEntryColumn::State));}void RemuxQueueModel::endProcessing(){	for (RemuxQueueEntry &entry : queue) {		if (entry.state == RemuxEntryState::Pending) {			entry.state = RemuxEntryState::Ready;		}	}	// Signal that the insertion point exists again.	isProcessing = false;	if (!autoRemux) {		beginInsertRows(QModelIndex(), queue.length(), queue.length());		endInsertRows();	}	emit dataChanged(index(0, RemuxEntryColumn::State), index(queue.length(), RemuxEntryColumn::State));}bool RemuxQueueModel::beginNextEntry(QString &inputPath, QString &outputPath){	bool anyStarted = false;	for (int row = 0; row < queue.length(); row++) {		RemuxQueueEntry &entry = queue[row];		if (entry.state == RemuxEntryState::Pending) {			entry.state = RemuxEntryState::InProgress;			inputPath = entry.sourcePath;			outputPath = entry.targetPath;			QModelIndex index = this->index(row, RemuxEntryColumn::State);			emit dataChanged(index, index);			anyStarted = true;			break;		}	}	return anyStarted;}void RemuxQueueModel::finishEntry(bool success){	for (int row = 0; row < queue.length(); row++) {		RemuxQueueEntry &entry = queue[row];		if (entry.state == RemuxEntryState::InProgress) {			if (success)				entry.state = RemuxEntryState::Complete;			else				entry.state = RemuxEntryState::Error;			QModelIndex index = this->index(row, RemuxEntryColumn::State);			emit dataChanged(index, index);			break;		}	}}
 |