viewerwindow: implemented displaying a viewer image fullscreen on another monitor

Implements an extra widget to display images on a separate monitor. Both
viewers have separate display color controls since different monitors may
conform to different standards/transforms.
This commit is contained in:
itsmattkc
2020-04-01 19:21:25 +11:00
parent 6ea6dd810e
commit ed48d24cbc
8 changed files with 298 additions and 50 deletions
+135 -42
View File
@@ -21,8 +21,10 @@
#include "viewer.h"
#include <QDateTime>
#include <QGuiApplication>
#include <QLabel>
#include <QResizeEvent>
#include <QScreen>
#include <QtMath>
#include <QVBoxLayout>
@@ -55,11 +57,12 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
sizer_ = new ViewerSizer();
stack_->addWidget(sizer_);
gl_widget_ = new ViewerGLWidget();
connect(gl_widget_, &ViewerGLWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
connect(gl_widget_, &ViewerGLWidget::CursorColor, this, &ViewerWidget::CursorColor);
connect(sizer_, &ViewerSizer::RequestMatrix, gl_widget_, &ViewerGLWidget::SetMatrix);
sizer_->SetWidget(gl_widget_);
ViewerGLWidget* main_widget = new ViewerGLWidget();
connect(main_widget, &ViewerGLWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
connect(main_widget, &ViewerGLWidget::CursorColor, this, &ViewerWidget::CursorColor);
connect(sizer_, &ViewerSizer::RequestMatrix, main_widget, &ViewerGLWidget::SetMatrix);
sizer_->SetWidget(main_widget);
gl_widgets_.append(main_widget);
// Create waveform view when audio is connected and video isn't
waveform_view_ = new AudioWaveformView();
@@ -145,12 +148,18 @@ void ViewerWidget::ConnectNodeInternal(ViewerOutput *n)
SizeChangedSlot(n->video_params().width(), n->video_params().height());
LengthChangedSlot(n->Length());
ColorManager* using_manager;
if (override_color_manager_) {
gl_widget_->ConnectColorManager(override_color_manager_);
using_manager = override_color_manager_;
} else if (n->parent()) {
gl_widget_->ConnectColorManager(static_cast<Sequence*>(n->parent())->project()->color_manager());
using_manager = static_cast<Sequence*>(n->parent())->project()->color_manager();
} else {
qWarning() << "Failed to find a suitable color manager for the connected viewer node";
using_manager = nullptr;
}
foreach (ViewerGLWidget* glw, gl_widgets_) {
glw->ConnectColorManager(using_manager);
}
divider_ = CalculateDivider();
@@ -181,7 +190,9 @@ void ViewerWidget::DisconnectNodeInternal(ViewerOutput *n)
// Effectively disables the viewer and clears the state
SizeChangedSlot(0, 0);
gl_widget_->DisconnectColorManager();
foreach (ViewerGLWidget* glw, gl_widgets_) {
glw->DisconnectColorManager();
}
waveform_view_->ConnectTimelinePoints(nullptr);
}
@@ -213,6 +224,16 @@ void ViewerWidget::resizeEvent(QResizeEvent *event)
UpdateMinimumScale();
}
const QList<ViewerGLWidget*> &ViewerWidget::gl_widgets() const
{
return gl_widgets_;
}
ViewerGLWidget *ViewerWidget::main_gl_widget() const
{
return gl_widgets_.first();
}
void ViewerWidget::TogglePlayPause()
{
if (IsPlaying()) {
@@ -249,7 +270,9 @@ void ViewerWidget::SetOverrideSize(int width, int height)
void ViewerWidget::SetMatrix(const QMatrix4x4 &mat)
{
gl_widget_->SetMatrix(mat);
foreach (ViewerGLWidget* glw, gl_widgets_) {
glw->SetMatrix(mat);
}
}
VideoRenderBackend *ViewerWidget::video_renderer() const
@@ -260,12 +283,12 @@ VideoRenderBackend *ViewerWidget::video_renderer() const
void ViewerWidget::UpdateTextureFromNode(const rational& time)
{
if (!GetConnectedNode() || time >= GetConnectedNode()->Length()) {
gl_widget_->SetImage(QString());
main_gl_widget()->SetImage(QString());
} else {
QString frame_fn = video_renderer_->GetCachedFrame(time);
if (!frame_fn.isEmpty()) {
gl_widget_->SetImage(frame_fn);
main_gl_widget()->SetImage(frame_fn);
}
}
}
@@ -294,7 +317,7 @@ void ViewerWidget::PlayInternal(int speed)
controls_->ShowPauseButton();
if (stack_->currentWidget() == sizer_) {
connect(gl_widget_, &ViewerGLWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate);
connect(main_gl_widget(), &ViewerGLWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate);
} else {
connect(AudioManager::instance(), &AudioManager::OutputNotified, this, &ViewerWidget::PlaybackTimerUpdate);
}
@@ -325,7 +348,7 @@ int ViewerWidget::CalculateDivider()
{
if (GetConnectedNode() && Config::Current()["AutoSelectDivider"].toBool()) {
int long_side_of_video = qMax(GetConnectedNode()->video_params().width(), GetConnectedNode()->video_params().height());
int long_side_of_widget = qMax(gl_widget_->width(), gl_widget_->height());
int long_side_of_widget = qMax(main_gl_widget()->width(), main_gl_widget()->height());
return qMax(1, long_side_of_video / long_side_of_widget);
}
@@ -356,6 +379,35 @@ void ViewerWidget::UpdateStack()
}
}
void ViewerWidget::SetFullScreenDisplay(QAction *action)
{
QScreen* target = QGuiApplication::screens().at(action->data().toInt());
ViewerWindow* vw = new ViewerWindow(this);
vw->showFullScreen();
vw->setGeometry(target->geometry());
vw->gl_widget()->ConnectColorManager(main_gl_widget()->color_manager());
main_gl_widget()->ConnectSibling(vw->gl_widget());
connect(vw, &ViewerWindow::destroyed, this, &ViewerWidget::WindowAboutToClose);
connect(vw->gl_widget(), &ViewerGLWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
if (GetConnectedNode()) {
vw->SetResolution(GetConnectedNode()->video_params().width(), GetConnectedNode()->video_params().height());
}
windows_.append(vw);
gl_widgets_.append(vw->gl_widget());
}
void ViewerWidget::WindowAboutToClose()
{
ViewerWindow* vw = static_cast<ViewerWindow*>(sender());
windows_.removeAll(vw);
gl_widgets_.removeAll(vw->gl_widget());
}
void ViewerWidget::UpdateRendererParameters()
{
if (!GetConnectedNode()) {
@@ -385,40 +437,42 @@ void ViewerWidget::UpdateRendererParameters()
void ViewerWidget::ShowContextMenu(const QPoint &pos)
{
QMenu menu(this);
QMenu menu(static_cast<QWidget*>(sender()));
context_menu_widget_ = static_cast<ViewerGLWidget*>(sender());
// Color options
if (gl_widget_->color_manager() && color_menu_enabled_) {
QStringList displays = gl_widget_->color_manager()->ListAvailableDisplays();
if (context_menu_widget_->color_manager() && color_menu_enabled_) {
QStringList displays = context_menu_widget_->color_manager()->ListAvailableDisplays();
QMenu* ocio_display_menu = menu.addMenu(tr("Display"));
connect(ocio_display_menu, &QMenu::triggered, this, &ViewerWidget::ColorDisplayChanged);
connect(ocio_display_menu, &QMenu::triggered, this, &ViewerWidget::ContextMenuOCIODisplay);
foreach (const QString& d, displays) {
QAction* action = ocio_display_menu->addAction(d);
action->setCheckable(true);
action->setChecked(gl_widget_->ocio_display() == d);
action->setChecked(context_menu_widget_->ocio_display() == d);
action->setData(d);
}
QStringList views = gl_widget_->color_manager()->ListAvailableViews(gl_widget_->ocio_display());
QStringList views = context_menu_widget_->color_manager()->ListAvailableViews(context_menu_widget_->ocio_display());
QMenu* ocio_view_menu = menu.addMenu(tr("View"));
connect(ocio_view_menu, &QMenu::triggered, this, &ViewerWidget::ColorViewChanged);
connect(ocio_view_menu, &QMenu::triggered, this, &ViewerWidget::ContextMenuOCIOView);
foreach (const QString& v, views) {
QAction* action = ocio_view_menu->addAction(v);
action->setCheckable(true);
action->setChecked(gl_widget_->ocio_view() == v);
action->setChecked(context_menu_widget_->ocio_view() == v);
action->setData(v);
}
QStringList looks = gl_widget_->color_manager()->ListAvailableLooks();
QStringList looks = context_menu_widget_->color_manager()->ListAvailableLooks();
QMenu* ocio_look_menu = menu.addMenu(tr("Look"));
connect(ocio_look_menu, &QMenu::triggered, this, &ViewerWidget::ColorLookChanged);
connect(ocio_look_menu, &QMenu::triggered, this, &ViewerWidget::ContextMenuOCIOLook);
QAction* no_look_action = ocio_look_menu->addAction(tr("(None)"));
no_look_action->setCheckable(true);
no_look_action->setChecked(gl_widget_->ocio_look().isEmpty());
no_look_action->setChecked(context_menu_widget_->ocio_look().isEmpty());
foreach (const QString& l, looks) {
QAction* action = ocio_look_menu->addAction(l);
action->setCheckable(true);
action->setChecked(gl_widget_->ocio_look() == l);
action->setChecked(context_menu_widget_->ocio_look() == l);
action->setData(l);
}
@@ -434,6 +488,13 @@ void ViewerWidget::ShowContextMenu(const QPoint &pos)
}
connect(playback_resolution_menu, &QMenu::triggered, this, &ViewerWidget::SetDividerFromMenu);
foreach (QAction* a, playback_resolution_menu->actions()) {
a->setCheckable(true);
if (a->data() == divider_) {
a->setChecked(true);
}
}
// Viewer Zoom Level
QMenu* zoom_menu = menu.addMenu(tr("Zoom"));
int zoom_levels[] = {10, 25, 50, 75, 100, 150, 200, 400};
@@ -443,12 +504,18 @@ void ViewerWidget::ShowContextMenu(const QPoint &pos)
}
connect(zoom_menu, &QMenu::triggered, this, &ViewerWidget::SetZoomFromMenu);
foreach (QAction* a, playback_resolution_menu->actions()) {
a->setCheckable(true);
if (a->data() == divider_) {
a->setChecked(true);
}
// Full Screen Menu
QMenu* full_screen_menu = menu.addMenu(tr("Full Screen"));
for (int i=0;i<QGuiApplication::screens().size();i++) {
QScreen* s = QGuiApplication::screens().at(i);
QAction* a = full_screen_menu->addAction(tr("Screen %1: %2x%3").arg(QString::number(i),
QString::number(s->size().width()),
QString::number(s->size().height())));
a->setData(i);
}
connect(full_screen_menu, &QMenu::triggered, this, &ViewerWidget::SetFullScreenDisplay);
menu.exec(static_cast<QWidget*>(sender())->mapToGlobal(pos));
}
@@ -466,7 +533,7 @@ void ViewerWidget::Pause()
controls_->ShowPlayButton();
if (stack_->currentWidget() == sizer_) {
disconnect(gl_widget_, &ViewerGLWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate);
disconnect(main_gl_widget(), &ViewerGLWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate);
} else {
disconnect(AudioManager::instance(), &AudioManager::OutputNotified, this, &ViewerWidget::PlaybackTimerUpdate);
}
@@ -514,27 +581,49 @@ void ViewerWidget::ShuttleRight()
void ViewerWidget::SetOCIOParameters(const QString &display, const QString &view, const QString &look)
{
gl_widget_->SetOCIOParameters(display, view, look);
SetOCIOParameters(display, view, look, main_gl_widget());
}
void ViewerWidget::SetOCIOParameters(const QString &display, const QString &view, const QString &look, ViewerGLWidget* sender)
{
sender->SetOCIOParameters(display, view, look);
}
void ViewerWidget::SetOCIODisplay(const QString &display)
{
gl_widget_->SetOCIODisplay(display);
SetOCIODisplay(display, main_gl_widget());
}
void ViewerWidget::SetOCIODisplay(const QString &display, ViewerGLWidget* sender)
{
sender->SetOCIODisplay(display);
}
void ViewerWidget::SetOCIOView(const QString &view)
{
gl_widget_->SetOCIOView(view);
SetOCIOView(view, main_gl_widget());
}
void ViewerWidget::SetOCIOLook(const QString &look)
{
gl_widget_->SetOCIOLook(look);
SetOCIOLook(look, main_gl_widget());
}
void ViewerWidget::SetOCIOView(const QString &view, ViewerGLWidget* sender)
{
sender->SetOCIOView(view);
}
void ViewerWidget::SetOCIOLook(const QString &look, ViewerGLWidget* sender)
{
sender->SetOCIOLook(look);
}
void ViewerWidget::SetSignalCursorColorEnabled(bool e)
{
gl_widget_->SetSignalCursorColorEnabled(e);
foreach (ViewerGLWidget* glw, gl_widgets_) {
glw->SetSignalCursorColorEnabled(e);
}
}
void ViewerWidget::TimebaseChangedEvent(const rational &timebase)
@@ -576,6 +665,10 @@ void ViewerWidget::RendererCachedTime(const rational &time, qint64 job_time)
void ViewerWidget::SizeChangedSlot(int width, int height)
{
sizer_->SetChildSize(width, height);
foreach (ViewerWindow* vw, windows_) {
vw->SetResolution(width, height);
}
}
void ViewerWidget::LengthChangedSlot(const rational &length)
@@ -585,19 +678,19 @@ void ViewerWidget::LengthChangedSlot(const rational &length)
UpdateMinimumScale();
}
void ViewerWidget::ColorDisplayChanged(QAction* action)
void ViewerWidget::ContextMenuOCIODisplay(QAction* action)
{
SetOCIODisplay(action->data().toString());
SetOCIODisplay(action->data().toString(), context_menu_widget_);
}
void ViewerWidget::ColorViewChanged(QAction *action)
void ViewerWidget::ContextMenuOCIOView(QAction *action)
{
SetOCIOView(action->data().toString());
SetOCIOView(action->data().toString(), context_menu_widget_);
}
void ViewerWidget::ColorLookChanged(QAction *action)
void ViewerWidget::ContextMenuOCIOLook(QAction *action)
{
SetOCIOLook(action->data().toString());
SetOCIOLook(action->data().toString(), context_menu_widget_);
}
void ViewerWidget::SetDividerFromMenu(QAction *action)