File indexing completed on 2024-05-12 04:57:14
0001 /* 0002 SPDX-FileCopyrightText: 2007-2009 Sergio Pistone <sergio_pistone@yahoo.com.ar> 0003 SPDX-FileCopyrightText: 2010-2022 Mladen Milinkovic <max@smoothware.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "config.h" 0009 0010 #include "appglobal.h" 0011 #include "application.h" 0012 #include "actions/krecentfilesactionext.h" 0013 #include "actions/useraction.h" 0014 #include "actions/useractionnames.h" 0015 #include "configs/configdialog.h" 0016 #include "core/richtext/richdocument.h" 0017 #include "core/subtitleiterator.h" 0018 #include "core/undo/undostack.h" 0019 #include "gui/currentlinewidget.h" 0020 #include "gui/subtitlemeta/subtitlemetawidget.h" 0021 #include "helpers/common.h" 0022 #include "dialogs/actionwithtargetdialog.h" 0023 #include "dialogs/shifttimesdialog.h" 0024 #include "dialogs/adjusttimesdialog.h" 0025 #include "dialogs/durationlimitsdialog.h" 0026 #include "dialogs/autodurationsdialog.h" 0027 #include "dialogs/changetextscasedialog.h" 0028 #include "dialogs/fixoverlappingtimesdialog.h" 0029 #include "dialogs/fixpunctuationdialog.h" 0030 #include "dialogs/smarttextsadjustdialog.h" 0031 #include "dialogs/changeframeratedialog.h" 0032 #include "dialogs/insertlinedialog.h" 0033 #include "dialogs/removelinesdialog.h" 0034 #include "dialogs/intinputdialog.h" 0035 #include "dialogs/subtitlecolordialog.h" 0036 #include "errors/errorfinder.h" 0037 #include "errors/errortracker.h" 0038 #include "formats/formatmanager.h" 0039 #include "formats/outputformat.h" 0040 #include "formats/textdemux/textdemux.h" 0041 #include "helpers/commondefs.h" 0042 #include "helpers/fileloadhelper.h" 0043 #include "helpers/filesavehelper.h" 0044 #include "gui/treeview/lineswidget.h" 0045 #include "mainwindow.h" 0046 #include "gui/playerwidget.h" 0047 #include "scripting/scriptsmanager.h" 0048 #include "speechprocessor/speechprocessor.h" 0049 #include "utils/finder.h" 0050 #include "utils/replacer.h" 0051 #include "utils/speller.h" 0052 #include "videoplayer/videoplayer.h" 0053 #include "gui/waveform/waveformwidget.h" 0054 0055 #include <limits> 0056 0057 #include <QAction> 0058 #include <QByteArrayList> 0059 #include <QDir> 0060 #include <QDockWidget> 0061 #include <QFileDialog> 0062 #include <QFileInfo> 0063 #include <QGridLayout> 0064 #include <QKeySequence> 0065 #include <QLabel> 0066 #include <QMenuBar> 0067 #include <QStatusBar> 0068 #include <QStringBuilder> 0069 #include <QTextCodec> 0070 #include <QThread> 0071 #include <QUndoGroup> 0072 #include <QUndoStack> 0073 0074 #include <KActionCollection> 0075 #include <KCharsets> 0076 #include <KComboBox> 0077 #include <KConfig> 0078 #include <KMessageBox> 0079 #include <KSelectAction> 0080 #include <KStandardShortcut> 0081 #include <KStandardAction> 0082 #include <KToggleAction> 0083 #include <KToolBar> 0084 #include <kxmlgui_version.h> 0085 0086 using namespace SubtitleComposer; 0087 0088 static void 0089 setupIconTheme(int argc, char **argv) 0090 { 0091 #ifdef SC_BUNDLE_SYSTEM_THEME 0092 QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << $(":/icons")); 0093 #endif 0094 if(QIcon::themeName().isEmpty()) 0095 QIcon::setThemeName($("breeze")); 0096 0097 const QStringList fallbackPaths = { 0098 $(":/icons-fallback/breeze/actions/22"), 0099 $(":/icons-fallback/breeze/apps/256"), 0100 $(":/icons-fallback/breeze/apps/128"), 0101 $(":/icons-fallback/breeze/apps/48"), 0102 $(":/icons-fallback/breeze/apps/32"), 0103 $(":/icons-fallback/breeze/apps/16"), 0104 }; 0105 0106 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) 0107 QIcon::setFallbackSearchPaths(QIcon::fallbackSearchPaths() 0108 #else 0109 QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() 0110 #endif 0111 // access the icons through breeze theme path 0112 << $(":/icons-fallback") 0113 // or directly as fallback 0114 << fallbackPaths); 0115 0116 #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) 0117 if(QIcon::fallbackThemeName().isEmpty()) 0118 QIcon::setFallbackThemeName($("breeze")); 0119 #endif 0120 0121 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) 0122 // LXQt just ignores QIcon::fallbackSearchPaths() 0123 QString platformThemeName = QString::fromLocal8Bit(qgetenv("QT_QPA_PLATFORMTHEME")); 0124 for(int i = 0; i < argc; i++) { 0125 if(strcmp(argv[i], "-platformtheme") == 0 && ++i < argc) { 0126 platformThemeName = QString::fromLocal8Bit(argv[i]); 0127 break; 0128 } 0129 } 0130 0131 if(platformThemeName == $("lxqt")) 0132 QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << fallbackPaths); 0133 #else 0134 Q_UNUSED(argc) 0135 Q_UNUSED(argv) 0136 #endif 0137 } 0138 0139 Application::Application(int &argc, char **argv) : 0140 QApplication(argc, argv), 0141 m_translationMode(false), 0142 m_textDemux(nullptr), 0143 m_speechProcessor(nullptr), 0144 m_lastFoundLine(nullptr), 0145 m_lastSubtitleUrl(QDir::homePath()), 0146 m_lastVideoUrl(QDir::homePath()), 0147 m_linkCurrentLineToPosition(false) 0148 { 0149 AppGlobal::app = this; 0150 0151 KLocalizedString::setApplicationDomain("subtitlecomposer"); 0152 0153 setupIconTheme(argc, argv); 0154 0155 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0156 setAttribute(Qt::AA_UseHighDpiPixmaps, true); 0157 #endif 0158 } 0159 0160 void 0161 Application::createMainWindow() 0162 { 0163 m_mainWindow = new MainWindow(); 0164 connect(m_mainWindow, &QObject::destroyed, this, [&](){ m_mainWindow = nullptr; }); 0165 0166 m_finder = new Finder(m_mainWindow->m_linesWidget); 0167 m_replacer = new Replacer(m_mainWindow->m_linesWidget); 0168 m_errorFinder = new ErrorFinder(m_mainWindow->m_linesWidget); 0169 m_speller = new Speller(m_mainWindow->m_linesWidget); 0170 0171 m_errorTracker = new ErrorTracker(this); 0172 0173 QStatusBar *statusBar = m_mainWindow->statusBar(); 0174 QMargins m = statusBar->contentsMargins(); 0175 m.setRight(m.left() + 5); 0176 statusBar->setContentsMargins(m); 0177 0178 m_labSubFormat = new QLabel(); 0179 statusBar->addPermanentWidget(m_labSubFormat); 0180 0181 m_labSubEncoding = new QLabel(); 0182 statusBar->addPermanentWidget(m_labSubEncoding); 0183 0184 m_textDemux = new TextDemux(m_mainWindow); 0185 statusBar->addPermanentWidget(m_textDemux->progressWidget()); 0186 0187 m_speechProcessor = new SpeechProcessor(m_mainWindow); 0188 statusBar->addPermanentWidget(m_speechProcessor->progressWidget()); 0189 0190 m_scriptsManager = new ScriptsManager(this); 0191 0192 AppGlobal::undoStack = new UndoStack(m_mainWindow); 0193 0194 UserActionManager *actionManager = UserActionManager::instance(); 0195 actionManager->setLinesWidget(m_mainWindow->m_linesWidget); 0196 actionManager->setFullScreenMode(false); 0197 0198 setupActions(); 0199 0200 connect(SCConfig::self(), &KCoreConfigSkeleton::configChanged, this, &Application::onConfigChanged); 0201 0202 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0203 connect(videoPlayer, &VideoPlayer::fileOpened, this, &Application::onPlayerFileOpened); 0204 connect(videoPlayer, &VideoPlayer::playing, this, &Application::onPlayerPlaying); 0205 connect(videoPlayer, &VideoPlayer::paused, this, &Application::onPlayerPaused); 0206 connect(videoPlayer, &VideoPlayer::stopped, this, &Application::onPlayerStopped); 0207 connect(videoPlayer, &VideoPlayer::audioStreamsChanged, this, &Application::onPlayerAudioStreamsChanged); 0208 connect(videoPlayer, &VideoPlayer::textStreamsChanged, this, &Application::onPlayerTextStreamsChanged); 0209 connect(videoPlayer, &VideoPlayer::activeAudioStreamChanged, this, &Application::onPlayerActiveAudioStreamChanged); 0210 connect(videoPlayer, &VideoPlayer::muteChanged, this, &Application::onPlayerMuteChanged); 0211 0212 #define CONNECT_SUB(c, x) \ 0213 connect(this, &Application::subtitleOpened, x, &c::setSubtitle); \ 0214 connect(this, &Application::subtitleClosed, x, [&](){ x->setSubtitle(nullptr); }); 0215 0216 CONNECT_SUB(UserActionManager, UserActionManager::instance()); 0217 CONNECT_SUB(PlayerWidget, m_mainWindow->m_playerWidget); 0218 CONNECT_SUB(SubtitleMetaWidget, m_mainWindow->m_metaWidget); 0219 CONNECT_SUB(LinesWidget, m_mainWindow->m_linesWidget); 0220 CONNECT_SUB(CurrentLineWidget, m_mainWindow->m_curLineWidget); 0221 CONNECT_SUB(Finder, m_finder); 0222 CONNECT_SUB(Replacer, m_replacer); 0223 CONNECT_SUB(ErrorFinder, m_errorFinder); 0224 CONNECT_SUB(Speller, m_speller); 0225 CONNECT_SUB(ErrorTracker, m_errorTracker); 0226 CONNECT_SUB(ScriptsManager, m_scriptsManager); 0227 CONNECT_SUB(WaveformWidget, m_mainWindow->m_waveformWidget); 0228 CONNECT_SUB(SpeechProcessor, m_speechProcessor); 0229 0230 #define CONNECT_TRANS(c, x) \ 0231 connect(this, &Application::translationModeChanged, x, &c::setTranslationMode); 0232 0233 CONNECT_TRANS(UserActionManager, UserActionManager::instance()); 0234 CONNECT_TRANS(PlayerWidget, m_mainWindow->m_playerWidget); 0235 CONNECT_TRANS(WaveformWidget, m_mainWindow->m_waveformWidget); 0236 CONNECT_TRANS(LinesWidget, m_mainWindow->m_linesWidget); 0237 CONNECT_TRANS(CurrentLineWidget, m_mainWindow->m_curLineWidget); 0238 CONNECT_TRANS(Finder, m_finder); 0239 CONNECT_TRANS(Replacer, m_replacer); 0240 CONNECT_TRANS(ErrorFinder, m_errorFinder); 0241 CONNECT_TRANS(Speller, m_speller); 0242 0243 connect(this, &Application::fullScreenModeChanged, actionManager, &UserActionManager::setFullScreenMode); 0244 0245 connect(m_mainWindow->m_waveformWidget, &WaveformWidget::doubleClick, this, &Application::onWaveformDoubleClicked); 0246 connect(m_mainWindow->m_waveformWidget, &WaveformWidget::middleMouseDown, this, &Application::onWaveformMiddleMouse); 0247 connect(m_mainWindow->m_waveformWidget, &WaveformWidget::middleMouseMove, this, &Application::onWaveformMiddleMouse); 0248 connect(m_mainWindow->m_waveformWidget, &WaveformWidget::middleMouseUp, this, &Application::onWaveformMiddleMouse); 0249 0250 connect(m_mainWindow->m_linesWidget, &LinesWidget::currentLineChanged, m_mainWindow->m_metaWidget, &SubtitleMetaWidget::setCurrentLine); 0251 0252 connect(m_mainWindow->m_linesWidget, &LinesWidget::currentLineChanged, m_mainWindow->m_curLineWidget, &CurrentLineWidget::setCurrentLine); 0253 connect(m_mainWindow->m_linesWidget, &LinesWidget::lineDoubleClicked, this, &Application::onLineDoubleClicked); 0254 0255 connect(m_mainWindow->m_playerWidget, &PlayerWidget::playingLineChanged, this, &Application::onPlayingLineChanged); 0256 0257 connect(m_finder, &Finder::found, this, &Application::onHighlightLine); 0258 connect(m_replacer, &Replacer::found, this, &Application::onHighlightLine); 0259 connect(m_errorFinder, &ErrorFinder::found, this, [this](SubtitleLine *l){ onHighlightLine(l); }); 0260 connect(m_speller, &Speller::misspelled, this, &Application::onHighlightLine); 0261 0262 connect(m_textDemux, &TextDemux::onError, this, [&](const QString &message){ KMessageBox::error(m_mainWindow, message); }); 0263 0264 connect(m_speechProcessor, &SpeechProcessor::onError, this, [&](const QString &message){ KMessageBox::error(m_mainWindow, message); }); 0265 0266 m_mainWindow->setupGUI(); 0267 0268 // Workaround for https://phabricator.kde.org/D13808 0269 // menubar can't be hidden so always show it 0270 m_mainWindow->findChild<QMenuBar *>(QString(), Qt::FindDirectChildrenOnly)->show(); 0271 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 1) && KXMLGUI_VERSION < QT_VERSION_CHECK(5, 49, 0) 0272 // show rest if we're on broken KF5/Qt 0273 m_mainWindow->findChild<QStatusBar *>(QString(), Qt::FindDirectChildrenOnly)->show(); 0274 m_mainWindow->findChild<QDockWidget *>(QStringLiteral("player_dock"), Qt::FindDirectChildrenOnly)->show(); 0275 m_mainWindow->findChild<QDockWidget *>(QStringLiteral("waveform_dock"), Qt::FindDirectChildrenOnly)->show(); 0276 foreach(KToolBar *toolbar, m_mainWindow->toolBars()) 0277 toolbar->show(); 0278 #endif 0279 0280 m_scriptsManager->reloadScripts(); 0281 0282 loadConfig(); 0283 } 0284 0285 Application::~Application() 0286 { 0287 // NOTE: The Application destructor is called after all widgets are destroyed 0288 // (NOT BEFORE). Therefore is not possible to save the program settings (nor do 0289 // pretty much anything) at this point. 0290 0291 // delete m_mainWindow; the window is destroyed when it's closed 0292 AppGlobal::app = nullptr; 0293 } 0294 0295 void 0296 Application::loadConfig() 0297 { 0298 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0299 KConfigGroup group(config->group("Application Settings")); 0300 0301 m_lastSubtitleUrl = QUrl(group.readPathEntry("LastSubtitleUrl", QDir::homePath())); 0302 m_recentSubtitlesAction->loadEntries(config->group("Recent Subtitles")); 0303 m_recentSubtitlesTrAction->loadEntries(config->group("Recent Translation Subtitles")); 0304 0305 m_lastVideoUrl = QUrl(group.readPathEntry("LastVideoUrl", QDir::homePath())); 0306 m_recentVideosAction->loadEntries(config->group("Recent Videos")); 0307 0308 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0309 videoPlayer->setMuted(group.readEntry<bool>("Muted", false)); 0310 videoPlayer->setVolume(group.readEntry<double>("Volume", 100.0)); 0311 0312 ((KToggleAction *)action(ACT_TOGGLE_MUTED))->setChecked(videoPlayer->isMuted()); 0313 0314 KConfigGroup wfGroup(config->group("Waveform Widget")); 0315 action(ACT_WAVEFORM_AUTOSCROLL)->setChecked(wfGroup.readEntry<bool>("AutoScroll", true)); 0316 if(wfGroup.hasKey("Zoom")) 0317 m_mainWindow->m_waveformWidget->setZoom(wfGroup.readEntry<quint32>("Zoom", 0)); 0318 0319 m_mainWindow->loadConfig(); 0320 m_mainWindow->m_playerWidget->loadConfig(); 0321 m_mainWindow->m_linesWidget->loadConfig(); 0322 m_mainWindow->m_curLineWidget->loadConfig(); 0323 } 0324 0325 void 0326 Application::saveConfig() 0327 { 0328 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0329 KConfigGroup group(config->group("Application Settings")); 0330 0331 group.writePathEntry("LastSubtitleUrl", m_lastSubtitleUrl.toString()); 0332 m_recentSubtitlesAction->saveEntries(config->group("Recent Subtitles")); 0333 m_recentSubtitlesTrAction->saveEntries(config->group("Recent Translation Subtitles")); 0334 0335 group.writePathEntry("LastVideoUrl", m_lastVideoUrl.toString()); 0336 m_recentVideosAction->saveEntries(config->group("Recent Videos")); 0337 0338 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0339 group.writeEntry("Muted", videoPlayer->isMuted()); 0340 group.writeEntry("Volume", videoPlayer->volume()); 0341 0342 KConfigGroup wfGroup(config->group("Waveform Widget")); 0343 wfGroup.writeEntry("AutoScroll", m_mainWindow->m_waveformWidget->autoScroll()); 0344 wfGroup.writeEntry("Zoom", m_mainWindow->m_waveformWidget->zoom()); 0345 0346 m_mainWindow->saveConfig(); 0347 m_mainWindow->m_playerWidget->saveConfig(); 0348 m_mainWindow->m_linesWidget->saveConfig(); 0349 m_mainWindow->m_curLineWidget->saveConfig(); 0350 } 0351 0352 bool 0353 Application::triggerAction(const QKeySequence &keySequence) 0354 { 0355 QList<QAction *> actions = m_mainWindow->actionCollection()->actions(); 0356 0357 for(QList<QAction *>::ConstIterator it = actions.constBegin(), end = actions.constEnd(); it != end; ++it) { 0358 if((*it)->isEnabled()) { 0359 if(QAction * action = qobject_cast<QAction *>(*it)) { 0360 QKeySequence shortcut = action->shortcut(); 0361 if(shortcut.matches(keySequence) == QKeySequence::ExactMatch) { 0362 action->trigger(); 0363 return true; 0364 } 0365 } else { 0366 if((*it)->shortcut() == keySequence) { 0367 (*it)->trigger(); 0368 return true; 0369 } 0370 } 0371 } 0372 } 0373 0374 return false; 0375 } 0376 0377 const QStringList & 0378 Application::availableEncodingNames() const 0379 { 0380 static QStringList encodingNames; 0381 0382 if(encodingNames.empty()) { 0383 QStringList encodings(KCharsets::charsets()->availableEncodingNames()); 0384 for(QStringList::Iterator it = encodings.begin(); it != encodings.end(); ++it) { 0385 QTextCodec *codec = QTextCodec::codecForName(it->toUtf8()); 0386 if(codec) 0387 encodingNames.append(codec->name().toUpper()); 0388 } 0389 encodingNames.sort(); 0390 } 0391 0392 return encodingNames; 0393 } 0394 0395 void 0396 Application::showPreferences() 0397 { 0398 (new ConfigDialog(m_mainWindow, "scconfig", SCConfig::self()))->show(); 0399 } 0400 0401 /// BEGIN ACTION HANDLERS 0402 0403 Time 0404 Application::videoPosition(bool compensate) 0405 { 0406 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0407 if(compensate && !videoPlayer->isPaused()) 0408 return Time(double(videoPlayer->position()) * 1000. - SCConfig::grabbedPositionCompensation()); 0409 else 0410 return Time(double(videoPlayer->position()) * 1000.); 0411 } 0412 0413 void 0414 Application::insertBeforeCurrentLine() 0415 { 0416 static InsertLineDialog *dlg = new InsertLineDialog(true, m_mainWindow); 0417 0418 if(dlg->exec() == QDialog::Accepted) { 0419 SubtitleLine *newLine; 0420 { 0421 LinesWidgetScrollToModelDetacher detacher(*m_mainWindow->m_linesWidget); 0422 SubtitleLine *currentLine = m_mainWindow->m_linesWidget->currentLine(); 0423 newLine = appSubtitle()->insertNewLine(currentLine ? currentLine->index() : 0, false, dlg->selectedTextsTarget()); 0424 } 0425 m_mainWindow->m_linesWidget->setCurrentLine(newLine, true); 0426 } 0427 } 0428 0429 void 0430 Application::insertAfterCurrentLine() 0431 { 0432 static InsertLineDialog *dlg = new InsertLineDialog(false, m_mainWindow); 0433 0434 if(dlg->exec() == QDialog::Accepted) { 0435 SubtitleLine *newLine; 0436 { 0437 LinesWidgetScrollToModelDetacher detacher(*m_mainWindow->m_linesWidget); 0438 0439 SubtitleLine *currentLine = m_mainWindow->m_linesWidget->currentLine(); 0440 newLine = appSubtitle()->insertNewLine(currentLine ? currentLine->index() + 1 : 0, true, dlg->selectedTextsTarget()); 0441 } 0442 m_mainWindow->m_linesWidget->setCurrentLine(newLine, true); 0443 } 0444 } 0445 0446 void 0447 Application::removeSelectedLines() 0448 { 0449 static RemoveLinesDialog *dlg = new RemoveLinesDialog(m_mainWindow); 0450 0451 if(dlg->exec() == QDialog::Accepted) { 0452 RangeList selectionRanges = m_mainWindow->m_linesWidget->selectionRanges(); 0453 0454 if(selectionRanges.isEmpty()) 0455 return; 0456 0457 { 0458 LinesWidgetScrollToModelDetacher detacher(*m_mainWindow->m_linesWidget); 0459 appSubtitle()->removeLines(selectionRanges, dlg->selectedTextsTarget()); 0460 } 0461 0462 int firstIndex = selectionRanges.firstIndex(); 0463 if(firstIndex < appSubtitle()->linesCount()) 0464 m_mainWindow->m_linesWidget->setCurrentLine(appSubtitle()->line(firstIndex), true); 0465 else if(firstIndex - 1 < appSubtitle()->linesCount()) 0466 m_mainWindow->m_linesWidget->setCurrentLine(appSubtitle()->line(firstIndex - 1), true); 0467 } 0468 } 0469 0470 void 0471 Application::joinSelectedLines() 0472 { 0473 const RangeList &ranges = m_mainWindow->m_linesWidget->selectionRanges(); 0474 0475 // if ( ranges.count() > 1 && KMessageBox::Continue != KMessageBox::warningContinueCancel( 0476 // m_mainWindow, 0477 // i18n( "Current selection has multiple ranges.\nContinuing will join them all." ), 0478 // i18n( "Join Lines" ) ) ) 0479 // return; 0480 0481 appSubtitle()->joinLines(ranges); 0482 } 0483 0484 void 0485 Application::splitSelectedLines() 0486 { 0487 appSubtitle()->splitLines(m_mainWindow->m_linesWidget->selectionRanges()); 0488 } 0489 0490 void 0491 Application::selectAllLines() 0492 { 0493 m_mainWindow->m_linesWidget->selectAll(); 0494 } 0495 0496 void 0497 Application::gotoLine() 0498 { 0499 IntInputDialog gotoLineDlg(i18n("Go to Line"), i18n("&Go to line:"), 1, appSubtitle()->linesCount(), m_mainWindow->m_linesWidget->currentLineIndex() + 1); 0500 0501 if(gotoLineDlg.exec() == QDialog::Accepted) 0502 m_mainWindow->m_linesWidget->setCurrentLine(appSubtitle()->line(gotoLineDlg.value() - 1), true); 0503 } 0504 0505 void 0506 Application::find() 0507 { 0508 m_lastFoundLine = nullptr; 0509 m_finder->find(m_mainWindow->m_linesWidget->selectionRanges(), m_mainWindow->m_linesWidget->currentLineIndex(), m_mainWindow->m_curLineWidget->focusedText(), false); 0510 } 0511 0512 void 0513 Application::findNext() 0514 { 0515 if(!m_finder->findNext()) { 0516 m_lastFoundLine = nullptr; 0517 m_finder->find(m_mainWindow->m_linesWidget->selectionRanges(), m_mainWindow->m_linesWidget->currentLineIndex(), m_mainWindow->m_curLineWidget->focusedText(), false); 0518 } 0519 } 0520 0521 void 0522 Application::findPrevious() 0523 { 0524 if(!m_finder->findPrevious()) { 0525 m_lastFoundLine = nullptr; 0526 m_finder->find(m_mainWindow->m_linesWidget->selectionRanges(), m_mainWindow->m_linesWidget->currentLineIndex(), m_mainWindow->m_curLineWidget->focusedText(), true); 0527 } 0528 } 0529 0530 void 0531 Application::replace() 0532 { 0533 m_replacer->replace(m_mainWindow->m_linesWidget->selectionRanges(), m_mainWindow->m_linesWidget->currentLineIndex(), m_mainWindow->m_curLineWidget->focusedText()); 0534 } 0535 0536 void 0537 Application::spellCheck() 0538 { 0539 m_speller->spellCheck(m_mainWindow->m_linesWidget->currentLineIndex()); 0540 } 0541 0542 void 0543 Application::retrocedeCurrentLine() 0544 { 0545 SubtitleLine *currentLine = m_mainWindow->m_linesWidget->currentLine(); 0546 if(currentLine && currentLine->prevLine()) 0547 m_mainWindow->m_linesWidget->setCurrentLine(currentLine->prevLine(), true); 0548 } 0549 0550 void 0551 Application::advanceCurrentLine() 0552 { 0553 SubtitleLine *currentLine = m_mainWindow->m_linesWidget->currentLine(); 0554 if(currentLine && currentLine->nextLine()) 0555 m_mainWindow->m_linesWidget->setCurrentLine(currentLine->nextLine(), true); 0556 } 0557 0558 void 0559 Application::toggleSelectedLinesBold() 0560 { 0561 appSubtitle()->toggleStyleFlag(m_mainWindow->m_linesWidget->selectionRanges(), RichString::Bold); 0562 } 0563 0564 void 0565 Application::toggleSelectedLinesItalic() 0566 { 0567 appSubtitle()->toggleStyleFlag(m_mainWindow->m_linesWidget->selectionRanges(), RichString::Italic); 0568 } 0569 0570 void 0571 Application::toggleSelectedLinesUnderline() 0572 { 0573 appSubtitle()->toggleStyleFlag(m_mainWindow->m_linesWidget->selectionRanges(), RichString::Underline); 0574 } 0575 0576 void 0577 Application::toggleSelectedLinesStrikeThrough() 0578 { 0579 appSubtitle()->toggleStyleFlag(m_mainWindow->m_linesWidget->selectionRanges(), RichString::StrikeThrough); 0580 } 0581 0582 void 0583 Application::changeSelectedLinesColor() 0584 { 0585 const RangeList range = m_mainWindow->m_linesWidget->selectionRanges(); 0586 SubtitleIterator it(*appSubtitle(), range); 0587 if(!it.current()) 0588 return; 0589 0590 QColor color = SubtitleColorDialog::getColor(QColor(it.current()->primaryDoc()->styleColorAt(0)), m_mainWindow); 0591 if(color.isValid()) 0592 appSubtitle()->changeTextColor(range, color.rgba()); 0593 } 0594 0595 void 0596 Application::shiftLines() 0597 { 0598 static ShiftTimesDialog *dlg = new ShiftTimesDialog(m_mainWindow); 0599 0600 dlg->resetShiftTime(); 0601 0602 if(dlg->exec() == QDialog::Accepted) 0603 appSubtitle()->shiftLines(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), dlg->shiftTimeMillis()); 0604 } 0605 0606 void 0607 Application::shiftSelectedLinesForwards() 0608 { 0609 appSubtitle()->shiftLines(m_mainWindow->m_linesWidget->selectionRanges(), SCConfig::linesQuickShiftAmount()); 0610 } 0611 0612 void 0613 Application::shiftSelectedLinesBackwards() 0614 { 0615 appSubtitle()->shiftLines(m_mainWindow->m_linesWidget->selectionRanges(), -SCConfig::linesQuickShiftAmount()); 0616 } 0617 0618 void 0619 Application::adjustLines() 0620 { 0621 static AdjustTimesDialog *dlg = new AdjustTimesDialog(m_mainWindow); 0622 0623 dlg->setFirstLineTime(appSubtitle()->firstLine()->showTime()); 0624 dlg->setLastLineTime(appSubtitle()->lastLine()->showTime()); 0625 0626 if(dlg->exec() == QDialog::Accepted) 0627 appSubtitle()->adjustLines(Range::full(), dlg->firstLineTime().toMillis(), dlg->lastLineTime().toMillis()); 0628 } 0629 0630 void 0631 Application::changeFrameRate() 0632 { 0633 static ChangeFrameRateDialog *dlg = new ChangeFrameRateDialog(appSubtitle()->framesPerSecond(), m_mainWindow); 0634 0635 dlg->setFromFramesPerSecond(appSubtitle()->framesPerSecond()); 0636 0637 if(dlg->exec() == QDialog::Accepted) { 0638 appSubtitle()->changeFramesPerSecond(dlg->toFramesPerSecond(), dlg->fromFramesPerSecond()); 0639 } 0640 } 0641 0642 void 0643 Application::enforceDurationLimits() 0644 { 0645 static DurationLimitsDialog *dlg = new DurationLimitsDialog(SCConfig::minDuration(), 0646 SCConfig::maxDuration(), 0647 m_mainWindow); 0648 0649 if(dlg->exec() == QDialog::Accepted) { 0650 appSubtitle()->applyDurationLimits(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0651 dlg->enforceMinDuration() ? dlg->minDuration() : Time(), 0652 dlg->enforceMaxDuration() ? dlg->maxDuration() : Time(std::numeric_limits<double>::max()), 0653 !dlg->preventOverlap()); 0654 } 0655 } 0656 0657 void 0658 Application::setAutoDurations() 0659 { 0660 static AutoDurationsDialog *dlg = new AutoDurationsDialog(60, 50, 50, m_mainWindow); 0661 0662 if(dlg->exec() == QDialog::Accepted) { 0663 appSubtitle()->setAutoDurations(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0664 dlg->charMillis(), dlg->wordMillis(), dlg->lineMillis(), 0665 !dlg->preventOverlap(), dlg->calculationMode()); 0666 } 0667 } 0668 0669 void 0670 Application::maximizeDurations() 0671 { 0672 static auto *dlg = new ActionWithLinesTargetDialog(i18n("Maximize Durations"), m_mainWindow); 0673 0674 if(dlg->exec() == QDialog::Accepted) 0675 appSubtitle()->setMaximumDurations(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget())); 0676 } 0677 0678 void 0679 Application::fixOverlappingLines() 0680 { 0681 static FixOverlappingTimesDialog *dlg = new FixOverlappingTimesDialog(m_mainWindow); 0682 0683 if(dlg->exec() == QDialog::Accepted) 0684 appSubtitle()->fixOverlappingLines(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), dlg->minimumInterval()); 0685 } 0686 0687 void 0688 Application::breakLines() 0689 { 0690 static SmartTextsAdjustDialog *dlg = new SmartTextsAdjustDialog(30, m_mainWindow); 0691 0692 if(dlg->exec() == QDialog::Accepted) 0693 appSubtitle()->breakLines(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0694 dlg->minLengthForLineBreak(), dlg->selectedTextsTarget()); 0695 } 0696 0697 void 0698 Application::unbreakTexts() 0699 { 0700 static ActionWithLinesAndTextsTargetDialog *dlg = new ActionWithLinesAndTextsTargetDialog(i18n("Unbreak Lines"), 0701 m_mainWindow); 0702 0703 if(dlg->exec() == QDialog::Accepted) 0704 appSubtitle()->unbreakTexts(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0705 dlg->selectedTextsTarget()); 0706 } 0707 0708 void 0709 Application::simplifySpaces() 0710 { 0711 static ActionWithLinesAndTextsTargetDialog *dlg = new ActionWithLinesAndTextsTargetDialog(i18n("Simplify Spaces"), 0712 m_mainWindow); 0713 0714 if(dlg->exec() == QDialog::Accepted) 0715 appSubtitle()->simplifyTextWhiteSpace(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0716 dlg->selectedTextsTarget()); 0717 } 0718 0719 void 0720 Application::changeCase() 0721 { 0722 static ChangeTextsCaseDialog *dlg = new ChangeTextsCaseDialog(m_mainWindow); 0723 0724 if(dlg->exec() == QDialog::Accepted) { 0725 switch(dlg->caseOperation()) { 0726 case ChangeTextsCaseDialog::Upper: 0727 appSubtitle()->upperCase(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0728 dlg->selectedTextsTarget()); 0729 break; 0730 case ChangeTextsCaseDialog::Lower: 0731 appSubtitle()->lowerCase(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0732 dlg->selectedTextsTarget()); 0733 break; 0734 case ChangeTextsCaseDialog::Title: 0735 appSubtitle()->titleCase(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0736 dlg->lowerFirst(), dlg->selectedTextsTarget()); 0737 break; 0738 case ChangeTextsCaseDialog::Sentence: 0739 appSubtitle()->sentenceCase(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0740 dlg->lowerFirst(), dlg->selectedTextsTarget()); 0741 break; 0742 } 0743 } 0744 } 0745 0746 void 0747 Application::fixPunctuation() 0748 { 0749 static FixPunctuationDialog *dlg = new FixPunctuationDialog(m_mainWindow); 0750 0751 if(dlg->exec() == QDialog::Accepted) { 0752 appSubtitle()->fixPunctuation(m_mainWindow->m_linesWidget->targetRanges(dlg->selectedLinesTarget()), 0753 dlg->spaces(), dlg->quotes(), dlg->englishI(), 0754 dlg->ellipsis(), dlg->selectedTextsTarget()); 0755 } 0756 } 0757 0758 void 0759 Application::openVideo(const QUrl &url) 0760 { 0761 if(url.scheme() != QStringLiteral("file")) 0762 return; 0763 0764 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0765 videoPlayer->closeFile(); 0766 videoPlayer->openFile(url.toLocalFile()); 0767 } 0768 0769 void 0770 Application::openVideo() 0771 { 0772 QFileDialog openDlg(m_mainWindow, i18n("Open Video"), QString(), buildMediaFilesFilter()); 0773 0774 openDlg.setModal(true); 0775 openDlg.selectUrl(m_lastVideoUrl); 0776 0777 if(openDlg.exec() == QDialog::Accepted) { 0778 m_lastVideoUrl = openDlg.selectedUrls().first(); 0779 openVideo(m_lastVideoUrl); 0780 } 0781 } 0782 0783 void 0784 Application::toggleFullScreenMode() 0785 { 0786 setFullScreenMode(!m_mainWindow->m_playerWidget->fullScreenMode()); 0787 } 0788 0789 void 0790 Application::setFullScreenMode(bool enabled) 0791 { 0792 if(enabled != m_mainWindow->m_playerWidget->fullScreenMode()) { 0793 m_mainWindow->m_playerWidget->setFullScreenMode(enabled); 0794 0795 KToggleAction *toggleFullScreenAction = static_cast<KToggleAction *>(action(ACT_TOGGLE_FULL_SCREEN)); 0796 toggleFullScreenAction->setChecked(enabled); 0797 0798 emit fullScreenModeChanged(enabled); 0799 } 0800 } 0801 0802 void 0803 Application::seekBackward() 0804 { 0805 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0806 double position = videoPlayer->position() - SCConfig::seekJumpLength(); 0807 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 0808 videoPlayer->seek(position > 0.0 ? position : 0.0); 0809 } 0810 0811 void 0812 Application::seekForward() 0813 { 0814 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0815 double position = videoPlayer->position() + SCConfig::seekJumpLength(); 0816 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 0817 videoPlayer->seek(position <= videoPlayer->duration() ? position : videoPlayer->duration()); 0818 } 0819 0820 void 0821 Application::stepBackward() 0822 { 0823 VideoPlayer::instance()->step(-SCConfig::stepJumpLength()); 0824 } 0825 0826 void 0827 Application::stepForward() 0828 { 0829 VideoPlayer::instance()->step(SCConfig::stepJumpLength()); 0830 } 0831 0832 void 0833 Application::seekToPrevLine() 0834 { 0835 int selectedIndex = m_mainWindow->m_linesWidget->firstSelectedIndex(); 0836 if(selectedIndex < 0) 0837 return; 0838 SubtitleLine *currentLine = appSubtitle()->line(selectedIndex); 0839 if(currentLine) { 0840 SubtitleLine *prevLine = currentLine->prevLine(); 0841 if(prevLine) { 0842 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 0843 VideoPlayer::instance()->seek(prevLine->showTime().toSeconds() - SCConfig::jumpLineOffset() / 1000.0); 0844 m_mainWindow->m_linesWidget->setCurrentLine(prevLine); 0845 m_mainWindow->m_curLineWidget->setCurrentLine(prevLine); 0846 } 0847 } 0848 } 0849 0850 void 0851 Application::playOnlyCurrentLine() 0852 { 0853 int selectedIndex = m_mainWindow->m_linesWidget->firstSelectedIndex(); 0854 if(selectedIndex < 0) 0855 return; 0856 SubtitleLine *currentLine = appSubtitle()->line(selectedIndex); 0857 if(currentLine) { 0858 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0859 if(!videoPlayer->isPlaying()) 0860 videoPlayer->play(); 0861 videoPlayer->seek(currentLine->showTime().toSeconds() - SCConfig::jumpLineOffset() / 1000.0); 0862 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(currentLine); 0863 } 0864 } 0865 0866 void 0867 Application::seekToCurrentLine() 0868 { 0869 int selectedIndex = m_mainWindow->m_linesWidget->firstSelectedIndex(); 0870 if(selectedIndex < 0) 0871 return; 0872 SubtitleLine *currentLine = appSubtitle()->line(selectedIndex); 0873 if(currentLine) { 0874 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 0875 VideoPlayer::instance()->seek(currentLine->showTime().toSeconds() - SCConfig::jumpLineOffset() / 1000.0); 0876 } 0877 } 0878 0879 void 0880 Application::seekToNextLine() 0881 { 0882 int selectedIndex = m_mainWindow->m_linesWidget->firstSelectedIndex(); 0883 if(selectedIndex < 0) 0884 return; 0885 SubtitleLine *currentLine = appSubtitle()->line(selectedIndex); 0886 if(currentLine) { 0887 SubtitleLine *nextLine = currentLine->nextLine(); 0888 if(nextLine) { 0889 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 0890 VideoPlayer::instance()->seek(nextLine->showTime().toSeconds() - SCConfig::jumpLineOffset() / 1000.0); 0891 m_mainWindow->m_linesWidget->setCurrentLine(nextLine); 0892 m_mainWindow->m_curLineWidget->setCurrentLine(nextLine); 0893 } 0894 } 0895 } 0896 0897 void 0898 Application::playrateIncrease() 0899 { 0900 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0901 const double speed = videoPlayer->playSpeed(); 0902 videoPlayer->playSpeed(speed + (speed >= 2.0 ? .5 : .1)); 0903 } 0904 0905 void 0906 Application::playrateDecrease() 0907 { 0908 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0909 const double speed = videoPlayer->playSpeed(); 0910 videoPlayer->playSpeed(speed - (speed > 2.0 ? .5 : .1)); 0911 } 0912 0913 void 0914 Application::setCurrentLineShowTimeFromVideo() 0915 { 0916 SubtitleLine *currentLine = m_mainWindow->m_linesWidget->currentLine(); 0917 if(currentLine) 0918 currentLine->setShowTime(videoPosition(true)); 0919 } 0920 0921 void 0922 Application::setCurrentLineHideTimeFromVideo() 0923 { 0924 SubtitleLine *currentLine = m_mainWindow->m_linesWidget->currentLine(); 0925 if(currentLine) 0926 currentLine->setHideTime(videoPosition(true)); 0927 } 0928 0929 void 0930 Application::setActiveSubtitleStream(int subtitleStream) 0931 { 0932 KSelectAction *activeSubtitleStreamAction = (KSelectAction *)action(ACT_SET_ACTIVE_SUBTITLE_STREAM); 0933 activeSubtitleStreamAction->setCurrentItem(subtitleStream); 0934 0935 const bool translationSelected = bool(subtitleStream); 0936 m_mainWindow->m_playerWidget->setShowTranslation(translationSelected); 0937 m_mainWindow->m_waveformWidget->setShowTranslation(translationSelected); 0938 m_speller->setUseTranslation(translationSelected); 0939 } 0940 0941 0942 void 0943 Application::anchorToggle() 0944 { 0945 appSubtitle()->toggleLineAnchor(m_mainWindow->m_linesWidget->currentLine()); 0946 } 0947 0948 void 0949 Application::anchorRemoveAll() 0950 { 0951 appSubtitle()->removeAllAnchors(); 0952 } 0953 0954 void 0955 Application::shiftToVideoPosition() 0956 { 0957 SubtitleLine *currentLine = m_mainWindow->m_linesWidget->currentLine(); 0958 if(currentLine) 0959 appSubtitle()->shiftLines(Range::full(), videoPosition(true).toMillis() - currentLine->showTime().toMillis()); 0960 } 0961 0962 /// END ACTION HANDLERS 0963 0964 void 0965 Application::updateTitle() 0966 { 0967 if(appSubtitle()) { 0968 if(m_translationMode) { 0969 const QString caption = QStringLiteral("%1%2 | %3").arg( 0970 m_subtitleUrl.isEmpty() ? i18n("Untitled") : m_subtitleFileName, 0971 appSubtitle()->isPrimaryDirty() ? $(" *") : QString(), 0972 m_subtitleTrUrl.isEmpty() ? i18n("Untitled Translation") : m_subtitleTrFileName 0973 ); 0974 m_mainWindow->setCaption(caption, appSubtitle()->isSecondaryDirty()); 0975 } else { 0976 m_mainWindow->setCaption( 0977 m_subtitleUrl.isEmpty() ? i18n("Untitled") : (m_subtitleUrl.isLocalFile() ? m_subtitleUrl.toLocalFile() : m_subtitleUrl.toString(QUrl::PreferLocalFile)), 0978 appSubtitle()->isPrimaryDirty()); 0979 } 0980 } else { 0981 m_mainWindow->setCaption(QString()); 0982 } 0983 } 0984 0985 void 0986 Application::onWaveformDoubleClicked(Time time) 0987 { 0988 VideoPlayer *videoPlayer = VideoPlayer::instance(); 0989 if(videoPlayer->state() == VideoPlayer::Stopped) 0990 videoPlayer->play(); 0991 0992 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 0993 videoPlayer->seek(time.toSeconds()); 0994 } 0995 0996 void 0997 Application::onWaveformMiddleMouse(Time time) 0998 { 0999 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 1000 VideoPlayer::instance()->seek(time.toSeconds()); 1001 } 1002 1003 void 1004 Application::onLineDoubleClicked(SubtitleLine *line) 1005 { 1006 VideoPlayer *videoPlayer = VideoPlayer::instance(); 1007 if(videoPlayer->state() == VideoPlayer::Stopped) 1008 videoPlayer->play(); 1009 1010 int mseconds = line->showTime().toMillis() - SCConfig::seekOffsetOnDoubleClick(); 1011 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 1012 videoPlayer->seek(mseconds > 0 ? mseconds / 1000.0 : 0.0); 1013 1014 if(videoPlayer->state() != VideoPlayer::Playing && SCConfig::unpauseOnDoubleClick()) 1015 videoPlayer->play(); 1016 1017 m_mainWindow->m_waveformWidget->setScrollPosition(line->showTime().toMillis()); 1018 } 1019 1020 void 1021 Application::onHighlightLine(SubtitleLine *line, bool primary, int firstIndex, int lastIndex) 1022 { 1023 if(m_mainWindow->m_playerWidget->fullScreenMode()) { 1024 if(m_lastFoundLine != line) { 1025 m_lastFoundLine = line; 1026 1027 m_mainWindow->m_playerWidget->pauseAfterPlayingLine(nullptr); 1028 VideoPlayer::instance()->seek(line->showTime().toSeconds()); 1029 } 1030 } else { 1031 m_mainWindow->m_linesWidget->setCurrentLine(line, true); 1032 1033 if(firstIndex >= 0 && lastIndex >= 0) { 1034 if(primary) 1035 m_mainWindow->m_curLineWidget->selectPrimaryText(firstIndex, lastIndex); 1036 else 1037 m_mainWindow->m_curLineWidget->selectTranslationText(firstIndex, lastIndex); 1038 } 1039 } 1040 } 1041 1042 void 1043 Application::onPlayingLineChanged(SubtitleLine *line) 1044 { 1045 m_mainWindow->m_linesWidget->setPlayingLine(line); 1046 1047 if(m_linkCurrentLineToPosition) 1048 m_mainWindow->m_linesWidget->setCurrentLine(line, true); 1049 } 1050 1051 void 1052 Application::onLinkCurrentLineToVideoToggled(bool value) 1053 { 1054 if(m_linkCurrentLineToPosition != value) { 1055 m_linkCurrentLineToPosition = value; 1056 1057 if(m_linkCurrentLineToPosition) 1058 m_mainWindow->m_linesWidget->setCurrentLine(m_mainWindow->m_playerWidget->playingLine(), true); 1059 } 1060 } 1061 1062 void 1063 Application::onPlayerFileOpened(const QString &filePath) 1064 { 1065 m_recentVideosAction->addUrl(QUrl::fromLocalFile(filePath)); 1066 } 1067 1068 void 1069 Application::onPlayerPlaying() 1070 { 1071 QAction *playPauseAction = action(ACT_PLAY_PAUSE); 1072 playPauseAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause"))); 1073 playPauseAction->setText(i18n("Pause")); 1074 } 1075 1076 void 1077 Application::onPlayerPaused() 1078 { 1079 QAction *playPauseAction = action(ACT_PLAY_PAUSE); 1080 playPauseAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); 1081 playPauseAction->setText(i18n("Play")); 1082 } 1083 1084 void 1085 Application::onPlayerStopped() 1086 { 1087 onPlayerPaused(); 1088 } 1089 1090 void 1091 Application::onPlayerTextStreamsChanged(const QStringList &textStreams) 1092 { 1093 QAction *demuxTextStreamAction = (KSelectAction *)action(ACT_DEMUX_TEXT_STREAM); 1094 QMenu *menu = demuxTextStreamAction->menu(); 1095 menu->clear(); 1096 int i = 0; 1097 foreach(const QString &textStream, textStreams) 1098 menu->addAction(textStream)->setData(QVariant::fromValue<int>(i++)); 1099 demuxTextStreamAction->setEnabled(i > 0); 1100 } 1101 1102 void 1103 Application::onPlayerAudioStreamsChanged(const QStringList &audioStreams) 1104 { 1105 KSelectAction *activeAudioStreamAction = (KSelectAction *)action(ACT_SET_ACTIVE_AUDIO_STREAM); 1106 activeAudioStreamAction->setItems(audioStreams); 1107 1108 QAction *speechImportStreamAction = (KSelectAction *)action(ACT_ASR_IMPORT_AUDIO_STREAM); 1109 QMenu *speechImportStreamActionMenu = speechImportStreamAction->menu(); 1110 speechImportStreamActionMenu->clear(); 1111 int i = 0; 1112 foreach(const QString &audioStream, audioStreams) 1113 speechImportStreamActionMenu->addAction(audioStream)->setData(QVariant::fromValue<int>(i++)); 1114 speechImportStreamAction->setEnabled(i > 0); 1115 } 1116 1117 void 1118 Application::onPlayerActiveAudioStreamChanged(int audioStream) 1119 { 1120 KSelectAction *activeAudioStreamAction = (KSelectAction *)action(ACT_SET_ACTIVE_AUDIO_STREAM); 1121 if(audioStream >= 0) { 1122 activeAudioStreamAction->setCurrentItem(audioStream); 1123 m_mainWindow->m_waveformWidget->setAudioStream(VideoPlayer::instance()->filePath(), audioStream); 1124 } else { 1125 m_mainWindow->m_waveformWidget->setNullAudioStream(VideoPlayer::instance()->duration() * 1000); 1126 } 1127 } 1128 1129 void 1130 Application::onPlayerMuteChanged(bool muted) 1131 { 1132 KToggleAction *toggleMutedAction = (KToggleAction *)action(ACT_TOGGLE_MUTED); 1133 toggleMutedAction->setChecked(muted); 1134 } 1135 1136 void 1137 Application::updateActionTexts() 1138 { 1139 const int shiftAmount = SCConfig::linesQuickShiftAmount(); 1140 const int jumpLength = SCConfig::seekJumpLength(); 1141 1142 action(ACT_SEEK_BACKWARD)->setStatusTip(i18np("Seek backwards 1 second", "Seek backwards %1 seconds", jumpLength)); 1143 action(ACT_SEEK_FORWARD)->setStatusTip(i18np("Seek forwards 1 second", "Seek forwards %1 seconds", jumpLength)); 1144 1145 QAction *shiftSelectedLinesFwdAction = action(ACT_SHIFT_SELECTED_LINES_FORWARDS); 1146 shiftSelectedLinesFwdAction->setText(i18np("Shift %2%1 millisecond", "Shift %2%1 milliseconds", shiftAmount, "+")); 1147 shiftSelectedLinesFwdAction->setStatusTip(i18np("Shift selected lines %2%1 millisecond", "Shift selected lines %2%1 milliseconds", shiftAmount, "+")); 1148 1149 QAction *shiftSelectedLinesBwdAction = action(ACT_SHIFT_SELECTED_LINES_BACKWARDS); 1150 shiftSelectedLinesBwdAction->setText(i18np("Shift %2%1 millisecond", "Shift %2%1 milliseconds", shiftAmount, "-")); 1151 shiftSelectedLinesBwdAction->setStatusTip(i18np("Shift selected lines %2%1 millisecond", "Shift selected lines %2%1 milliseconds", shiftAmount, "-")); 1152 } 1153 1154 void 1155 Application::onConfigChanged() 1156 { 1157 updateActionTexts(); 1158 } 1159