change: change code style to Linux style except indent.
This commit is contained in:
@@ -27,76 +27,80 @@
|
||||
#include "config/config.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super SeekableWidget
|
||||
|
||||
AudioWaveformView::AudioWaveformView(QWidget *parent) :
|
||||
super(parent),
|
||||
playback_(nullptr)
|
||||
AudioWaveformView::AudioWaveformView(QWidget *parent)
|
||||
: super(parent)
|
||||
, playback_(nullptr)
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
setBackgroundRole(QPalette::Base);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setAutoFillBackground(true);
|
||||
setBackgroundRole(QPalette::Base);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
// NOTE: At some point it might make sense for this to be AlignCenter since the waveform
|
||||
// originates from the center. But we're leaving it top/left for now since it was just
|
||||
// ported from a QWidget's paintEvent.
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
// NOTE: At some point it might make sense for this to be AlignCenter since the waveform
|
||||
// originates from the center. But we're leaving it top/left for now since it was just
|
||||
// ported from a QWidget's paintEvent.
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
}
|
||||
|
||||
void AudioWaveformView::SetViewer(ViewerOutput *playback)
|
||||
{
|
||||
if (playback_) {
|
||||
pool_.clear();
|
||||
pool_.waitForDone();
|
||||
if (playback_) {
|
||||
pool_.clear();
|
||||
pool_.waitForDone();
|
||||
|
||||
disconnect(playback_, &ViewerOutput::ConnectedWaveformChanged, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
||||
disconnect(playback_, &ViewerOutput::ConnectedWaveformChanged,
|
||||
viewport(),
|
||||
static_cast<void (QWidget::*)()>(&QWidget::update));
|
||||
|
||||
SetTimebase(0);
|
||||
}
|
||||
SetTimebase(0);
|
||||
}
|
||||
|
||||
playback_ = playback;
|
||||
playback_ = playback;
|
||||
|
||||
if (playback_) {
|
||||
connect(playback_, &ViewerOutput::ConnectedWaveformChanged, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
||||
if (playback_) {
|
||||
connect(playback_, &ViewerOutput::ConnectedWaveformChanged, viewport(),
|
||||
static_cast<void (QWidget::*)()>(&QWidget::update));
|
||||
|
||||
SetTimebase(playback_->GetAudioParams().sample_rate_as_time_base());
|
||||
}
|
||||
SetTimebase(playback_->GetAudioParams().sample_rate_as_time_base());
|
||||
}
|
||||
}
|
||||
|
||||
void AudioWaveformView::drawForeground(QPainter *p, const QRectF &rect)
|
||||
{
|
||||
super::drawForeground(p, rect);
|
||||
super::drawForeground(p, rect);
|
||||
|
||||
if (!playback_) {
|
||||
return;
|
||||
}
|
||||
if (!playback_) {
|
||||
return;
|
||||
}
|
||||
|
||||
const AudioWaveformCache *wave = playback_->GetConnectedWaveform();
|
||||
if (!wave) {
|
||||
return;
|
||||
}
|
||||
const AudioWaveformCache *wave = playback_->GetConnectedWaveform();
|
||||
if (!wave) {
|
||||
return;
|
||||
}
|
||||
|
||||
const AudioParams& params = wave->GetParameters();
|
||||
if (!params.is_valid()) {
|
||||
return;
|
||||
}
|
||||
const AudioParams ¶ms = wave->GetParameters();
|
||||
if (!params.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw in/out points
|
||||
DrawWorkArea(p);
|
||||
DrawMarkers(p);
|
||||
// Draw in/out points
|
||||
DrawWorkArea(p);
|
||||
DrawMarkers(p);
|
||||
|
||||
// Draw waveform
|
||||
p->setPen(QColor(64, 255, 160)); // FIXME: Hardcoded color
|
||||
wave->Draw(p, rect.toRect(), GetScale(), SceneToTime(GetScroll()));
|
||||
// Draw waveform
|
||||
p->setPen(QColor(64, 255, 160)); // FIXME: Hardcoded color
|
||||
wave->Draw(p, rect.toRect(), GetScale(), SceneToTime(GetScroll()));
|
||||
|
||||
// Draw playhead
|
||||
p->setPen(PLAYHEAD_COLOR);
|
||||
// Draw playhead
|
||||
p->setPen(PLAYHEAD_COLOR);
|
||||
|
||||
int playhead_x = TimeToScene(GetViewerNode()->GetPlayhead());
|
||||
p->drawLine(playhead_x, 0, playhead_x, height());
|
||||
int playhead_x = TimeToScene(GetViewerNode()->GetPlayhead());
|
||||
p->drawLine(playhead_x, 0, playhead_x, height());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,24 +27,23 @@
|
||||
#include "render/audioplaybackcache.h"
|
||||
#include "widget/timeruler/seekablewidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class AudioWaveformView : public SeekableWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioWaveformView(QWidget* parent = nullptr);
|
||||
|
||||
void SetViewer(ViewerOutput *playback);
|
||||
class AudioWaveformView : public SeekableWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioWaveformView(QWidget *parent = nullptr);
|
||||
|
||||
void SetViewer(ViewerOutput *playback);
|
||||
|
||||
protected:
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
private:
|
||||
QThreadPool pool_;
|
||||
|
||||
ViewerOutput *playback_;
|
||||
QThreadPool pool_;
|
||||
|
||||
ViewerOutput *playback_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -26,98 +26,108 @@
|
||||
#include "config/config.h"
|
||||
#include "node/project.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super ViewerWidget
|
||||
|
||||
FootageViewerWidget::FootageViewerWidget(QWidget *parent) :
|
||||
super(parent)
|
||||
FootageViewerWidget::FootageViewerWidget(QWidget *parent)
|
||||
: super(parent)
|
||||
{
|
||||
connect(display_widget(), &ViewerDisplayWidget::DragStarted, this, &FootageViewerWidget::StartFootageDrag);
|
||||
connect(display_widget(), &ViewerDisplayWidget::DragStarted, this,
|
||||
&FootageViewerWidget::StartFootageDrag);
|
||||
|
||||
controls_->SetAudioVideoDragButtonsVisible(true);
|
||||
connect(controls_, &PlaybackControls::VideoClicked, this, &FootageViewerWidget::VideoButtonClicked);
|
||||
connect(controls_, &PlaybackControls::AudioClicked, this, &FootageViewerWidget::AudioButtonClicked);
|
||||
connect(controls_, &PlaybackControls::VideoDragged, this, &FootageViewerWidget::StartVideoDrag);
|
||||
connect(controls_, &PlaybackControls::AudioDragged, this, &FootageViewerWidget::StartAudioDrag);
|
||||
controls_->SetAudioVideoDragButtonsVisible(true);
|
||||
connect(controls_, &PlaybackControls::VideoClicked, this,
|
||||
&FootageViewerWidget::VideoButtonClicked);
|
||||
connect(controls_, &PlaybackControls::AudioClicked, this,
|
||||
&FootageViewerWidget::AudioButtonClicked);
|
||||
connect(controls_, &PlaybackControls::VideoDragged, this,
|
||||
&FootageViewerWidget::StartVideoDrag);
|
||||
connect(controls_, &PlaybackControls::AudioDragged, this,
|
||||
&FootageViewerWidget::StartAudioDrag);
|
||||
|
||||
override_workarea_ = new TimelineWorkArea(this);
|
||||
override_workarea_ = new TimelineWorkArea(this);
|
||||
}
|
||||
|
||||
void FootageViewerWidget::OverrideWorkArea(const TimeRange &r)
|
||||
{
|
||||
override_workarea_->set_enabled(true);
|
||||
override_workarea_->set_range(r);
|
||||
this->ConnectWorkArea(override_workarea_);
|
||||
override_workarea_->set_enabled(true);
|
||||
override_workarea_->set_range(r);
|
||||
this->ConnectWorkArea(override_workarea_);
|
||||
}
|
||||
|
||||
void FootageViewerWidget::ResetWorkArea()
|
||||
{
|
||||
if (GetConnectedWorkArea() == override_workarea_) {
|
||||
this->ConnectWorkArea(GetConnectedNode() ? GetConnectedNode()->GetWorkArea() : nullptr);
|
||||
}
|
||||
if (GetConnectedWorkArea() == override_workarea_) {
|
||||
this->ConnectWorkArea(
|
||||
GetConnectedNode() ? GetConnectedNode()->GetWorkArea() : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void FootageViewerWidget::StartFootageDragInternal(bool enable_video, bool enable_audio)
|
||||
void FootageViewerWidget::StartFootageDragInternal(bool enable_video,
|
||||
bool enable_audio)
|
||||
{
|
||||
if (!GetConnectedNode()) {
|
||||
return;
|
||||
}
|
||||
if (!GetConnectedNode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDrag* drag = new QDrag(this);
|
||||
QMimeData* mimedata = new QMimeData();
|
||||
QDrag *drag = new QDrag(this);
|
||||
QMimeData *mimedata = new QMimeData();
|
||||
|
||||
QByteArray encoded_data;
|
||||
QDataStream data_stream(&encoded_data, QIODevice::WriteOnly);
|
||||
QByteArray encoded_data;
|
||||
QDataStream data_stream(&encoded_data, QIODevice::WriteOnly);
|
||||
|
||||
QVector<Track::Reference> streams = GetConnectedNode()->GetEnabledStreamsAsReferences();
|
||||
QVector<Track::Reference> streams =
|
||||
GetConnectedNode()->GetEnabledStreamsAsReferences();
|
||||
|
||||
// Disable streams that have been disabled
|
||||
if (!enable_video || !enable_audio) {
|
||||
for (int i=0; i<streams.size(); i++) {
|
||||
const Track::Reference& ref = streams.at(i);
|
||||
// Disable streams that have been disabled
|
||||
if (!enable_video || !enable_audio) {
|
||||
for (int i = 0; i < streams.size(); i++) {
|
||||
const Track::Reference &ref = streams.at(i);
|
||||
|
||||
if ((ref.type() == Track::kVideo && !enable_video)
|
||||
|| (ref.type() == Track::kAudio && !enable_audio)) {
|
||||
streams.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ref.type() == Track::kVideo && !enable_video) ||
|
||||
(ref.type() == Track::kAudio && !enable_audio)) {
|
||||
streams.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!streams.isEmpty()) {
|
||||
data_stream << streams << reinterpret_cast<quintptr>(GetConnectedNode());
|
||||
if (!streams.isEmpty()) {
|
||||
data_stream << streams
|
||||
<< reinterpret_cast<quintptr>(GetConnectedNode());
|
||||
|
||||
mimedata->setData(Project::kItemMimeType, encoded_data);
|
||||
drag->setMimeData(mimedata);
|
||||
mimedata->setData(Project::kItemMimeType, encoded_data);
|
||||
drag->setMimeData(mimedata);
|
||||
|
||||
drag->exec();
|
||||
}
|
||||
drag->exec();
|
||||
}
|
||||
}
|
||||
|
||||
void FootageViewerWidget::StartFootageDrag()
|
||||
{
|
||||
StartFootageDragInternal(true, true);
|
||||
StartFootageDragInternal(true, true);
|
||||
}
|
||||
|
||||
void FootageViewerWidget::StartVideoDrag()
|
||||
{
|
||||
StartFootageDragInternal(true, false);
|
||||
StartFootageDragInternal(true, false);
|
||||
}
|
||||
|
||||
void FootageViewerWidget::StartAudioDrag()
|
||||
{
|
||||
StartFootageDragInternal(false, true);
|
||||
StartFootageDragInternal(false, true);
|
||||
}
|
||||
|
||||
void FootageViewerWidget::VideoButtonClicked()
|
||||
{
|
||||
this->SetWaveformMode(kWFAutomatic);
|
||||
this->SetWaveformMode(kWFAutomatic);
|
||||
}
|
||||
|
||||
void FootageViewerWidget::AudioButtonClicked()
|
||||
{
|
||||
this->SetWaveformMode(kWFWaveformOnly);
|
||||
this->SetWaveformMode(kWFWaveformOnly);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,33 +24,32 @@
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "viewer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class FootageViewerWidget : public ViewerWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FootageViewerWidget(QWidget* parent = nullptr);
|
||||
|
||||
void OverrideWorkArea(const TimeRange &r);
|
||||
void ResetWorkArea();
|
||||
class FootageViewerWidget : public ViewerWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FootageViewerWidget(QWidget *parent = nullptr);
|
||||
|
||||
void OverrideWorkArea(const TimeRange &r);
|
||||
void ResetWorkArea();
|
||||
|
||||
private:
|
||||
void StartFootageDragInternal(bool enable_video, bool enable_audio);
|
||||
void StartFootageDragInternal(bool enable_video, bool enable_audio);
|
||||
|
||||
TimelineWorkArea *override_workarea_;
|
||||
TimelineWorkArea *override_workarea_;
|
||||
|
||||
private slots:
|
||||
void StartFootageDrag();
|
||||
void StartFootageDrag();
|
||||
|
||||
void StartVideoDrag();
|
||||
void StartVideoDrag();
|
||||
|
||||
void StartAudioDrag();
|
||||
void StartAudioDrag();
|
||||
|
||||
void VideoButtonClicked();
|
||||
|
||||
void AudioButtonClicked();
|
||||
void VideoButtonClicked();
|
||||
|
||||
void AudioButtonClicked();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+1371
-1176
File diff suppressed because it is too large
Load Diff
+217
-210
@@ -40,381 +40,388 @@
|
||||
#include "widget/timebased/timebasedwidget.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class MulticamWidget;
|
||||
|
||||
/**
|
||||
* @brief An OpenGL-based viewer widget with playback controls (a PlaybackControls widget).
|
||||
*/
|
||||
class ViewerWidget : public TimeBasedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
class ViewerWidget : public TimeBasedWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum WaveformMode {
|
||||
kWFAutomatic,
|
||||
kWFViewerOnly,
|
||||
kWFWaveformOnly,
|
||||
kWFViewerAndWaveform
|
||||
};
|
||||
enum WaveformMode {
|
||||
kWFAutomatic,
|
||||
kWFViewerOnly,
|
||||
kWFWaveformOnly,
|
||||
kWFViewerAndWaveform
|
||||
};
|
||||
|
||||
ViewerWidget(QWidget* parent = nullptr) :
|
||||
ViewerWidget(new ViewerDisplayWidget(), parent)
|
||||
{}
|
||||
ViewerWidget(QWidget *parent = nullptr)
|
||||
: ViewerWidget(new ViewerDisplayWidget(), parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ViewerWidget() override;
|
||||
virtual ~ViewerWidget() override;
|
||||
|
||||
void SetPlaybackControlsEnabled(bool enabled);
|
||||
void SetPlaybackControlsEnabled(bool enabled);
|
||||
|
||||
void SetTimeRulerEnabled(bool enabled);
|
||||
void SetTimeRulerEnabled(bool enabled);
|
||||
|
||||
void TogglePlayPause();
|
||||
void TogglePlayPause();
|
||||
|
||||
bool IsPlaying() const;
|
||||
bool IsPlaying() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Enable or disable the color management menu
|
||||
*
|
||||
* While the Viewer is _always_ color managed, In some contexts, the color management may be controlled from an
|
||||
* external UI making the menu unnecessary.
|
||||
*/
|
||||
void SetColorMenuEnabled(bool enabled);
|
||||
void SetColorMenuEnabled(bool enabled);
|
||||
|
||||
void SetMatrix(const QMatrix4x4& mat);
|
||||
void SetMatrix(const QMatrix4x4 &mat);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Creates a ViewerWindow widget and places it full screen on another screen
|
||||
*
|
||||
* If `screen` is nullptr, the screen will be automatically selected as whichever one contains the mouse cursor.
|
||||
*/
|
||||
void SetFullScreen(QScreen* screen = nullptr);
|
||||
void SetFullScreen(QScreen *screen = nullptr);
|
||||
|
||||
ColorManager* color_manager() const
|
||||
{
|
||||
return display_widget_->color_manager();
|
||||
}
|
||||
ColorManager *color_manager() const
|
||||
{
|
||||
return display_widget_->color_manager();
|
||||
}
|
||||
|
||||
void SetGizmos(Node* node);
|
||||
void SetGizmos(Node *node);
|
||||
|
||||
void StartCapture(TimelineWidget *source, const TimeRange &time, const Track::Reference &track);
|
||||
void StartCapture(TimelineWidget *source, const TimeRange &time,
|
||||
const Track::Reference &track);
|
||||
|
||||
void SetAudioScrubbingEnabled(bool e)
|
||||
{
|
||||
enable_audio_scrubbing_ = e;
|
||||
}
|
||||
void SetAudioScrubbingEnabled(bool e)
|
||||
{
|
||||
enable_audio_scrubbing_ = e;
|
||||
}
|
||||
|
||||
void AddPlaybackDevice(ViewerDisplayWidget *vw)
|
||||
{
|
||||
playback_devices_.push_back(vw);
|
||||
}
|
||||
void AddPlaybackDevice(ViewerDisplayWidget *vw)
|
||||
{
|
||||
playback_devices_.push_back(vw);
|
||||
}
|
||||
|
||||
void SetTimelineSelectedBlocks(const QVector<Block*> &b)
|
||||
{
|
||||
timeline_selected_blocks_ = b;
|
||||
void SetTimelineSelectedBlocks(const QVector<Block *> &b)
|
||||
{
|
||||
timeline_selected_blocks_ = b;
|
||||
|
||||
if (!IsPlaying()) {
|
||||
// If is playing, this will happen by the next frame automatically
|
||||
DetectMulticamNodeNow();
|
||||
UpdateTextureFromNode();
|
||||
}
|
||||
}
|
||||
if (!IsPlaying()) {
|
||||
// If is playing, this will happen by the next frame automatically
|
||||
DetectMulticamNodeNow();
|
||||
UpdateTextureFromNode();
|
||||
}
|
||||
}
|
||||
|
||||
void SetNodeViewSelections(const QVector<Node*> &n)
|
||||
{
|
||||
node_view_selected_ = n;
|
||||
void SetNodeViewSelections(const QVector<Node *> &n)
|
||||
{
|
||||
node_view_selected_ = n;
|
||||
|
||||
if (!IsPlaying()) {
|
||||
// If is playing, this will happen by the next frame automatically
|
||||
DetectMulticamNodeNow();
|
||||
UpdateTextureFromNode();
|
||||
}
|
||||
}
|
||||
if (!IsPlaying()) {
|
||||
// If is playing, this will happen by the next frame automatically
|
||||
DetectMulticamNodeNow();
|
||||
UpdateTextureFromNode();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectMulticamWidget(MulticamWidget *p);
|
||||
void ConnectMulticamWidget(MulticamWidget *p);
|
||||
|
||||
public slots:
|
||||
void Play(bool in_to_out_only);
|
||||
void Play(bool in_to_out_only);
|
||||
|
||||
void Play();
|
||||
void Play();
|
||||
|
||||
void Pause();
|
||||
void Pause();
|
||||
|
||||
void ShuttleLeft();
|
||||
void ShuttleLeft();
|
||||
|
||||
void ShuttleStop();
|
||||
void ShuttleStop();
|
||||
|
||||
void ShuttleRight();
|
||||
void ShuttleRight();
|
||||
|
||||
void SetColorTransform(const ColorTransform& transform);
|
||||
void SetColorTransform(const ColorTransform &transform);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Wrapper for ViewerGLWidget::SetSignalCursorColorEnabled()
|
||||
*/
|
||||
void SetSignalCursorColorEnabled(bool e);
|
||||
void SetSignalCursorColorEnabled(bool e);
|
||||
|
||||
void CacheEntireSequence();
|
||||
void CacheEntireSequence();
|
||||
|
||||
void CacheSequenceInOut();
|
||||
void CacheSequenceInOut();
|
||||
|
||||
void SetViewerResolution(int width, int height);
|
||||
void SetViewerResolution(int width, int height);
|
||||
|
||||
void SetViewerPixelAspect(const rational& ratio);
|
||||
void SetViewerPixelAspect(const rational &ratio);
|
||||
|
||||
void UpdateTextureFromNode();
|
||||
void UpdateTextureFromNode();
|
||||
|
||||
void RequestStartEditingText()
|
||||
{
|
||||
display_widget_->RequestStartEditingText();
|
||||
}
|
||||
void RequestStartEditingText()
|
||||
{
|
||||
display_widget_->RequestStartEditingText();
|
||||
}
|
||||
|
||||
signals:
|
||||
/**
|
||||
/**
|
||||
* @brief Wrapper for ViewerGLWidget::CursorColor()
|
||||
*/
|
||||
void CursorColor(const Color& reference, const Color& display);
|
||||
void CursorColor(const Color &reference, const Color &display);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Signal emitted when a new frame is loaded
|
||||
*/
|
||||
void TextureChanged(TexturePtr t);
|
||||
void TextureChanged(TexturePtr t);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Wrapper for ViewerGLWidget::ColorProcessorChanged()
|
||||
*/
|
||||
void ColorProcessorChanged(ColorProcessorPtr processor);
|
||||
void ColorProcessorChanged(ColorProcessorPtr processor);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Wrapper for ViewerGLWidget::ColorManagerChanged()
|
||||
*/
|
||||
void ColorManagerChanged(ColorManager* color_manager);
|
||||
void ColorManagerChanged(ColorManager *color_manager);
|
||||
|
||||
protected:
|
||||
ViewerWidget(ViewerDisplayWidget *display, QWidget* parent = nullptr);
|
||||
ViewerWidget(ViewerDisplayWidget *display, QWidget *parent = nullptr);
|
||||
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void TimeChangedEvent(const rational &time) override;
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void TimeChangedEvent(const rational &time) override;
|
||||
|
||||
virtual void ConnectNodeEvent(ViewerOutput *) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput *) override;
|
||||
virtual void ConnectedNodeChangeEvent(ViewerOutput *) override;
|
||||
virtual void ConnectedWorkAreaChangeEvent(TimelineWorkArea *) override;
|
||||
virtual void ConnectedMarkersChangeEvent(TimelineMarkerList *) override;
|
||||
virtual void ConnectNodeEvent(ViewerOutput *) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput *) override;
|
||||
virtual void ConnectedNodeChangeEvent(ViewerOutput *) override;
|
||||
virtual void ConnectedWorkAreaChangeEvent(TimelineWorkArea *) override;
|
||||
virtual void ConnectedMarkersChangeEvent(TimelineMarkerList *) override;
|
||||
|
||||
virtual void ScaleChangedEvent(const double& s) override;
|
||||
virtual void ScaleChangedEvent(const double &s) override;
|
||||
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
PlaybackControls* controls_;
|
||||
PlaybackControls *controls_;
|
||||
|
||||
ViewerDisplayWidget* display_widget() const
|
||||
{
|
||||
return display_widget_;
|
||||
}
|
||||
ViewerDisplayWidget *display_widget() const
|
||||
{
|
||||
return display_widget_;
|
||||
}
|
||||
|
||||
void IgnoreNextScrubEvent()
|
||||
{
|
||||
ignore_scrub_++;
|
||||
}
|
||||
void IgnoreNextScrubEvent()
|
||||
{
|
||||
ignore_scrub_++;
|
||||
}
|
||||
|
||||
RenderTicketPtr GetSingleFrame(const rational &t, bool dry = false);
|
||||
RenderTicketPtr GetSingleFrame(const rational &t, bool dry = false);
|
||||
|
||||
void SetWaveformMode(WaveformMode wf);
|
||||
void SetWaveformMode(WaveformMode wf);
|
||||
|
||||
private:
|
||||
int64_t GetTimestamp() const
|
||||
{
|
||||
return Timecode::time_to_timestamp(GetConnectedNode()->GetPlayhead(), timebase(), Timecode::kFloor);
|
||||
}
|
||||
int64_t GetTimestamp() const
|
||||
{
|
||||
return Timecode::time_to_timestamp(GetConnectedNode()->GetPlayhead(),
|
||||
timebase(), Timecode::kFloor);
|
||||
}
|
||||
|
||||
void UpdateTimeInternal(int64_t i);
|
||||
void UpdateTimeInternal(int64_t i);
|
||||
|
||||
void PlayInternal(int speed, bool in_to_out_only);
|
||||
void PlayInternal(int speed, bool in_to_out_only);
|
||||
|
||||
void PauseInternal();
|
||||
void PauseInternal();
|
||||
|
||||
void PushScrubbedAudio();
|
||||
void PushScrubbedAudio();
|
||||
|
||||
void UpdateMinimumScale();
|
||||
void UpdateMinimumScale();
|
||||
|
||||
void SetColorTransform(const ColorTransform& transform, ViewerDisplayWidget* sender);
|
||||
void SetColorTransform(const ColorTransform &transform,
|
||||
ViewerDisplayWidget *sender);
|
||||
|
||||
QString GetCachedFilenameFromTime(const rational& time);
|
||||
QString GetCachedFilenameFromTime(const rational &time);
|
||||
|
||||
bool FrameExistsAtTime(const rational& time);
|
||||
bool FrameExistsAtTime(const rational &time);
|
||||
|
||||
bool ViewerMightBeAStill();
|
||||
bool ViewerMightBeAStill();
|
||||
|
||||
void SetDisplayImage(RenderTicketPtr ticket);
|
||||
void SetDisplayImage(RenderTicketPtr ticket);
|
||||
|
||||
RenderTicketWatcher *RequestNextFrameForQueue(bool increment = true);
|
||||
RenderTicketWatcher *RequestNextFrameForQueue(bool increment = true);
|
||||
|
||||
RenderTicketPtr GetFrame(const rational& t);
|
||||
RenderTicketPtr GetFrame(const rational &t);
|
||||
|
||||
void FinishPlayPreprocess();
|
||||
void FinishPlayPreprocess();
|
||||
|
||||
int DeterminePlaybackQueueSize();
|
||||
int DeterminePlaybackQueueSize();
|
||||
|
||||
static FramePtr DecodeCachedImage(const QString &cache_path, const QUuid &cache_id, const int64_t& time);
|
||||
static FramePtr DecodeCachedImage(const QString &cache_path,
|
||||
const QUuid &cache_id,
|
||||
const int64_t &time);
|
||||
|
||||
static void DecodeCachedImage(RenderTicketPtr ticket, const QString &cache_path, const QUuid &cache_id, const int64_t &time);
|
||||
static void DecodeCachedImage(RenderTicketPtr ticket,
|
||||
const QString &cache_path,
|
||||
const QUuid &cache_id, const int64_t &time);
|
||||
|
||||
bool ShouldForceWaveform() const;
|
||||
bool ShouldForceWaveform() const;
|
||||
|
||||
void SetEmptyImage();
|
||||
void SetEmptyImage();
|
||||
|
||||
void UpdateAutoCacher();
|
||||
void UpdateAutoCacher();
|
||||
|
||||
void DecrementPrequeuedAudio();
|
||||
void DecrementPrequeuedAudio();
|
||||
|
||||
void ArmForRecording();
|
||||
void ArmForRecording();
|
||||
|
||||
void DisarmRecording();
|
||||
void DisarmRecording();
|
||||
|
||||
void CloseAudioProcessor();
|
||||
void CloseAudioProcessor();
|
||||
|
||||
void DetectMulticamNode(const rational &time);
|
||||
void DetectMulticamNode(const rational &time);
|
||||
|
||||
bool IsVideoVisible() const;
|
||||
bool IsVideoVisible() const;
|
||||
|
||||
ViewerSizer* sizer_;
|
||||
ViewerSizer *sizer_;
|
||||
|
||||
int playback_speed_;
|
||||
int playback_speed_;
|
||||
|
||||
rational last_time_;
|
||||
rational last_time_;
|
||||
|
||||
bool color_menu_enabled_;
|
||||
bool color_menu_enabled_;
|
||||
|
||||
bool time_changed_from_timer_;
|
||||
bool time_changed_from_timer_;
|
||||
|
||||
bool play_in_to_out_only_;
|
||||
bool play_in_to_out_only_;
|
||||
|
||||
AudioWaveformView* waveform_view_;
|
||||
AudioWaveformView *waveform_view_;
|
||||
|
||||
QHash<QScreen*, ViewerWindow*> windows_;
|
||||
QHash<QScreen *, ViewerWindow *> windows_;
|
||||
|
||||
ViewerDisplayWidget* display_widget_;
|
||||
ViewerDisplayWidget *display_widget_;
|
||||
|
||||
ViewerDisplayWidget* context_menu_widget_;
|
||||
ViewerDisplayWidget *context_menu_widget_;
|
||||
|
||||
QTimer playback_backup_timer_;
|
||||
QTimer playback_backup_timer_;
|
||||
|
||||
int64_t playback_queue_next_frame_;
|
||||
int64_t dry_run_next_frame_;
|
||||
QVector<ViewerDisplayWidget*> playback_devices_;
|
||||
int64_t playback_queue_next_frame_;
|
||||
int64_t dry_run_next_frame_;
|
||||
QVector<ViewerDisplayWidget *> playback_devices_;
|
||||
|
||||
bool prequeuing_video_;
|
||||
int prequeuing_audio_;
|
||||
bool prequeuing_video_;
|
||||
int prequeuing_audio_;
|
||||
|
||||
QList<RenderTicketWatcher*> nonqueue_watchers_;
|
||||
QList<RenderTicketWatcher *> nonqueue_watchers_;
|
||||
|
||||
rational last_length_;
|
||||
rational last_length_;
|
||||
|
||||
int prequeue_length_;
|
||||
int prequeue_count_;
|
||||
int prequeue_length_;
|
||||
int prequeue_count_;
|
||||
|
||||
QVector<RenderTicketWatcher*> queue_watchers_;
|
||||
QVector<RenderTicketWatcher *> queue_watchers_;
|
||||
|
||||
std::list<RenderTicketWatcher*> audio_playback_queue_;
|
||||
rational audio_playback_queue_time_;
|
||||
AudioProcessor audio_processor_;
|
||||
QByteArray prequeued_audio_;
|
||||
static const rational kAudioPlaybackInterval;
|
||||
std::list<RenderTicketWatcher *> audio_playback_queue_;
|
||||
rational audio_playback_queue_time_;
|
||||
AudioProcessor audio_processor_;
|
||||
QByteArray prequeued_audio_;
|
||||
static const rational kAudioPlaybackInterval;
|
||||
|
||||
static QVector<ViewerWidget*> instances_;
|
||||
static QVector<ViewerWidget *> instances_;
|
||||
|
||||
std::list<RenderTicketWatcher*> audio_scrub_watchers_;
|
||||
std::list<RenderTicketWatcher *> audio_scrub_watchers_;
|
||||
|
||||
bool record_armed_;
|
||||
bool recording_;
|
||||
TimelineWidget *recording_callback_;
|
||||
TimeRange recording_range_;
|
||||
Track::Reference recording_track_;
|
||||
QString recording_filename_;
|
||||
bool record_armed_;
|
||||
bool recording_;
|
||||
TimelineWidget *recording_callback_;
|
||||
TimeRange recording_range_;
|
||||
Track::Reference recording_track_;
|
||||
QString recording_filename_;
|
||||
|
||||
qint64 queue_starved_start_;
|
||||
RenderTicketWatcher *first_requeue_watcher_;
|
||||
qint64 queue_starved_start_;
|
||||
RenderTicketWatcher *first_requeue_watcher_;
|
||||
|
||||
bool enable_audio_scrubbing_;
|
||||
bool enable_audio_scrubbing_;
|
||||
|
||||
WaveformMode waveform_mode_;
|
||||
WaveformMode waveform_mode_;
|
||||
|
||||
QVector<RenderTicketWatcher*> dry_run_watchers_;
|
||||
QVector<RenderTicketWatcher *> dry_run_watchers_;
|
||||
|
||||
int ignore_scrub_;
|
||||
int ignore_scrub_;
|
||||
|
||||
QVector<Block*> timeline_selected_blocks_;
|
||||
QVector<Node*> node_view_selected_;
|
||||
QVector<Block *> timeline_selected_blocks_;
|
||||
QVector<Node *> node_view_selected_;
|
||||
|
||||
MulticamWidget *multicam_panel_;
|
||||
MulticamWidget *multicam_panel_;
|
||||
|
||||
private slots:
|
||||
void PlaybackTimerUpdate();
|
||||
void PlaybackTimerUpdate();
|
||||
|
||||
void LengthChangedSlot(const rational& length);
|
||||
void LengthChangedSlot(const rational &length);
|
||||
|
||||
void InterlacingChangedSlot(VideoParams::Interlacing interlacing);
|
||||
void InterlacingChangedSlot(VideoParams::Interlacing interlacing);
|
||||
|
||||
void UpdateRendererVideoParameters();
|
||||
void UpdateRendererVideoParameters();
|
||||
|
||||
void UpdateRendererAudioParameters();
|
||||
void UpdateRendererAudioParameters();
|
||||
|
||||
void ShowContextMenu(const QPoint& pos);
|
||||
void ShowContextMenu(const QPoint &pos);
|
||||
|
||||
void SetZoomFromMenu(QAction* action);
|
||||
void SetZoomFromMenu(QAction *action);
|
||||
|
||||
void UpdateWaveformViewFromMode();
|
||||
void UpdateWaveformViewFromMode();
|
||||
|
||||
void ContextMenuSetFullScreen(QAction* action);
|
||||
void ContextMenuSetFullScreen(QAction *action);
|
||||
|
||||
void ContextMenuSetPlaybackRes(QAction* action);
|
||||
void ContextMenuSetPlaybackRes(QAction *action);
|
||||
|
||||
void ContextMenuDisableSafeMargins();
|
||||
void ContextMenuDisableSafeMargins();
|
||||
|
||||
void ContextMenuSetSafeMargins();
|
||||
void ContextMenuSetSafeMargins();
|
||||
|
||||
void ContextMenuSetCustomSafeMargins();
|
||||
void ContextMenuSetCustomSafeMargins();
|
||||
|
||||
void WindowAboutToClose();
|
||||
void WindowAboutToClose();
|
||||
|
||||
void RendererGeneratedFrame();
|
||||
void RendererGeneratedFrame();
|
||||
|
||||
void RendererGeneratedFrameForQueue();
|
||||
void RendererGeneratedFrameForQueue();
|
||||
|
||||
void ViewerInvalidatedVideoRange(const olive::TimeRange &range);
|
||||
void ViewerInvalidatedVideoRange(const olive::TimeRange &range);
|
||||
|
||||
void UpdateWaveformModeFromMenu(QAction *a);
|
||||
void UpdateWaveformModeFromMenu(QAction *a);
|
||||
|
||||
void DragEntered(QDragEnterEvent* event);
|
||||
void DragEntered(QDragEnterEvent *event);
|
||||
|
||||
void Dropped(QDropEvent* event);
|
||||
void Dropped(QDropEvent *event);
|
||||
|
||||
void QueueNextAudioBuffer();
|
||||
void QueueNextAudioBuffer();
|
||||
|
||||
void ReceivedAudioBufferForPlayback();
|
||||
void ReceivedAudioBufferForPlayback();
|
||||
|
||||
void ReceivedAudioBufferForScrubbing();
|
||||
void ReceivedAudioBufferForScrubbing();
|
||||
|
||||
void QueueStarved();
|
||||
void QueueNoLongerStarved();
|
||||
void QueueStarved();
|
||||
void QueueNoLongerStarved();
|
||||
|
||||
void ForceRequeueFromCurrentTime();
|
||||
void ForceRequeueFromCurrentTime();
|
||||
|
||||
void UpdateAudioProcessor();
|
||||
void UpdateAudioProcessor();
|
||||
|
||||
void CreateAddableAt(const QRectF &f);
|
||||
void CreateAddableAt(const QRectF &f);
|
||||
|
||||
void HandleFirstRequeueDestroy();
|
||||
void HandleFirstRequeueDestroy();
|
||||
|
||||
void ShowSubtitleProperties();
|
||||
void ShowSubtitleProperties();
|
||||
|
||||
void DryRunFinished();
|
||||
void DryRunFinished();
|
||||
|
||||
void RequestNextDryRun();
|
||||
void RequestNextDryRun();
|
||||
|
||||
void SaveFrameAsImage();
|
||||
|
||||
void DetectMulticamNodeNow();
|
||||
void SaveFrameAsImage();
|
||||
|
||||
void DetectMulticamNodeNow();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+1022
-934
File diff suppressed because it is too large
Load Diff
+234
-217
@@ -37,7 +37,8 @@
|
||||
#include "widget/manageddisplay/manageddisplay.h"
|
||||
#include "widget/timetarget/timetarget.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The inner display/rendering widget of a Viewer class.
|
||||
@@ -54,393 +55,409 @@ namespace olive {
|
||||
* the same texture object, use SetTexture() since it will nearly always be faster to just set it than to check *and*
|
||||
* set it.
|
||||
*/
|
||||
class ViewerDisplayWidget : public ManagedDisplayWidget, public TimeTargetObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class ViewerDisplayWidget : public ManagedDisplayWidget,
|
||||
public TimeTargetObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
/**
|
||||
* @brief ViewerGLWidget Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent.
|
||||
*/
|
||||
ViewerDisplayWidget(QWidget* parent = nullptr);
|
||||
ViewerDisplayWidget(QWidget *parent = nullptr);
|
||||
|
||||
virtual ~ViewerDisplayWidget() override;
|
||||
virtual ~ViewerDisplayWidget() override;
|
||||
|
||||
const ViewerSafeMarginInfo& GetSafeMargin() const;
|
||||
void SetSafeMargins(const ViewerSafeMarginInfo& safe_margin);
|
||||
const ViewerSafeMarginInfo &GetSafeMargin() const;
|
||||
void SetSafeMargins(const ViewerSafeMarginInfo &safe_margin);
|
||||
|
||||
void SetGizmos(Node* node);
|
||||
void SetGizmos(Node *node);
|
||||
|
||||
const VideoParams &GetVideoParams() const { return gizmo_params_; }
|
||||
void SetVideoParams(const VideoParams ¶ms);
|
||||
const VideoParams &GetVideoParams() const
|
||||
{
|
||||
return gizmo_params_;
|
||||
}
|
||||
void SetVideoParams(const VideoParams ¶ms);
|
||||
|
||||
const AudioParams &GetAudioParams() const { return gizmo_audio_params_; }
|
||||
void SetAudioParams(const AudioParams &p);
|
||||
const AudioParams &GetAudioParams() const
|
||||
{
|
||||
return gizmo_audio_params_;
|
||||
}
|
||||
void SetAudioParams(const AudioParams &p);
|
||||
|
||||
void SetTime(const rational& time);
|
||||
void SetSubtitleTracks(Sequence *list);
|
||||
void SetTime(const rational &time);
|
||||
void SetSubtitleTracks(Sequence *list);
|
||||
|
||||
void SetShowWidgetBackground(bool e)
|
||||
{
|
||||
show_widget_background_ = e;
|
||||
update();
|
||||
}
|
||||
void SetShowWidgetBackground(bool e)
|
||||
{
|
||||
show_widget_background_ = e;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Transform a point from viewer space to the buffer space.
|
||||
* Multiplies by the inverted transform matrix to undo the scaling and translation.
|
||||
*/
|
||||
QPointF TransformViewerSpaceToBufferSpace(const QPointF &pos);
|
||||
QPointF TransformViewerSpaceToBufferSpace(const QPointF &pos);
|
||||
|
||||
bool IsDeinterlacing() const
|
||||
{
|
||||
return deinterlace_;
|
||||
}
|
||||
bool IsDeinterlacing() const
|
||||
{
|
||||
return deinterlace_;
|
||||
}
|
||||
|
||||
void ResetFPSTimer();
|
||||
void ResetFPSTimer();
|
||||
|
||||
bool GetShowFPS() const
|
||||
{
|
||||
return show_fps_;
|
||||
}
|
||||
bool GetShowFPS() const
|
||||
{
|
||||
return show_fps_;
|
||||
}
|
||||
|
||||
bool GetShowSubtitles() const { return show_subtitles_; }
|
||||
void SetShowSubtitles(bool e) { show_subtitles_ = e; update(); }
|
||||
bool GetShowSubtitles() const
|
||||
{
|
||||
return show_subtitles_;
|
||||
}
|
||||
void SetShowSubtitles(bool e)
|
||||
{
|
||||
show_subtitles_ = e;
|
||||
update();
|
||||
}
|
||||
|
||||
void IncrementSkippedFrames();
|
||||
void IncrementSkippedFrames();
|
||||
|
||||
void IncrementFrameCount()
|
||||
{
|
||||
fps_timer_update_count_++;
|
||||
}
|
||||
void IncrementFrameCount()
|
||||
{
|
||||
fps_timer_update_count_++;
|
||||
}
|
||||
|
||||
TexturePtr GetCurrentTexture() const
|
||||
{
|
||||
return texture_;
|
||||
}
|
||||
TexturePtr GetCurrentTexture() const
|
||||
{
|
||||
return texture_;
|
||||
}
|
||||
|
||||
void Play(const int64_t &start_timestamp, const int &playback_speed, const rational &timebase, bool start_updating);
|
||||
void Play(const int64_t &start_timestamp, const int &playback_speed,
|
||||
const rational &timebase, bool start_updating);
|
||||
|
||||
void Pause();
|
||||
void Pause();
|
||||
|
||||
ViewerQueue* queue()
|
||||
{
|
||||
return &queue_;
|
||||
}
|
||||
ViewerQueue *queue()
|
||||
{
|
||||
return &queue_;
|
||||
}
|
||||
|
||||
ViewerPlaybackTimer *timer()
|
||||
{
|
||||
return &timer_;
|
||||
}
|
||||
ViewerPlaybackTimer *timer()
|
||||
{
|
||||
return &timer_;
|
||||
}
|
||||
|
||||
QPointF ScreenToScenePoint(const QPoint &p);
|
||||
QPointF ScreenToScenePoint(const QPoint &p);
|
||||
|
||||
virtual bool eventFilter(QObject *o, QEvent *e) override;
|
||||
virtual bool eventFilter(QObject *o, QEvent *e) override;
|
||||
|
||||
public slots:
|
||||
/**
|
||||
/**
|
||||
* @brief Set the transformation matrix to draw with
|
||||
*
|
||||
* Set this if you want the drawing to pass through some sort of transform (most of the time you won't want this).
|
||||
*/
|
||||
void SetMatrixTranslate(const QMatrix4x4& mat);
|
||||
void SetMatrixTranslate(const QMatrix4x4 &mat);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set the scale matrix.
|
||||
*/
|
||||
void SetMatrixZoom(const QMatrix4x4& mat);
|
||||
void SetMatrixZoom(const QMatrix4x4 &mat);
|
||||
|
||||
void SetMatrixCrop(const QMatrix4x4& mat);
|
||||
void SetMatrixCrop(const QMatrix4x4 &mat);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Enables or disables whether this color at the cursor should be emitted
|
||||
*
|
||||
* Since tracking the mouse every movement, reading pixels, and doing color transforms are processor intensive, we
|
||||
* have an option for it. Ideally, this should be connected to a PixelSamplerPanel::visibilityChanged signal so that
|
||||
* it can automatically be enabled when the user is pixel sampling and disabled for optimization when they're not.
|
||||
*/
|
||||
void SetSignalCursorColorEnabled(bool e);
|
||||
void SetSignalCursorColorEnabled(bool e);
|
||||
|
||||
void SetImage(const QVariant &buffer);
|
||||
void SetImage(const QVariant &buffer);
|
||||
|
||||
void SetBlank();
|
||||
void SetBlank();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Changes the pointer type if the tool is changed to the hand tool. Otherwise resets the pointer to it's
|
||||
* normal type.
|
||||
*/
|
||||
void UpdateCursor();
|
||||
void UpdateCursor();
|
||||
|
||||
void ToolChanged();
|
||||
void ToolChanged();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Enables/disables a basic deinterlace on the viewer
|
||||
*/
|
||||
void SetDeinterlacing(bool e);
|
||||
void SetDeinterlacing(bool e);
|
||||
|
||||
void SetShowFPS(bool e);
|
||||
void SetShowFPS(bool e);
|
||||
|
||||
void RequestStartEditingText();
|
||||
void RequestStartEditingText();
|
||||
|
||||
signals:
|
||||
/**
|
||||
/**
|
||||
* @brief Signal emitted when the user starts dragging from the viewer
|
||||
*/
|
||||
void DragStarted(const QPoint &p);
|
||||
void DragStarted(const QPoint &p);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Signal emitted when a hand drag starts
|
||||
*/
|
||||
void HandDragStarted();
|
||||
void HandDragStarted();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Signal emitted when a hand drag moves
|
||||
*/
|
||||
void HandDragMoved(int x, int y);
|
||||
void HandDragMoved(int x, int y);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Signal emitted when a hand drag ends
|
||||
*/
|
||||
void HandDragEnded();
|
||||
void HandDragEnded();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Signal emitted when cursor color is enabled and the user's mouse position changes
|
||||
*/
|
||||
void CursorColor(const Color& reference, const Color& display);
|
||||
void CursorColor(const Color &reference, const Color &display);
|
||||
|
||||
void DragEntered(QDragEnterEvent* event);
|
||||
void DragEntered(QDragEnterEvent *event);
|
||||
|
||||
void DragLeft(QDragLeaveEvent* event);
|
||||
void DragLeft(QDragLeaveEvent *event);
|
||||
|
||||
void Dropped(QDropEvent* event);
|
||||
void Dropped(QDropEvent *event);
|
||||
|
||||
void TextureChanged(TexturePtr texture);
|
||||
void TextureChanged(TexturePtr texture);
|
||||
|
||||
void QueueStarved();
|
||||
void QueueStarved();
|
||||
|
||||
void QueueNoLongerStarved();
|
||||
void QueueNoLongerStarved();
|
||||
|
||||
void CreateAddableAt(const QRectF &rect);
|
||||
void CreateAddableAt(const QRectF &rect);
|
||||
|
||||
protected:
|
||||
QTransform GenerateWorldTransform();
|
||||
QTransform GenerateWorldTransform();
|
||||
|
||||
QTransform GenerateDisplayTransform();
|
||||
QTransform GenerateDisplayTransform();
|
||||
|
||||
QTransform GenerateGizmoTransform(NodeTraverser >, const TimeRange &range);
|
||||
QTransform GenerateGizmoTransform()
|
||||
{
|
||||
NodeTraverser t;
|
||||
t.SetCacheVideoParams(gizmo_params_);
|
||||
return GenerateGizmoTransform(t, GenerateGizmoTime());
|
||||
}
|
||||
QTransform GenerateGizmoTransform(NodeTraverser >,
|
||||
const TimeRange &range);
|
||||
QTransform GenerateGizmoTransform()
|
||||
{
|
||||
NodeTraverser t;
|
||||
t.SetCacheVideoParams(gizmo_params_);
|
||||
return GenerateGizmoTransform(t, GenerateGizmoTime());
|
||||
}
|
||||
|
||||
TimeRange GenerateGizmoTime()
|
||||
{
|
||||
rational node_time = GetGizmoTime();
|
||||
return TimeRange(node_time, node_time + gizmo_params_.frame_rate_as_time_base());
|
||||
}
|
||||
TimeRange GenerateGizmoTime()
|
||||
{
|
||||
rational node_time = GetGizmoTime();
|
||||
return TimeRange(node_time,
|
||||
node_time + gizmo_params_.frame_rate_as_time_base());
|
||||
}
|
||||
|
||||
virtual TexturePtr LoadCustomTextureFromFrame(const QVariant &v)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual TexturePtr LoadCustomTextureFromFrame(const QVariant &v)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected slots:
|
||||
/**
|
||||
/**
|
||||
* @brief Paint function to display the texture (received in SetTexture()) on screen.
|
||||
*
|
||||
* Simple OpenGL drawing function for painting the texture on screen. Standardized around OpenGL ES 3.2 Core.
|
||||
*/
|
||||
virtual void OnPaint() override;
|
||||
virtual void OnPaint() override;
|
||||
|
||||
virtual void OnDestroy() override;
|
||||
virtual void OnDestroy() override;
|
||||
|
||||
private:
|
||||
QPointF GetTexturePosition(const QPoint& screen_pos);
|
||||
QPointF GetTexturePosition(const QSize& size);
|
||||
QPointF GetTexturePosition(const double& x, const double& y);
|
||||
QPointF GetTexturePosition(const QPoint &screen_pos);
|
||||
QPointF GetTexturePosition(const QSize &size);
|
||||
QPointF GetTexturePosition(const double &x, const double &y);
|
||||
|
||||
static void DrawTextWithCrudeShadow(QPainter* painter, const QRect& rect, const QString& text, const QTextOption &opt = QTextOption());
|
||||
static void DrawTextWithCrudeShadow(QPainter *painter, const QRect &rect,
|
||||
const QString &text,
|
||||
const QTextOption &opt = QTextOption());
|
||||
|
||||
rational GetGizmoTime();
|
||||
rational GetGizmoTime();
|
||||
|
||||
bool IsHandDrag(QMouseEvent* event) const;
|
||||
bool IsHandDrag(QMouseEvent *event) const;
|
||||
|
||||
void UpdateMatrix();
|
||||
void UpdateMatrix();
|
||||
|
||||
NodeGizmo *TryGizmoPress(const NodeValueRow &row, const QPointF &p);
|
||||
NodeGizmo *TryGizmoPress(const NodeValueRow &row, const QPointF &p);
|
||||
|
||||
void OpenTextGizmo(TextGizmo *text, QMouseEvent *event = nullptr);
|
||||
void OpenTextGizmo(TextGizmo *text, QMouseEvent *event = nullptr);
|
||||
|
||||
bool OnMousePress(QMouseEvent *e);
|
||||
bool OnMouseMove(QMouseEvent *e);
|
||||
bool OnMouseRelease(QMouseEvent *e);
|
||||
bool OnMouseDoubleClick(QMouseEvent *e);
|
||||
bool OnMousePress(QMouseEvent *e);
|
||||
bool OnMouseMove(QMouseEvent *e);
|
||||
bool OnMouseRelease(QMouseEvent *e);
|
||||
bool OnMouseDoubleClick(QMouseEvent *e);
|
||||
|
||||
bool OnKeyPress(QKeyEvent *e);
|
||||
bool OnKeyRelease(QKeyEvent *e);
|
||||
bool OnKeyPress(QKeyEvent *e);
|
||||
bool OnKeyRelease(QKeyEvent *e);
|
||||
|
||||
void EmitColorAtCursor(QMouseEvent* e);
|
||||
void EmitColorAtCursor(QMouseEvent *e);
|
||||
|
||||
void DrawSubtitleTracks();
|
||||
void DrawSubtitleTracks();
|
||||
|
||||
QPointF GetVirtualPosForTextEdit(const QPointF &p)
|
||||
{
|
||||
return text_transform_inverted_.map(p) - text_edit_pos_;
|
||||
}
|
||||
QPointF GetVirtualPosForTextEdit(const QPointF &p)
|
||||
{
|
||||
return text_transform_inverted_.map(p) - text_edit_pos_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ForwardDragEventToTextEdit(T *event);
|
||||
template <typename T> void ForwardDragEventToTextEdit(T *event);
|
||||
|
||||
bool ForwardMouseEventToTextEdit(QMouseEvent *event, bool check_if_outside = false);
|
||||
bool ForwardEventToTextEdit(QEvent *event);
|
||||
bool ForwardMouseEventToTextEdit(QMouseEvent *event,
|
||||
bool check_if_outside = false);
|
||||
bool ForwardEventToTextEdit(QEvent *event);
|
||||
|
||||
QPointF AdjustPosByVAlign(QPointF p);
|
||||
QPointF AdjustPosByVAlign(QPointF p);
|
||||
|
||||
void CloseTextEditor();
|
||||
void CloseTextEditor();
|
||||
|
||||
void GenerateGizmoTransforms();
|
||||
void GenerateGizmoTransforms();
|
||||
|
||||
void DrawBlank(const VideoParams &device_params);
|
||||
void DrawBlank(const VideoParams &device_params);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL().
|
||||
*/
|
||||
TexturePtr texture_;
|
||||
TexturePtr texture_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Internal texture to deinterlace to
|
||||
*/
|
||||
TexturePtr deinterlace_texture_;
|
||||
TexturePtr deinterlace_texture_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Deinterlace shader
|
||||
*/
|
||||
QVariant deinterlace_shader_;
|
||||
QVariant deinterlace_shader_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Blank shader
|
||||
*/
|
||||
QVariant blank_shader_;
|
||||
QVariant blank_shader_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Translation only matrix (defaults to identity).
|
||||
*/
|
||||
QMatrix4x4 translate_matrix_;
|
||||
QMatrix4x4 translate_matrix_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Scale only matrix.
|
||||
*/
|
||||
QMatrix4x4 scale_matrix_;
|
||||
QMatrix4x4 scale_matrix_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Crop only matrix
|
||||
*/
|
||||
QMatrix4x4 crop_matrix_;
|
||||
QMatrix4x4 crop_matrix_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Cached result of translate_matrix_ and scale_matrix_ multiplied
|
||||
*/
|
||||
QMatrix4x4 combined_matrix_;
|
||||
QMatrix4x4 combined_matrix_flipped_;
|
||||
QMatrix4x4 combined_matrix_;
|
||||
QMatrix4x4 combined_matrix_flipped_;
|
||||
|
||||
bool signal_cursor_color_;
|
||||
bool signal_cursor_color_;
|
||||
|
||||
ViewerSafeMarginInfo safe_margin_;
|
||||
ViewerSafeMarginInfo safe_margin_;
|
||||
|
||||
Node* gizmos_;
|
||||
NodeValueRow gizmo_db_;
|
||||
VideoParams gizmo_params_;
|
||||
AudioParams gizmo_audio_params_;
|
||||
QPoint gizmo_start_drag_;
|
||||
QPoint gizmo_last_drag_;
|
||||
TimeRange gizmo_draw_time_;
|
||||
NodeGizmo *current_gizmo_;
|
||||
bool gizmo_drag_started_;
|
||||
QTransform gizmo_last_draw_transform_;
|
||||
QTransform gizmo_last_draw_transform_inverted_;
|
||||
Node *gizmos_;
|
||||
NodeValueRow gizmo_db_;
|
||||
VideoParams gizmo_params_;
|
||||
AudioParams gizmo_audio_params_;
|
||||
QPoint gizmo_start_drag_;
|
||||
QPoint gizmo_last_drag_;
|
||||
TimeRange gizmo_draw_time_;
|
||||
NodeGizmo *current_gizmo_;
|
||||
bool gizmo_drag_started_;
|
||||
QTransform gizmo_last_draw_transform_;
|
||||
QTransform gizmo_last_draw_transform_inverted_;
|
||||
|
||||
bool show_subtitles_;
|
||||
Sequence *subtitle_tracks_;
|
||||
bool show_subtitles_;
|
||||
Sequence *subtitle_tracks_;
|
||||
|
||||
rational time_;
|
||||
rational time_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Position of mouse to calculate delta from.
|
||||
*/
|
||||
QPoint hand_last_drag_pos_;
|
||||
bool hand_dragging_;
|
||||
QPoint hand_last_drag_pos_;
|
||||
bool hand_dragging_;
|
||||
|
||||
bool deinterlace_;
|
||||
bool deinterlace_;
|
||||
|
||||
qint64 fps_timer_start_;
|
||||
int fps_timer_update_count_;
|
||||
qint64 fps_timer_start_;
|
||||
int fps_timer_update_count_;
|
||||
|
||||
bool show_fps_;
|
||||
int frames_skipped_;
|
||||
bool show_fps_;
|
||||
int frames_skipped_;
|
||||
|
||||
QVector<double> frame_rate_averages_;
|
||||
int frame_rate_average_count_;
|
||||
QVector<double> frame_rate_averages_;
|
||||
int frame_rate_average_count_;
|
||||
|
||||
bool show_widget_background_;
|
||||
bool show_widget_background_;
|
||||
|
||||
QVariant load_frame_;
|
||||
QVariant load_frame_;
|
||||
|
||||
int playback_speed_;
|
||||
int playback_speed_;
|
||||
|
||||
enum PushMode {
|
||||
/// New frame to push to internal texture
|
||||
kPushFrame,
|
||||
enum PushMode {
|
||||
/// New frame to push to internal texture
|
||||
kPushFrame,
|
||||
|
||||
/// Internal texture reference is up to date, keep showing it
|
||||
kPushUnnecessary,
|
||||
/// Internal texture reference is up to date, keep showing it
|
||||
kPushUnnecessary,
|
||||
|
||||
/// Draw blank/black screen
|
||||
kPushBlank,
|
||||
/// Draw blank/black screen
|
||||
kPushBlank,
|
||||
|
||||
/// Draw nothing (not even a black frame)
|
||||
kPushNull,
|
||||
};
|
||||
/// Draw nothing (not even a black frame)
|
||||
kPushNull,
|
||||
};
|
||||
|
||||
PushMode push_mode_;
|
||||
PushMode push_mode_;
|
||||
|
||||
// Playback
|
||||
ViewerQueue queue_;
|
||||
// Playback
|
||||
ViewerQueue queue_;
|
||||
|
||||
ViewerPlaybackTimer timer_;
|
||||
ViewerPlaybackTimer timer_;
|
||||
|
||||
rational playback_timebase_;
|
||||
rational playback_timebase_;
|
||||
|
||||
bool add_band_;
|
||||
QPoint add_band_start_;
|
||||
QPoint add_band_end_;
|
||||
bool add_band_;
|
||||
QPoint add_band_start_;
|
||||
QPoint add_band_end_;
|
||||
|
||||
bool queue_starved_;
|
||||
bool queue_starved_;
|
||||
|
||||
TextGizmo *active_text_gizmo_;
|
||||
QPointF text_edit_pos_;
|
||||
ViewerTextEditor *text_edit_;
|
||||
ViewerTextEditorToolBar *text_toolbar_;
|
||||
QTransform text_transform_;
|
||||
QTransform text_transform_inverted_;
|
||||
TextGizmo *active_text_gizmo_;
|
||||
QPointF text_edit_pos_;
|
||||
ViewerTextEditor *text_edit_;
|
||||
ViewerTextEditorToolBar *text_toolbar_;
|
||||
QTransform text_transform_;
|
||||
QTransform text_transform_inverted_;
|
||||
|
||||
private slots:
|
||||
void UpdateFromQueue();
|
||||
void UpdateFromQueue();
|
||||
|
||||
void TextEditChanged();
|
||||
void TextEditDestroyed();
|
||||
void TextEditChanged();
|
||||
void TextEditDestroyed();
|
||||
|
||||
void SubtitlesChanged(const TimeRange &r);
|
||||
|
||||
void FocusChanged(QWidget *old, QWidget *now);
|
||||
|
||||
QRectF UpdateActiveTextGizmoSize();
|
||||
void SubtitlesChanged(const TimeRange &r);
|
||||
|
||||
void FocusChanged(QWidget *old, QWidget *now);
|
||||
|
||||
QRectF UpdateActiveTextGizmoSize();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,23 +23,27 @@
|
||||
#include <QDateTime>
|
||||
#include <QtMath>
|
||||
|
||||
namespace olive {
|
||||
|
||||
void ViewerPlaybackTimer::Start(const int64_t &start_timestamp, const int &playback_speed, const double &timebase)
|
||||
namespace olive
|
||||
{
|
||||
start_msec_ = QDateTime::currentMSecsSinceEpoch();
|
||||
start_timestamp_ = start_timestamp;
|
||||
playback_speed_ = playback_speed;
|
||||
timebase_ = timebase * 1000;
|
||||
|
||||
void ViewerPlaybackTimer::Start(const int64_t &start_timestamp,
|
||||
const int &playback_speed,
|
||||
const double &timebase)
|
||||
{
|
||||
start_msec_ = QDateTime::currentMSecsSinceEpoch();
|
||||
start_timestamp_ = start_timestamp;
|
||||
playback_speed_ = playback_speed;
|
||||
timebase_ = timebase * 1000;
|
||||
}
|
||||
|
||||
int64_t ViewerPlaybackTimer::GetTimestampNow() const
|
||||
{
|
||||
int64_t real_time = QDateTime::currentMSecsSinceEpoch() - start_msec_;
|
||||
int64_t real_time = QDateTime::currentMSecsSinceEpoch() - start_msec_;
|
||||
|
||||
int64_t frames_since_start = qFloor(static_cast<double>(real_time) / (timebase_));
|
||||
int64_t frames_since_start =
|
||||
qFloor(static_cast<double>(real_time) / (timebase_));
|
||||
|
||||
return start_timestamp_ + frames_since_start * playback_speed_;
|
||||
return start_timestamp_ + frames_since_start * playback_speed_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,22 +25,23 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class ViewerPlaybackTimer {
|
||||
public:
|
||||
void Start(const int64_t& start_timestamp, const int& playback_speed, const double& timebase);
|
||||
void Start(const int64_t &start_timestamp, const int &playback_speed,
|
||||
const double &timebase);
|
||||
|
||||
int64_t GetTimestampNow() const;
|
||||
int64_t GetTimestampNow() const;
|
||||
|
||||
private:
|
||||
qint64 start_msec_;
|
||||
int64_t start_timestamp_;
|
||||
qint64 start_msec_;
|
||||
int64_t start_timestamp_;
|
||||
|
||||
int playback_speed_;
|
||||
|
||||
double timebase_;
|
||||
int playback_speed_;
|
||||
|
||||
double timebase_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
#include <QtDBus/QtDBus>
|
||||
#endif
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
IOPMAssertionID assertionID = 0;
|
||||
@@ -21,53 +22,59 @@ IOPMAssertionID assertionID = 0;
|
||||
void PreventSleep(bool on)
|
||||
{
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
SetThreadExecutionState(on ? ES_DISPLAY_REQUIRED | ES_CONTINUOUS : ES_CONTINUOUS);
|
||||
SetThreadExecutionState(on ? ES_DISPLAY_REQUIRED | ES_CONTINUOUS :
|
||||
ES_CONTINUOUS);
|
||||
#elif defined(Q_OS_MAC)
|
||||
if (on) {
|
||||
static const CFStringRef reasonForActivity = CFSTR("Video Playback");
|
||||
if (on) {
|
||||
static const CFStringRef reasonForActivity = CFSTR("Video Playback");
|
||||
|
||||
IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
|
||||
kIOPMAssertionLevelOn, reasonForActivity, &assertionID);
|
||||
} else if (assertionID) {
|
||||
IOPMAssertionRelease(assertionID);
|
||||
assertionID = 0;
|
||||
}
|
||||
IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
|
||||
kIOPMAssertionLevelOn, reasonForActivity,
|
||||
&assertionID);
|
||||
} else if (assertionID) {
|
||||
IOPMAssertionRelease(assertionID);
|
||||
assertionID = 0;
|
||||
}
|
||||
#elif defined(Q_OS_LINUX)
|
||||
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||
if(bus.isConnected()) {
|
||||
static const QStringList sleep_services = {
|
||||
QStringLiteral("org.freedesktop.ScreenSaver"),
|
||||
//QStringLiteral("org.gnome.SessionManager")
|
||||
};
|
||||
static const QStringList sleep_paths = {
|
||||
QStringLiteral("/org/freedesktop/ScreenSaver"),
|
||||
//QStringLiteral("/org/gnome/SessionManager")
|
||||
};
|
||||
static QVector<uint> sleep_cookies;
|
||||
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||
if (bus.isConnected()) {
|
||||
static const QStringList sleep_services = {
|
||||
QStringLiteral("org.freedesktop.ScreenSaver"),
|
||||
//QStringLiteral("org.gnome.SessionManager")
|
||||
};
|
||||
static const QStringList sleep_paths = {
|
||||
QStringLiteral("/org/freedesktop/ScreenSaver"),
|
||||
//QStringLiteral("/org/gnome/SessionManager")
|
||||
};
|
||||
static QVector<uint> sleep_cookies;
|
||||
|
||||
// Initialize vector to 0
|
||||
if (sleep_cookies.isEmpty()) {
|
||||
sleep_cookies.resize(sleep_services.size());
|
||||
sleep_cookies.fill(0);
|
||||
}
|
||||
// Initialize vector to 0
|
||||
if (sleep_cookies.isEmpty()) {
|
||||
sleep_cookies.resize(sleep_services.size());
|
||||
sleep_cookies.fill(0);
|
||||
}
|
||||
|
||||
for (int i=0; i<sleep_cookies.size(); i++) {
|
||||
QDBusInterface interface(sleep_services.at(i), sleep_paths.at(i), sleep_services.at(i), bus);
|
||||
if (interface.isValid()) {
|
||||
QDBusReply<uint> reply;
|
||||
for (int i = 0; i < sleep_cookies.size(); i++) {
|
||||
QDBusInterface interface(sleep_services.at(i), sleep_paths.at(i),
|
||||
sleep_services.at(i), bus);
|
||||
if (interface.isValid()) {
|
||||
QDBusReply<uint> reply;
|
||||
|
||||
if (on) {
|
||||
reply = interface.call(QStringLiteral("Inhibit"), QStringLiteral("Olive Video Editor"), QStringLiteral("Video Playback"));
|
||||
} else {
|
||||
reply = interface.call(QStringLiteral("UnInhibit"), sleep_cookies.at(i));
|
||||
}
|
||||
if (on) {
|
||||
reply = interface.call(QStringLiteral("Inhibit"),
|
||||
QStringLiteral("Olive Video Editor"),
|
||||
QStringLiteral("Video Playback"));
|
||||
} else {
|
||||
reply = interface.call(QStringLiteral("UnInhibit"),
|
||||
sleep_cookies.at(i));
|
||||
}
|
||||
|
||||
if (reply.isValid()) {
|
||||
sleep_cookies[i] = reply.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reply.isValid()) {
|
||||
sleep_cookies[i] = reply.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef VIEWERPREVENTSLEEP_H
|
||||
#define VIEWERPREVENTSLEEP_H
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
void PreventSleep(bool on);
|
||||
|
||||
|
||||
@@ -23,41 +23,41 @@
|
||||
|
||||
#include "codec/frame.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
struct ViewerPlaybackFrame
|
||||
namespace olive
|
||||
{
|
||||
rational timestamp;
|
||||
QVariant frame;
|
||||
|
||||
struct ViewerPlaybackFrame {
|
||||
rational timestamp;
|
||||
QVariant frame;
|
||||
};
|
||||
|
||||
class ViewerQueue : public std::list<ViewerPlaybackFrame>
|
||||
{
|
||||
class ViewerQueue : public std::list<ViewerPlaybackFrame> {
|
||||
public:
|
||||
ViewerQueue() = default;
|
||||
ViewerQueue() = default;
|
||||
|
||||
void AppendTimewise(const ViewerPlaybackFrame& f, int playback_speed)
|
||||
{
|
||||
if (this->empty() || (this->back().timestamp < f.timestamp) == (playback_speed > 0)) {
|
||||
this->push_back(f);
|
||||
} else {
|
||||
for (auto i=this->begin(); i!=this->end(); i++) {
|
||||
if ((i->timestamp > f.timestamp) == (playback_speed > 0)) {
|
||||
this->insert(i, f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PurgeBefore(const rational &time, int playback_speed)
|
||||
{
|
||||
while (!this->empty()
|
||||
&& ((playback_speed > 0 && this->front().timestamp < time) || (playback_speed < 0 && this->front().timestamp > time))) {
|
||||
this->pop_front();
|
||||
}
|
||||
}
|
||||
void AppendTimewise(const ViewerPlaybackFrame &f, int playback_speed)
|
||||
{
|
||||
if (this->empty() ||
|
||||
(this->back().timestamp < f.timestamp) == (playback_speed > 0)) {
|
||||
this->push_back(f);
|
||||
} else {
|
||||
for (auto i = this->begin(); i != this->end(); i++) {
|
||||
if ((i->timestamp > f.timestamp) == (playback_speed > 0)) {
|
||||
this->insert(i, f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PurgeBefore(const rational &time, int playback_speed)
|
||||
{
|
||||
while (!this->empty() &&
|
||||
((playback_speed > 0 && this->front().timestamp < time) ||
|
||||
(playback_speed < 0 && this->front().timestamp > time))) {
|
||||
this->pop_front();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,49 +25,51 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class ViewerSafeMarginInfo {
|
||||
public:
|
||||
ViewerSafeMarginInfo() :
|
||||
enabled_(false)
|
||||
{
|
||||
}
|
||||
ViewerSafeMarginInfo()
|
||||
: enabled_(false)
|
||||
{
|
||||
}
|
||||
|
||||
ViewerSafeMarginInfo(bool enabled, double ratio = 0) :
|
||||
enabled_(enabled),
|
||||
ratio_(ratio)
|
||||
{
|
||||
}
|
||||
ViewerSafeMarginInfo(bool enabled, double ratio = 0)
|
||||
: enabled_(enabled)
|
||||
, ratio_(ratio)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_enabled() const
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
bool is_enabled() const
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
bool custom_ratio() const
|
||||
{
|
||||
return (ratio_ > 0);
|
||||
}
|
||||
bool custom_ratio() const
|
||||
{
|
||||
return (ratio_ > 0);
|
||||
}
|
||||
|
||||
double ratio() const
|
||||
{
|
||||
return ratio_;
|
||||
}
|
||||
double ratio() const
|
||||
{
|
||||
return ratio_;
|
||||
}
|
||||
|
||||
bool operator==(const ViewerSafeMarginInfo& rhs) const {
|
||||
return (enabled_ == rhs.enabled_ && qFuzzyCompare(ratio_, rhs.ratio_));
|
||||
}
|
||||
bool operator==(const ViewerSafeMarginInfo &rhs) const
|
||||
{
|
||||
return (enabled_ == rhs.enabled_ && qFuzzyCompare(ratio_, rhs.ratio_));
|
||||
}
|
||||
|
||||
bool operator!=(const ViewerSafeMarginInfo& rhs) const {
|
||||
return (enabled_ != rhs.enabled_ || !qFuzzyCompare(ratio_, rhs.ratio_));
|
||||
}
|
||||
bool operator!=(const ViewerSafeMarginInfo &rhs) const
|
||||
{
|
||||
return (enabled_ != rhs.enabled_ || !qFuzzyCompare(ratio_, rhs.ratio_));
|
||||
}
|
||||
|
||||
private:
|
||||
bool enabled_;
|
||||
|
||||
double ratio_;
|
||||
bool enabled_;
|
||||
|
||||
double ratio_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+184
-166
@@ -27,262 +27,280 @@
|
||||
|
||||
#include "widget/handmovableview/handmovableview.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
ViewerSizer::ViewerSizer(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
widget_(nullptr),
|
||||
width_(0),
|
||||
height_(0),
|
||||
pixel_aspect_(1),
|
||||
zoom_(-1),
|
||||
current_widget_scale_(0)
|
||||
namespace olive
|
||||
{
|
||||
horiz_scrollbar_ = new QScrollBar(Qt::Horizontal, this);
|
||||
horiz_scrollbar_->setVisible(false);
|
||||
connect(horiz_scrollbar_, &QScrollBar::valueChanged, this, &ViewerSizer::ScrollBarMoved);
|
||||
|
||||
vert_scrollbar_ = new QScrollBar(Qt::Vertical, this);
|
||||
vert_scrollbar_->setVisible(false);
|
||||
connect(vert_scrollbar_, &QScrollBar::valueChanged, this, &ViewerSizer::ScrollBarMoved);
|
||||
ViewerSizer::ViewerSizer(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, widget_(nullptr)
|
||||
, width_(0)
|
||||
, height_(0)
|
||||
, pixel_aspect_(1)
|
||||
, zoom_(-1)
|
||||
, current_widget_scale_(0)
|
||||
{
|
||||
horiz_scrollbar_ = new QScrollBar(Qt::Horizontal, this);
|
||||
horiz_scrollbar_->setVisible(false);
|
||||
connect(horiz_scrollbar_, &QScrollBar::valueChanged, this,
|
||||
&ViewerSizer::ScrollBarMoved);
|
||||
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
vert_scrollbar_ = new QScrollBar(Qt::Vertical, this);
|
||||
vert_scrollbar_->setVisible(false);
|
||||
connect(vert_scrollbar_, &QScrollBar::valueChanged, this,
|
||||
&ViewerSizer::ScrollBarMoved);
|
||||
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
}
|
||||
|
||||
void ViewerSizer::SetWidget(QWidget *widget)
|
||||
{
|
||||
// Delete any previous widgets occupying this space
|
||||
delete widget_;
|
||||
// Delete any previous widgets occupying this space
|
||||
delete widget_;
|
||||
|
||||
widget_ = widget;
|
||||
widget_ = widget;
|
||||
|
||||
if (widget_ != nullptr) {
|
||||
widget_->setParent(this);
|
||||
widget_->installEventFilter(this);
|
||||
if (widget_ != nullptr) {
|
||||
widget_->setParent(this);
|
||||
widget_->installEventFilter(this);
|
||||
|
||||
UpdateSize();
|
||||
}
|
||||
UpdateSize();
|
||||
}
|
||||
}
|
||||
|
||||
QSize ViewerSizer::GetContainerSize() const
|
||||
{
|
||||
double s = GetRealCurrentZoom();
|
||||
return QSize(std::min(this->width(), int(width_ * s)) - vert_scrollbar_->width(), std::min(int(height_ * s), this->height()) - horiz_scrollbar_->height());
|
||||
double s = GetRealCurrentZoom();
|
||||
return QSize(std::min(this->width(), int(width_ * s)) -
|
||||
vert_scrollbar_->width(),
|
||||
std::min(int(height_ * s), this->height()) -
|
||||
horiz_scrollbar_->height());
|
||||
}
|
||||
|
||||
void ViewerSizer::SetChildSize(int width, int height)
|
||||
{
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
|
||||
UpdateSize();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void ViewerSizer::SetPixelAspectRatio(const rational &pixel_aspect)
|
||||
{
|
||||
pixel_aspect_ = pixel_aspect;
|
||||
pixel_aspect_ = pixel_aspect;
|
||||
|
||||
UpdateSize();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void ViewerSizer::SetZoom(double percent)
|
||||
{
|
||||
zoom_ = percent;
|
||||
zoom_ = percent;
|
||||
|
||||
UpdateSize();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void ViewerSizer::SetZoomAnchored(double next_scale, double cursor_x, double cursor_y)
|
||||
void ViewerSizer::SetZoomAnchored(double next_scale, double cursor_x,
|
||||
double cursor_y)
|
||||
{
|
||||
if (next_scale > 0) {
|
||||
double cur_scale = GetRealCurrentZoom();
|
||||
if (next_scale > 0) {
|
||||
double cur_scale = GetRealCurrentZoom();
|
||||
|
||||
// Clamp scale within safe values
|
||||
next_scale = std::clamp(next_scale, kZoomLevels[0], kZoomLevels[kZoomLevelCount-1]);
|
||||
// Clamp scale within safe values
|
||||
next_scale = std::clamp(next_scale, kZoomLevels[0],
|
||||
kZoomLevels[kZoomLevelCount - 1]);
|
||||
|
||||
int anchor_x = qRound(double(cursor_x + horiz_scrollbar_->value()) / cur_scale * next_scale - cursor_x);
|
||||
int anchor_y = qRound(double(cursor_y + vert_scrollbar_->value()) / cur_scale * next_scale - cursor_y);
|
||||
int anchor_x = qRound(double(cursor_x + horiz_scrollbar_->value()) /
|
||||
cur_scale * next_scale -
|
||||
cursor_x);
|
||||
int anchor_y = qRound(double(cursor_y + vert_scrollbar_->value()) /
|
||||
cur_scale * next_scale -
|
||||
cursor_y);
|
||||
|
||||
SetZoom(next_scale);
|
||||
SetZoom(next_scale);
|
||||
|
||||
horiz_scrollbar_->setValue(anchor_x);
|
||||
vert_scrollbar_->setValue(anchor_y);
|
||||
} else {
|
||||
SetZoom(-1);
|
||||
horiz_scrollbar_->setValue(anchor_x);
|
||||
vert_scrollbar_->setValue(anchor_y);
|
||||
} else {
|
||||
SetZoom(-1);
|
||||
|
||||
horiz_scrollbar_->setValue(0);
|
||||
vert_scrollbar_->setValue(0);
|
||||
}
|
||||
horiz_scrollbar_->setValue(0);
|
||||
vert_scrollbar_->setValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerSizer::HandDragMove(int x, int y)
|
||||
{
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
horiz_scrollbar_->setValue(horiz_scrollbar_->value() - x);
|
||||
}
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
horiz_scrollbar_->setValue(horiz_scrollbar_->value() - x);
|
||||
}
|
||||
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
vert_scrollbar_->setValue(vert_scrollbar_->value() - y);
|
||||
}
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
vert_scrollbar_->setValue(vert_scrollbar_->value() - y);
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewerSizer::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (watched == widget_) {
|
||||
if (event->type() == QEvent::Wheel) {
|
||||
QWheelEvent *w = static_cast<QWheelEvent*>(event);
|
||||
if (watched == widget_) {
|
||||
if (event->type() == QEvent::Wheel) {
|
||||
QWheelEvent *w = static_cast<QWheelEvent *>(event);
|
||||
|
||||
if (HandMovableView::WheelEventIsAZoomEvent(w)) {
|
||||
double next_scale = GetRealCurrentZoom() * HandMovableView::GetScrollZoomMultiplier(w);
|
||||
QPointF cursor_pos = w->position();
|
||||
SetZoomAnchored(next_scale, cursor_pos.x(), cursor_pos.y());
|
||||
} else {
|
||||
// Pass scroll values to scrollbars
|
||||
QPoint p = w->pixelDelta();
|
||||
horiz_scrollbar_->setValue(horiz_scrollbar_->value() - p.x());
|
||||
vert_scrollbar_->setValue(vert_scrollbar_->value() - p.y());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (HandMovableView::WheelEventIsAZoomEvent(w)) {
|
||||
double next_scale = GetRealCurrentZoom() *
|
||||
HandMovableView::GetScrollZoomMultiplier(w);
|
||||
QPointF cursor_pos = w->position();
|
||||
SetZoomAnchored(next_scale, cursor_pos.x(), cursor_pos.y());
|
||||
} else {
|
||||
// Pass scroll values to scrollbars
|
||||
QPoint p = w->pixelDelta();
|
||||
horiz_scrollbar_->setValue(horiz_scrollbar_->value() - p.x());
|
||||
vert_scrollbar_->setValue(vert_scrollbar_->value() - p.y());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(watched, event);
|
||||
return QWidget::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void ViewerSizer::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
QWidget::resizeEvent(event);
|
||||
|
||||
UpdateSize();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void ViewerSizer::UpdateSize()
|
||||
{
|
||||
if (widget_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (widget_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the aspect ratio is 0, default to taking all space
|
||||
if (!width_ || !height_) {
|
||||
widget_->move(0, 0);
|
||||
widget_->resize(width(), height());
|
||||
return;
|
||||
}
|
||||
// If the aspect ratio is 0, default to taking all space
|
||||
if (!width_ || !height_) {
|
||||
widget_->move(0, 0);
|
||||
widget_->resize(width(), height());
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate how much UI space is available (it will be less if we have to show scrollbars)
|
||||
int available_width = width();
|
||||
int available_height = height();
|
||||
// Calculate how much UI space is available (it will be less if we have to show scrollbars)
|
||||
int available_width = width();
|
||||
int available_height = height();
|
||||
|
||||
// Determine if we need scrollbars for the zoom we want
|
||||
horiz_scrollbar_->setVisible(zoom_ > 0 && GetZoomedValue(width_) > available_width);
|
||||
vert_scrollbar_->setVisible(zoom_ > 0 && GetZoomedValue(height_) > available_height);
|
||||
// Determine if we need scrollbars for the zoom we want
|
||||
horiz_scrollbar_->setVisible(zoom_ > 0 &&
|
||||
GetZoomedValue(width_) > available_width);
|
||||
vert_scrollbar_->setVisible(zoom_ > 0 &&
|
||||
GetZoomedValue(height_) > available_height);
|
||||
|
||||
// Horizontal scrollbar will reduce the available height
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
available_height -= horiz_scrollbar_->sizeHint().height();
|
||||
}
|
||||
// Horizontal scrollbar will reduce the available height
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
available_height -= horiz_scrollbar_->sizeHint().height();
|
||||
}
|
||||
|
||||
// Vertical scrollbar will reduce the available width
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
available_width -= vert_scrollbar_->sizeHint().width();
|
||||
}
|
||||
// Vertical scrollbar will reduce the available width
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
available_width -= vert_scrollbar_->sizeHint().width();
|
||||
}
|
||||
|
||||
// Set correct values on horizontal scrollbar
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
horiz_scrollbar_->resize(available_width, horiz_scrollbar_->sizeHint().height());
|
||||
horiz_scrollbar_->move(0, this->height() - horiz_scrollbar_->height() - 1);
|
||||
horiz_scrollbar_->setMaximum(GetZoomedValue(width_) - available_width);
|
||||
horiz_scrollbar_->setPageStep(available_width);
|
||||
}
|
||||
// Set correct values on horizontal scrollbar
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
horiz_scrollbar_->resize(available_width,
|
||||
horiz_scrollbar_->sizeHint().height());
|
||||
horiz_scrollbar_->move(0,
|
||||
this->height() - horiz_scrollbar_->height() - 1);
|
||||
horiz_scrollbar_->setMaximum(GetZoomedValue(width_) - available_width);
|
||||
horiz_scrollbar_->setPageStep(available_width);
|
||||
}
|
||||
|
||||
// Set correct values on vertical scrollbar
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
vert_scrollbar_->resize(vert_scrollbar_->sizeHint().width(), available_height);
|
||||
vert_scrollbar_->move(this->width() - vert_scrollbar_->width() - 1, 0);
|
||||
vert_scrollbar_->setMaximum(GetZoomedValue(height_) - available_height);
|
||||
vert_scrollbar_->setPageStep(available_height);
|
||||
}
|
||||
// Set correct values on vertical scrollbar
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
vert_scrollbar_->resize(vert_scrollbar_->sizeHint().width(),
|
||||
available_height);
|
||||
vert_scrollbar_->move(this->width() - vert_scrollbar_->width() - 1, 0);
|
||||
vert_scrollbar_->setMaximum(GetZoomedValue(height_) - available_height);
|
||||
vert_scrollbar_->setPageStep(available_height);
|
||||
}
|
||||
|
||||
// Size widget to the UI space we've calculated
|
||||
widget_->resize(available_width, available_height);
|
||||
// Size widget to the UI space we've calculated
|
||||
widget_->resize(available_width, available_height);
|
||||
|
||||
// Adjust to aspect ratio
|
||||
double sequence_aspect_ratio = double(width_) / double(height_)
|
||||
* pixel_aspect_.toDouble();
|
||||
double our_aspect_ratio = double(available_width) / double(available_height);
|
||||
// Adjust to aspect ratio
|
||||
double sequence_aspect_ratio =
|
||||
double(width_) / double(height_) * pixel_aspect_.toDouble();
|
||||
double our_aspect_ratio =
|
||||
double(available_width) / double(available_height);
|
||||
|
||||
QMatrix4x4 child_matrix;
|
||||
double current_scale;
|
||||
QMatrix4x4 child_matrix;
|
||||
double current_scale;
|
||||
|
||||
if (our_aspect_ratio > sequence_aspect_ratio) {
|
||||
if (our_aspect_ratio > sequence_aspect_ratio) {
|
||||
// This container is wider than the image, scale by height
|
||||
child_matrix.scale(sequence_aspect_ratio / our_aspect_ratio, 1.0);
|
||||
current_scale = double(available_height) / double(height_);
|
||||
|
||||
// This container is wider than the image, scale by height
|
||||
child_matrix.scale(sequence_aspect_ratio / our_aspect_ratio, 1.0);
|
||||
current_scale = double(available_height) / double(height_);
|
||||
} else {
|
||||
// This container is taller than the image, scale by width
|
||||
child_matrix.scale(1.0, our_aspect_ratio / sequence_aspect_ratio);
|
||||
current_scale = double(available_width) / double(width_);
|
||||
}
|
||||
|
||||
} else {
|
||||
current_widget_scale_ = current_scale;
|
||||
|
||||
// This container is taller than the image, scale by width
|
||||
child_matrix.scale(1.0, our_aspect_ratio / sequence_aspect_ratio);
|
||||
current_scale = double(available_width) / double(width_);
|
||||
if (zoom_ > 0) {
|
||||
// Scale to get to the requested zoom
|
||||
double zoom_diff = zoom_ / current_scale;
|
||||
child_matrix.scale(zoom_diff, zoom_diff, 1.0);
|
||||
}
|
||||
|
||||
}
|
||||
emit RequestScale(child_matrix);
|
||||
|
||||
current_widget_scale_ = current_scale;
|
||||
|
||||
if (zoom_ > 0) {
|
||||
|
||||
// Scale to get to the requested zoom
|
||||
double zoom_diff = zoom_ / current_scale;
|
||||
child_matrix.scale(zoom_diff, zoom_diff, 1.0);
|
||||
|
||||
}
|
||||
|
||||
emit RequestScale(child_matrix);
|
||||
|
||||
ScrollBarMoved();
|
||||
ScrollBarMoved();
|
||||
}
|
||||
|
||||
int ViewerSizer::GetZoomedValue(int value)
|
||||
{
|
||||
return qRound(value * zoom_);
|
||||
return qRound(value * zoom_);
|
||||
}
|
||||
|
||||
double ViewerSizer::GetRealCurrentZoom() const
|
||||
{
|
||||
if (zoom_ < 0) {
|
||||
// Currently set to "fit"
|
||||
return current_widget_scale_;
|
||||
} else {
|
||||
// Explicit zoom set
|
||||
return zoom_;
|
||||
}
|
||||
if (zoom_ < 0) {
|
||||
// Currently set to "fit"
|
||||
return current_widget_scale_;
|
||||
} else {
|
||||
// Explicit zoom set
|
||||
return zoom_;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerSizer::ScrollBarMoved()
|
||||
{
|
||||
QMatrix4x4 mat;
|
||||
QMatrix4x4 mat;
|
||||
|
||||
float x_scroll, y_scroll;
|
||||
float x_scroll, y_scroll;
|
||||
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
int zoomed_width = GetZoomedValue(width_);
|
||||
x_scroll = (zoomed_width/2 - horiz_scrollbar_->value() - widget_->width() / 2) * (2.0 / zoomed_width);
|
||||
} else {
|
||||
x_scroll = 0;
|
||||
}
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
int zoomed_width = GetZoomedValue(width_);
|
||||
x_scroll = (zoomed_width / 2 - horiz_scrollbar_->value() -
|
||||
widget_->width() / 2) *
|
||||
(2.0 / zoomed_width);
|
||||
} else {
|
||||
x_scroll = 0;
|
||||
}
|
||||
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
int zoomed_height = GetZoomedValue(height_);
|
||||
y_scroll = (zoomed_height/2 - vert_scrollbar_->value() - widget_->height() / 2) * (2.0 / zoomed_height);
|
||||
} else {
|
||||
y_scroll = 0;
|
||||
}
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
int zoomed_height = GetZoomedValue(height_);
|
||||
y_scroll = (zoomed_height / 2 - vert_scrollbar_->value() -
|
||||
widget_->height() / 2) *
|
||||
(2.0 / zoomed_height);
|
||||
} else {
|
||||
y_scroll = 0;
|
||||
}
|
||||
|
||||
// Zero translate is centered, so we need to determine how much "off center" we are
|
||||
mat.translate(x_scroll, y_scroll);
|
||||
// Zero translate is centered, so we need to determine how much "off center" we are
|
||||
mat.translate(x_scroll, y_scroll);
|
||||
|
||||
emit RequestTranslate(mat);
|
||||
emit RequestTranslate(mat);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include <QScrollBar>
|
||||
#include <QWidget>
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
using namespace core;
|
||||
|
||||
@@ -38,97 +39,97 @@ using namespace core;
|
||||
* The aspect ratio is calculated width divided by height. If the aspect ratio is zero (either width or height == 0),
|
||||
* the widget is hidden until a valid size is provided.
|
||||
*/
|
||||
class ViewerSizer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
class ViewerSizer : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerSizer(QWidget* parent = nullptr);
|
||||
ViewerSizer(QWidget *parent = nullptr);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set the widget to be adjusted by this widget
|
||||
*
|
||||
* ViewerSizer takes ownership of this widget. If a widget was previously set, it is destroyed.
|
||||
*/
|
||||
void SetWidget(QWidget* widget);
|
||||
void SetWidget(QWidget *widget);
|
||||
|
||||
QSize GetContainerSize() const;
|
||||
QSize GetContainerSize() const;
|
||||
|
||||
static constexpr int kZoomLevelCount = 10;
|
||||
static constexpr double kZoomLevels[kZoomLevelCount] = {0.05, 0.1, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 4.0, 8.0};
|
||||
static constexpr int kZoomLevelCount = 10;
|
||||
static constexpr double kZoomLevels[kZoomLevelCount] = {
|
||||
0.05, 0.1, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 4.0, 8.0
|
||||
};
|
||||
|
||||
public slots:
|
||||
/**
|
||||
/**
|
||||
* @brief Set resolution to use
|
||||
*
|
||||
* This is not the actual resolution of the viewer, it's used to calculate the aspect ratio
|
||||
*/
|
||||
void SetChildSize(int width, int height);
|
||||
void SetChildSize(int width, int height);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set pixel aspect ratio
|
||||
*/
|
||||
void SetPixelAspectRatio(const rational& pixel_aspect);
|
||||
void SetPixelAspectRatio(const rational &pixel_aspect);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set the zoom value of the child widget
|
||||
*
|
||||
* The number is an integer percentage (100 = 100%). Set to 0 to auto-fit.
|
||||
*/
|
||||
void SetZoom(double percent);
|
||||
void SetZoomAnchored(double percent, double cursor_x, double cursor_y);
|
||||
void SetZoom(double percent);
|
||||
void SetZoomAnchored(double percent, double cursor_x, double cursor_y);
|
||||
|
||||
void HandDragMove(int x, int y);
|
||||
void HandDragMove(int x, int y);
|
||||
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
signals:
|
||||
void RequestScale(const QMatrix4x4& matrix);
|
||||
void RequestScale(const QMatrix4x4 &matrix);
|
||||
|
||||
void RequestTranslate(const QMatrix4x4& matrix);
|
||||
void RequestTranslate(const QMatrix4x4 &matrix);
|
||||
|
||||
protected:
|
||||
/**
|
||||
/**
|
||||
* @brief Listen for resize events to ensure the child widget remains correctly sized
|
||||
*/
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
/**
|
||||
* @brief Main sizing function, resizes widget_ to fit aspect_ratio_ (or hides if aspect ratio is 0)
|
||||
*/
|
||||
void UpdateSize();
|
||||
void UpdateSize();
|
||||
|
||||
int GetZoomedValue(int value);
|
||||
int GetZoomedValue(int value);
|
||||
|
||||
double GetRealCurrentZoom() const;
|
||||
double GetRealCurrentZoom() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Reference to widget
|
||||
*
|
||||
* If this is nullptr, all sizing operations are no-ops
|
||||
*/
|
||||
QWidget* widget_;
|
||||
QWidget *widget_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Internal resolution values
|
||||
*/
|
||||
int width_;
|
||||
int height_;
|
||||
int width_;
|
||||
int height_;
|
||||
|
||||
rational pixel_aspect_;
|
||||
rational pixel_aspect_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Internal zoom value
|
||||
*/
|
||||
double zoom_;
|
||||
double current_widget_scale_;
|
||||
double zoom_;
|
||||
double current_widget_scale_;
|
||||
|
||||
QScrollBar* horiz_scrollbar_;
|
||||
QScrollBar* vert_scrollbar_;
|
||||
QScrollBar *horiz_scrollbar_;
|
||||
QScrollBar *vert_scrollbar_;
|
||||
|
||||
private slots:
|
||||
void ScrollBarMoved();
|
||||
|
||||
void ScrollBarMoved();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -32,550 +32,604 @@
|
||||
#include "common/qtutils.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QTextEdit
|
||||
|
||||
ViewerTextEditor::ViewerTextEditor(double scale, QWidget *parent) :
|
||||
super(parent),
|
||||
transparent_clone_(nullptr),
|
||||
block_update_toolbar_signal_(false),
|
||||
forced_default_(false)
|
||||
ViewerTextEditor::ViewerTextEditor(double scale, QWidget *parent)
|
||||
: super(parent)
|
||||
, transparent_clone_(nullptr)
|
||||
, block_update_toolbar_signal_(false)
|
||||
, forced_default_(false)
|
||||
{
|
||||
// Ensure default text color is white
|
||||
QPalette p = palette();
|
||||
p.setColor(QPalette::Text, Qt::white);
|
||||
setPalette(p);
|
||||
// Ensure default text color is white
|
||||
QPalette p = palette();
|
||||
p.setColor(QPalette::Text, Qt::white);
|
||||
setPalette(p);
|
||||
|
||||
document()->setDefaultStyleSheet(QStringLiteral("body { color: white; }"));
|
||||
document()->setDefaultStyleSheet(QStringLiteral("body { color: white; }"));
|
||||
|
||||
// Ensure cursor is visible at this scale
|
||||
setCursorWidth(std::ceil(1.0 / scale));
|
||||
// Ensure cursor is visible at this scale
|
||||
setCursorWidth(std::ceil(1.0 / scale));
|
||||
|
||||
viewport()->setAutoFillBackground(false);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
connect(horizontalScrollBar(), &QScrollBar::rangeChanged, this, &ViewerTextEditor::LockScrollBarMaximumToZero);
|
||||
connect(verticalScrollBar(), &QScrollBar::rangeChanged, this, &ViewerTextEditor::LockScrollBarMaximumToZero);
|
||||
viewport()->setAutoFillBackground(false);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
connect(horizontalScrollBar(), &QScrollBar::rangeChanged, this,
|
||||
&ViewerTextEditor::LockScrollBarMaximumToZero);
|
||||
connect(verticalScrollBar(), &QScrollBar::rangeChanged, this,
|
||||
&ViewerTextEditor::LockScrollBarMaximumToZero);
|
||||
|
||||
// Force DPI to the same one that we're using in the actual render
|
||||
dpi_force_ = QImage(1, 1, QImage::Format_RGBA8888_Premultiplied);
|
||||
// Force DPI to the same one that we're using in the actual render
|
||||
dpi_force_ = QImage(1, 1, QImage::Format_RGBA8888_Premultiplied);
|
||||
|
||||
const int dpm = 3780;
|
||||
dpi_force_.setDotsPerMeterX(dpm);
|
||||
dpi_force_.setDotsPerMeterY(dpm);
|
||||
document()->documentLayout()->setPaintDevice(&dpi_force_);
|
||||
const int dpm = 3780;
|
||||
dpi_force_.setDotsPerMeterX(dpm);
|
||||
dpi_force_.setDotsPerMeterY(dpm);
|
||||
document()->documentLayout()->setPaintDevice(&dpi_force_);
|
||||
|
||||
connect(this, &QTextEdit::currentCharFormatChanged, this, &ViewerTextEditor::FormatChanged);
|
||||
connect(document(), &QTextDocument::contentsChanged, this, &ViewerTextEditor::DocumentChanged, Qt::QueuedConnection);
|
||||
connect(this, &QTextEdit::currentCharFormatChanged, this,
|
||||
&ViewerTextEditor::FormatChanged);
|
||||
connect(document(), &QTextDocument::contentsChanged, this,
|
||||
&ViewerTextEditor::DocumentChanged, Qt::QueuedConnection);
|
||||
|
||||
setAcceptRichText(false);
|
||||
setAcceptRichText(false);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::ConnectToolBar(ViewerTextEditorToolBar *toolbar)
|
||||
{
|
||||
connect(toolbar, &ViewerTextEditorToolBar::FamilyChanged, this, &ViewerTextEditor::SetFamily);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::SizeChanged, this, &ViewerTextEditor::setFontPointSize);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::StyleChanged, this, &ViewerTextEditor::SetStyle);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::UnderlineChanged, this, &ViewerTextEditor::setFontUnderline);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::StrikethroughChanged, this, &ViewerTextEditor::SetFontStrikethrough);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::ColorChanged, this, &ViewerTextEditor::setTextColor);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::SmallCapsChanged, this, &ViewerTextEditor::SetSmallCaps);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::StretchChanged, this, &ViewerTextEditor::SetFontStretch);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::KerningChanged, this, &ViewerTextEditor::SetFontKerning);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::LineHeightChanged, this, &ViewerTextEditor::SetLineHeight);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::AlignmentChanged, this, [this](Qt::Alignment a){
|
||||
this->setAlignment(a);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::FamilyChanged, this,
|
||||
&ViewerTextEditor::SetFamily);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::SizeChanged, this,
|
||||
&ViewerTextEditor::setFontPointSize);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::StyleChanged, this,
|
||||
&ViewerTextEditor::SetStyle);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::UnderlineChanged, this,
|
||||
&ViewerTextEditor::setFontUnderline);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::StrikethroughChanged, this,
|
||||
&ViewerTextEditor::SetFontStrikethrough);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::ColorChanged, this,
|
||||
&ViewerTextEditor::setTextColor);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::SmallCapsChanged, this,
|
||||
&ViewerTextEditor::SetSmallCaps);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::StretchChanged, this,
|
||||
&ViewerTextEditor::SetFontStretch);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::KerningChanged, this,
|
||||
&ViewerTextEditor::SetFontKerning);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::LineHeightChanged, this,
|
||||
&ViewerTextEditor::SetLineHeight);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::AlignmentChanged, this,
|
||||
[this](Qt::Alignment a) {
|
||||
this->setAlignment(a);
|
||||
|
||||
// Ensure no buttons are checked that shouldn't be
|
||||
static_cast<ViewerTextEditorToolBar*>(sender())->SetAlignment(a);
|
||||
});
|
||||
// Ensure no buttons are checked that shouldn't be
|
||||
static_cast<ViewerTextEditorToolBar *>(sender())->SetAlignment(
|
||||
a);
|
||||
});
|
||||
|
||||
UpdateToolBar(toolbar, this->currentCharFormat(), this->textCursor().blockFormat(), this->alignment());
|
||||
UpdateToolBar(toolbar, this->currentCharFormat(),
|
||||
this->textCursor().blockFormat(), this->alignment());
|
||||
|
||||
toolbars_.append(toolbar);
|
||||
toolbars_.append(toolbar);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::Paint(QPainter *p, Qt::Alignment valign)
|
||||
{
|
||||
QAbstractTextDocumentLayout::PaintContext ctx;
|
||||
QAbstractTextDocumentLayout::PaintContext ctx;
|
||||
|
||||
QRect clip = this->rect();
|
||||
p->setClipRect(clip, Qt::IntersectClip);
|
||||
ctx.clip = clip;
|
||||
QRect clip = this->rect();
|
||||
p->setClipRect(clip, Qt::IntersectClip);
|
||||
ctx.clip = clip;
|
||||
|
||||
ctx.cursorPosition = this->textCursor().position();
|
||||
ctx.cursorPosition = this->textCursor().position();
|
||||
|
||||
if (this->textCursor().hasSelection()) {
|
||||
QAbstractTextDocumentLayout::Selection selection;
|
||||
selection.cursor = this->textCursor();
|
||||
if (this->textCursor().hasSelection()) {
|
||||
QAbstractTextDocumentLayout::Selection selection;
|
||||
selection.cursor = this->textCursor();
|
||||
|
||||
QPalette::ColorGroup cg = this->hasFocus() ? QPalette::Active : QPalette::Inactive;
|
||||
QBrush b = ctx.palette.brush(cg, QPalette::Highlight);
|
||||
QColor bc = b.color();
|
||||
bc.setAlpha(128);
|
||||
b.setColor(bc);
|
||||
selection.format.setBackground(b);
|
||||
QStyleOption opt;
|
||||
opt.initFrom(this);
|
||||
if (this->style()->styleHint(QStyle::SH_RichText_FullWidthSelection, &opt, this)) {
|
||||
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||
}
|
||||
ctx.selections.append(selection);
|
||||
}
|
||||
QPalette::ColorGroup cg = this->hasFocus() ? QPalette::Active :
|
||||
QPalette::Inactive;
|
||||
QBrush b = ctx.palette.brush(cg, QPalette::Highlight);
|
||||
QColor bc = b.color();
|
||||
bc.setAlpha(128);
|
||||
b.setColor(bc);
|
||||
selection.format.setBackground(b);
|
||||
QStyleOption opt;
|
||||
opt.initFrom(this);
|
||||
if (this->style()->styleHint(QStyle::SH_RichText_FullWidthSelection,
|
||||
&opt, this)) {
|
||||
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||
}
|
||||
ctx.selections.append(selection);
|
||||
}
|
||||
|
||||
switch (valign) {
|
||||
case Qt::AlignTop:
|
||||
// Do nothing
|
||||
break;
|
||||
case Qt::AlignVCenter:
|
||||
p->translate(0, clip.height()/2-document()->size().height()/2);
|
||||
break;
|
||||
case Qt::AlignBottom:
|
||||
p->translate(0, clip.height()-document()->size().height());
|
||||
break;
|
||||
}
|
||||
switch (valign) {
|
||||
case Qt::AlignTop:
|
||||
// Do nothing
|
||||
break;
|
||||
case Qt::AlignVCenter:
|
||||
p->translate(0, clip.height() / 2 - document()->size().height() / 2);
|
||||
break;
|
||||
case Qt::AlignBottom:
|
||||
p->translate(0, clip.height() - document()->size().height());
|
||||
break;
|
||||
}
|
||||
|
||||
const bool use_transparent_clone = true;
|
||||
if (transparent_clone_ && use_transparent_clone) {
|
||||
transparent_clone_->setPageSize(this->document()->pageSize());
|
||||
transparent_clone_->documentLayout()->draw(p, ctx);
|
||||
} else {
|
||||
document()->documentLayout()->draw(p, ctx);
|
||||
}
|
||||
const bool use_transparent_clone = true;
|
||||
if (transparent_clone_ && use_transparent_clone) {
|
||||
transparent_clone_->setPageSize(this->document()->pageSize());
|
||||
transparent_clone_->documentLayout()->draw(p, ctx);
|
||||
} else {
|
||||
document()->documentLayout()->draw(p, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerTextEditor::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
// Disable painting
|
||||
// Disable painting
|
||||
}
|
||||
|
||||
void ViewerTextEditor::UpdateToolBar(ViewerTextEditorToolBar *toolbar, const QTextCharFormat &f, const QTextBlockFormat &b, Qt::Alignment alignment)
|
||||
void ViewerTextEditor::UpdateToolBar(ViewerTextEditorToolBar *toolbar,
|
||||
const QTextCharFormat &f,
|
||||
const QTextBlockFormat &b,
|
||||
Qt::Alignment alignment)
|
||||
{
|
||||
QStringList families = f.fontFamilies().toStringList();
|
||||
QString family;
|
||||
if (families.isEmpty()) {
|
||||
family = qApp->font().family();
|
||||
} else {
|
||||
family = families.first();
|
||||
}
|
||||
QStringList families = f.fontFamilies().toStringList();
|
||||
QString family;
|
||||
if (families.isEmpty()) {
|
||||
family = qApp->font().family();
|
||||
} else {
|
||||
family = families.first();
|
||||
}
|
||||
|
||||
QString style = f.fontStyleName().toString();
|
||||
QStringList styles = QFontDatabase().styles(family);
|
||||
if (!styles.isEmpty() && (style.isEmpty() || !styles.contains(style))) {
|
||||
// There seems to be no better way to find the "regular" style outside of this heuristic.
|
||||
// Feel free to add more if a font isn't working right.
|
||||
style = QStringLiteral("Regular");
|
||||
if (!styles.contains(style)) {
|
||||
style = QStringLiteral("Normal");
|
||||
}
|
||||
if (!styles.contains(style)) {
|
||||
style = QStringLiteral("R");
|
||||
}
|
||||
if (!styles.contains(style)) {
|
||||
style = styles.first();
|
||||
}
|
||||
}
|
||||
QString style = f.fontStyleName().toString();
|
||||
QStringList styles = QFontDatabase().styles(family);
|
||||
if (!styles.isEmpty() && (style.isEmpty() || !styles.contains(style))) {
|
||||
// There seems to be no better way to find the "regular" style outside of this heuristic.
|
||||
// Feel free to add more if a font isn't working right.
|
||||
style = QStringLiteral("Regular");
|
||||
if (!styles.contains(style)) {
|
||||
style = QStringLiteral("Normal");
|
||||
}
|
||||
if (!styles.contains(style)) {
|
||||
style = QStringLiteral("R");
|
||||
}
|
||||
if (!styles.contains(style)) {
|
||||
style = styles.first();
|
||||
}
|
||||
}
|
||||
|
||||
toolbar->SetFontFamily(family);
|
||||
toolbar->SetFontSize(f.fontPointSize());
|
||||
toolbar->SetStyle(style);
|
||||
toolbar->SetUnderline(f.fontUnderline());
|
||||
toolbar->SetStrikethrough(f.fontStrikeOut());
|
||||
toolbar->SetAlignment(alignment);
|
||||
toolbar->SetColor(f.foreground().color());
|
||||
toolbar->SetSmallCaps(f.fontCapitalization() == QFont::SmallCaps);
|
||||
toolbar->SetStretch(f.fontStretch() == 0 ? 100 : f.fontStretch());
|
||||
toolbar->SetKerning(f.fontLetterSpacing() == 0.0 ? 100 : f.fontLetterSpacing());
|
||||
toolbar->SetLineHeight(b.lineHeight() == 0.0 ? 100 : b.lineHeight());
|
||||
toolbar->SetFontFamily(family);
|
||||
toolbar->SetFontSize(f.fontPointSize());
|
||||
toolbar->SetStyle(style);
|
||||
toolbar->SetUnderline(f.fontUnderline());
|
||||
toolbar->SetStrikethrough(f.fontStrikeOut());
|
||||
toolbar->SetAlignment(alignment);
|
||||
toolbar->SetColor(f.foreground().color());
|
||||
toolbar->SetSmallCaps(f.fontCapitalization() == QFont::SmallCaps);
|
||||
toolbar->SetStretch(f.fontStretch() == 0 ? 100 : f.fontStretch());
|
||||
toolbar->SetKerning(f.fontLetterSpacing() == 0.0 ? 100 :
|
||||
f.fontLetterSpacing());
|
||||
toolbar->SetLineHeight(b.lineHeight() == 0.0 ? 100 : b.lineHeight());
|
||||
}
|
||||
|
||||
void ViewerTextEditor::FormatChanged(const QTextCharFormat &f)
|
||||
{
|
||||
if (!block_update_toolbar_signal_) {
|
||||
foreach (ViewerTextEditorToolBar *toolbar, toolbars_) {
|
||||
UpdateToolBar(toolbar, f, textCursor().blockFormat(), this->alignment());
|
||||
}
|
||||
}
|
||||
if (!block_update_toolbar_signal_) {
|
||||
foreach (ViewerTextEditorToolBar *toolbar, toolbars_) {
|
||||
UpdateToolBar(toolbar, f, textCursor().blockFormat(),
|
||||
this->alignment());
|
||||
}
|
||||
}
|
||||
|
||||
if (!(document()->blockCount() == 1 && document()->firstBlock().text().isEmpty())) {
|
||||
default_fmt_ = f;
|
||||
}
|
||||
if (!(document()->blockCount() == 1 &&
|
||||
document()->firstBlock().text().isEmpty())) {
|
||||
default_fmt_ = f;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerTextEditor::SetFamily(const QString &s)
|
||||
{
|
||||
ViewerTextEditorToolBar *toolbar = static_cast<ViewerTextEditorToolBar *>(sender());
|
||||
ViewerTextEditorToolBar *toolbar =
|
||||
static_cast<ViewerTextEditorToolBar *>(sender());
|
||||
|
||||
QTextCharFormat f;
|
||||
f.setFontFamilies({s});
|
||||
QTextCharFormat f;
|
||||
f.setFontFamilies({ s });
|
||||
|
||||
ApplyStyle(&f, s, toolbar->GetFontStyleName());
|
||||
ApplyStyle(&f, s, toolbar->GetFontStyleName());
|
||||
|
||||
MergeCharFormat(f);
|
||||
MergeCharFormat(f);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::SetStyle(const QString &s)
|
||||
{
|
||||
ViewerTextEditorToolBar *toolbar = static_cast<ViewerTextEditorToolBar *>(sender());
|
||||
ViewerTextEditorToolBar *toolbar =
|
||||
static_cast<ViewerTextEditorToolBar *>(sender());
|
||||
|
||||
QTextCharFormat f;
|
||||
QTextCharFormat f;
|
||||
|
||||
ApplyStyle(&f, toolbar->GetFontFamily(), s);
|
||||
ApplyStyle(&f, toolbar->GetFontFamily(), s);
|
||||
|
||||
MergeCharFormat(f);
|
||||
MergeCharFormat(f);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::SetFontStrikethrough(bool e)
|
||||
{
|
||||
QTextCharFormat f;
|
||||
f.setFontStrikeOut(e);
|
||||
MergeCharFormat(f);
|
||||
QTextCharFormat f;
|
||||
f.setFontStrikeOut(e);
|
||||
MergeCharFormat(f);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::SetSmallCaps(bool e)
|
||||
{
|
||||
QTextCharFormat f;
|
||||
f.setFontCapitalization(e ? QFont::SmallCaps : QFont::MixedCase);
|
||||
MergeCharFormat(f);
|
||||
QTextCharFormat f;
|
||||
f.setFontCapitalization(e ? QFont::SmallCaps : QFont::MixedCase);
|
||||
MergeCharFormat(f);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::SetFontStretch(int i)
|
||||
{
|
||||
QTextCharFormat f;
|
||||
f.setFontStretch(i);
|
||||
MergeCharFormat(f);
|
||||
QTextCharFormat f;
|
||||
f.setFontStretch(i);
|
||||
MergeCharFormat(f);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::SetFontKerning(qreal i)
|
||||
{
|
||||
QTextCharFormat f;
|
||||
f.setFontLetterSpacing(i);
|
||||
MergeCharFormat(f);
|
||||
QTextCharFormat f;
|
||||
f.setFontLetterSpacing(i);
|
||||
MergeCharFormat(f);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::MergeCharFormat(const QTextCharFormat &fmt)
|
||||
{
|
||||
// mergeCurrentCharFormat throws a currentCharFormatChanged signal that updates the toolbar,
|
||||
// this can be undesirable if the user is currently typing a font
|
||||
block_update_toolbar_signal_ = true;
|
||||
mergeCurrentCharFormat(fmt);
|
||||
//default_fmt_ = this->currentCharFormat();
|
||||
block_update_toolbar_signal_ = false;
|
||||
// mergeCurrentCharFormat throws a currentCharFormatChanged signal that updates the toolbar,
|
||||
// this can be undesirable if the user is currently typing a font
|
||||
block_update_toolbar_signal_ = true;
|
||||
mergeCurrentCharFormat(fmt);
|
||||
//default_fmt_ = this->currentCharFormat();
|
||||
block_update_toolbar_signal_ = false;
|
||||
}
|
||||
|
||||
void ViewerTextEditor::ApplyStyle(QTextCharFormat *format, const QString &family, const QString &style)
|
||||
void ViewerTextEditor::ApplyStyle(QTextCharFormat *format,
|
||||
const QString &family, const QString &style)
|
||||
{
|
||||
// NOTE: Windows appears to require setting weight and italic manually, while macOS and Linux are
|
||||
// perfectly fine with just the style name
|
||||
format->setFontWeight(QFontDatabase().weight(family, style));
|
||||
format->setFontItalic(QFontDatabase().italic(family, style));
|
||||
// NOTE: Windows appears to require setting weight and italic manually, while macOS and Linux are
|
||||
// perfectly fine with just the style name
|
||||
format->setFontWeight(QFontDatabase().weight(family, style));
|
||||
format->setFontItalic(QFontDatabase().italic(family, style));
|
||||
|
||||
format->setFontStyleName(style);
|
||||
format->setFontStyleName(style);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::SetLineHeight(qreal i)
|
||||
{
|
||||
QTextBlockFormat f = this->textCursor().blockFormat();
|
||||
f.setLineHeight(i, QTextBlockFormat::ProportionalHeight);
|
||||
this->textCursor().setBlockFormat(f);
|
||||
QTextBlockFormat f = this->textCursor().blockFormat();
|
||||
f.setLineHeight(i, QTextBlockFormat::ProportionalHeight);
|
||||
this->textCursor().setBlockFormat(f);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::LockScrollBarMaximumToZero()
|
||||
{
|
||||
static_cast<QScrollBar*>(sender())->setMaximum(0);
|
||||
static_cast<QScrollBar *>(sender())->setMaximum(0);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::DocumentChanged()
|
||||
{
|
||||
if (document()->blockCount() == 1 && document()->firstBlock().text().isEmpty()) {
|
||||
if (!forced_default_) {
|
||||
QTextCursor c(document()->firstBlock());
|
||||
c.setBlockCharFormat(default_fmt_);
|
||||
forced_default_ = true;
|
||||
}
|
||||
} else {
|
||||
if (default_fmt_.isEmpty()) {
|
||||
default_fmt_ = document()->firstBlock().charFormat();
|
||||
}
|
||||
forced_default_ = false;
|
||||
}
|
||||
if (document()->blockCount() == 1 &&
|
||||
document()->firstBlock().text().isEmpty()) {
|
||||
if (!forced_default_) {
|
||||
QTextCursor c(document()->firstBlock());
|
||||
c.setBlockCharFormat(default_fmt_);
|
||||
forced_default_ = true;
|
||||
}
|
||||
} else {
|
||||
if (default_fmt_.isEmpty()) {
|
||||
default_fmt_ = document()->firstBlock().charFormat();
|
||||
}
|
||||
forced_default_ = false;
|
||||
}
|
||||
|
||||
// HACK: We want to show the text cursor and selections without necessarily rendering the text,
|
||||
// because the text is already being rendered underneath the gizmo (and rendering twice will
|
||||
// alter the overall look of the text while editing). This is something that Qt does not
|
||||
// support by default, and while it could be solved by subclassing QAbstractTextDocumentLayout,
|
||||
// this seems like overkill since 99% of QTextDocumentLayout's (the subclass used by default)
|
||||
// functionality and would need to be fully implemented ourselves. So instead, we clone the
|
||||
// document, set all of its colors to rgba(0,0,0,0) to make them transparent, and draw that
|
||||
// document instead. The result is cursor and selections being rendered without the text.
|
||||
// While this isn't the fastest code, nor is it the cleanest solution, it definitely works.
|
||||
delete transparent_clone_;
|
||||
transparent_clone_ = document()->clone(this);
|
||||
transparent_clone_->documentLayout()->setPaintDevice(&dpi_force_);
|
||||
transparent_clone_->documentLayout()->setProperty("cursorWidth", document()->documentLayout()->property("cursorWidth"));
|
||||
// HACK: We want to show the text cursor and selections without necessarily rendering the text,
|
||||
// because the text is already being rendered underneath the gizmo (and rendering twice will
|
||||
// alter the overall look of the text while editing). This is something that Qt does not
|
||||
// support by default, and while it could be solved by subclassing QAbstractTextDocumentLayout,
|
||||
// this seems like overkill since 99% of QTextDocumentLayout's (the subclass used by default)
|
||||
// functionality and would need to be fully implemented ourselves. So instead, we clone the
|
||||
// document, set all of its colors to rgba(0,0,0,0) to make them transparent, and draw that
|
||||
// document instead. The result is cursor and selections being rendered without the text.
|
||||
// While this isn't the fastest code, nor is it the cleanest solution, it definitely works.
|
||||
delete transparent_clone_;
|
||||
transparent_clone_ = document()->clone(this);
|
||||
transparent_clone_->documentLayout()->setPaintDevice(&dpi_force_);
|
||||
transparent_clone_->documentLayout()->setProperty(
|
||||
"cursorWidth", document()->documentLayout()->property("cursorWidth"));
|
||||
|
||||
QTextCursor cursor(transparent_clone_);
|
||||
cursor.select(QTextCursor::Document);
|
||||
QTextCursor cursor(transparent_clone_);
|
||||
cursor.select(QTextCursor::Document);
|
||||
|
||||
QTextCharFormat fmt;
|
||||
fmt.setForeground(QColor(0, 0, 0, 0));
|
||||
cursor.mergeCharFormat(fmt);
|
||||
QTextCharFormat fmt;
|
||||
fmt.setForeground(QColor(0, 0, 0, 0));
|
||||
cursor.mergeCharFormat(fmt);
|
||||
}
|
||||
|
||||
ViewerTextEditorToolBar::ViewerTextEditorToolBar(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
painted_(false),
|
||||
drag_enabled_(true)
|
||||
ViewerTextEditorToolBar::ViewerTextEditorToolBar(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, painted_(false)
|
||||
, drag_enabled_(true)
|
||||
{
|
||||
QVBoxLayout *outer_layout = new QVBoxLayout(this);
|
||||
QVBoxLayout *outer_layout = new QVBoxLayout(this);
|
||||
|
||||
const int advanced_slider_width = QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral("9999.9%"));
|
||||
const int advanced_slider_width =
|
||||
QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral("9999.9%"));
|
||||
|
||||
{
|
||||
QHBoxLayout *row_layout = new QHBoxLayout();
|
||||
row_layout->setSpacing(0);
|
||||
outer_layout->addLayout(row_layout);
|
||||
{
|
||||
QHBoxLayout *row_layout = new QHBoxLayout();
|
||||
row_layout->setSpacing(0);
|
||||
outer_layout->addLayout(row_layout);
|
||||
|
||||
font_combo_ = new QFontComboBox();
|
||||
connect(font_combo_, &QFontComboBox::currentTextChanged, this, &ViewerTextEditorToolBar::UpdateFontStyleListAndEmitFamilyChanged);
|
||||
row_layout->addWidget(font_combo_);
|
||||
font_combo_ = new QFontComboBox();
|
||||
connect(
|
||||
font_combo_, &QFontComboBox::currentTextChanged, this,
|
||||
&ViewerTextEditorToolBar::UpdateFontStyleListAndEmitFamilyChanged);
|
||||
row_layout->addWidget(font_combo_);
|
||||
|
||||
font_sz_slider_ = new FloatSlider();
|
||||
font_sz_slider_->SetMinimum(0.1);
|
||||
font_sz_slider_->SetMaximum(9999.9);
|
||||
font_sz_slider_->SetDecimalPlaces(1);
|
||||
font_sz_slider_->SetAlignment(Qt::AlignCenter);
|
||||
font_sz_slider_->setFixedWidth(advanced_slider_width);
|
||||
connect(font_sz_slider_, &FloatSlider::ValueChanged, this, &ViewerTextEditorToolBar::SizeChanged);
|
||||
font_sz_slider_->SetLadderElementCount(2);
|
||||
row_layout->addWidget(font_sz_slider_);
|
||||
font_sz_slider_ = new FloatSlider();
|
||||
font_sz_slider_->SetMinimum(0.1);
|
||||
font_sz_slider_->SetMaximum(9999.9);
|
||||
font_sz_slider_->SetDecimalPlaces(1);
|
||||
font_sz_slider_->SetAlignment(Qt::AlignCenter);
|
||||
font_sz_slider_->setFixedWidth(advanced_slider_width);
|
||||
connect(font_sz_slider_, &FloatSlider::ValueChanged, this,
|
||||
&ViewerTextEditorToolBar::SizeChanged);
|
||||
font_sz_slider_->SetLadderElementCount(2);
|
||||
row_layout->addWidget(font_sz_slider_);
|
||||
|
||||
style_combo_ = new QComboBox();
|
||||
connect(style_combo_, &QComboBox::currentTextChanged, this, &ViewerTextEditorToolBar::StyleChanged);
|
||||
row_layout->addWidget(style_combo_);
|
||||
style_combo_ = new QComboBox();
|
||||
connect(style_combo_, &QComboBox::currentTextChanged, this,
|
||||
&ViewerTextEditorToolBar::StyleChanged);
|
||||
row_layout->addWidget(style_combo_);
|
||||
|
||||
underline_btn_ = new QPushButton();
|
||||
connect(underline_btn_, &QPushButton::clicked, this, &ViewerTextEditorToolBar::UnderlineChanged);
|
||||
underline_btn_->setCheckable(true);
|
||||
underline_btn_->setIcon(icon::TextUnderline);
|
||||
row_layout->addWidget(underline_btn_);
|
||||
underline_btn_ = new QPushButton();
|
||||
connect(underline_btn_, &QPushButton::clicked, this,
|
||||
&ViewerTextEditorToolBar::UnderlineChanged);
|
||||
underline_btn_->setCheckable(true);
|
||||
underline_btn_->setIcon(icon::TextUnderline);
|
||||
row_layout->addWidget(underline_btn_);
|
||||
|
||||
strikethrough_btn_ = new QPushButton();
|
||||
connect(strikethrough_btn_, &QPushButton::clicked, this, &ViewerTextEditorToolBar::StrikethroughChanged);
|
||||
strikethrough_btn_->setCheckable(true);
|
||||
strikethrough_btn_->setIcon(icon::TextStrikethrough);
|
||||
row_layout->addWidget(strikethrough_btn_);
|
||||
strikethrough_btn_ = new QPushButton();
|
||||
connect(strikethrough_btn_, &QPushButton::clicked, this,
|
||||
&ViewerTextEditorToolBar::StrikethroughChanged);
|
||||
strikethrough_btn_->setCheckable(true);
|
||||
strikethrough_btn_->setIcon(icon::TextStrikethrough);
|
||||
row_layout->addWidget(strikethrough_btn_);
|
||||
|
||||
AddSpacer(row_layout);
|
||||
AddSpacer(row_layout);
|
||||
|
||||
color_btn_ = new QPushButton();
|
||||
color_btn_->setAutoFillBackground(true);
|
||||
connect(color_btn_, &QPushButton::clicked, this, [this]{
|
||||
QColor c = color_btn_->property("color").value<QColor>();
|
||||
color_btn_ = new QPushButton();
|
||||
color_btn_->setAutoFillBackground(true);
|
||||
connect(color_btn_, &QPushButton::clicked, this, [this] {
|
||||
QColor c = color_btn_->property("color").value<QColor>();
|
||||
|
||||
QColorDialog cd(c, this);
|
||||
if (cd.exec() == QDialog::Accepted) {
|
||||
c = cd.selectedColor();
|
||||
SetColor(c);
|
||||
emit ColorChanged(c);
|
||||
}
|
||||
});
|
||||
row_layout->addWidget(color_btn_);
|
||||
QColorDialog cd(c, this);
|
||||
if (cd.exec() == QDialog::Accepted) {
|
||||
c = cd.selectedColor();
|
||||
SetColor(c);
|
||||
emit ColorChanged(c);
|
||||
}
|
||||
});
|
||||
row_layout->addWidget(color_btn_);
|
||||
|
||||
row_layout->addStretch();
|
||||
}
|
||||
row_layout->addStretch();
|
||||
}
|
||||
|
||||
{
|
||||
QHBoxLayout *row_layout = new QHBoxLayout();
|
||||
row_layout->setSpacing(0);
|
||||
outer_layout->addLayout(row_layout);
|
||||
{
|
||||
QHBoxLayout *row_layout = new QHBoxLayout();
|
||||
row_layout->setSpacing(0);
|
||||
outer_layout->addLayout(row_layout);
|
||||
|
||||
align_left_btn_ = new QPushButton();
|
||||
align_left_btn_->setCheckable(true);
|
||||
align_left_btn_->setIcon(icon::TextAlignLeft);
|
||||
connect(align_left_btn_, &QPushButton::clicked, this, [this]{emit AlignmentChanged(Qt::AlignLeft);});
|
||||
row_layout->addWidget(align_left_btn_);
|
||||
align_left_btn_ = new QPushButton();
|
||||
align_left_btn_->setCheckable(true);
|
||||
align_left_btn_->setIcon(icon::TextAlignLeft);
|
||||
connect(align_left_btn_, &QPushButton::clicked, this,
|
||||
[this] { emit AlignmentChanged(Qt::AlignLeft); });
|
||||
row_layout->addWidget(align_left_btn_);
|
||||
|
||||
align_center_btn_ = new QPushButton();
|
||||
align_center_btn_->setCheckable(true);
|
||||
align_center_btn_->setIcon(icon::TextAlignCenter);
|
||||
connect(align_center_btn_, &QPushButton::clicked, this, [this]{emit AlignmentChanged(Qt::AlignHCenter);});
|
||||
row_layout->addWidget(align_center_btn_);
|
||||
align_center_btn_ = new QPushButton();
|
||||
align_center_btn_->setCheckable(true);
|
||||
align_center_btn_->setIcon(icon::TextAlignCenter);
|
||||
connect(align_center_btn_, &QPushButton::clicked, this,
|
||||
[this] { emit AlignmentChanged(Qt::AlignHCenter); });
|
||||
row_layout->addWidget(align_center_btn_);
|
||||
|
||||
align_right_btn_ = new QPushButton();
|
||||
align_right_btn_->setCheckable(true);
|
||||
align_right_btn_->setIcon(icon::TextAlignRight);
|
||||
connect(align_right_btn_, &QPushButton::clicked, this, [this]{emit AlignmentChanged(Qt::AlignRight);});
|
||||
row_layout->addWidget(align_right_btn_);
|
||||
align_right_btn_ = new QPushButton();
|
||||
align_right_btn_->setCheckable(true);
|
||||
align_right_btn_->setIcon(icon::TextAlignRight);
|
||||
connect(align_right_btn_, &QPushButton::clicked, this,
|
||||
[this] { emit AlignmentChanged(Qt::AlignRight); });
|
||||
row_layout->addWidget(align_right_btn_);
|
||||
|
||||
align_justify_btn_ = new QPushButton();
|
||||
align_justify_btn_->setCheckable(true);
|
||||
align_justify_btn_->setIcon(icon::TextAlignJustify);
|
||||
connect(align_justify_btn_, &QPushButton::clicked, this, [this]{emit AlignmentChanged(Qt::AlignJustify);});
|
||||
row_layout->addWidget(align_justify_btn_);
|
||||
align_justify_btn_ = new QPushButton();
|
||||
align_justify_btn_->setCheckable(true);
|
||||
align_justify_btn_->setIcon(icon::TextAlignJustify);
|
||||
connect(align_justify_btn_, &QPushButton::clicked, this,
|
||||
[this] { emit AlignmentChanged(Qt::AlignJustify); });
|
||||
row_layout->addWidget(align_justify_btn_);
|
||||
|
||||
AddSpacer(row_layout);
|
||||
AddSpacer(row_layout);
|
||||
|
||||
align_top_btn_ = new QPushButton();
|
||||
align_top_btn_->setCheckable(true);
|
||||
align_top_btn_->setIcon(icon::TextAlignTop);
|
||||
connect(align_top_btn_, &QPushButton::clicked, this, [this]{emit VerticalAlignmentChanged(Qt::AlignTop);});
|
||||
row_layout->addWidget(align_top_btn_);
|
||||
align_top_btn_ = new QPushButton();
|
||||
align_top_btn_->setCheckable(true);
|
||||
align_top_btn_->setIcon(icon::TextAlignTop);
|
||||
connect(align_top_btn_, &QPushButton::clicked, this,
|
||||
[this] { emit VerticalAlignmentChanged(Qt::AlignTop); });
|
||||
row_layout->addWidget(align_top_btn_);
|
||||
|
||||
align_middle_btn_ = new QPushButton();
|
||||
align_middle_btn_->setCheckable(true);
|
||||
align_middle_btn_->setIcon(icon::TextAlignMiddle);
|
||||
connect(align_middle_btn_, &QPushButton::clicked, this, [this]{emit VerticalAlignmentChanged(Qt::AlignVCenter);});
|
||||
row_layout->addWidget(align_middle_btn_);
|
||||
align_middle_btn_ = new QPushButton();
|
||||
align_middle_btn_->setCheckable(true);
|
||||
align_middle_btn_->setIcon(icon::TextAlignMiddle);
|
||||
connect(align_middle_btn_, &QPushButton::clicked, this,
|
||||
[this] { emit VerticalAlignmentChanged(Qt::AlignVCenter); });
|
||||
row_layout->addWidget(align_middle_btn_);
|
||||
|
||||
align_bottom_btn_ = new QPushButton();
|
||||
align_bottom_btn_->setCheckable(true);
|
||||
align_bottom_btn_->setIcon(icon::TextAlignBottom);
|
||||
connect(align_bottom_btn_, &QPushButton::clicked, this, [this]{emit VerticalAlignmentChanged(Qt::AlignBottom);});
|
||||
row_layout->addWidget(align_bottom_btn_);
|
||||
align_bottom_btn_ = new QPushButton();
|
||||
align_bottom_btn_->setCheckable(true);
|
||||
align_bottom_btn_->setIcon(icon::TextAlignBottom);
|
||||
connect(align_bottom_btn_, &QPushButton::clicked, this,
|
||||
[this] { emit VerticalAlignmentChanged(Qt::AlignBottom); });
|
||||
row_layout->addWidget(align_bottom_btn_);
|
||||
|
||||
AddSpacer(row_layout);
|
||||
AddSpacer(row_layout);
|
||||
|
||||
small_caps_btn_ = new QPushButton();
|
||||
small_caps_btn_->setIcon(icon::TextSmallCaps);
|
||||
small_caps_btn_->setCheckable(true);
|
||||
connect(small_caps_btn_, &QPushButton::clicked, this, &ViewerTextEditorToolBar::SmallCapsChanged);
|
||||
row_layout->addWidget(small_caps_btn_);
|
||||
small_caps_btn_ = new QPushButton();
|
||||
small_caps_btn_->setIcon(icon::TextSmallCaps);
|
||||
small_caps_btn_->setCheckable(true);
|
||||
connect(small_caps_btn_, &QPushButton::clicked, this,
|
||||
&ViewerTextEditorToolBar::SmallCapsChanged);
|
||||
row_layout->addWidget(small_caps_btn_);
|
||||
|
||||
AddSpacer(row_layout);
|
||||
AddSpacer(row_layout);
|
||||
|
||||
row_layout->addWidget(new QLabel(tr("Stretch: "))); // FIXME: Procure icon
|
||||
row_layout->addWidget(
|
||||
new QLabel(tr("Stretch: "))); // FIXME: Procure icon
|
||||
|
||||
stretch_slider_ = new IntegerSlider();
|
||||
stretch_slider_->SetMinimum(0);
|
||||
stretch_slider_->SetDefaultValue(100);
|
||||
stretch_slider_->setFixedWidth(advanced_slider_width);
|
||||
stretch_slider_->SetFormat(tr("%1%"));
|
||||
connect(stretch_slider_, &IntegerSlider::ValueChanged, this, &ViewerTextEditorToolBar::StretchChanged);
|
||||
row_layout->addWidget(stretch_slider_);
|
||||
stretch_slider_ = new IntegerSlider();
|
||||
stretch_slider_->SetMinimum(0);
|
||||
stretch_slider_->SetDefaultValue(100);
|
||||
stretch_slider_->setFixedWidth(advanced_slider_width);
|
||||
stretch_slider_->SetFormat(tr("%1%"));
|
||||
connect(stretch_slider_, &IntegerSlider::ValueChanged, this,
|
||||
&ViewerTextEditorToolBar::StretchChanged);
|
||||
row_layout->addWidget(stretch_slider_);
|
||||
|
||||
row_layout->addWidget(new QLabel(tr("Kerning: "))); // FIXME: Procure icon
|
||||
row_layout->addWidget(
|
||||
new QLabel(tr("Kerning: "))); // FIXME: Procure icon
|
||||
|
||||
kerning_slider_ = new FloatSlider();
|
||||
kerning_slider_->SetMinimum(0);
|
||||
kerning_slider_->SetDefaultValue(100);
|
||||
kerning_slider_->SetDecimalPlaces(1);
|
||||
kerning_slider_->setFixedWidth(advanced_slider_width);
|
||||
kerning_slider_->SetFormat(tr("%1%"));
|
||||
connect(kerning_slider_, &FloatSlider::ValueChanged, this, &ViewerTextEditorToolBar::KerningChanged);
|
||||
row_layout->addWidget(kerning_slider_);
|
||||
kerning_slider_ = new FloatSlider();
|
||||
kerning_slider_->SetMinimum(0);
|
||||
kerning_slider_->SetDefaultValue(100);
|
||||
kerning_slider_->SetDecimalPlaces(1);
|
||||
kerning_slider_->setFixedWidth(advanced_slider_width);
|
||||
kerning_slider_->SetFormat(tr("%1%"));
|
||||
connect(kerning_slider_, &FloatSlider::ValueChanged, this,
|
||||
&ViewerTextEditorToolBar::KerningChanged);
|
||||
row_layout->addWidget(kerning_slider_);
|
||||
|
||||
row_layout->addWidget(new QLabel(tr("Line Height: "))); // FIXME: Procure icon
|
||||
row_layout->addWidget(
|
||||
new QLabel(tr("Line Height: "))); // FIXME: Procure icon
|
||||
|
||||
line_height_slider_ = new FloatSlider();
|
||||
line_height_slider_->SetMinimum(0);
|
||||
line_height_slider_->SetDefaultValue(100);
|
||||
line_height_slider_->SetDecimalPlaces(1);
|
||||
line_height_slider_->setFixedWidth(advanced_slider_width);
|
||||
line_height_slider_->SetFormat(tr("%1%"));
|
||||
connect(line_height_slider_, &FloatSlider::ValueChanged, this, &ViewerTextEditorToolBar::LineHeightChanged);
|
||||
row_layout->addWidget(line_height_slider_);
|
||||
line_height_slider_ = new FloatSlider();
|
||||
line_height_slider_->SetMinimum(0);
|
||||
line_height_slider_->SetDefaultValue(100);
|
||||
line_height_slider_->SetDecimalPlaces(1);
|
||||
line_height_slider_->setFixedWidth(advanced_slider_width);
|
||||
line_height_slider_->SetFormat(tr("%1%"));
|
||||
connect(line_height_slider_, &FloatSlider::ValueChanged, this,
|
||||
&ViewerTextEditorToolBar::LineHeightChanged);
|
||||
row_layout->addWidget(line_height_slider_);
|
||||
|
||||
row_layout->addStretch();
|
||||
}
|
||||
row_layout->addStretch();
|
||||
}
|
||||
|
||||
setAutoFillBackground(true);
|
||||
setAutoFillBackground(true);
|
||||
|
||||
resize(sizeHint());
|
||||
resize(sizeHint());
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::SetAlignment(Qt::Alignment a)
|
||||
{
|
||||
align_left_btn_->setChecked(a == Qt::AlignLeft);
|
||||
align_center_btn_->setChecked(a == Qt::AlignHCenter);
|
||||
align_right_btn_->setChecked(a == Qt::AlignRight);
|
||||
align_justify_btn_->setChecked(a == Qt::AlignJustify);
|
||||
align_left_btn_->setChecked(a == Qt::AlignLeft);
|
||||
align_center_btn_->setChecked(a == Qt::AlignHCenter);
|
||||
align_right_btn_->setChecked(a == Qt::AlignRight);
|
||||
align_justify_btn_->setChecked(a == Qt::AlignJustify);
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::SetVerticalAlignment(Qt::Alignment a)
|
||||
{
|
||||
align_top_btn_->setChecked(a == Qt::AlignTop);
|
||||
align_middle_btn_->setChecked(a == Qt::AlignVCenter);
|
||||
align_bottom_btn_->setChecked(a == Qt::AlignBottom);
|
||||
align_top_btn_->setChecked(a == Qt::AlignTop);
|
||||
align_middle_btn_->setChecked(a == Qt::AlignVCenter);
|
||||
align_bottom_btn_->setChecked(a == Qt::AlignBottom);
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::SetColor(const QColor &c)
|
||||
{
|
||||
color_btn_->setProperty("color", c);
|
||||
color_btn_->setStyleSheet(QStringLiteral("QPushButton { background: %1; }").arg(c.name()));
|
||||
color_btn_->setProperty("color", c);
|
||||
color_btn_->setStyleSheet(
|
||||
QStringLiteral("QPushButton { background: %1; }").arg(c.name()));
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
if (!painted_) {
|
||||
emit FirstPaint();
|
||||
painted_ = true;
|
||||
}
|
||||
QWidget::paintEvent(event);
|
||||
if (!painted_) {
|
||||
emit FirstPaint();
|
||||
painted_ = true;
|
||||
}
|
||||
QWidget::paintEvent(event);
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::AddSpacer(QLayout *l)
|
||||
{
|
||||
const int spacing = this->fontMetrics().height()/4;
|
||||
QWidget *a = new QWidget();
|
||||
a->setFixedSize(spacing, 1);
|
||||
l->addWidget(a);
|
||||
const int spacing = this->fontMetrics().height() / 4;
|
||||
QWidget *a = new QWidget();
|
||||
a->setFixedSize(spacing, 1);
|
||||
l->addWidget(a);
|
||||
|
||||
l->addWidget(QtUtils::CreateVerticalLine());
|
||||
l->addWidget(QtUtils::CreateVerticalLine());
|
||||
|
||||
QWidget *b = new QWidget();
|
||||
b->setFixedSize(spacing, 1);
|
||||
l->addWidget(b);
|
||||
QWidget *b = new QWidget();
|
||||
b->setFixedSize(spacing, 1);
|
||||
l->addWidget(b);
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::UpdateFontStyleList(const QString &family)
|
||||
{
|
||||
QString temp = style_combo_->currentText();
|
||||
QString temp = style_combo_->currentText();
|
||||
|
||||
style_combo_->blockSignals(true);
|
||||
style_combo_->clear();
|
||||
QStringList l = QFontDatabase().styles(family);
|
||||
foreach (const QString &style, l) {
|
||||
style_combo_->addItem(style);
|
||||
}
|
||||
style_combo_->setCurrentText(temp);
|
||||
style_combo_->blockSignals(false);
|
||||
style_combo_->blockSignals(true);
|
||||
style_combo_->clear();
|
||||
QStringList l = QFontDatabase().styles(family);
|
||||
foreach (const QString &style, l) {
|
||||
style_combo_->addItem(style);
|
||||
}
|
||||
style_combo_->setCurrentText(temp);
|
||||
style_combo_->blockSignals(false);
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::UpdateFontStyleListAndEmitFamilyChanged(const QString &family)
|
||||
void ViewerTextEditorToolBar::UpdateFontStyleListAndEmitFamilyChanged(
|
||||
const QString &family)
|
||||
{
|
||||
// Ensures correct ordering of commands
|
||||
UpdateFontStyleList(family);
|
||||
emit FamilyChanged(family);
|
||||
// Ensures correct ordering of commands
|
||||
UpdateFontStyleList(family);
|
||||
emit FamilyChanged(family);
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mousePressEvent(event);
|
||||
QWidget::mousePressEvent(event);
|
||||
|
||||
if (event->button() == Qt::LeftButton && drag_enabled_) {
|
||||
drag_anchor_ = event->pos();
|
||||
}
|
||||
if (event->button() == Qt::LeftButton && drag_enabled_) {
|
||||
drag_anchor_ = event->pos();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mouseMoveEvent(event);
|
||||
QWidget::mouseMoveEvent(event);
|
||||
|
||||
if ((event->buttons() & Qt::LeftButton) && drag_enabled_) {
|
||||
this->move(mapToParent(QPoint(event->pos() - drag_anchor_)));
|
||||
}
|
||||
if ((event->buttons() & Qt::LeftButton) && drag_enabled_) {
|
||||
this->move(mapToParent(QPoint(event->pos() - drag_anchor_)));
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerTextEditorToolBar::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,176 +30,210 @@
|
||||
#include "widget/slider/floatslider.h"
|
||||
#include "widget/slider/integerslider.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ViewerTextEditorToolBar : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ViewerTextEditorToolBar : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerTextEditorToolBar(QWidget *parent = nullptr);
|
||||
ViewerTextEditorToolBar(QWidget *parent = nullptr);
|
||||
|
||||
QString GetFontFamily() const
|
||||
{
|
||||
return font_combo_->currentText();
|
||||
}
|
||||
QString GetFontFamily() const
|
||||
{
|
||||
return font_combo_->currentText();
|
||||
}
|
||||
|
||||
QString GetFontStyleName() const
|
||||
{
|
||||
return style_combo_->currentText();
|
||||
}
|
||||
QString GetFontStyleName() const
|
||||
{
|
||||
return style_combo_->currentText();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetFontFamily(QString s)
|
||||
{
|
||||
font_combo_->blockSignals(true);
|
||||
font_combo_->setCurrentFont(s);
|
||||
UpdateFontStyleList(s);
|
||||
font_combo_->blockSignals(false);
|
||||
}
|
||||
void SetFontFamily(QString s)
|
||||
{
|
||||
font_combo_->blockSignals(true);
|
||||
font_combo_->setCurrentFont(s);
|
||||
UpdateFontStyleList(s);
|
||||
font_combo_->blockSignals(false);
|
||||
}
|
||||
|
||||
void SetStyle(QString style)
|
||||
{
|
||||
style_combo_->blockSignals(true);
|
||||
style_combo_->setCurrentText(style);
|
||||
style_combo_->blockSignals(false);
|
||||
}
|
||||
void SetStyle(QString style)
|
||||
{
|
||||
style_combo_->blockSignals(true);
|
||||
style_combo_->setCurrentText(style);
|
||||
style_combo_->blockSignals(false);
|
||||
}
|
||||
|
||||
void SetFontSize(double d) { font_sz_slider_->SetValue(d); }
|
||||
void SetUnderline(bool e) { underline_btn_->setChecked(e); }
|
||||
void SetStrikethrough(bool e) { strikethrough_btn_->setChecked(e); }
|
||||
void SetAlignment(Qt::Alignment a);
|
||||
void SetVerticalAlignment(Qt::Alignment a);
|
||||
void SetColor(const QColor &c);
|
||||
void SetSmallCaps(bool e) { small_caps_btn_->setChecked(e); }
|
||||
void SetStretch(int i) { stretch_slider_->SetValue(i); }
|
||||
void SetKerning(qreal i) { kerning_slider_->SetValue(i); }
|
||||
void SetLineHeight(qreal i) { line_height_slider_->SetValue(i); }
|
||||
void SetFontSize(double d)
|
||||
{
|
||||
font_sz_slider_->SetValue(d);
|
||||
}
|
||||
void SetUnderline(bool e)
|
||||
{
|
||||
underline_btn_->setChecked(e);
|
||||
}
|
||||
void SetStrikethrough(bool e)
|
||||
{
|
||||
strikethrough_btn_->setChecked(e);
|
||||
}
|
||||
void SetAlignment(Qt::Alignment a);
|
||||
void SetVerticalAlignment(Qt::Alignment a);
|
||||
void SetColor(const QColor &c);
|
||||
void SetSmallCaps(bool e)
|
||||
{
|
||||
small_caps_btn_->setChecked(e);
|
||||
}
|
||||
void SetStretch(int i)
|
||||
{
|
||||
stretch_slider_->SetValue(i);
|
||||
}
|
||||
void SetKerning(qreal i)
|
||||
{
|
||||
kerning_slider_->SetValue(i);
|
||||
}
|
||||
void SetLineHeight(qreal i)
|
||||
{
|
||||
line_height_slider_->SetValue(i);
|
||||
}
|
||||
|
||||
signals:
|
||||
void FamilyChanged(const QString &s);
|
||||
void SizeChanged(double d);
|
||||
void StyleChanged(const QString &s);
|
||||
void UnderlineChanged(bool e);
|
||||
void StrikethroughChanged(bool e);
|
||||
void AlignmentChanged(Qt::Alignment alignment);
|
||||
void VerticalAlignmentChanged(Qt::Alignment alignment);
|
||||
void ColorChanged(const QColor &c);
|
||||
void SmallCapsChanged(bool e);
|
||||
void StretchChanged(int i);
|
||||
void KerningChanged(qreal i);
|
||||
void LineHeightChanged(qreal i);
|
||||
void FamilyChanged(const QString &s);
|
||||
void SizeChanged(double d);
|
||||
void StyleChanged(const QString &s);
|
||||
void UnderlineChanged(bool e);
|
||||
void StrikethroughChanged(bool e);
|
||||
void AlignmentChanged(Qt::Alignment alignment);
|
||||
void VerticalAlignmentChanged(Qt::Alignment alignment);
|
||||
void ColorChanged(const QColor &c);
|
||||
void SmallCapsChanged(bool e);
|
||||
void StretchChanged(int i);
|
||||
void KerningChanged(qreal i);
|
||||
void LineHeightChanged(qreal i);
|
||||
|
||||
void FirstPaint();
|
||||
void FirstPaint();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
void AddSpacer(QLayout *l);
|
||||
void AddSpacer(QLayout *l);
|
||||
|
||||
QPoint drag_anchor_;
|
||||
QPoint drag_anchor_;
|
||||
|
||||
QFontComboBox *font_combo_;
|
||||
QFontComboBox *font_combo_;
|
||||
|
||||
FloatSlider *font_sz_slider_;
|
||||
FloatSlider *font_sz_slider_;
|
||||
|
||||
QComboBox *style_combo_;
|
||||
QComboBox *style_combo_;
|
||||
|
||||
QPushButton *underline_btn_;
|
||||
QPushButton *strikethrough_btn_;
|
||||
QPushButton *underline_btn_;
|
||||
QPushButton *strikethrough_btn_;
|
||||
|
||||
QPushButton *align_left_btn_;
|
||||
QPushButton *align_center_btn_;
|
||||
QPushButton *align_right_btn_;
|
||||
QPushButton *align_justify_btn_;
|
||||
QPushButton *align_left_btn_;
|
||||
QPushButton *align_center_btn_;
|
||||
QPushButton *align_right_btn_;
|
||||
QPushButton *align_justify_btn_;
|
||||
|
||||
QPushButton *align_top_btn_;
|
||||
QPushButton *align_middle_btn_;
|
||||
QPushButton *align_bottom_btn_;
|
||||
QPushButton *align_top_btn_;
|
||||
QPushButton *align_middle_btn_;
|
||||
QPushButton *align_bottom_btn_;
|
||||
|
||||
IntegerSlider *stretch_slider_;
|
||||
FloatSlider *kerning_slider_;
|
||||
FloatSlider *line_height_slider_;
|
||||
QPushButton *small_caps_btn_;
|
||||
IntegerSlider *stretch_slider_;
|
||||
FloatSlider *kerning_slider_;
|
||||
FloatSlider *line_height_slider_;
|
||||
QPushButton *small_caps_btn_;
|
||||
|
||||
QPushButton *color_btn_;
|
||||
QPushButton *color_btn_;
|
||||
|
||||
bool painted_;
|
||||
bool painted_;
|
||||
|
||||
bool drag_enabled_;
|
||||
bool drag_enabled_;
|
||||
|
||||
private slots:
|
||||
void UpdateFontStyleList(const QString &family);
|
||||
|
||||
void UpdateFontStyleListAndEmitFamilyChanged(const QString &family);
|
||||
void UpdateFontStyleList(const QString &family);
|
||||
|
||||
void UpdateFontStyleListAndEmitFamilyChanged(const QString &family);
|
||||
};
|
||||
|
||||
class ViewerTextEditor : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
class ViewerTextEditor : public QTextEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerTextEditor(double scale, QWidget *parent = nullptr);
|
||||
ViewerTextEditor(double scale, QWidget *parent = nullptr);
|
||||
|
||||
void ConnectToolBar(ViewerTextEditorToolBar *toolbar);
|
||||
void ConnectToolBar(ViewerTextEditorToolBar *toolbar);
|
||||
|
||||
void Paint(QPainter *p, Qt::Alignment valign);
|
||||
void Paint(QPainter *p, Qt::Alignment valign);
|
||||
|
||||
virtual void dragEnterEvent(QDragEnterEvent *e) override { return QTextEdit::dragEnterEvent(e); }
|
||||
virtual void dragMoveEvent(QDragMoveEvent *e) override { return QTextEdit::dragMoveEvent(e); }
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *e) override { return QTextEdit::dragLeaveEvent(e); }
|
||||
virtual void dropEvent(QDropEvent *e) override { return QTextEdit::dropEvent(e); }
|
||||
virtual void dragEnterEvent(QDragEnterEvent *e) override
|
||||
{
|
||||
return QTextEdit::dragEnterEvent(e);
|
||||
}
|
||||
virtual void dragMoveEvent(QDragMoveEvent *e) override
|
||||
{
|
||||
return QTextEdit::dragMoveEvent(e);
|
||||
}
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *e) override
|
||||
{
|
||||
return QTextEdit::dragLeaveEvent(e);
|
||||
}
|
||||
virtual void dropEvent(QDropEvent *e) override
|
||||
{
|
||||
return QTextEdit::dropEvent(e);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
static void UpdateToolBar(ViewerTextEditorToolBar *toolbar, const QTextCharFormat &f, const QTextBlockFormat &b, Qt::Alignment alignment);
|
||||
static void UpdateToolBar(ViewerTextEditorToolBar *toolbar,
|
||||
const QTextCharFormat &f,
|
||||
const QTextBlockFormat &b,
|
||||
Qt::Alignment alignment);
|
||||
|
||||
void MergeCharFormat(const QTextCharFormat &fmt);
|
||||
void MergeCharFormat(const QTextCharFormat &fmt);
|
||||
|
||||
void ApplyStyle(QTextCharFormat *format, const QString &family, const QString &style);
|
||||
void ApplyStyle(QTextCharFormat *format, const QString &family,
|
||||
const QString &style);
|
||||
|
||||
QVector<ViewerTextEditorToolBar *> toolbars_;
|
||||
QVector<ViewerTextEditorToolBar *> toolbars_;
|
||||
|
||||
QImage dpi_force_;
|
||||
QImage dpi_force_;
|
||||
|
||||
QTextDocument *transparent_clone_;
|
||||
QTextDocument *transparent_clone_;
|
||||
|
||||
bool block_update_toolbar_signal_;
|
||||
bool block_update_toolbar_signal_;
|
||||
|
||||
bool forced_default_;
|
||||
QTextCharFormat default_fmt_;
|
||||
bool forced_default_;
|
||||
QTextCharFormat default_fmt_;
|
||||
|
||||
private slots:
|
||||
void FormatChanged(const QTextCharFormat &f);
|
||||
void FormatChanged(const QTextCharFormat &f);
|
||||
|
||||
void SetFamily(const QString &s);
|
||||
void SetFamily(const QString &s);
|
||||
|
||||
void SetStyle(const QString &s);
|
||||
void SetStyle(const QString &s);
|
||||
|
||||
void SetFontStrikethrough(bool e);
|
||||
void SetFontStrikethrough(bool e);
|
||||
|
||||
void SetSmallCaps(bool e);
|
||||
void SetSmallCaps(bool e);
|
||||
|
||||
void SetFontStretch(int i);
|
||||
void SetFontStretch(int i);
|
||||
|
||||
void SetFontKerning(qreal i);
|
||||
void SetFontKerning(qreal i);
|
||||
|
||||
void SetLineHeight(qreal i);
|
||||
void SetLineHeight(qreal i);
|
||||
|
||||
void LockScrollBarMaximumToZero();
|
||||
|
||||
void DocumentChanged();
|
||||
void LockScrollBarMaximumToZero();
|
||||
|
||||
void DocumentChanged();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,82 +23,85 @@
|
||||
#include <QKeyEvent>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace olive {
|
||||
|
||||
ViewerWindow::ViewerWindow(QWidget *parent) :
|
||||
QWidget(parent, Qt::Window | Qt::WindowStaysOnTopHint),
|
||||
pixel_aspect_(1)
|
||||
namespace olive
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
display_widget_ = new ViewerDisplayWidget();
|
||||
layout->addWidget(display_widget_);
|
||||
ViewerWindow::ViewerWindow(QWidget *parent)
|
||||
: QWidget(parent, Qt::Window | Qt::WindowStaysOnTopHint)
|
||||
, pixel_aspect_(1)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
display_widget_ = new ViewerDisplayWidget();
|
||||
layout->addWidget(display_widget_);
|
||||
}
|
||||
|
||||
ViewerDisplayWidget *ViewerWindow::display_widget() const
|
||||
{
|
||||
return display_widget_;
|
||||
return display_widget_;
|
||||
}
|
||||
|
||||
void ViewerWindow::SetVideoParams(const VideoParams ¶ms)
|
||||
{
|
||||
width_ = params.width();
|
||||
height_ = params.height();
|
||||
pixel_aspect_ = params.pixel_aspect_ratio();
|
||||
width_ = params.width();
|
||||
height_ = params.height();
|
||||
pixel_aspect_ = params.pixel_aspect_ratio();
|
||||
|
||||
UpdateMatrix();
|
||||
UpdateMatrix();
|
||||
}
|
||||
|
||||
void ViewerWindow::SetResolution(int width, int height)
|
||||
{
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
|
||||
UpdateMatrix();
|
||||
UpdateMatrix();
|
||||
}
|
||||
|
||||
void ViewerWindow::SetPixelAspectRatio(const rational &pixel_aspect)
|
||||
{
|
||||
pixel_aspect_ = pixel_aspect;
|
||||
pixel_aspect_ = pixel_aspect;
|
||||
|
||||
UpdateMatrix();
|
||||
UpdateMatrix();
|
||||
}
|
||||
|
||||
void ViewerWindow::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
QWidget::keyPressEvent(e);
|
||||
QWidget::keyPressEvent(e);
|
||||
|
||||
if (e->key() == Qt::Key_Escape) {
|
||||
close();
|
||||
}
|
||||
if (e->key() == Qt::Key_Escape) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWindow::closeEvent(QCloseEvent *e)
|
||||
{
|
||||
QWidget::closeEvent(e);
|
||||
QWidget::closeEvent(e);
|
||||
|
||||
deleteLater();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void ViewerWindow::UpdateMatrix()
|
||||
{
|
||||
// Set GL widget matrix to maintain this texture's aspect ratio
|
||||
double window_ar = static_cast<double>(this->width()) / static_cast<double>(this->height());
|
||||
double image_ar = static_cast<double>(width_) / static_cast<double>(height_) * pixel_aspect_.toDouble();
|
||||
// Set GL widget matrix to maintain this texture's aspect ratio
|
||||
double window_ar = static_cast<double>(this->width()) /
|
||||
static_cast<double>(this->height());
|
||||
double image_ar = static_cast<double>(width_) /
|
||||
static_cast<double>(height_) * pixel_aspect_.toDouble();
|
||||
|
||||
QMatrix4x4 mat;
|
||||
QMatrix4x4 mat;
|
||||
|
||||
if (window_ar > image_ar) {
|
||||
// Window is wider than image, adjust X scale
|
||||
mat.scale(image_ar / window_ar, 1.0f, 1.0f);
|
||||
} else if (window_ar < image_ar) {
|
||||
// Window is taller than image, adjust Y scale
|
||||
mat.scale(1.0f, window_ar / image_ar, 1.0f);
|
||||
}
|
||||
if (window_ar > image_ar) {
|
||||
// Window is wider than image, adjust X scale
|
||||
mat.scale(image_ar / window_ar, 1.0f, 1.0f);
|
||||
} else if (window_ar < image_ar) {
|
||||
// Window is taller than image, adjust Y scale
|
||||
mat.scale(1.0f, window_ar / image_ar, 1.0f);
|
||||
}
|
||||
|
||||
display_widget_->SetMatrixZoom(mat);
|
||||
display_widget_->SetMatrixZoom(mat);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,49 +25,48 @@
|
||||
|
||||
#include "viewerdisplay.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ViewerWindow : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class ViewerWindow : public QWidget {
|
||||
public:
|
||||
ViewerWindow(QWidget* parent = nullptr);
|
||||
ViewerWindow(QWidget *parent = nullptr);
|
||||
|
||||
ViewerDisplayWidget* display_widget() const;
|
||||
ViewerDisplayWidget *display_widget() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Used to adjust resulting picture to be the right aspect ratio
|
||||
*
|
||||
* Equivalent to calling SetResolution and SetPixelAspectRatio, just slightly faster since we
|
||||
* only calculate the matrix once rather than twice.
|
||||
*/
|
||||
void SetVideoParams(const VideoParams ¶ms);
|
||||
void SetVideoParams(const VideoParams ¶ms);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Used to adjust resulting picture to be the right aspect ratio
|
||||
*/
|
||||
void SetResolution(int width, int height);
|
||||
void SetResolution(int width, int height);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Used to adjust resulting picture to be the right aspect ratio
|
||||
*/
|
||||
void SetPixelAspectRatio(const rational& pixel_aspect);
|
||||
void SetPixelAspectRatio(const rational &pixel_aspect);
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent* e) override;
|
||||
virtual void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
virtual void closeEvent(QCloseEvent* e) override;
|
||||
virtual void closeEvent(QCloseEvent *e) override;
|
||||
|
||||
private:
|
||||
void UpdateMatrix();
|
||||
void UpdateMatrix();
|
||||
|
||||
int width_;
|
||||
int width_;
|
||||
|
||||
int height_;
|
||||
int height_;
|
||||
|
||||
ViewerDisplayWidget* display_widget_;
|
||||
|
||||
rational pixel_aspect_;
|
||||
ViewerDisplayWidget *display_widget_;
|
||||
|
||||
rational pixel_aspect_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user