1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3
4 #include <cmath>
5 #include <QLibraryInfo>
6 #include <QMimeData>
7 #include <QDesktopWidget>
8
9 #include "bakaengine.h"
10 #include "mpvhandler.h"
11 #include "gesturehandler.h"
12 #include "overlayhandler.h"
13 #include "util.h"
14 #include "widgets/dimdialog.h"
15 #include "inputdialog.h"
16 #include "screenshotdialog.h"
17
MainWindow(QWidget * parent)18 MainWindow::MainWindow(QWidget *parent):
19 QMainWindow(parent),
20 ui(new Ui::MainWindow)
21 {
22 ui->setupUi(this);
23 #if defined(Q_OS_UNIX) || defined(Q_OS_LINUX)
24 // update streaming support disabled on unix platforms
25 ui->actionUpdate_Streaming_Support->setEnabled(false);
26 #endif
27 ShowPlaylist(false);
28 addActions(ui->menubar->actions()); // makes menubar shortcuts work even when menubar is hidden
29
30 // initialize managers/handlers
31 baka = new BakaEngine(this);
32 mpv = baka->mpv;
33
34 ui->playlistWidget->AttachEngine(baka);
35 ui->mpvFrame->installEventFilter(this); // capture events on mpvFrame in the eventFilter function
36 ui->mpvFrame->setMouseTracking(true);
37 autohide = new QTimer(this);
38
39 // command action mappings (action (right) performs command (left))
40 commandActionMap = {
41 {"mpv add chapter +1", ui->action_Next_Chapter},
42 {"mpv add chapter -1", ui->action_Previous_Chapter},
43 {"mpv set sub-scale 1", ui->action_Reset_Size},
44 {"mpv add sub-scale +0.1", ui->action_Size},
45 {"mpv add sub-scale -0.1", ui->actionS_ize},
46 {"mpv set video-aspect -1", ui->action_Auto_Detect}, // todo: make these baka-commands so we can output messages when they change
47 {"mpv set video-aspect 16:9", ui->actionForce_16_9},
48 {"mpv set video-aspect 2.35:1", ui->actionForce_2_35_1},
49 {"mpv set video-aspect 4:3", ui->actionForce_4_3},
50 {"mpv cycle sub-visibility", ui->actionShow_Subtitles},
51 {"mpv set time-pos 0", ui->action_Restart},
52 {"mpv frame_step", ui->action_Frame_Step},
53 {"mpv frame_back_step", ui->actionFrame_Back_Step},
54 {"deinterlace", ui->action_Deinterlace},
55 {"interpolate", ui->action_Motion_Interpolation},
56 {"mute", ui->action_Mute},
57 {"screenshot subtitles", ui->actionWith_Subtitles},
58 {"screenshot", ui->actionWithout_Subtitles},
59 {"add_subtitles", ui->action_Add_Subtitle_File},
60 {"add_audio", ui->action_Add_Audio_File},
61 {"fitwindow", ui->action_To_Current_Size},
62 {"fitwindow 50", ui->action50},
63 {"fitwindow 75", ui->action75},
64 {"fitwindow 100", ui->action100},
65 {"fitwindow 150", ui->action150},
66 {"fitwindow 200", ui->action200},
67 {"fullscreen", ui->action_Full_Screen},
68 {"hide_all_controls", ui->actionHide_All_Controls},
69 {"jump", ui->action_Jump_to_Time},
70 {"media_info", ui->actionMedia_Info},
71 {"new", ui->action_New_Player},
72 {"open", ui->action_Open_File},
73 {"open_clipboard", ui->actionOpen_Path_from_Clipboard},
74 {"open_location", ui->actionOpen_URL},
75 {"playlist play +1", ui->actionPlay_Next_File},
76 {"playlist play -1", ui->actionPlay_Previous_File},
77 {"playlist repeat off", ui->action_Off},
78 {"playlist repeat playlist", ui->action_Playlist},
79 {"playlist repeat this", ui->action_This_File},
80 {"playlist shuffle", ui->actionSh_uffle},
81 {"playlist toggle", ui->action_Show_Playlist},
82 {"playlist full", ui->action_Hide_Album_Art},
83 {"dim", ui->action_Dim_Lights},
84 {"play_pause", ui->action_Play},
85 {"quit", ui->actionE_xit},
86 {"show_in_folder", ui->actionShow_in_Folder},
87 {"stop", ui->action_Stop},
88 {"volume +5", ui->action_Increase_Volume},
89 {"volume -5", ui->action_Decrease_Volume},
90 {"speed +0.1", ui->action_Increase},
91 {"speed -0.1", ui->action_Decrease},
92 {"speed 1.0", ui->action_Reset},
93 {"output", ui->actionShow_D_ebug_Output},
94 {"preferences", ui->action_Preferences},
95 {"online_help", ui->actionOnline_Help},
96 {"update", ui->action_Check_for_Updates},
97 {"update youtube-dl", ui->actionUpdate_Streaming_Support},
98 {"about qt", ui->actionAbout_Qt},
99 {"about", ui->actionAbout_Baka_MPlayer}
100 };
101
102 // map actions to commands
103 for(auto action = commandActionMap.begin(); action != commandActionMap.end(); ++action)
104 {
105 const QString cmd = action.key();
106 connect(*action, &QAction::triggered,
107 [=] { baka->Command(cmd); });
108 }
109
110 // setup signals & slots
111
112 // mainwindow
113 connect(this, &MainWindow::langChanged,
114 [=](QString lang)
115 {
116 if(lang == "auto") // fetch lang from locale
117 lang = QLocale::system().name();
118
119 if(lang != "en")
120 {
121 QTranslator *tmp;
122
123 // load the system translations provided by Qt
124 tmp = baka->qtTranslator;
125 baka->qtTranslator = new QTranslator();
126 baka->qtTranslator->load(QString("qt_%0").arg(lang), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
127 qApp->installTranslator(baka->qtTranslator);
128 if(tmp != nullptr)
129 delete tmp;
130
131 // load the application translations
132 tmp = baka->translator;
133 baka->translator = new QTranslator();
134 baka->translator->load(QString("baka-mplayer_%0").arg(lang), BAKA_MPLAYER_LANG_PATH);
135 qApp->installTranslator(baka->translator);
136 if(tmp != nullptr)
137 delete tmp;
138 }
139 else
140 {
141 if(baka->qtTranslator != nullptr)
142 qApp->removeTranslator(baka->qtTranslator);
143 if(baka->translator != nullptr)
144 qApp->removeTranslator(baka->translator);
145 }
146
147 // save strings we want to keep
148 QString title = windowTitle(),
149 duration = ui->durationLabel->text(),
150 remaining = ui->remainingLabel->text(),
151 index = ui->indexLabel->text();
152
153 ui->retranslateUi(this);
154
155 // reload strings we kept
156 setWindowTitle(title);
157 ui->durationLabel->setText(duration);
158 ui->remainingLabel->setText(remaining);
159 ui->indexLabel->setText(index);
160 });
161
162 connect(this, &MainWindow::onTopChanged,
163 [=](QString onTop)
164 {
165 if(onTop == "never")
166 Util::SetAlwaysOnTop(winId(), false);
167 else if(onTop == "always")
168 Util::SetAlwaysOnTop(winId(), true);
169 else if(onTop == "playing" && mpv->getPlayState() > 0)
170 Util::SetAlwaysOnTop(winId(), true);
171 });
172
173 connect(this, &MainWindow::remainingChanged,
174 [=]
175 {
176 SetRemainingLabels(mpv->getTime());
177 });
178
179 connect(this, &MainWindow::debugChanged,
180 [=](bool b)
181 {
182 ui->actionShow_D_ebug_Output->setChecked(b);
183 ui->verticalWidget->setVisible(b);
184 mouseMoveEvent(new QMouseEvent(QMouseEvent::MouseMove,
185 QCursor::pos(),
186 Qt::NoButton,Qt::NoButton,Qt::NoModifier));
187 if(b)
188 ui->inputLineEdit->setFocus();
189 });
190
191 connect(this, &MainWindow::hideAllControlsChanged,
192 [=](bool b)
193 {
194 HideAllControls(b);
195 blockSignals(true);
196 ui->actionHide_All_Controls->setChecked(b);
197 blockSignals(false);
198 });
199
200 connect(baka->sysTrayIcon, &QSystemTrayIcon::activated,
201 [=](QSystemTrayIcon::ActivationReason reason)
202 {
203 if(reason == QSystemTrayIcon::Trigger)
204 {
205 if(!hidePopup)
206 {
207 if(mpv->getPlayState() == Mpv::Playing)
208 baka->sysTrayIcon->showMessage("Baka MPlayer", tr("Playing"), QSystemTrayIcon::NoIcon, 4000);
209 else if(mpv->getPlayState() == Mpv::Paused)
210 baka->sysTrayIcon->showMessage("Baka MPlayer", tr("Paused"), QSystemTrayIcon::NoIcon, 4000);
211 }
212 baka->PlayPause();
213 }
214
215 });
216
217 // connect(this, &MainWindow::hidePopupChanged,
218 // [=](bool b)
219 // {
220 // });
221
222 connect(autohide, &QTimer::timeout, // cursor autohide
223 [=]
224 {
225 if(ui->mpvFrame->geometry().contains(ui->mpvFrame->mapFromGlobal(cursor().pos())))
226 setCursor(QCursor(Qt::BlankCursor));
227 if(autohide)
228 autohide->stop();
229 });
230
231 // dimDialog
232 connect(baka->dimDialog, &DimDialog::visbilityChanged,
233 [=](bool dim)
234 {
235 ui->action_Dim_Lights->setChecked(dim);
236 if(dim)
237 Util::SetAlwaysOnTop(winId(), true);
238 else if(onTop == "never" || (onTop == "playing" && mpv->getPlayState() > 0))
239 Util::SetAlwaysOnTop(winId(), false);
240 });
241
242 // mpv
243
244 connect(mpv, &MpvHandler::playlistChanged,
245 [=](const QStringList &list)
246 {
247 if(list.length() > 1)
248 {
249 ui->actionSh_uffle->setEnabled(true);
250 ui->actionStop_after_Current->setEnabled(true);
251 ShowPlaylist(true);
252 }
253 else
254 {
255 ui->actionSh_uffle->setEnabled(false);
256 ui->actionStop_after_Current->setEnabled(false);
257 }
258
259 if(list.length() > 0)
260 ui->menuR_epeat->setEnabled(true);
261 else
262 ui->menuR_epeat->setEnabled(false);
263 });
264
265 connect(mpv, &MpvHandler::fileInfoChanged,
266 [=](const Mpv::FileInfo &fileInfo)
267 {
268 if(mpv->getPlayState() > 0)
269 {
270 if(fileInfo.media_title == "")
271 setWindowTitle("Baka MPlayer");
272 else if(fileInfo.media_title == "-")
273 setWindowTitle("Baka MPlayer: stdin"); // todo: disable playlist?
274 else
275 setWindowTitle(fileInfo.media_title);
276
277 QString f = mpv->getFile(), file = mpv->getPath()+f;
278 if(f != QString() && maxRecent > 0)
279 {
280 int i = recent.indexOf(file);
281 if(i >= 0)
282 {
283 int t = recent.at(i).time;
284 if(t > 0 && resume)
285 mpv->Seek(t);
286 recent.removeAt(i);
287 }
288 if(recent.isEmpty() || recent.front() != file)
289 {
290 UpdateRecentFiles(); // update after initialization and only if the current file is different from the first recent
291 while(recent.length() > maxRecent-1)
292 recent.removeLast();
293 recent.push_front(
294 Recent(file,
295 (mpv->getPath() == QString() || !Util::IsValidFile(file)) ?
296 fileInfo.media_title : QString()));
297 current = &recent.front();
298 }
299 }
300
301 // reset speed if length isn't known and we have a streaming video
302 // todo: don't save this reset, put their speed back when a normal video comes on
303 // todo: disable speed alteration during streaming media
304 if(fileInfo.length == 0)
305 if(mpv->getSpeed() != 1)
306 mpv->Speed(1);
307
308 ui->seekBar->setTracking(fileInfo.length);
309
310 if(ui->actionMedia_Info->isChecked())
311 baka->MediaInfo(true);
312
313 SetRemainingLabels(fileInfo.length);
314 }
315 });
316
317 connect(mpv, &MpvHandler::trackListChanged,
318 [=](const QList<Mpv::Track> &trackList)
319 {
320 if(mpv->getPlayState() > 0)
321 {
322 QAction *action;
323 bool video = false,
324 albumArt = false;
325
326 ui->menuSubtitle_Track->clear();
327 ui->menuSubtitle_Track->addAction(ui->action_Add_Subtitle_File);
328 ui->menuAudio_Tracks->clear();
329 ui->menuAudio_Tracks->addAction(ui->action_Add_Audio_File);
330 for(auto &track : trackList)
331 {
332 if(track.type == "sub")
333 {
334 action = ui->menuSubtitle_Track->addAction(QString("%0: %1 (%2)").arg(QString::number(track.id), track.title, track.external ? "external" : track.lang).replace("&", "&&"));
335 connect(action, &QAction::triggered,
336 [=]
337 {
338 // basically, if you uncheck the selected subtitle id, we hide subtitles
339 // when you check a subtitle id, we make sure subtitles are showing and set it
340 if(mpv->getSid() == track.id)
341 {
342 if(mpv->getSubtitleVisibility())
343 {
344 mpv->ShowSubtitles(false);
345 return;
346 }
347 else
348 mpv->ShowSubtitles(true);
349 }
350 else if(!mpv->getSubtitleVisibility())
351 mpv->ShowSubtitles(true);
352 mpv->Sid(track.id);
353 mpv->ShowText(QString("%0 %1: %2 (%3)").arg(tr("Sub"), QString::number(track.id), track.title, track.external ? "external" : track.lang));
354 });
355 }
356 else if(track.type == "audio")
357 {
358 action = ui->menuAudio_Tracks->addAction(QString("%0: %1 (%2)").arg(QString::number(track.id), track.title, track.lang).replace("&", "&&"));
359 connect(action, &QAction::triggered,
360 [=]
361 {
362 if(mpv->getAid() != track.id) // don't allow selection of the same track
363 {
364 mpv->Aid(track.id);
365 mpv->ShowText(QString("%0 %1: %2 (%3)").arg(tr("Audio"), QString::number(track.id), track.title, track.lang));
366 }
367 else
368 action->setChecked(true); // recheck the track
369 });
370 }
371 else if(track.type == "video") // video track
372 {
373 if(!track.albumart) // isn't album art
374 video = true;
375 else
376 albumArt = true;
377 }
378 }
379 if(video)
380 {
381 // if we were hiding album art, show it--we've gone to a video
382 if(ui->mpvFrame->styleSheet() != QString()) // remove filler album art
383 ui->mpvFrame->setStyleSheet("");
384 if(ui->action_Hide_Album_Art->isChecked())
385 HideAlbumArt(false);
386 ui->action_Hide_Album_Art->setEnabled(false);
387 ui->menuSubtitle_Track->setEnabled(true);
388 if(ui->menuSubtitle_Track->actions().count() > 1)
389 {
390 ui->menuFont_Si_ze->setEnabled(true);
391 ui->actionShow_Subtitles->setEnabled(true);
392 ui->actionShow_Subtitles->setChecked(mpv->getSubtitleVisibility());
393 }
394 else
395 {
396 ui->menuFont_Si_ze->setEnabled(false);
397 ui->actionShow_Subtitles->setEnabled(false);
398 ui->actionShow_Subtitles->setChecked(false);
399 }
400 ui->menuTake_Screenshot->setEnabled(true);
401 ui->menuFit_Window->setEnabled(true);
402 ui->menuAspect_Ratio->setEnabled(true);
403 ui->action_Frame_Step->setEnabled(true);
404 ui->actionFrame_Back_Step->setEnabled(true);
405 ui->action_Deinterlace->setEnabled(true);
406 ui->action_Motion_Interpolation->setEnabled(true);
407 }
408 else
409 {
410 if(!albumArt)
411 {
412 // put in filler albumArt
413 if(ui->mpvFrame->styleSheet() == QString())
414 ui->mpvFrame->setStyleSheet("background-image:url(:/img/album-art.png);background-repeat:no-repeat;background-position:center;");
415 }
416 ui->action_Hide_Album_Art->setEnabled(true);
417 ui->menuSubtitle_Track->setEnabled(false);
418 ui->menuFont_Si_ze->setEnabled(false);
419 ui->actionShow_Subtitles->setEnabled(false);
420 ui->actionShow_Subtitles->setChecked(false);
421 ui->menuTake_Screenshot->setEnabled(false);
422 ui->menuFit_Window->setEnabled(false);
423 ui->menuAspect_Ratio->setEnabled(false);
424 ui->action_Frame_Step->setEnabled(false);
425 ui->actionFrame_Back_Step->setEnabled(false);
426 ui->action_Deinterlace->setEnabled(false);
427 ui->action_Motion_Interpolation->setEnabled(false);
428
429 if(baka->sysTrayIcon->isVisible() && !hidePopup)
430 {
431 // todo: use {artist} - {title}
432 baka->sysTrayIcon->showMessage("Baka MPlayer", mpv->getFileInfo().media_title, QSystemTrayIcon::NoIcon, 4000);
433 }
434 }
435
436 if(ui->menuAudio_Tracks->actions().count() == 1)
437 ui->menuAudio_Tracks->actions().first()->setEnabled(false);
438
439 if(pathChanged && autoFit)
440 {
441 baka->FitWindow(autoFit, false);
442 pathChanged = false;
443 }
444 }
445 });
446
447 connect(mpv, &MpvHandler::chaptersChanged,
448 [=](const QList<Mpv::Chapter> &chapters)
449 {
450 if(mpv->getPlayState() > 0)
451 {
452 QAction *action;
453 QList<int> ticks;
454 int n = 1,
455 N = chapters.length();
456 ui->menu_Chapters->clear();
457 for(auto &ch : chapters)
458 {
459 action = ui->menu_Chapters->addAction(QString("%0: %1").arg(Util::FormatNumberWithAmpersand(n, N), ch.title));
460 if(n <= 9)
461 action->setShortcut(QKeySequence("Ctrl+"+QString::number(n)));
462 connect(action, &QAction::triggered,
463 [=]
464 {
465 mpv->Seek(ch.time);
466 });
467 ticks.push_back(ch.time);
468 n++;
469 }
470 if(ui->menu_Chapters->actions().count() == 0)
471 {
472 ui->menu_Chapters->setEnabled(false);
473 ui->action_Next_Chapter->setEnabled(false);
474 ui->action_Previous_Chapter->setEnabled(false);
475 }
476 else
477 {
478 ui->menu_Chapters->setEnabled(true);
479 ui->action_Next_Chapter->setEnabled(true);
480 ui->action_Previous_Chapter->setEnabled(true);
481 }
482
483 ui->seekBar->setTicks(ticks);
484 }
485 });
486
487 connect(mpv, &MpvHandler::playStateChanged,
488 [=](Mpv::PlayState playState)
489 {
490 switch(playState)
491 {
492 case Mpv::Loaded:
493 baka->mpv->ShowText("Loading...", 0);
494 break;
495
496 case Mpv::Started:
497 if(!init) // will only happen the first time a file is loaded.
498 {
499 ui->action_Play->setEnabled(true);
500 ui->playButton->setEnabled(true);
501 #if defined(Q_OS_WIN)
502 playpause_toolbutton->setEnabled(true);
503 #endif
504 ui->playlistButton->setEnabled(true);
505 ui->action_Show_Playlist->setEnabled(true);
506 ui->menuAudio_Tracks->setEnabled(true);
507 init = true;
508 }
509 SetPlaybackControls(true);
510 mpv->Play();
511 baka->overlay->showStatusText(QString(), 0);
512 case Mpv::Playing:
513 SetPlayButtonIcon(false);
514 if(onTop == "playing")
515 Util::SetAlwaysOnTop(winId(), true);
516 break;
517
518 case Mpv::Paused:
519 case Mpv::Stopped:
520 SetPlayButtonIcon(true);
521 if(onTop == "playing")
522 Util::SetAlwaysOnTop(winId(), false);
523 break;
524
525 case Mpv::Idle:
526 if(init)
527 {
528 if(ui->action_This_File->isChecked()) // repeat this file
529 ui->playlistWidget->PlayIndex(0, true); // restart file
530 else if(ui->actionStop_after_Current->isChecked() || // stop after playing this file
531 ui->playlistWidget->CurrentIndex() >= ui->playlistWidget->count()-1) // end of the playlist
532 {
533 if(!ui->actionStop_after_Current->isChecked() && // not supposed to stop after current
534 ui->action_Playlist->isChecked() && // we're supposed to restart the playlist
535 ui->playlistWidget->count() > 0) // playlist isn't empty
536 {
537 ui->playlistWidget->PlayIndex(0); // restart playlist
538 }
539 else // stop
540 {
541 setWindowTitle("Baka MPlayer");
542 SetPlaybackControls(false);
543 ui->seekBar->setTracking(0);
544 ui->actionStop_after_Current->setChecked(false);
545 if(ui->mpvFrame->styleSheet() != QString()) // remove filler album art
546 ui->mpvFrame->setStyleSheet("");
547 }
548 }
549 else
550 ui->playlistWidget->PlayIndex(1, true);
551 }
552 break;
553 }
554 });
555
556 connect(mpv, &MpvHandler::pathChanged,
557 [=]()
558 {
559 pathChanged = true;
560 });
561
562 connect(mpv, &MpvHandler::fileChanging,
563 [=](int t, int l)
564 {
565 if(current != nullptr)
566 {
567 if(t > 0.05*l && t < 0.95*l) // only save if within the middle 90%
568 current->time = t;
569 else
570 current->time = 0;
571 }
572 });
573
574 // connect(mpv, &MpvHandler::fileChanged,
575 // [=](QString f)
576 // {
577 // });
578
579 connect(mpv, &MpvHandler::timeChanged,
580 [=](int i)
581 {
582 const Mpv::FileInfo &fi = mpv->getFileInfo();
583 // set the seekBar's location with NoSignal function so that it doesn't trigger a seek
584 // the formula is a simple ratio seekBar's max * time/totalTime
585 ui->seekBar->setValueNoSignal(ui->seekBar->maximum()*((double)i/fi.length));
586
587 SetRemainingLabels(i);
588
589 // set next/previous chapter's enabled state
590 if(fi.chapters.length() > 0)
591 {
592 ui->action_Next_Chapter->setEnabled(i < fi.chapters.last().time);
593 ui->action_Previous_Chapter->setEnabled(i > fi.chapters.first().time);
594 }
595 });
596
597 connect(mpv, &MpvHandler::volumeChanged,
598 [=](int volume)
599 {
600 ui->volumeSlider->setValueNoSignal(volume);
601 });
602
603 connect(mpv, &MpvHandler::speedChanged,
604 [=](double speed)
605 {
606 static double last = 1;
607 if(last != speed)
608 {
609 if(init)
610 mpv->ShowText(tr("Speed: %0x").arg(QString::number(speed)));
611 if(speed <= 0.25)
612 ui->action_Decrease->setEnabled(false);
613 else
614 ui->action_Decrease->setEnabled(true);
615 last = speed;
616 }
617 });
618
619 connect(mpv, &MpvHandler::sidChanged,
620 [=](int sid)
621 {
622 QList<QAction*> actions = ui->menuSubtitle_Track->actions();
623 for(auto &action : actions)
624 {
625 if(action->text().startsWith(QString::number(sid)))
626 {
627 action->setCheckable(true);
628 action->setChecked(true);
629 }
630 else
631 action->setChecked(false);
632 }
633 });
634
635 connect(mpv, &MpvHandler::aidChanged,
636 [=](int aid)
637 {
638 QList<QAction*> actions = ui->menuAudio_Tracks->actions();
639 for(auto &action : actions)
640 {
641 if(action->text().startsWith(QString::number(aid)))
642 {
643 action->setCheckable(true);
644 action->setChecked(true);
645 }
646 else
647 action->setChecked(false);
648 }
649 });
650
651 connect(mpv, &MpvHandler::subtitleVisibilityChanged,
652 [=](bool b)
653 {
654 if(ui->actionShow_Subtitles->isEnabled())
655 ui->actionShow_Subtitles->setChecked(b);
656 if(init)
657 mpv->ShowText(b ? tr("Subtitles visible") : tr("Subtitles hidden"));
658 });
659
660 connect(mpv, &MpvHandler::muteChanged,
661 [=](bool b)
662 {
663 if(b)
664 ui->muteButton->setIcon(QIcon(":/img/default_mute.svg"));
665 else
666 ui->muteButton->setIcon(QIcon(":/img/default_unmute.svg"));
667 mpv->ShowText(b ? tr("Muted") : tr("Unmuted"));
668 });
669
670 connect(mpv, &MpvHandler::voChanged,
671 [=](QString vo)
672 {
673 ui->action_Motion_Interpolation->setChecked(vo.contains("interpolation"));
674 });
675 // ui
676
677 connect(ui->seekBar, &SeekBar::valueChanged, // Playback: Seekbar clicked
678 [=](int i)
679 {
680 mpv->Seek(mpv->Relative(((double)i/ui->seekBar->maximum())*mpv->getFileInfo().length), true);
681 });
682
683 connect(ui->openButton, &OpenButton::LeftClick, // Playback: Open button (left click)
684 [=]
685 {
686 baka->Open();
687 });
688
689 connect(ui->openButton, &OpenButton::MiddleClick, // Playback: Open button (middle click)
690 [=]
691 {
692 baka->Jump();
693 });
694
695 connect(ui->openButton, &OpenButton::RightClick, // Playback: Open button (right click)
696 [=]
697 {
698 baka->OpenLocation();
699 });
700
701 connect(ui->rewindButton, &QPushButton::clicked, // Playback: Rewind button
702 [=]
703 {
704 mpv->Rewind();
705 });
706
707 connect(ui->previousButton, &IndexButton::clicked, // Playback: Previous button
708 [=]
709 {
710 ui->playlistWidget->PlayIndex(-1, true);
711 });
712
713 connect(ui->playButton, &QPushButton::clicked, // Playback: Play/pause button
714 [=]
715 {
716 baka->PlayPause();
717 });
718
719 connect(ui->nextButton, &IndexButton::clicked, // Playback: Next button
720 [=]
721 {
722 ui->playlistWidget->PlayIndex(1, true);
723 });
724
725 connect(ui->muteButton, &QPushButton::clicked,
726 [=]
727 {
728 mpv->Mute(!mpv->getMute());
729 });
730
731 connect(ui->volumeSlider, &CustomSlider::valueChanged, // Playback: Volume slider adjusted
732 [=](int i)
733 {
734 mpv->Volume(i, true);
735 });
736
737 connect(ui->playlistButton, &QPushButton::clicked, // Playback: Clicked the playlist button
738 [=]
739 {
740 TogglePlaylist();
741 });
742
743 connect(ui->splitter, &CustomSplitter::positionChanged, // Splitter position changed
744 [=](int i)
745 {
746 blockSignals(true);
747 if(i == 0) // right-most, playlist is hidden
748 {
749 ui->action_Show_Playlist->setChecked(false);
750 ui->action_Hide_Album_Art->setChecked(false);
751 ui->playlistLayoutWidget->setVisible(false);
752 }
753 else if(i == ui->splitter->max()) // left-most, album art is hidden, playlist is visible
754 {
755 ui->action_Show_Playlist->setChecked(true);
756 ui->action_Hide_Album_Art->setChecked(true);
757 }
758 else // in the middle, album art is visible, playlist is visible
759 {
760 ui->action_Show_Playlist->setChecked(true);
761 ui->action_Hide_Album_Art->setChecked(false);
762 }
763 ui->playlistLayoutWidget->setVisible(ui->action_Show_Playlist->isChecked());
764 blockSignals(false);
765 if(ui->actionMedia_Info->isChecked())
766 baka->overlay->showInfoText();
767 });
768
769 connect(ui->searchBox, &QLineEdit::textChanged, // Playlist: Search box
770 [=](QString s)
771 {
772 ui->playlistWidget->Search(s);
773 });
774
775 connect(ui->indexLabel, &CustomLabel::clicked, // Playlist: Clicked the indexLabel
776 [=]
777 {
778 QString res = InputDialog::getInput(tr("Enter the file number you want to play:\nNote: Value must be from %0 - %1").arg("1", QString::number(ui->playlistWidget->count())),
779 tr("Enter File Number"),
780 [this](QString input)
781 {
782 int in = input.toInt();
783 if(in >= 1 && in <= ui->playlistWidget->count())
784 return true;
785 return false;
786 },
787 this);
788 if(res != "")
789 ui->playlistWidget->PlayIndex(res.toInt()-1); // user index will be 1 greater than actual
790 });
791
792 connect(ui->playlistWidget, &PlaylistWidget::currentRowChanged, // Playlist: Playlist selection changed
793 [=](int)
794 {
795 SetIndexLabels(true);
796 });
797
798 connect(ui->currentFileButton, &QPushButton::clicked, // Playlist: Select current file button
799 [=]
800 {
801 ui->playlistWidget->SelectIndex(ui->playlistWidget->CurrentIndex());
802 });
803
804 connect(ui->hideFilesButton, &QPushButton::clicked, // Playlist: Hide files button
805 [=](bool b)
806 {
807 ui->playlistWidget->ShowAll(!b);
808 });
809
810 connect(ui->refreshButton, &QPushButton::clicked, // Playlist: Refresh playlist button
811 [=]
812 {
813 ui->playlistWidget->RefreshPlaylist();
814 });
815
816 connect(ui->inputLineEdit, &CustomLineEdit::submitted,
817 [=](QString s)
818 {
819 baka->Command(s);
820 ui->inputLineEdit->setText("");
821 });
822
823 // add multimedia shortcuts
824 ui->action_Play->setShortcuts({ui->action_Play->shortcut(), QKeySequence(Qt::Key_MediaPlay)});
825 ui->action_Stop->setShortcuts({ui->action_Stop->shortcut(), QKeySequence(Qt::Key_MediaStop)});
826 ui->actionPlay_Next_File->setShortcuts({ui->actionPlay_Next_File->shortcut(), QKeySequence(Qt::Key_MediaNext)});
827 ui->actionPlay_Previous_File->setShortcuts({ui->actionPlay_Previous_File->shortcut(), QKeySequence(Qt::Key_MediaPrevious)});
828 }
829
~MainWindow()830 MainWindow::~MainWindow()
831 {
832 if(current != nullptr)
833 {
834 int t = mpv->getTime(),
835 l = mpv->getFileInfo().length;
836 if(t > 0.05*l && t < 0.95*l) // only save if within the middle 90%
837 current->time = t;
838 else
839 current->time = 0;
840 }
841 baka->SaveSettings();
842
843 // Note: child objects _should_ not need to be deleted because
844 // all children should get deleted when mainwindow is deleted
845 // see: http://qt-project.org/doc/qt-4.8/objecttrees.html
846
847 // but apparently they don't (https://github.com/u8sand/Baka-MPlayer/issues/47)
848 #if defined(Q_OS_WIN)
849 delete prev_toolbutton;
850 delete playpause_toolbutton;
851 delete next_toolbutton;
852 delete thumbnail_toolbar;
853 #endif
854 delete baka;
855 delete ui;
856 }
857
Load(QString file)858 void MainWindow::Load(QString file)
859 {
860 // load the settings here--the constructor has already been called
861 // this solves some issues with setting things before the constructor has ended
862 menuVisible = ui->menubar->isVisible(); // does the OS use a menubar? (appmenu doesn't)
863 #if defined(Q_OS_WIN)
864 // add windows 7+ thubnail toolbar buttons
865 thumbnail_toolbar = new QWinThumbnailToolBar(this);
866 thumbnail_toolbar->setWindow(this->windowHandle());
867
868 prev_toolbutton = new QWinThumbnailToolButton(thumbnail_toolbar);
869 prev_toolbutton->setEnabled(false);
870 prev_toolbutton->setToolTip(tr("Previous"));
871 prev_toolbutton->setIcon(QIcon(":/img/tool-previous.ico"));
872 connect(prev_toolbutton, &QWinThumbnailToolButton::clicked,
873 [=]
874 {
875 ui->playlistWidget->PlayIndex(-1, true);
876 });
877
878 playpause_toolbutton = new QWinThumbnailToolButton(thumbnail_toolbar);
879 playpause_toolbutton->setEnabled(false);
880 playpause_toolbutton->setToolTip(tr("Play"));
881 playpause_toolbutton->setIcon(QIcon(":/img/tool-play.ico"));
882 connect(playpause_toolbutton, &QWinThumbnailToolButton::clicked,
883 [=]
884 {
885 baka->PlayPause();
886 });
887
888 next_toolbutton = new QWinThumbnailToolButton(thumbnail_toolbar);
889 next_toolbutton->setEnabled(false);
890 next_toolbutton->setToolTip(tr("Next"));
891 next_toolbutton->setIcon(QIcon(":/img/tool-next.ico"));
892 connect(next_toolbutton, &QWinThumbnailToolButton::clicked,
893 [=]
894 {
895 ui->playlistWidget->PlayIndex(1, true);
896 });
897
898 thumbnail_toolbar->addButton(prev_toolbutton);
899 thumbnail_toolbar->addButton(playpause_toolbutton);
900 thumbnail_toolbar->addButton(next_toolbutton);
901 #endif
902 baka->LoadSettings();
903 mpv->Initialize();
904 mpv->LoadFile(file);
905 }
906
MapShortcuts()907 void MainWindow::MapShortcuts()
908 {
909 auto tmp = commandActionMap;
910 // map shortcuts to actions
911 for(auto input_iter = baka->input.begin(); input_iter != baka->input.end(); ++input_iter)
912 {
913 auto commandAction = tmp.find(input_iter->first);
914 if(commandAction != tmp.end())
915 {
916 (*commandAction)->setShortcut(QKeySequence(input_iter.key()));
917 tmp.erase(commandAction);
918 }
919 }
920 // clear the rest
921 for(auto iter = tmp.begin(); iter != tmp.end(); ++iter)
922 (*iter)->setShortcut(QKeySequence());
923 }
924
dragEnterEvent(QDragEnterEvent * event)925 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
926 {
927 if(event->mimeData()->hasUrls() || event->mimeData()->hasText()) // url / text
928 event->acceptProposedAction();
929 }
930
dropEvent(QDropEvent * event)931 void MainWindow::dropEvent(QDropEvent *event)
932 {
933 const QMimeData *mimeData = event->mimeData();
934 if(mimeData->hasUrls()) // urls
935 {
936 for(QUrl &url : mimeData->urls())
937 {
938 if(url.isLocalFile())
939 mpv->LoadFile(url.toLocalFile());
940 else
941 mpv->LoadFile(url.url());
942 }
943 }
944 else if(mimeData->hasText()) // text
945 mpv->LoadFile(mimeData->text());
946 }
947
mousePressEvent(QMouseEvent * event)948 void MainWindow::mousePressEvent(QMouseEvent *event)
949 {
950 if(event->button() == Qt::LeftButton)
951 {
952 if(gestures)
953 {
954 if(ui->mpvFrame->geometry().contains(event->pos())) // mouse is in the mpvFrame
955 baka->gesture->Begin(GestureHandler::HSEEK_VVOLUME, event->globalPos(), pos());
956 else if(!isFullScreen()) // not fullscreen
957 baka->gesture->Begin(GestureHandler::MOVE, event->globalPos(), pos());
958 }
959 else if(!isFullScreen()) // not fullscreen
960 baka->gesture->Begin(GestureHandler::MOVE, event->globalPos(), pos());
961
962 if(ui->remainingLabel->rect().contains(ui->remainingLabel->mapFrom(this, event->pos()))) // clicked timeLayoutWidget
963 setRemaining(!remaining); // todo: use a bakacommand
964 }
965 else if(event->button() == Qt::RightButton &&
966 !isFullScreenMode() && // not fullscreen mode
967 mpv->getPlayState() > 0 && // playing
968 ui->mpvFrame->geometry().contains(event->pos())) // mouse is in the mpvFrame
969 {
970 mpv->PlayPause(ui->playlistWidget->CurrentItem());
971 }
972 QMainWindow::mousePressEvent(event);
973 }
974
mouseReleaseEvent(QMouseEvent * event)975 void MainWindow::mouseReleaseEvent(QMouseEvent *event)
976 {
977 baka->gesture->End();
978 QMainWindow::mouseReleaseEvent(event);
979 }
980
mouseMoveEvent(QMouseEvent * event)981 void MainWindow::mouseMoveEvent(QMouseEvent *event)
982 {
983 if(baka->gesture->Process(event->globalPos()))
984 event->accept();
985 else if(isFullScreenMode())
986 {
987 setCursor(QCursor(Qt::ArrowCursor)); // show the cursor
988 autohide->stop();
989
990 QRect playbackRect = geometry();
991 playbackRect.setTop(playbackRect.bottom() - 60);
992 bool showPlayback = playbackRect.contains(event->globalPos());
993 ui->playbackLayoutWidget->setVisible(showPlayback || ui->outputTextEdit->isVisible());
994 ui->seekBar->setVisible(showPlayback || ui->outputTextEdit->isVisible());
995
996 QRect playlistRect = geometry();
997 playlistRect.setLeft(playlistRect.right() - std::ceil(playlistRect.width()/7.0));
998 bool showPlaylist = playlistRect.contains(event->globalPos());
999 ShowPlaylist(showPlaylist);
1000
1001 if(!(showPlayback || showPlaylist) && autohide)
1002 autohide->start(500);
1003 }
1004 QMainWindow::mouseMoveEvent(event);
1005 }
1006
leaveEvent(QEvent * event)1007 void MainWindow::leaveEvent(QEvent *event)
1008 {
1009 mouseMoveEvent(new QMouseEvent(QMouseEvent::MouseMove,
1010 QCursor::pos(),
1011 Qt::NoButton,Qt::NoButton,Qt::NoModifier));
1012 QMainWindow::leaveEvent(event);
1013 }
1014
eventFilter(QObject * obj,QEvent * event)1015 bool MainWindow::eventFilter(QObject *obj, QEvent *event)
1016 {
1017 if(obj == ui->mpvFrame && isFullScreenMode() && event->type() == QEvent::MouseMove)
1018 {
1019 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
1020 mouseMoveEvent(mouseEvent);
1021 }
1022 else if(event->type() == 6) // QEvent::KeyPress = 6 (but using QEvent::KeyPress causes compile errors, not sure why)
1023 {
1024 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
1025 keyPressEvent(keyEvent);
1026 }
1027 return false;
1028 }
1029
wheelEvent(QWheelEvent * event)1030 void MainWindow::wheelEvent(QWheelEvent *event)
1031 {
1032 if(event->delta() > 0)
1033 mpv->Volume(mpv->getVolume()+5, true);
1034 else
1035 mpv->Volume(mpv->getVolume()-5, true);
1036 QMainWindow::wheelEvent(event);
1037 }
1038
keyPressEvent(QKeyEvent * event)1039 void MainWindow::keyPressEvent(QKeyEvent *event)
1040 {
1041 // keyboard shortcuts
1042 if(!baka->input.empty())
1043 {
1044 QString key = QKeySequence(event->modifiers()|event->key()).toString();
1045
1046 // TODO: Add more protection/find a better way to protect edit boxes from executing commands
1047 if(focusWidget() == ui->inputLineEdit &&
1048 key == "Return")
1049 return;
1050
1051 // Escape exits fullscreen
1052 if(isFullScreen() &&
1053 key == "Esc") {
1054 FullScreen(false);
1055 return;
1056 }
1057
1058 // find shortcut in input hash table
1059 auto iter = baka->input.find(key);
1060 if(iter != baka->input.end())
1061 baka->Command(iter->first); // execute command
1062 }
1063 }
1064
resizeEvent(QResizeEvent * event)1065 void MainWindow::resizeEvent(QResizeEvent *event)
1066 {
1067 if(ui->actionMedia_Info->isChecked())
1068 baka->overlay->showInfoText();
1069 QMainWindow::resizeEvent(event);
1070 }
1071
mouseDoubleClickEvent(QMouseEvent * event)1072 void MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
1073 {
1074 if(event->button() == Qt::LeftButton && ui->mpvFrame->geometry().contains(event->pos())) // if mouse is in the mpvFrame
1075 {
1076 if(!isFullScreen() && ui->action_Full_Screen->isEnabled()) // don't allow people to go full screen if they shouldn't be able to
1077 FullScreen(true);
1078 else // they can leave fullscreen even if it's disabled (eg. video ends while in full screen)
1079 FullScreen(false);
1080 event->accept();
1081 }
1082 QMainWindow::mouseDoubleClickEvent(event);
1083 }
1084
SetIndexLabels(bool enable)1085 void MainWindow::SetIndexLabels(bool enable)
1086 {
1087 int i = ui->playlistWidget->currentRow(),
1088 index = ui->playlistWidget->CurrentIndex();
1089
1090 // next file
1091 if(enable && index+1 < ui->playlistWidget->count()) // not the last entry
1092 {
1093 SetNextButtonEnabled(true);
1094 ui->nextButton->setIndex(index+2); // starting at 1 instead of at 0 like actual index
1095
1096 }
1097 else
1098 SetNextButtonEnabled(false);
1099
1100 // previous file
1101 if(enable && index-1 >= 0) // not the first entry
1102 {
1103 SetPreviousButtonEnabled(true);
1104 ui->previousButton->setIndex(-index); // we use a negative index value for the left button
1105 }
1106 else
1107 SetPreviousButtonEnabled(false);
1108
1109 if(i == -1) // no selection
1110 {
1111 ui->indexLabel->setText(tr("No selection"));
1112 ui->indexLabel->setEnabled(false);
1113 }
1114 else
1115 {
1116 ui->indexLabel->setEnabled(true);
1117 ui->indexLabel->setText(tr("File %0 of %1").arg(QString::number(i+1), QString::number(ui->playlistWidget->count())));
1118 }
1119 }
1120
SetPlaybackControls(bool enable)1121 void MainWindow::SetPlaybackControls(bool enable)
1122 {
1123 // playback controls
1124 ui->seekBar->setEnabled(enable);
1125 ui->rewindButton->setEnabled(enable);
1126
1127 SetIndexLabels(enable);
1128
1129 // menubar
1130 ui->action_Stop->setEnabled(enable);
1131 ui->action_Restart->setEnabled(enable);
1132 ui->menuS_peed->setEnabled(enable);
1133 ui->action_Jump_to_Time->setEnabled(enable);
1134 ui->actionMedia_Info->setEnabled(enable);
1135 ui->actionShow_in_Folder->setEnabled(enable && baka->mpv->getPath() != QString());
1136 ui->action_Full_Screen->setEnabled(enable);
1137 if(!enable)
1138 {
1139 ui->action_Hide_Album_Art->setEnabled(false);
1140 ui->menuSubtitle_Track->setEnabled(false);
1141 ui->menuFont_Si_ze->setEnabled(false);
1142 }
1143 }
1144
HideAllControls(bool w,bool s)1145 void MainWindow::HideAllControls(bool w, bool s)
1146 {
1147 if(s)
1148 {
1149 hideAllControls = w;
1150 if(isFullScreen())
1151 return;
1152 }
1153 if(w)
1154 {
1155 if(s || !hideAllControls)
1156 playlistState = ui->playlistLayoutWidget->isVisible();
1157 ui->menubar->setVisible(false);
1158 setContextMenuPolicy(Qt::ActionsContextMenu);
1159 mouseMoveEvent(new QMouseEvent(QMouseEvent::MouseMove,
1160 QCursor::pos(),
1161 Qt::NoButton,Qt::NoButton,Qt::NoModifier));
1162 }
1163 else
1164 {
1165 if(menuVisible)
1166 ui->menubar->setVisible(true);
1167 ui->seekBar->setVisible(true);
1168 ui->playbackLayoutWidget->setVisible(true);
1169 setContextMenuPolicy(Qt::NoContextMenu);
1170 setCursor(QCursor(Qt::ArrowCursor)); // show cursor
1171 autohide->stop();
1172 ShowPlaylist(playlistState);
1173 }
1174 }
1175
FullScreen(bool fs)1176 void MainWindow::FullScreen(bool fs)
1177 {
1178 if(fs)
1179 {
1180 if(baka->dimDialog && baka->dimDialog->isVisible())
1181 baka->Dim(false);
1182 setWindowState(windowState() | Qt::WindowFullScreen);
1183 if(!hideAllControls)
1184 HideAllControls(true, false);
1185 }
1186 else
1187 {
1188 setWindowState(windowState() & ~Qt::WindowFullScreen);
1189 if(!hideAllControls)
1190 HideAllControls(false, false);
1191 }
1192 }
1193
isPlaylistVisible()1194 bool MainWindow::isPlaylistVisible()
1195 {
1196 // if the position is 0, playlist is hidden
1197 return (ui->splitter->position() != 0);
1198 }
1199
TogglePlaylist()1200 void MainWindow::TogglePlaylist()
1201 {
1202 ShowPlaylist(!isPlaylistVisible());
1203 }
1204
ShowPlaylist(bool visible)1205 void MainWindow::ShowPlaylist(bool visible)
1206 {
1207 if(ui->splitter->position() != 0 && visible) // ignore showing if it's already visible as it resets original position
1208 return;
1209
1210 if(visible)
1211 ui->splitter->setPosition(ui->splitter->normalPosition()); // bring splitter position to normal
1212 else
1213 {
1214 if(ui->splitter->position() != ui->splitter->max() && ui->splitter->position() != 0)
1215 ui->splitter->setNormalPosition(ui->splitter->position()); // save current splitter position as the normal position
1216 ui->splitter->setPosition(0); // set splitter position to right-most
1217 setFocus();
1218 }
1219 }
1220
HideAlbumArt(bool hide)1221 void MainWindow::HideAlbumArt(bool hide)
1222 {
1223 if(hide)
1224 {
1225 if(ui->splitter->position() != ui->splitter->max() && ui->splitter->position() != 0)
1226 ui->splitter->setNormalPosition(ui->splitter->position()); // save splitter position as the normal position
1227 ui->splitter->setPosition(ui->splitter->max()); // bring the splitter position to the left-most
1228 }
1229 else
1230 ui->splitter->setPosition(ui->splitter->normalPosition()); // bring the splitter to normal position
1231 }
1232
UpdateRecentFiles()1233 void MainWindow::UpdateRecentFiles()
1234 {
1235 ui->menu_Recently_Opened->clear();
1236 QAction *action;
1237 int n = 1,
1238 N = recent.length();
1239 for(auto &f : recent)
1240 {
1241 action = ui->menu_Recently_Opened->addAction(QString("%0. %1").arg(Util::FormatNumberWithAmpersand(n, N), Util::ShortenPathToParent(f).replace("&","&&")));
1242 if(n++ == 1)
1243 action->setShortcut(QKeySequence("Ctrl+Z"));
1244 connect(action, &QAction::triggered,
1245 [=]
1246 {
1247 mpv->LoadFile(f);
1248 });
1249 }
1250 }
1251
SetNextButtonEnabled(bool enable)1252 void MainWindow::SetNextButtonEnabled(bool enable)
1253 {
1254 ui->nextButton->setEnabled(enable);
1255 ui->actionPlay_Next_File->setEnabled(enable);
1256 #if defined(Q_OS_WIN)
1257 next_toolbutton->setEnabled(enable);
1258 #endif
1259 }
1260
SetPreviousButtonEnabled(bool enable)1261 void MainWindow::SetPreviousButtonEnabled(bool enable)
1262 {
1263 ui->previousButton->setEnabled(enable);
1264 ui->actionPlay_Previous_File->setEnabled(enable);
1265 #if defined(Q_OS_WIN)
1266 prev_toolbutton->setEnabled(enable);
1267 #endif
1268 }
1269
SetPlayButtonIcon(bool play)1270 void MainWindow::SetPlayButtonIcon(bool play)
1271 {
1272 if(play)
1273 {
1274 ui->playButton->setIcon(QIcon(":/img/default_play.svg"));
1275 ui->action_Play->setText(tr("&Play"));
1276 #if defined(Q_OS_WIN)
1277 playpause_toolbutton->setToolTip(tr("Play"));
1278 playpause_toolbutton->setIcon(QIcon(":/img/tool-play.ico"));
1279 #endif
1280 }
1281 else // pause icon
1282 {
1283 ui->playButton->setIcon(QIcon(":/img/default_pause.svg"));
1284 ui->action_Play->setText(tr("&Pause"));
1285 #if defined(Q_OS_WIN)
1286 playpause_toolbutton->setToolTip(tr("Pause"));
1287 playpause_toolbutton->setIcon(QIcon(":/img/tool-pause.ico"));
1288 #endif
1289 }
1290 }
1291
SetRemainingLabels(int time)1292 void MainWindow::SetRemainingLabels(int time)
1293 {
1294 // todo: move setVisible functions outside of this function which gets called every second and somewhere at the start of a video
1295 const Mpv::FileInfo &fi = mpv->getFileInfo();
1296 if(fi.length == 0)
1297 {
1298 ui->durationLabel->setText(Util::FormatTime(time, time));
1299 ui->remainingLabel->setVisible(false);
1300 ui->seperatorLabel->setVisible(false);
1301 }
1302 else
1303 {
1304 ui->remainingLabel->setVisible(true);
1305 ui->seperatorLabel->setVisible(true);
1306
1307 ui->durationLabel->setText(Util::FormatTime(time, fi.length));
1308 if(remaining)
1309 {
1310 int remainingTime = fi.length - time;
1311 QString text = "-" + Util::FormatTime(remainingTime, fi.length);
1312 if(mpv->getSpeed() != 1)
1313 {
1314 double speed = mpv->getSpeed();
1315 text += QString(" (-%0)").arg(Util::FormatTime(int(remainingTime/speed), int(fi.length/speed)));
1316 }
1317 ui->remainingLabel->setText(text);
1318 }
1319 else
1320 {
1321 QString text = Util::FormatTime(fi.length, fi.length);
1322 if(mpv->getSpeed() != 1)
1323 {
1324 double speed = mpv->getSpeed();
1325 text += QString(" (%0)").arg(Util::FormatTime(int(fi.length/speed), int(fi.length/speed)));
1326 }
1327 ui->remainingLabel->setText(text);
1328 }
1329 }
1330 }
1331