// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #include "tasktable.hpp" #include "logdialog.hpp" #include "libvideostitch-base/logmanager.hpp" #include "autoelidelabel.hpp" #include <QResizeEvent> #include <QAbstractButton> #include <QMessageBox> #include <QProgressBar> #include <QHeaderView> #include <QAction> #include <QMenu> TaskList::TaskList(QObject *parent) : QObject(parent) { beingStitched = -1; } TaskList::TaskList(const TaskList ©) : QObject(copy.parent()), QList<BatcherTask *>() { beingStitched = copy.beingStitched; qCopy(copy.begin(), copy.begin(), begin()); } bool TaskList::isRunning() const { return beingStitched != -1; } void TaskList::signalFinished() { beingStitched = -1; emit finished(); } void TaskList::stitchNext() { if (beingStitched != -1 && at(beingStitched)->isRunning()) { disconnect(at(beingStitched), SIGNAL(finished()), this, SLOT(stitchNext())); at(beingStitched)->kill(); signalFinished(); return; } if (isEmpty()) { return; } ++beingStitched; if (beingStitched > 0) { disconnect(at(beingStitched - 1), SIGNAL(finished()), this, SLOT(stitchNext())); } if (beingStitched >= size()) { signalFinished(); return; } connect(at(beingStitched), SIGNAL(finished()), this, SLOT(stitchNext())); at(beingStitched)->start(); } void TaskList::removeItem(BatcherTask *item) { removeAll(item); if (item->isRunning()) { beingStitched--; item->kill(); } delete item; } TaskTable::TaskTable(QWidget *parent) : QTableWidget(parent), vsWindow(nullptr), selectedRow(-1), state(Idle) { setColumnCount(BatcherTask::getTaskModel().size()); setRowCount(0); setShowGrid(false); setHorizontalHeaderLabels(BatcherTask::getTaskModel()); setEditTriggers(QAbstractItemView::NoEditTriggers); connect(&tasks, SIGNAL(finished()), this, SLOT(taskListFinished())); connect(this, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(onCurrentCellChanged(int, int, int, int))); verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); setGridStyle(Qt::NoPen); } void TaskTable::addTask(const QString &ptvLocation) { if (taskNames.contains(ptvLocation)) { raise(); activateWindow(); QMessageBox::warning(this, tr("Couldn't add duplicate project."), tr("Couldn't add duplicate project %0.").arg(ptvLocation)); return; } VideoStitch::Helper::LogManager::getInstance()->writeToLogFile(QString("Adding %0 to batch list").arg(ptvLocation)); BatcherTask *task = new BatcherTask(this); AutoElideLabel *nameLabel = new AutoElideLabel(Qt::ElideLeft, this); nameLabel->setText(ptvLocation); QProgressBar *bar = new QProgressBar(this); task->setTaskProgress(bar); task->setPtvName(nameLabel); setRowCount(rowCount() + 1); int index = rowCount() - 1; setCellWidget(index, 0, nameLabel); setCellWidget(index, 1, bar); tasks.push_back(task); task->setID(BatcherTask::lastID++); task->setDevices(selectedDevices); updateColumnSize(width()); taskNames << ptvLocation; } TaskTable::State TaskTable::getState() const { return state; } BatcherTask *TaskTable::getTaskAt(int row) { return (row >= 0 && tasks.size() > row) ? tasks[row] : NULL; } void TaskTable::removeSelected() { if (selectedRow >= 0 && selectedRow < rowCount()) { removeTaskAt(selectedRow); } } void TaskTable::startStitching() { VideoStitch::Helper::LogManager::getInstance()->writeToLogFile("Starting to stitch the batch list."); state = RUNNING; emit processing(); tasks.stitchNext(); } void TaskTable::onCurrentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn) { Q_UNUSED(currentColumn) Q_UNUSED(previousRow) Q_UNUSED(previousColumn) selectedRow = currentRow; } void TaskTable::updateColumnSize(int width) { for (int i = 0; i < columnCount(); i++) { setColumnWidth(i, width / columnCount()); } } void TaskTable::showEvent(QShowEvent *) { updateColumnSize(width()); } void TaskTable::resizeEvent(QResizeEvent *event) { updateColumnSize(event->size().width()); } void TaskTable::mousePressEvent(QMouseEvent *event) { QTableWidget::mousePressEvent(event); if (event->button() == Qt::RightButton) { BatcherTask *task = getTaskAt(rowAt(event->pos().y())); if (task) { QMenu menu; QAction *removeTask = menu.addAction(tr("Remove task")); QAction *openWithVS = menu.addAction(tr("Open With %0").arg(VIDEOSTITCH_STUDIO_APP_NAME)); QAction *resetTask = (task->isRunning()) ? NULL : menu.addAction(tr("Reset task")); QAction *openLog = menu.addAction(tr("Open Log")); QAction *selectedAction = menu.exec(event->globalPos()); if (selectedAction == removeTask) { removeTaskAt(rowAt(event->pos().y())); } else if (selectedAction == openWithVS) { emit reqOpenVS(task->getPtvName()); VideoStitch::Helper::LogManager::getInstance()->writeToLogFile( QString("Asking %0 to open %1").arg(VIDEOSTITCH_STUDIO_APP_NAME).arg(task->getPtvName())); } else if (selectedAction == resetTask) { task->resetState(); VideoStitch::Helper::LogManager::getInstance()->writeToLogFile( QString("Resetting task state %0 at index %1.") .arg(task->getPtvName(), QString::number(rowAt(event->pos().y())))); } else if (selectedAction == openLog) { LogDialog dialog(task->getLog(), task->getPtvName(), this); connect(task, SIGNAL(newLogLine(QString)), &dialog, SLOT(appendLogLine(QString))); dialog.exec(); VideoStitch::Helper::LogManager::getInstance()->writeToLogFile( QString("Opening log of %0.").arg(task->getPtvName())); } } } } void TaskTable::mouseDoubleClickEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { BatcherTask *task = getTaskAt(rowAt(event->pos().y())); if (task) { if (task->getState() == BatcherTask::Error || task->getState() == BatcherTask::Finished) { LogDialog dialog(task->getLog(), task->getPtvName(), this); dialog.exec(); } } } } void TaskTable::updateGeometries() { QTableWidget::updateGeometries(); QAbstractButton *cornerButton = findChild<QAbstractButton *>(); if (cornerButton) { cornerButton->hide(); } } void TaskTable::removeTaskAt(int row) { if (row < 0) { return; } removeRow(row); BatcherTask *task = tasks.at(row); taskNames.remove(task->getPtvName()); VideoStitch::Helper::LogManager::getInstance()->writeToLogFile( QString("Removing %0 from batch list").arg(task->getPtvName())); tasks.removeItem(task); if (selectedRow >= rowCount()) { selectedRow = rowCount() - 1; } emit removedTask(); } void TaskTable::removeAll() { while (!tasks.isEmpty()) { removeTaskAt(0); } } void TaskTable::taskListFinished() { state = Idle; emit finished(); } void TaskTable::onDeviceSelectionChanged(QList<int> devices) { selectedDevices = devices; for (auto i = 0; i < tasks.size(); ++i) { tasks.at(i)->setDevices(selectedDevices); } }