Marble

TourCaptureDialog.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2014 Sanjiban Bairagya <[email protected]>
4 //
5 
6 #include "TourCaptureDialog.h"
7 #include "ui_TourCaptureDialog.h"
8 
9 #include <QFileDialog>
10 #include <QMessageBox>
11 #include <QTimer>
12 
13 #include "MarbleWidget.h"
14 #include "MovieCapture.h"
15 #include "TourPlayback.h"
16 
17 namespace Marble {
18 
19 TourCaptureDialog::TourCaptureDialog(MarbleWidget *widget, QWidget *parent) :
20  QDialog(parent),
21  ui(new Ui::TourCaptureDialog),
22  m_recorder(new MovieCapture(widget, parent)),
23  m_playback(nullptr),
24  m_writingPossible( true ),
25  m_current_position( 0.0 )
26 {
27  ui->setupUi(this);
28  m_recorder->setSnapshotMethod(MovieCapture::DataDriven);
29  ui->progressBar->setValue(0);
30 
31  connect(ui->fpsSlider, SIGNAL(valueChanged(int)),
32  ui->fpsSpin, SLOT(setValue(int)));
33 
34  connect(ui->fpsSpin, SIGNAL(valueChanged(int)),
35  ui->fpsSlider, SLOT(setValue(int)));
36 
37  connect(ui->fpsSlider, SIGNAL(valueChanged(int)),
38  m_recorder, SLOT(setFps(int)));
39 
40  connect(ui->closeButton, SIGNAL(clicked()),
41  this, SLOT(close()));
42 
43  connect(ui->startButton, SIGNAL(clicked()),
44  this, SLOT(startRecording()));
45 
46  connect(ui->openButton, SIGNAL(clicked()),
47  this, SLOT(loadDestinationFile()));
48 
49  connect(m_recorder, SIGNAL(rateCalculated(double)),
50  this, SLOT(setRate(double))) ;
51 
52  connect(m_recorder, SIGNAL(errorOccured()),
53  this, SLOT(handleError()) );
54 }
55 
56 TourCaptureDialog::~TourCaptureDialog()
57 {
58  delete ui;
59 }
60 
61 void TourCaptureDialog::loadDestinationFile()
62 {
63  const QVector<MovieFormat> formats = m_recorder->availableFormats();
64  if( formats.isEmpty() ) {
65  QMessageBox::warning( this, tr( "Codecs are unavailable" ), tr( "Supported codecs are not found." ) );
66  return;
67  }
68  QString filter = formats.first().name() + QLatin1String(" (*.") + formats.first().extension() + QLatin1Char(')');
69  for( int i = 1; i < formats.size(); i++ )
70  {
71  filter += QLatin1String(";;") + formats.at(i).name() + QLatin1String(" (*.") + formats.at(i).extension() + QLatin1Char(')');
72  }
73  const QString defaultFileName =
74  ui->destinationEdit->text().isEmpty() ? m_defaultFileName : ui->destinationEdit->text();
75 
76  const QString destination =
77  QFileDialog::getSaveFileName(this, tr("Save video file"), defaultFileName,
78  filter );
79 
80  if (destination.isEmpty()) {
81  return;
82  }
83 
84  bool supported = false;
85  for(const MovieFormat &format: formats) {
86  if (destination.endsWith(QLatin1Char('.') + format.extension())) {
87  supported = true;
88  break;
89  }
90  }
91 
92  if (!supported) {
93  QString formatsExtensions = QLatin1Char('.') + formats.at(0).extension();
94  for( int i = 1; i < formats.size(); ++i )
95  {
96  formatsExtensions += QLatin1String(", .") + formats.at(i).extension();
97  }
98  QMessageBox::warning(this, tr("Filename is not valid"),
99  tr("This file format is not supported. "
100  "Please, use %1 instead").arg( formatsExtensions ) );
101  return;
102  }
103 
104  ui->destinationEdit->setText(destination);
105  m_recorder->setFilename(destination);
106 }
107 
108 void TourCaptureDialog::startRecording()
109 {
110  if( ui->startButton->text() == tr("Start") ){
111  ui->startButton->setText(tr("Cancel"));
112  ui->closeButton->setDisabled(true);
113  const QString path = ui->destinationEdit->text();
114 
115  if( path.isEmpty() ){
116  QMessageBox::warning(this, tr("Missing filename"),
117  tr("Destination video file is not set. "
118  "I don't know where to save recorded "
119  "video. Please, specify one."));
120  return;
121  }
122 
123  m_recorder->setSnapshotMethod( MovieCapture::DataDriven );
124  m_recorder->setFps(ui->fpsSlider->value());
125  m_recorder->startRecording();
126  m_current_position = 0.0;
127  recordNextFrame();
128  }
129  else{
130  ui->startButton->setText(tr("Start"));
131  m_recorder->cancelRecording();
132  ui->progressBar->setValue(0);
133  ui->closeButton->setEnabled(true);
134  }
135 }
136 
137 void TourCaptureDialog::updateProgress(double position)
138 {
139  ui->progressBar->setValue(position);
140 }
141 
142 void TourCaptureDialog::recordNextFrame()
143 {
144  double const shift = 1.0 / ( ui->fpsSlider->value() );
145  double const duration = m_playback->duration();
146 
147  if (!m_writingPossible) {
148  ui->rate->setText(QString("<font color=\"red\">%1</font>").arg(tr("Video writing failed.")));
149  return;
150  }
151 
152  if (ui->startButton->text() == QLatin1String("Start")) {
153  return;
154  }
155 
156  if (m_current_position <= duration) {
157  m_playback->seek( m_current_position );
158  m_recorder->recordFrame();
159  updateProgress( m_current_position * 100 );
160  m_current_position += shift;
161  QTimer::singleShot(1, this, SLOT(recordNextFrame()));
162  } else {
163  m_recorder->stopRecording();
164  ui->progressBar->setValue(duration*100);
165  ui->startButton->setText(tr("Start"));
166  ui->rate->setText(QString("<font color=\"green\">%1</font>").arg(tr("Video export completed.")));
167  ui->closeButton->setEnabled(true);
168  }
169 }
170 
171 void TourCaptureDialog::setRate(double rate)
172 {
173  ui->rate->setText(QString("%1 KBytes/sec").arg(rate));
174 }
175 
176 void TourCaptureDialog::stopRecording()
177 {
178  m_recorder->stopRecording();
179 }
180 
181 void TourCaptureDialog::setTourPlayback( TourPlayback* playback )
182 {
183  m_playback = playback;
184  ui->progressBar->setMaximum(playback->duration() * 100);
185 }
186 
187 void TourCaptureDialog::setDefaultFilename(const QString &filename)
188 {
189  m_defaultFileName = filename;
190 }
191 
192 void TourCaptureDialog::handleError()
193 {
194  m_writingPossible = false;
195 }
196 
197 } // namespace Marble
198 
199 #include "moc_TourCaptureDialog.cpp"
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
T & first()
QLatin1Char at(int pos) const const
const T & at(int i) const const
bool isEmpty() const const
QAction * close(const QObject *recvr, const char *slot, QObject *parent)
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
Binds a QML item to a specific geodetic location in screen coordinates.
void setupUi(QWidget *widget)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
int size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu May 26 2022 04:07:51 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.