feat: capture and render media particles
This commit is contained in:
+102
-29
@@ -31,12 +31,21 @@
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include "media/mediahandler.h"
|
||||
#include "dialogs/mediapreviewdialog.h"
|
||||
#include "mediaparticlegenerator.h"
|
||||
#include "widgets/textparticlewidget.h"
|
||||
#include "widgets/mediaparticlewidget.h"
|
||||
#include <QStackedWidget>
|
||||
#include <QUrl>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent), m_trayIcon(nullptr), m_authManager(new AuthManager(this)), m_settingsDialog(nullptr),
|
||||
m_authDialog(nullptr), m_store(nullptr), m_networkStreamModel(nullptr), m_particleListModel(nullptr),
|
||||
m_selectedParticleRow(-1), m_isDragging(false), m_textInputDialog(nullptr), m_createStreamDialog(nullptr),
|
||||
m_networkDetailWidget(nullptr)
|
||||
: QMainWindow(parent), m_trayIcon(nullptr), m_networkDetailWidget(nullptr),
|
||||
m_authManager(new AuthManager(this)), m_authDialog(nullptr), m_settingsDialog(nullptr),
|
||||
m_textInputDialog(nullptr), m_createStreamDialog(nullptr),
|
||||
m_store(nullptr), m_networkStreamModel(nullptr), m_particleListModel(nullptr),
|
||||
m_selectedParticleRow(-1), m_isDragging(false), m_media{new MediaHandler{this}},
|
||||
m_spaceHeld(false)
|
||||
{
|
||||
m_authDialog = new AuthDialog(this);
|
||||
m_textInputDialog = new TextInputDialog(this);
|
||||
@@ -142,6 +151,42 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
|
||||
m_authManager->tryRestoreSession();
|
||||
|
||||
connect(m_media, &MediaHandler::errorOccurred, this, [this](const QString &message) {
|
||||
m_statusBar->showMessage(message);
|
||||
});
|
||||
|
||||
m_mediaPreviewDialog = new MediaPreviewDialog(this);
|
||||
m_mediaParticleGenerator = new MediaParticleGenerator(m_store, this);
|
||||
|
||||
connect(m_media, &MediaHandler::recordingComplete, this,
|
||||
[this](const QUrl &url, qint64 durationMs, const QString &mimeType) {
|
||||
m_media->stop();
|
||||
m_recordedFileUrl = url;
|
||||
m_recordedDurationMs = durationMs;
|
||||
m_recordedMimeType = mimeType;
|
||||
m_mediaPreviewDialog->showPreview(url);
|
||||
});
|
||||
|
||||
connect(m_mediaPreviewDialog, &MediaPreviewDialog::spaceReleased, this, [this]() {
|
||||
m_spaceHeld = false;
|
||||
m_media->recordStop();
|
||||
});
|
||||
|
||||
connect(m_mediaPreviewDialog, &QDialog::accepted, this, [this]() {
|
||||
m_mediaPreviewDialog->reset();
|
||||
if (m_selectedStreamId.isEmpty() || m_selectedNetworkId.isEmpty()) return;
|
||||
m_mediaParticleGenerator->generate(
|
||||
m_recordedFileUrl, m_recordedMimeType,
|
||||
m_selectedNetworkId, m_recordedDurationMs, m_selectedStreamId);
|
||||
});
|
||||
|
||||
connect(m_mediaPreviewDialog, &QDialog::rejected, this, [this]() {
|
||||
m_mediaPreviewDialog->reset();
|
||||
});
|
||||
|
||||
connect(m_mediaParticleGenerator, &MediaParticleGenerator::errorOccurred, this,
|
||||
[this](const QString &msg) { m_statusBar->showMessage(msg); });
|
||||
|
||||
setupTrayIcon();
|
||||
}
|
||||
|
||||
@@ -207,39 +252,28 @@ void MainWindow::buildUi()
|
||||
contentLayout->setSpacing(2);
|
||||
contentLayout->setContentsMargins(0, 0, 0, 2);
|
||||
|
||||
// Content container with spacers and labels
|
||||
auto *contentContainer = new QWidget();
|
||||
contentContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
auto *contentContainerLayout = new QVBoxLayout(contentContainer);
|
||||
contentContainerLayout->setSpacing(2);
|
||||
contentContainerLayout->setContentsMargins(0, 0, 0, 0);
|
||||
// Stacked widget for particle type-specific content
|
||||
m_contentStack = new QStackedWidget();
|
||||
m_contentStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
|
||||
contentContainerLayout->addStretch();
|
||||
m_textParticleWidget = new TextParticleWidget();
|
||||
m_mediaParticleWidget = new MediaParticleWidget();
|
||||
|
||||
m_particleContentLabel = new QLabel();
|
||||
QFont contentFont;
|
||||
contentFont.setPointSize(36);
|
||||
m_particleContentLabel->setFont(contentFont);
|
||||
m_particleContentLabel->setMaximumSize(500, 300);
|
||||
m_particleContentLabel->setAlignment(Qt::AlignCenter);
|
||||
m_particleContentLabel->setWordWrap(true);
|
||||
m_particleContentLabel->setScaledContents(true);
|
||||
contentContainerLayout->addWidget(m_particleContentLabel);
|
||||
m_contentStack->addWidget(m_textParticleWidget);
|
||||
m_contentStack->addWidget(m_mediaParticleWidget);
|
||||
|
||||
contentContainerLayout->addStretch();
|
||||
contentLayout->addWidget(m_contentStack);
|
||||
|
||||
m_creatorLabel = new QLabel();
|
||||
QFont creatorFont;
|
||||
creatorFont.setPointSize(15);
|
||||
m_creatorLabel->setFont(creatorFont);
|
||||
m_creatorLabel->setAlignment(Qt::AlignCenter);
|
||||
contentContainerLayout->addWidget(m_creatorLabel);
|
||||
contentLayout->addWidget(m_creatorLabel);
|
||||
|
||||
m_ackLabel = new QLabel();
|
||||
m_ackLabel->setAlignment(Qt::AlignCenter);
|
||||
contentContainerLayout->addWidget(m_ackLabel);
|
||||
|
||||
contentLayout->addWidget(contentContainer);
|
||||
contentLayout->addWidget(m_ackLabel);
|
||||
|
||||
// Content toolbar (empty, matches widget_4 from .ui)
|
||||
auto *contentToolbar = new QWidget();
|
||||
@@ -366,6 +400,10 @@ void MainWindow::setupTrayIcon()
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
if (m_spaceHeld)
|
||||
{
|
||||
m_media->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_exitButton_clicked()
|
||||
@@ -639,7 +677,8 @@ void MainWindow::onParticleSelectionChanged(const QItemSelection &selected, cons
|
||||
|
||||
if (selected.indexes().isEmpty())
|
||||
{
|
||||
m_particleContentLabel->setText("");
|
||||
m_textParticleWidget->clear();
|
||||
m_mediaParticleWidget->clear();
|
||||
m_creatorLabel->setText("");
|
||||
m_ackLabel->setText("");
|
||||
m_selectedParticleId.clear();
|
||||
@@ -658,11 +697,15 @@ void MainWindow::onParticleSelectionChanged(const QItemSelection &selected, cons
|
||||
|
||||
if (particle->type == "text")
|
||||
{
|
||||
m_particleContentLabel->setText(particle->data.value("content").toString());
|
||||
m_mediaParticleWidget->clear();
|
||||
m_textParticleWidget->setParticle(particle);
|
||||
m_contentStack->setCurrentWidget(m_textParticleWidget);
|
||||
}
|
||||
else
|
||||
else if (particle->type == "media")
|
||||
{
|
||||
m_particleContentLabel->setText("");
|
||||
m_textParticleWidget->clear();
|
||||
m_mediaParticleWidget->setParticle(particle);
|
||||
m_contentStack->setCurrentWidget(m_mediaParticleWidget);
|
||||
}
|
||||
|
||||
// Show ack info
|
||||
@@ -808,6 +851,16 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
auto *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (keyEvent->key() == Qt::Key_Space && !keyEvent->isAutoRepeat() && !m_spaceHeld)
|
||||
{
|
||||
if (!m_selectedNetworkId.isEmpty() && !m_selectedStreamId.isEmpty())
|
||||
{
|
||||
m_spaceHeld = true;
|
||||
m_mediaPreviewDialog->showRecording();
|
||||
m_media->startRecording(m_mediaPreviewDialog->videoSink());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (keyEvent->key() == Qt::Key_T && keyEvent->modifiers() == Qt::NoModifier && !m_selectedStreamId.isEmpty())
|
||||
{
|
||||
showTextInputDialog();
|
||||
@@ -819,6 +872,16 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (event->type() == QEvent::KeyRelease)
|
||||
{
|
||||
auto *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (keyEvent->key() == Qt::Key_Space && !keyEvent->isAutoRepeat() && m_spaceHeld)
|
||||
{
|
||||
m_spaceHeld = false;
|
||||
m_media->recordStop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QMainWindow::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
@@ -840,6 +903,16 @@ void MainWindow::onTextMessageSubmitted(const QString &text)
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
QMainWindow::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void MainWindow::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
QMainWindow::keyReleaseEvent(event);
|
||||
}
|
||||
|
||||
void MainWindow::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
|
||||
Reference in New Issue
Block a user