23 #include <QCheckBox> |
23 #include <QCheckBox> |
24 #include <QLabel> |
24 #include <QLabel> |
25 #include <QLineEdit> |
25 #include <QLineEdit> |
26 #include <QSpinBox> |
26 #include <QSpinBox> |
27 #include <QTableWidget> |
27 #include <QTableWidget> |
28 |
28 #include <QDir> |
|
29 #include <QProgressBar> |
|
30 #include <QStringList> |
|
31 #include <QDesktopServices> |
|
32 #include <QUrl> |
|
33 #include <QList> |
|
34 #include <QMessageBox> |
|
35 #include <QHeaderView> |
|
36 #include <QKeyEvent> |
|
37 #include <QVBoxLayout> |
|
38 #include <QFileSystemWatcher> |
|
39 |
|
40 #include "hwconsts.h" |
29 #include "pagevideos.h" |
41 #include "pagevideos.h" |
30 #include "igbox.h" |
42 #include "igbox.h" |
31 #include "libav_iteraction.h" |
43 #include "libav_iteraction.h" |
32 #include "gameuiconfig.h" |
44 #include "gameuiconfig.h" |
|
45 #include "recorder.h" |
|
46 |
|
47 // columns in table with list of video files |
|
48 enum VideosColumns |
|
49 { |
|
50 vcName, |
|
51 vcSize, |
|
52 vcProgress, |
|
53 |
|
54 vcNumColumns, |
|
55 }; |
|
56 |
|
57 class VideoItem : public QTableWidgetItem |
|
58 { |
|
59 // note: QTableWidgetItem is not Q_OBJECT |
|
60 |
|
61 public: |
|
62 VideoItem(const QString& name); |
|
63 ~VideoItem(); |
|
64 |
|
65 QString name; |
|
66 QString desc; // description |
|
67 HWRecorder * pRecorder; // non NULL if file is being encoded |
|
68 bool seen; // used when updating directory |
|
69 float lastSizeUpdate; |
|
70 |
|
71 bool ready() |
|
72 { return !pRecorder; } |
|
73 |
|
74 QString path() |
|
75 { return cfgdir->absoluteFilePath("Videos/" + name); } |
|
76 }; |
|
77 |
|
78 VideoItem::VideoItem(const QString& name) |
|
79 : QTableWidgetItem(name, UserType) |
|
80 { |
|
81 this->name = name; |
|
82 pRecorder = NULL; |
|
83 lastSizeUpdate = 0; |
|
84 } |
|
85 |
|
86 VideoItem::~VideoItem() |
|
87 {} |
33 |
88 |
34 QLayout * PageVideos::bodyLayoutDefinition() |
89 QLayout * PageVideos::bodyLayoutDefinition() |
35 { |
90 { |
36 QGridLayout * pageLayout = new QGridLayout(); |
91 QGridLayout * pPageLayout = new QGridLayout(); |
37 pageLayout->setColumnStretch(0, 1); |
92 pPageLayout->setColumnStretch(0, 1); |
38 pageLayout->setColumnStretch(1, 1); |
93 pPageLayout->setColumnStretch(1, 1); |
39 |
94 |
40 { |
95 { |
41 IconedGroupBox* groupRec = new IconedGroupBox(this); |
96 IconedGroupBox* pOptionsGroup = new IconedGroupBox(this); |
42 groupRec->setIcon(QIcon(":/res/graphicsicon.png")); |
97 pOptionsGroup->setIcon(QIcon(":/res/graphicsicon.png")); |
43 groupRec->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
98 pOptionsGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
44 groupRec->setTitle(QGroupBox::tr("Video recording options")); |
99 pOptionsGroup->setTitle(QGroupBox::tr("Video recording options")); |
45 QGridLayout * RecLayout = new QGridLayout(groupRec); |
100 QGridLayout * pOptLayout = new QGridLayout(pOptionsGroup); |
46 |
101 |
47 // Label for format |
102 // label for format |
48 QLabel *labelFormat = new QLabel(groupRec); |
103 QLabel *labelFormat = new QLabel(pOptionsGroup); |
49 labelFormat->setText(QLabel::tr("Format")); |
104 labelFormat->setText(QLabel::tr("Format")); |
50 RecLayout->addWidget(labelFormat, 0, 0); |
105 pOptLayout->addWidget(labelFormat, 0, 0); |
51 |
106 |
52 // List of supported formats |
107 // list of supported formats |
53 CBAVFormats = new QComboBox(groupRec); |
108 comboAVFormats = new QComboBox(pOptionsGroup); |
54 RecLayout->addWidget(CBAVFormats, 0, 1, 1, 4); |
109 pOptLayout->addWidget(comboAVFormats, 0, 1, 1, 4); |
55 LibavIteraction::instance().FillFormats(CBAVFormats); |
110 LibavIteraction::instance().fillFormats(comboAVFormats); |
56 |
111 |
57 QFrame * hr = new QFrame(groupRec); |
112 // separator |
|
113 QFrame * hr = new QFrame(pOptionsGroup); |
58 hr->setFrameStyle(QFrame::HLine); |
114 hr->setFrameStyle(QFrame::HLine); |
59 hr->setLineWidth(3); |
115 hr->setLineWidth(3); |
60 hr->setFixedHeight(10); |
116 hr->setFixedHeight(10); |
61 RecLayout->addWidget(hr, 1, 0, 1, 5); |
117 pOptLayout->addWidget(hr, 1, 0, 1, 5); |
62 |
118 |
63 // Label for audio codec |
119 // label for audio codec |
64 QLabel *labelACodec = new QLabel(groupRec); |
120 QLabel *labelACodec = new QLabel(pOptionsGroup); |
65 labelACodec->setText(QLabel::tr("Audio codec")); |
121 labelACodec->setText(QLabel::tr("Audio codec")); |
66 RecLayout->addWidget(labelACodec, 2, 0); |
122 pOptLayout->addWidget(labelACodec, 2, 0); |
67 |
123 |
68 // List of supported audio codecs |
124 // list of supported audio codecs |
69 CBAudioCodecs = new QComboBox(groupRec); |
125 comboAudioCodecs = new QComboBox(pOptionsGroup); |
70 RecLayout->addWidget(CBAudioCodecs, 2, 1, 1, 3); |
126 pOptLayout->addWidget(comboAudioCodecs, 2, 1, 1, 3); |
71 |
127 |
72 // record audio |
128 // checkbox 'record audio' |
73 CBRecordAudio = new QCheckBox(groupRec); |
129 checkRecordAudio = new QCheckBox(pOptionsGroup); |
74 CBRecordAudio->setText(QCheckBox::tr("Record audio")); |
130 checkRecordAudio->setText(QCheckBox::tr("Record audio")); |
75 RecLayout->addWidget(CBRecordAudio, 2, 4); |
131 pOptLayout->addWidget(checkRecordAudio, 2, 4); |
76 |
132 |
77 hr = new QFrame(groupRec); |
133 // separator |
|
134 hr = new QFrame(pOptionsGroup); |
78 hr->setFrameStyle(QFrame::HLine); |
135 hr->setFrameStyle(QFrame::HLine); |
79 hr->setLineWidth(3); |
136 hr->setLineWidth(3); |
80 hr->setFixedHeight(10); |
137 hr->setFixedHeight(10); |
81 RecLayout->addWidget(hr, 3, 0, 1, 5); |
138 pOptLayout->addWidget(hr, 3, 0, 1, 5); |
82 |
139 |
83 // Label for video codec |
140 // label for video codec |
84 QLabel *labelVCodec = new QLabel(groupRec); |
141 QLabel *labelVCodec = new QLabel(pOptionsGroup); |
85 labelVCodec->setText(QLabel::tr("Video codec")); |
142 labelVCodec->setText(QLabel::tr("Video codec")); |
86 RecLayout->addWidget(labelVCodec, 4, 0); |
143 pOptLayout->addWidget(labelVCodec, 4, 0); |
87 |
144 |
88 // List of supported video codecs |
145 // list of supported video codecs |
89 CBVideoCodecs = new QComboBox(groupRec); |
146 comboVideoCodecs = new QComboBox(pOptionsGroup); |
90 RecLayout->addWidget(CBVideoCodecs, 4, 1, 1, 4); |
147 pOptLayout->addWidget(comboVideoCodecs, 4, 1, 1, 4); |
91 |
148 |
92 // Label for resolution |
149 // label for resolution |
93 QLabel *labelRes = new QLabel(groupRec); |
150 QLabel *labelRes = new QLabel(pOptionsGroup); |
94 labelRes->setText(QLabel::tr("Resolution")); |
151 labelRes->setText(QLabel::tr("Resolution")); |
95 RecLayout->addWidget(labelRes, 5, 0); |
152 pOptLayout->addWidget(labelRes, 5, 0); |
96 |
153 |
97 // width |
154 // width |
98 widthEdit = new QLineEdit(groupRec); |
155 widthEdit = new QLineEdit(pOptionsGroup); |
99 widthEdit->setValidator(new QIntValidator(this)); |
156 widthEdit->setValidator(new QIntValidator(this)); |
100 RecLayout->addWidget(widthEdit, 5, 1); |
157 pOptLayout->addWidget(widthEdit, 5, 1); |
101 |
158 |
102 // x |
159 // x |
103 QLabel *labelX = new QLabel(groupRec); |
160 QLabel *labelX = new QLabel(pOptionsGroup); |
104 labelX->setText("X"); |
161 labelX->setText("X"); |
105 RecLayout->addWidget(labelX, 5, 2); |
162 pOptLayout->addWidget(labelX, 5, 2); |
106 |
163 |
107 // height |
164 // height |
108 heightEdit = new QLineEdit(groupRec); |
165 heightEdit = new QLineEdit(pOptionsGroup); |
109 heightEdit->setValidator(new QIntValidator(groupRec)); |
166 heightEdit->setValidator(new QIntValidator(pOptionsGroup)); |
110 RecLayout->addWidget(heightEdit, 5, 3); |
167 pOptLayout->addWidget(heightEdit, 5, 3); |
111 |
168 |
112 // use game res |
169 // checkbox 'use game resolution' |
113 CBUseGameRes = new QCheckBox(groupRec); |
170 checkUseGameRes = new QCheckBox(pOptionsGroup); |
114 CBUseGameRes->setText(QCheckBox::tr("Use game resolution")); |
171 checkUseGameRes->setText(QCheckBox::tr("Use game resolution")); |
115 RecLayout->addWidget(CBUseGameRes, 5, 4); |
172 pOptLayout->addWidget(checkUseGameRes, 5, 4); |
116 |
173 |
117 // Label for framerate |
174 // label for framerate |
118 QLabel *labelFramerate = new QLabel(groupRec); |
175 QLabel *labelFramerate = new QLabel(pOptionsGroup); |
119 labelFramerate->setText(QLabel::tr("Framerate")); |
176 labelFramerate->setText(QLabel::tr("Framerate")); |
120 RecLayout->addWidget(labelFramerate, 6, 0); |
177 pOptLayout->addWidget(labelFramerate, 6, 0); |
121 |
178 |
122 // framerate |
179 // framerate |
123 framerateBox = new QSpinBox(groupRec); |
180 framerateBox = new QSpinBox(pOptionsGroup); |
124 framerateBox->setRange(1, 200); |
181 framerateBox->setRange(1, 200); |
125 framerateBox->setSingleStep(1); |
182 framerateBox->setSingleStep(1); |
126 RecLayout->addWidget(framerateBox, 6, 1); |
183 pOptLayout->addWidget(framerateBox, 6, 1); |
127 |
184 |
128 BtnDefaults = new QPushButton(groupRec); |
185 // button 'set default options' |
129 BtnDefaults->setText(QPushButton::tr("Set default options")); |
186 btnDefaults = new QPushButton(pOptionsGroup); |
130 RecLayout->addWidget(BtnDefaults, 7, 0, 1, 5); |
187 btnDefaults->setText(QPushButton::tr("Set default options")); |
131 |
188 pOptLayout->addWidget(btnDefaults, 7, 0, 1, 5); |
132 pageLayout->addWidget(groupRec, 0, 0); |
189 |
133 } |
190 pPageLayout->addWidget(pOptionsGroup, 1, 0); |
134 |
191 } |
135 { |
192 |
136 IconedGroupBox* groupTable = new IconedGroupBox(this); |
193 { |
137 //groupRec->setContentTopPadding(0); |
194 IconedGroupBox* pTableGroup = new IconedGroupBox(this); |
138 groupTable->setIcon(QIcon(":/res/graphicsicon.png")); |
195 pTableGroup->setIcon(QIcon(":/res/graphicsicon.png")); |
139 groupTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
196 pTableGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
140 groupTable->setTitle(QGroupBox::tr("Videos")); |
197 pTableGroup->setTitle(QGroupBox::tr("Videos")); |
141 |
198 |
142 QStringList columns; |
199 QStringList columns; |
143 columns << tr("Name") << tr("Lenght") << tr("..."); |
200 columns << tr("Name"); |
144 |
201 columns << tr("Size"); |
145 filesTable = new QTableWidget(groupTable); |
202 columns << tr("..."); |
146 filesTable->setColumnCount(3); |
203 |
|
204 filesTable = new QTableWidget(pTableGroup); |
|
205 filesTable->setColumnCount(vcNumColumns); |
147 filesTable->setHorizontalHeaderLabels(columns); |
206 filesTable->setHorizontalHeaderLabels(columns); |
148 QVBoxLayout *box = new QVBoxLayout(groupTable); |
207 filesTable->setSelectionBehavior(QAbstractItemView::SelectRows); |
|
208 filesTable->setEditTriggers(QAbstractItemView::SelectedClicked); |
|
209 filesTable->verticalHeader()->hide(); |
|
210 |
|
211 QHeaderView * header = filesTable->horizontalHeader(); |
|
212 int length = header->length(); // FIXME |
|
213 // header->setResizeMode(QHeaderView::ResizeToContents); |
|
214 header->resizeSection(vcName, length/2); |
|
215 header->resizeSection(vcSize, length/4); |
|
216 header->resizeSection(vcProgress, length/4); |
|
217 |
|
218 btnOpenDir = new QPushButton(QPushButton::tr("Open videos directory"), pTableGroup); |
|
219 |
|
220 QVBoxLayout *box = new QVBoxLayout(pTableGroup); |
149 box->addWidget(filesTable); |
221 box->addWidget(filesTable); |
150 |
222 box->addWidget(btnOpenDir); |
151 pageLayout->addWidget(groupTable, 0, 1, 2, 1); |
223 |
152 } |
224 pPageLayout->addWidget(pTableGroup, 0, 1, 2, 1); |
153 |
225 } |
154 return pageLayout; |
226 |
|
227 { |
|
228 IconedGroupBox* pDescGroup = new IconedGroupBox(this); |
|
229 pDescGroup->setIcon(QIcon(":/res/graphicsicon.png")); |
|
230 pDescGroup->setTitle(QGroupBox::tr("Description")); |
|
231 QGridLayout* pDescLayout = new QGridLayout(pDescGroup); |
|
232 |
|
233 labelThumbnail = new QLabel(pDescGroup); |
|
234 pDescLayout->addWidget(labelThumbnail, 0, 0); |
|
235 |
|
236 // label with file description |
|
237 labelDesc = new QLabel(pDescGroup); |
|
238 labelDesc->setAlignment(Qt::AlignLeft | Qt::AlignTop); |
|
239 pDescLayout->addWidget(labelDesc, 0, 1); |
|
240 |
|
241 // buttons: play and delete |
|
242 btnPlay = new QPushButton(QPushButton::tr("Play"), pDescGroup); |
|
243 pDescLayout->addWidget(btnPlay, 1, 0); |
|
244 btnDelete = new QPushButton(QPushButton::tr("Delete"), pDescGroup); |
|
245 pDescLayout->addWidget(btnDelete, 1, 1); |
|
246 |
|
247 pPageLayout->addWidget(pDescGroup, 0, 0); |
|
248 } |
|
249 |
|
250 return pPageLayout; |
155 } |
251 } |
156 |
252 |
157 QLayout * PageVideos::footerLayoutDefinition() |
253 QLayout * PageVideos::footerLayoutDefinition() |
158 { |
254 { |
159 return NULL; |
255 return NULL; |
160 } |
256 } |
161 |
257 |
162 void PageVideos::connectSignals() |
258 void PageVideos::connectSignals() |
163 { |
259 { |
164 connect(CBUseGameRes, SIGNAL(stateChanged(int)), this, SLOT(changeUseGameRes(int))); |
260 connect(checkUseGameRes, SIGNAL(stateChanged(int)), this, SLOT(changeUseGameRes(int))); |
165 connect(CBRecordAudio, SIGNAL(stateChanged(int)), this, SLOT(changeRecordAudio(int))); |
261 connect(checkRecordAudio, SIGNAL(stateChanged(int)), this, SLOT(changeRecordAudio(int))); |
166 connect(CBAVFormats, SIGNAL(currentIndexChanged(int)), this, SLOT(changeAVFormat(int))); |
262 connect(comboAVFormats, SIGNAL(currentIndexChanged(int)), this, SLOT(changeAVFormat(int))); |
167 connect(BtnDefaults, SIGNAL(clicked()), this, SLOT(setDefaultOptions())); |
263 connect(btnDefaults, SIGNAL(clicked()), this, SLOT(setDefaultOptions())); |
168 } |
264 connect(filesTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(cellDoubleClicked(int, int))); |
169 |
265 connect(filesTable, SIGNAL(cellChanged(int,int)), this, SLOT(cellChanged(int, int))); |
170 PageVideos::PageVideos(QWidget* parent) : AbstractPage(parent) |
266 connect(filesTable, SIGNAL(currentCellChanged(int,int,int,int)), this, SLOT(currentCellChanged(int,int,int,int))); |
171 { |
267 connect(btnPlay, SIGNAL(clicked()), this, SLOT(playSelectedFile())); |
|
268 connect(btnDelete, SIGNAL(clicked()), this, SLOT(deleteSelectedFiles())); |
|
269 connect(btnOpenDir, SIGNAL(clicked()), this, SLOT(openVideosDirectory())); |
|
270 |
|
271 QString path = cfgdir->absolutePath() + "/Videos"; |
|
272 QFileSystemWatcher * pWatcher = new QFileSystemWatcher(this); |
|
273 pWatcher->addPath(path); |
|
274 connect(pWatcher, SIGNAL(directoryChanged(const QString &)), this, SLOT(updateFileList(const QString &))); |
|
275 updateFileList(path); |
|
276 } |
|
277 |
|
278 PageVideos::PageVideos(QWidget* parent) : AbstractPage(parent), |
|
279 config(0) |
|
280 { |
|
281 nameChangedFromCode = false; |
172 initPage(); |
282 initPage(); |
173 } |
283 } |
174 |
284 |
|
285 // user changed file format, we need to update list of codecs |
175 void PageVideos::changeAVFormat(int index) |
286 void PageVideos::changeAVFormat(int index) |
176 { |
287 { |
177 QString prevVCodec = getVideoCodec(); |
288 // remember selected codecs |
178 QString prevACodec = getAudioCodec(); |
289 QString prevVCodec = videoCodec(); |
179 CBVideoCodecs->clear(); |
290 QString prevACodec = audioCodec(); |
180 CBAudioCodecs->clear(); |
291 |
181 LibavIteraction::instance().FillCodecs(CBAVFormats->itemData(index), CBVideoCodecs, CBAudioCodecs); |
292 // clear lists of codecs |
182 if (CBAudioCodecs->count() == 0) |
293 comboVideoCodecs->clear(); |
183 { |
294 comboAudioCodecs->clear(); |
184 CBRecordAudio->setChecked(false); |
295 |
185 CBRecordAudio->setEnabled(false); |
296 // get list of codecs for specified format |
|
297 LibavIteraction::instance().fillCodecs(comboAVFormats->itemData(index).toString(), comboVideoCodecs, comboAudioCodecs); |
|
298 |
|
299 // disable audio if there is no audio codec |
|
300 if (comboAudioCodecs->count() == 0) |
|
301 { |
|
302 checkRecordAudio->setChecked(false); |
|
303 checkRecordAudio->setEnabled(false); |
186 } |
304 } |
187 else |
305 else |
188 CBRecordAudio->setEnabled(true); |
306 checkRecordAudio->setEnabled(true); |
189 int iVCodec = CBVideoCodecs->findData(prevVCodec); |
307 |
|
308 // restore selected codecs if possible |
|
309 int iVCodec = comboVideoCodecs->findData(prevVCodec); |
190 if (iVCodec != -1) |
310 if (iVCodec != -1) |
191 CBVideoCodecs->setCurrentIndex(iVCodec); |
311 comboVideoCodecs->setCurrentIndex(iVCodec); |
192 int iACodec = CBAudioCodecs->findData(prevACodec); |
312 int iACodec = comboAudioCodecs->findData(prevACodec); |
193 if (iACodec != -1) |
313 if (iACodec != -1) |
194 CBAudioCodecs->setCurrentIndex(iACodec); |
314 comboAudioCodecs->setCurrentIndex(iACodec); |
195 } |
315 } |
196 |
316 |
|
317 // user switched checkbox 'use game resolution' |
197 void PageVideos::changeUseGameRes(int state) |
318 void PageVideos::changeUseGameRes(int state) |
198 { |
319 { |
199 if (state && config) |
320 if (state && config) |
200 { |
321 { |
|
322 // set resolution to game resolution |
201 QRect resolution = config->vid_Resolution(); |
323 QRect resolution = config->vid_Resolution(); |
202 widthEdit->setText(QString::number(resolution.width())); |
324 widthEdit->setText(QString::number(resolution.width())); |
203 heightEdit->setText(QString::number(resolution.height())); |
325 heightEdit->setText(QString::number(resolution.height())); |
204 } |
326 } |
205 widthEdit->setEnabled(!state); |
327 widthEdit->setEnabled(!state); |
206 heightEdit->setEnabled(!state); |
328 heightEdit->setEnabled(!state); |
207 } |
329 } |
208 |
330 |
|
331 // user switched checkbox 'record audio' |
209 void PageVideos::changeRecordAudio(int state) |
332 void PageVideos::changeRecordAudio(int state) |
210 { |
333 { |
211 CBAudioCodecs->setEnabled(!!state); |
334 comboAudioCodecs->setEnabled(!!state); |
212 } |
335 } |
213 |
336 |
214 void PageVideos::setDefaultCodecs() |
337 void PageVideos::setDefaultCodecs() |
215 { |
338 { |
216 if (tryCodecs("mp4", "libx264", "libmp3lame")) |
339 if (tryCodecs("mp4", "libx264", "libmp3lame")) |
217 return; |
340 return; |
218 if (tryCodecs("mp4", "libx264", "ac3_fixed")) |
341 if (tryCodecs("mp4", "libx264", "libfaac")) |
|
342 return; |
|
343 if (tryCodecs("mp4", "libx264", "libvo_aacenc")) |
|
344 return; |
|
345 if (tryCodecs("mp4", "libx264", "aac")) |
|
346 return; |
|
347 if (tryCodecs("mp4", "libx264", "mp2")) |
219 return; |
348 return; |
220 if (tryCodecs("avi", "libxvid", "libmp3lame")) |
349 if (tryCodecs("avi", "libxvid", "libmp3lame")) |
221 return; |
350 return; |
222 if (tryCodecs("avi", "libxvid", "ac3_fixed")) |
351 if (tryCodecs("avi", "libxvid", "ac3_fixed")) |
223 return; |
352 return; |
|
353 if (tryCodecs("avi", "libxvid", "mp2")) |
|
354 return; |
224 if (tryCodecs("avi", "mpeg4", "libmp3lame")) |
355 if (tryCodecs("avi", "mpeg4", "libmp3lame")) |
225 return; |
356 return; |
226 if (tryCodecs("avi", "mpeg4", "ac3_fixed")) |
357 if (tryCodecs("avi", "mpeg4", "ac3_fixed")) |
|
358 return; |
|
359 if (tryCodecs("avi", "mpeg4", "mp2")) |
227 return; |
360 return; |
228 |
361 |
229 // this shouldn't happen, just in case |
362 // this shouldn't happen, just in case |
230 if (tryCodecs("ogg", "libtheora", "libvorbis")) |
363 if (tryCodecs("ogg", "libtheora", "libvorbis")) |
231 return; |
364 return; |
233 } |
366 } |
234 |
367 |
235 void PageVideos::setDefaultOptions() |
368 void PageVideos::setDefaultOptions() |
236 { |
369 { |
237 framerateBox->setValue(25); |
370 framerateBox->setValue(25); |
238 CBRecordAudio->setChecked(true); |
371 checkRecordAudio->setChecked(true); |
239 CBUseGameRes->setChecked(true); |
372 checkUseGameRes->setChecked(true); |
240 setDefaultCodecs(); |
373 setDefaultCodecs(); |
241 } |
374 } |
242 |
375 |
243 bool PageVideos::tryCodecs(const QString & format, const QString & vcodec, const QString & acodec) |
376 bool PageVideos::tryCodecs(const QString & format, const QString & vcodec, const QString & acodec) |
244 { |
377 { |
245 int iFormat = CBAVFormats->findData(format); |
378 // first we should change format |
|
379 int iFormat = comboAVFormats->findData(format); |
246 if (iFormat == -1) |
380 if (iFormat == -1) |
247 return false; |
381 return false; |
248 CBAVFormats->setCurrentIndex(iFormat); |
382 comboAVFormats->setCurrentIndex(iFormat); |
249 |
383 |
250 int iVCodec = CBVideoCodecs->findData(vcodec); |
384 // try to find video codec |
|
385 int iVCodec = comboVideoCodecs->findData(vcodec); |
251 if (iVCodec == -1) |
386 if (iVCodec == -1) |
252 return false; |
387 return false; |
253 CBVideoCodecs->setCurrentIndex(iVCodec); |
388 comboVideoCodecs->setCurrentIndex(iVCodec); |
254 |
389 |
255 int iACodec = CBAudioCodecs->findData(acodec); |
390 // try to find audio codec |
256 if (iACodec == -1 && CBRecordAudio->isChecked()) |
391 int iACodec = comboAudioCodecs->findData(acodec); |
|
392 if (iACodec == -1 && checkRecordAudio->isChecked()) |
257 return false; |
393 return false; |
258 if (iACodec != -1) |
394 if (iACodec != -1) |
259 CBAudioCodecs->setCurrentIndex(iACodec); |
395 comboAudioCodecs->setCurrentIndex(iACodec); |
260 |
396 |
261 return true; |
397 return true; |
262 } |
398 } |
|
399 |
|
400 // get file size as string |
|
401 QString FileSizeStr(const QString & path) |
|
402 { |
|
403 quint64 size = QFileInfo(path).size(); |
|
404 |
|
405 quint64 KiB = 1024; |
|
406 quint64 MiB = 1024*KiB; |
|
407 quint64 GiB = 1024*MiB; |
|
408 QString sizeStr; |
|
409 if (size >= GiB) |
|
410 return QString("%1 GiB").arg(QString::number(float(size)/GiB, 'f', 2)); |
|
411 if (size >= MiB) |
|
412 return QString("%1 MiB").arg(QString::number(float(size)/MiB, 'f', 2)); |
|
413 if (size >= KiB) |
|
414 return QString("%1 KiB").arg(QString::number(float(size)/KiB, 'f', 2)); |
|
415 return PageVideos::tr("%1 bytes").arg(QString::number(size)); |
|
416 } |
|
417 |
|
418 // set file size in file list in specified row |
|
419 void PageVideos::updateSize(int row) |
|
420 { |
|
421 VideoItem * item = nameItem(row); |
|
422 QString path = item->ready()? item->path() : cfgdir->absoluteFilePath("VideoTemp/" + item->pRecorder->name); |
|
423 filesTable->item(row, vcSize)->setText(FileSizeStr(path)); |
|
424 } |
|
425 |
|
426 void PageVideos::updateFileList(const QString & path) |
|
427 { |
|
428 // mark all files as non seen |
|
429 int numRows = filesTable->rowCount(); |
|
430 for (int i = 0; i < numRows; i++) |
|
431 nameItem(i)->seen = false; |
|
432 |
|
433 QStringList files = QDir(path).entryList(QDir::Files); |
|
434 foreach (const QString & name, files) |
|
435 { |
|
436 int row = -1; |
|
437 foreach (QTableWidgetItem * item, filesTable->findItems(name, Qt::MatchExactly)) |
|
438 { |
|
439 if (item->type() != QTableWidgetItem::UserType || !((VideoItem*)item)->ready()) |
|
440 continue; |
|
441 row = item->row(); |
|
442 break; |
|
443 } |
|
444 if (row == -1) |
|
445 row = appendRow(name); |
|
446 VideoItem * item = nameItem(row); |
|
447 item->seen = true; |
|
448 item->desc = ""; |
|
449 updateSize(row); |
|
450 } |
|
451 |
|
452 // remove all non seen files |
|
453 for (int i = 0; i < filesTable->rowCount();) |
|
454 { |
|
455 VideoItem * item = nameItem(i); |
|
456 if (item->ready() && !item->seen) |
|
457 filesTable->removeRow(i); |
|
458 else |
|
459 i++; |
|
460 } |
|
461 } |
|
462 |
|
463 void PageVideos::addRecorder(HWRecorder* pRecorder) |
|
464 { |
|
465 int row = appendRow(pRecorder->name); |
|
466 VideoItem * item = nameItem(row); |
|
467 item->pRecorder = pRecorder; |
|
468 pRecorder->item = item; |
|
469 |
|
470 // add progress bar |
|
471 QProgressBar * progressBar = new QProgressBar(filesTable); |
|
472 progressBar->setMinimum(0); |
|
473 progressBar->setMaximum(10000); |
|
474 progressBar->setValue(0); |
|
475 connect(pRecorder, SIGNAL(onProgress(float)), this, SLOT(updateProgress(float))); |
|
476 connect(pRecorder, SIGNAL(encodingFinished(bool)), this, SLOT(encodingFinished(bool))); |
|
477 filesTable->setCellWidget(row, vcProgress, progressBar); |
|
478 } |
|
479 |
|
480 void PageVideos::updateProgress(float value) |
|
481 { |
|
482 HWRecorder * pRecorder = (HWRecorder*)sender(); |
|
483 VideoItem * item = (VideoItem*)pRecorder->item; |
|
484 int row = filesTable->row(item); |
|
485 |
|
486 // update file size every percent |
|
487 if (value - item->lastSizeUpdate > 0.01) |
|
488 { |
|
489 updateSize(row); |
|
490 item->lastSizeUpdate = value; |
|
491 } |
|
492 |
|
493 // update progress bar |
|
494 QProgressBar * progressBar = (QProgressBar*)filesTable->cellWidget(row, vcProgress); |
|
495 progressBar->setValue(value*10000); |
|
496 progressBar->setFormat(QString("%1%").arg(value*100, 0, 'f', 2)); |
|
497 } |
|
498 |
|
499 void PageVideos::encodingFinished(bool success) |
|
500 { |
|
501 HWRecorder * pRecorder = (HWRecorder*)sender(); |
|
502 VideoItem * item = (VideoItem*)pRecorder->item; |
|
503 int row = filesTable->row(item); |
|
504 |
|
505 if (success) |
|
506 { |
|
507 // move file to destination |
|
508 success = cfgdir->rename("VideoTemp/" + pRecorder->name, "Videos/" + item->name); |
|
509 if (!success) |
|
510 { |
|
511 // unable to rename for some reason (maybe user entered incorrect name); |
|
512 // try to use temp name instead. |
|
513 success = cfgdir->rename("VideoTemp/" + pRecorder->name, "Videos/" + pRecorder->name); |
|
514 if (success) |
|
515 setName(item, pRecorder->name); |
|
516 } |
|
517 } |
|
518 |
|
519 if (!success) |
|
520 { |
|
521 filesTable->removeRow(row); |
|
522 return; |
|
523 } |
|
524 |
|
525 filesTable->setCellWidget(row, vcProgress, NULL); // remove progress bar |
|
526 item->pRecorder = NULL; |
|
527 updateSize(row); |
|
528 updateDescription(); |
|
529 } |
|
530 |
|
531 void PageVideos::cellDoubleClicked(int row, int column) |
|
532 { |
|
533 play(row); |
|
534 } |
|
535 |
|
536 void PageVideos::cellChanged(int row, int column) |
|
537 { |
|
538 // user can only edit name |
|
539 if (column != vcName || nameChangedFromCode) |
|
540 return; |
|
541 |
|
542 // user has edited filename, so we should rename the file |
|
543 VideoItem * item = nameItem(row); |
|
544 QString oldName = item->name; |
|
545 QString newName = item->text(); |
|
546 item->name = newName; |
|
547 if (item->ready()) |
|
548 { |
|
549 if(!cfgdir->rename("Videos/" + oldName, "Videos/" + newName)) |
|
550 { |
|
551 // unable to rename for some reason (maybe user entered incorrect name), |
|
552 // therefore restore old name in cell |
|
553 setName(item, oldName); |
|
554 } |
|
555 } |
|
556 } |
|
557 |
|
558 void PageVideos::setName(VideoItem * item, const QString & newName) |
|
559 { |
|
560 nameChangedFromCode = true; |
|
561 item->setText(newName); |
|
562 nameChangedFromCode = false; |
|
563 item->name = newName; |
|
564 } |
|
565 |
|
566 int PageVideos::appendRow(const QString & name) |
|
567 { |
|
568 int row = filesTable->rowCount(); |
|
569 filesTable->setRowCount(row+1); |
|
570 |
|
571 // add 'name' item |
|
572 QTableWidgetItem * item = new VideoItem(name); |
|
573 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable); |
|
574 nameChangedFromCode = true; |
|
575 filesTable->setItem(row, vcName, item); |
|
576 nameChangedFromCode = false; |
|
577 |
|
578 // add 'size' item |
|
579 item = new QTableWidgetItem(); |
|
580 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); |
|
581 item->setTextAlignment(Qt::AlignRight); |
|
582 filesTable->setItem(row, vcSize, item); |
|
583 |
|
584 // add 'progress' item |
|
585 item = new QTableWidgetItem(); |
|
586 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); |
|
587 filesTable->setItem(row, vcProgress, item); |
|
588 |
|
589 return row; |
|
590 } |
|
591 |
|
592 VideoItem* PageVideos::nameItem(int row) |
|
593 { |
|
594 return (VideoItem*)filesTable->item(row, vcName); |
|
595 } |
|
596 |
|
597 void PageVideos::updateDescription() |
|
598 { |
|
599 VideoItem * item = nameItem(filesTable->currentRow()); |
|
600 QString desc = ""; |
|
601 if (item) |
|
602 { |
|
603 QString t = item->name; |
|
604 desc += item->name + "\n"; |
|
605 // t.replace(".mp4", ".bmp"); |
|
606 // QMessageBox::information(this, "1", cfgdir->absoluteFilePath("Screenshots/" + t)); |
|
607 // m_pic.load(cfgdir->absoluteFilePath("Screenshots/" + t)); |
|
608 // m_pic = m_pic.scaledToWidth(400); |
|
609 // m_thumbnail.setPixmap(m_pic); |
|
610 |
|
611 if (item->ready()) |
|
612 { |
|
613 QString path = item->path(); |
|
614 desc += tr("\nSize: ") + FileSizeStr(path) + "\n"; |
|
615 if (item->desc == "") |
|
616 item->desc = LibavIteraction::instance().getFileInfo(path); |
|
617 desc += item->desc; |
|
618 } |
|
619 else |
|
620 desc += tr("(in progress...)"); |
|
621 } |
|
622 labelDesc->setText(desc); |
|
623 } |
|
624 |
|
625 // user selected another cell, so we should change description |
|
626 void PageVideos::currentCellChanged(int row, int column, int previousRow, int previousColumn) |
|
627 { |
|
628 updateDescription(); |
|
629 } |
|
630 |
|
631 // open video file in external media player |
|
632 void PageVideos::play(int row) |
|
633 { |
|
634 VideoItem * item = nameItem(row); |
|
635 if (item->ready()) |
|
636 QDesktopServices::openUrl(QUrl("file:///" + item->path())); |
|
637 } |
|
638 |
|
639 void PageVideos::playSelectedFile() |
|
640 { |
|
641 int index = filesTable->currentRow(); |
|
642 if (index != -1) |
|
643 play(index); |
|
644 } |
|
645 |
|
646 void PageVideos::deleteSelectedFiles() |
|
647 { |
|
648 QList<QTableWidgetItem*> items = filesTable->selectedItems(); |
|
649 int num = items.size() / vcNumColumns; |
|
650 if (num == 0) |
|
651 return; |
|
652 |
|
653 // ask user if (s)he is serious |
|
654 if (QMessageBox::question(this, |
|
655 tr("Are you sure?"), |
|
656 tr("Do you really want do remove %1 file(s)?").arg(num), |
|
657 QMessageBox::Yes | QMessageBox::No) |
|
658 != QMessageBox::Yes) |
|
659 return; |
|
660 |
|
661 // remove |
|
662 foreach (QTableWidgetItem * witem, items) |
|
663 { |
|
664 if (witem->type() != QTableWidgetItem::UserType) |
|
665 continue; |
|
666 VideoItem * item = (VideoItem*)witem; |
|
667 if (!item->ready()) |
|
668 item->pRecorder->deleteLater(); |
|
669 else |
|
670 cfgdir->remove("Videos/" + item->name); |
|
671 } |
|
672 } |
|
673 |
|
674 void PageVideos::keyPressEvent(QKeyEvent * pEvent) |
|
675 { |
|
676 if (filesTable->hasFocus()) |
|
677 { |
|
678 if (pEvent->key() == Qt::Key_Delete) |
|
679 { |
|
680 deleteSelectedFiles(); |
|
681 return; |
|
682 } |
|
683 if (pEvent->key() == Qt::Key_Enter) // doesn't work |
|
684 { |
|
685 playSelectedFile(); |
|
686 return; |
|
687 } |
|
688 } |
|
689 AbstractPage::keyPressEvent(pEvent); |
|
690 } |
|
691 |
|
692 void PageVideos::openVideosDirectory() |
|
693 { |
|
694 QDesktopServices::openUrl(QUrl("file:///"+cfgdir->absolutePath() + "/Videos")); |
|
695 } |