File indexing completed on 2024-11-10 04:24:49
0001 /* 0002 SPDX-FileCopyrightText: 2017 Nicolas Carion 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 #include "assetpanel.hpp" 0007 #include "core.h" 0008 #include "definitions.h" 0009 #include "effects/effectsrepository.hpp" 0010 #include "effects/effectstack/model/effectitemmodel.hpp" 0011 #include "effects/effectstack/model/effectstackmodel.hpp" 0012 #include "effects/effectstack/view/effectstackview.hpp" 0013 #include "kdenlivesettings.h" 0014 #include "model/assetparametermodel.hpp" 0015 #include "monitor/monitor.h" 0016 #include "transitions/transitionsrepository.hpp" 0017 #include "transitions/view/mixstackview.hpp" 0018 #include "transitions/view/transitionstackview.hpp" 0019 0020 #include "view/assetparameterview.hpp" 0021 0022 #include <KColorScheme> 0023 #include <KColorUtils> 0024 #include <KDualAction> 0025 #include <KLocalizedString> 0026 #include <KMessageWidget> 0027 #include <KSqueezedTextLabel> 0028 #include <QApplication> 0029 #include <QComboBox> 0030 #include <QFontDatabase> 0031 #include <QScrollArea> 0032 #include <QScrollBar> 0033 #include <QToolBar> 0034 #include <QToolButton> 0035 #include <QVBoxLayout> 0036 0037 AssetPanel::AssetPanel(QWidget *parent) 0038 : QWidget(parent) 0039 , m_lay(new QVBoxLayout(this)) 0040 , m_assetTitle(new KSqueezedTextLabel(this)) 0041 , m_container(new QWidget(this)) 0042 , m_transitionWidget(new TransitionStackView(this)) 0043 , m_mixWidget(new MixStackView(this)) 0044 , m_effectStackWidget(new EffectStackView(this)) 0045 { 0046 auto *buttonToolbar = new QToolBar(this); 0047 m_titleAction = buttonToolbar->addWidget(m_assetTitle); 0048 int size = style()->pixelMetric(QStyle::PM_SmallIconSize); 0049 QSize iconSize(size, size); 0050 buttonToolbar->setIconSize(iconSize); 0051 // Edit composition button 0052 m_switchCompoButton = new QComboBox(this); 0053 m_switchCompoButton->setFrame(false); 0054 auto allTransitions = TransitionsRepository::get()->getNames(); 0055 for (const auto &transition : qAsConst(allTransitions)) { 0056 if (transition.first != QLatin1String("mix")) { 0057 m_switchCompoButton->addItem(transition.second, transition.first); 0058 } 0059 } 0060 connect(m_switchCompoButton, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [&]() { 0061 if (m_transitionWidget->stackOwner().type == KdenliveObjectType::TimelineComposition) { 0062 Q_EMIT switchCurrentComposition(m_transitionWidget->stackOwner().itemId, m_switchCompoButton->currentData().toString()); 0063 } else if (m_mixWidget->isVisible()) { 0064 Q_EMIT switchCurrentComposition(m_mixWidget->stackOwner().itemId, m_switchCompoButton->currentData().toString()); 0065 } 0066 }); 0067 m_switchCompoButton->setToolTip(i18n("Change composition type")); 0068 m_switchAction = buttonToolbar->addWidget(m_switchCompoButton); 0069 m_switchAction->setVisible(false); 0070 0071 // spacer 0072 QWidget *empty = new QWidget(); 0073 empty->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum); 0074 buttonToolbar->addWidget(empty); 0075 0076 m_switchBuiltStack = new QToolButton(this); 0077 m_switchBuiltStack->setIcon(QIcon::fromTheme(QStringLiteral("adjustlevels"))); 0078 m_switchBuiltStack->setToolTip(i18n("Adjust clip")); 0079 m_switchBuiltStack->setCheckable(true); 0080 m_switchBuiltStack->setChecked(KdenliveSettings::showbuiltstack()); 0081 m_switchBuiltStack->setVisible(false); 0082 // connect(m_switchBuiltStack, &QToolButton::toggled, m_effectStackWidget, &EffectStackView::switchBuiltStack); 0083 buttonToolbar->addWidget(m_switchBuiltStack); 0084 0085 m_saveEffectStack = new QToolButton(this); 0086 m_saveEffectStack->setIcon(QIcon::fromTheme(QStringLiteral("document-save-all"))); 0087 m_saveEffectStack->setToolTip(i18n("Save Effect Stackā¦")); 0088 m_saveEffectStack->setWhatsThis(xi18nc("@info:whatsthis", "Saves the entire effect stack as an XML file for use in other projects.")); 0089 0090 // Would be better to have something like `setVisible(false)` here, but this apparently removes the button. 0091 // See https://stackoverflow.com/a/17645563/5172513 0092 m_saveEffectStack->setEnabled(false); 0093 connect(m_saveEffectStack, &QToolButton::released, this, &AssetPanel::slotSaveStack); 0094 buttonToolbar->addWidget(m_saveEffectStack); 0095 0096 m_splitButton = new KDualAction(i18n("Normal view"), i18n("Compare effect"), this); 0097 m_splitButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("view-right-close"))); 0098 m_splitButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right"))); 0099 m_splitButton->setToolTip(i18n("Compare effect")); 0100 m_splitButton->setWhatsThis(xi18nc( 0101 "@info:whatsthis", 0102 "Turns on or off the split view in the project and/or clip monitor: on the left the clip with effect is shown, on the right the clip without effect.")); 0103 m_splitButton->setVisible(false); 0104 connect(m_splitButton, &KDualAction::activeChangedByUser, this, &AssetPanel::processSplitEffect); 0105 buttonToolbar->addAction(m_splitButton); 0106 0107 m_enableStackButton = new KDualAction(i18n("Effects disabled"), i18n("Effects enabled"), this); 0108 m_enableStackButton->setWhatsThis( 0109 xi18nc("@info:whatsthis", 0110 "Toggles the effect stack to be enabled or disabled. Useful to see the difference between original and edited or to speed up scrubbing.")); 0111 m_enableStackButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("hint"))); 0112 m_enableStackButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("visibility"))); 0113 connect(m_enableStackButton, &KDualAction::activeChangedByUser, this, &AssetPanel::enableStack); 0114 m_enableStackButton->setVisible(false); 0115 buttonToolbar->addAction(m_enableStackButton); 0116 0117 m_timelineButton = new KDualAction(i18n("Display keyframes in timeline"), i18n("Hide keyframes in timeline"), this); 0118 m_timelineButton->setWhatsThis(xi18nc("@info:whatsthis", "Toggles the display of keyframes in the clip on the timeline")); 0119 m_timelineButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("keyframe-disable"))); 0120 m_timelineButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("keyframe"))); 0121 m_timelineButton->setVisible(false); 0122 connect(m_timelineButton, &KDualAction::activeChangedByUser, this, &AssetPanel::showKeyframes); 0123 buttonToolbar->addAction(m_timelineButton); 0124 0125 m_lay->addWidget(buttonToolbar); 0126 m_lay->setContentsMargins(0, 0, 0, 0); 0127 m_lay->setSpacing(0); 0128 auto *lay = new QVBoxLayout(m_container); 0129 lay->setContentsMargins(0, 0, 0, 0); 0130 lay->addWidget(m_transitionWidget); 0131 lay->addWidget(m_mixWidget); 0132 lay->addWidget(m_effectStackWidget); 0133 m_sc = new QScrollArea; 0134 m_sc->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); 0135 m_sc->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); 0136 m_sc->setFrameStyle(QFrame::NoFrame); 0137 m_sc->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding)); 0138 m_container->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding)); 0139 m_sc->setWidgetResizable(true); 0140 0141 m_lay->addWidget(m_sc); 0142 m_infoMessage = new KMessageWidget(this); 0143 m_lay->addWidget(m_infoMessage); 0144 m_infoMessage->hide(); 0145 m_sc->setWidget(m_container); 0146 m_transitionWidget->setVisible(false); 0147 m_mixWidget->setVisible(false); 0148 m_effectStackWidget->setVisible(false); 0149 updatePalette(); 0150 connect(m_effectStackWidget, &EffectStackView::checkScrollBar, this, &AssetPanel::slotCheckWheelEventFilter); 0151 connect(m_effectStackWidget, &EffectStackView::scrollView, this, &AssetPanel::scrollTo); 0152 connect(m_effectStackWidget, &EffectStackView::seekToPos, this, &AssetPanel::seekToPos); 0153 connect(m_effectStackWidget, &EffectStackView::reloadEffect, this, &AssetPanel::reloadEffect); 0154 connect(m_transitionWidget, &TransitionStackView::seekToTransPos, this, &AssetPanel::seekToPos); 0155 connect(m_mixWidget, &MixStackView::seekToTransPos, this, &AssetPanel::seekToPos); 0156 connect(m_effectStackWidget, &EffectStackView::updateEnabledState, this, 0157 [this]() { m_enableStackButton->setActive(m_effectStackWidget->isStackEnabled()); }); 0158 0159 connect(this, &AssetPanel::slotSaveStack, m_effectStackWidget, &EffectStackView::slotSaveStack); 0160 } 0161 0162 void AssetPanel::showTransition(int tid, const std::shared_ptr<AssetParameterModel> &transitionModel) 0163 { 0164 Q_UNUSED(tid) 0165 ObjectId id = transitionModel->getOwnerId(); 0166 if (m_transitionWidget->stackOwner() == id) { 0167 // already on this effect stack, do nothing 0168 return; 0169 } 0170 clear(); 0171 m_switchCompoButton->setCurrentIndex(m_switchCompoButton->findData(transitionModel->getAssetId())); 0172 m_switchAction->setVisible(true); 0173 m_titleAction->setVisible(false); 0174 m_assetTitle->clear(); 0175 m_transitionWidget->setVisible(true); 0176 m_timelineButton->setVisible(true); 0177 m_enableStackButton->setVisible(false); 0178 QSize s = pCore->getCompositionSizeOnTrack(id); 0179 m_transitionWidget->setModel(transitionModel, s, true); 0180 } 0181 0182 void AssetPanel::showMix(int cid, const std::shared_ptr<AssetParameterModel> &transitionModel, bool refreshOnly) 0183 { 0184 if (cid == -1) { 0185 clear(); 0186 return; 0187 } 0188 ObjectId id(KdenliveObjectType::TimelineMix, cid, transitionModel->getOwnerId().uuid); 0189 if (refreshOnly) { 0190 if (m_mixWidget->stackOwner() != id) { 0191 // item not currently displayed, ignore 0192 return; 0193 } 0194 } else { 0195 if (m_mixWidget->stackOwner() == id) { 0196 // already on this effect stack, do nothing 0197 return; 0198 } 0199 } 0200 clear(); 0201 // There is only 1 audio composition, so hide switch combobox 0202 m_switchAction->setVisible(transitionModel->getAssetId() != QLatin1String("mix")); 0203 m_titleAction->setVisible(false); 0204 m_assetTitle->clear(); 0205 m_mixWidget->setVisible(true); 0206 m_timelineButton->setVisible(false); 0207 m_enableStackButton->setVisible(false); 0208 m_switchCompoButton->setCurrentIndex(m_switchCompoButton->findData(transitionModel->getAssetId())); 0209 m_mixWidget->setModel(transitionModel, QSize(), true); 0210 } 0211 0212 void AssetPanel::showEffectStack(const QString &itemName, const std::shared_ptr<EffectStackModel> &effectsModel, QSize frameSize, bool showKeyframes) 0213 { 0214 if (effectsModel == nullptr) { 0215 // Item is not ready 0216 m_splitButton->setVisible(false); 0217 m_enableStackButton->setVisible(false); 0218 m_saveEffectStack->setEnabled(false); 0219 clear(); 0220 return; 0221 } 0222 ObjectId id = effectsModel->getOwnerId(); 0223 if (m_effectStackWidget->stackOwner() == id) { 0224 // already on this effect stack, do nothing 0225 // Disable split effect in case clip was moved 0226 if (id.type == KdenliveObjectType::TimelineClip && m_splitButton->isActive()) { 0227 m_splitButton->setActive(false); 0228 processSplitEffect(false); 0229 } 0230 return; 0231 } 0232 clear(); 0233 QString title; 0234 bool showSplit = false; 0235 bool enableKeyframes = false; 0236 switch (id.type) { 0237 case KdenliveObjectType::TimelineClip: 0238 title = i18n("%1 effects", itemName); 0239 showSplit = true; 0240 enableKeyframes = true; 0241 break; 0242 case KdenliveObjectType::TimelineComposition: 0243 title = i18n("%1 parameters", itemName); 0244 enableKeyframes = true; 0245 break; 0246 case KdenliveObjectType::TimelineTrack: 0247 title = i18n("Track %1 effects", itemName); 0248 // TODO: track keyframes 0249 // enableKeyframes = true; 0250 break; 0251 case KdenliveObjectType::BinClip: 0252 title = i18n("Bin %1 effects", itemName); 0253 showSplit = true; 0254 break; 0255 default: 0256 title = itemName; 0257 break; 0258 } 0259 m_assetTitle->setText(title); 0260 m_titleAction->setVisible(true); 0261 m_splitButton->setVisible(showSplit); 0262 m_saveEffectStack->setEnabled(true); 0263 m_enableStackButton->setVisible(id.type != KdenliveObjectType::TimelineComposition); 0264 m_enableStackButton->setActive(effectsModel->isStackEnabled()); 0265 if (showSplit) { 0266 m_splitButton->setEnabled(effectsModel->rowCount() > 0); 0267 QObject::connect(effectsModel.get(), &EffectStackModel::dataChanged, this, [&]() { 0268 if (m_effectStackWidget->isEmpty()) { 0269 m_splitButton->setActive(false); 0270 } 0271 m_splitButton->setEnabled(!m_effectStackWidget->isEmpty()); 0272 }); 0273 } 0274 m_timelineButton->setVisible(enableKeyframes); 0275 m_timelineButton->setActive(showKeyframes); 0276 // Disable built stack until properly implemented 0277 // m_switchBuiltStack->setVisible(true); 0278 m_effectStackWidget->setVisible(true); 0279 m_effectStackWidget->setModel(effectsModel, frameSize); 0280 } 0281 0282 void AssetPanel::clearAssetPanel(int itemId) 0283 { 0284 if (itemId == -1) { 0285 // closing project, reset panel 0286 clear(); 0287 return; 0288 } 0289 ObjectId id = m_effectStackWidget->stackOwner(); 0290 if (id.type == KdenliveObjectType::TimelineClip && id.itemId == itemId) { 0291 clear(); 0292 return; 0293 } 0294 id = m_transitionWidget->stackOwner(); 0295 if (id.type == KdenliveObjectType::TimelineComposition && id.itemId == itemId) { 0296 clear(); 0297 return; 0298 } 0299 id = m_mixWidget->stackOwner(); 0300 if (id.type == KdenliveObjectType::TimelineMix && id.itemId == itemId) { 0301 clear(); 0302 } 0303 } 0304 0305 void AssetPanel::clear() 0306 { 0307 if (m_splitButton->isActive()) { 0308 m_splitButton->setActive(false); 0309 processSplitEffect(false); 0310 } 0311 m_switchAction->setVisible(false); 0312 m_transitionWidget->setVisible(false); 0313 m_transitionWidget->unsetModel(); 0314 m_mixWidget->setVisible(false); 0315 m_mixWidget->unsetModel(); 0316 m_effectStackWidget->setVisible(false); 0317 m_splitButton->setVisible(false); 0318 m_saveEffectStack->setEnabled(false); 0319 m_timelineButton->setVisible(false); 0320 m_switchBuiltStack->setVisible(false); 0321 m_effectStackWidget->unsetModel(); 0322 m_assetTitle->clear(); 0323 } 0324 0325 void AssetPanel::updatePalette() 0326 { 0327 QString styleSheet = getStyleSheet(); 0328 setStyleSheet(styleSheet); 0329 m_transitionWidget->setStyleSheet(styleSheet); 0330 m_effectStackWidget->setStyleSheet(styleSheet); 0331 m_mixWidget->setStyleSheet(styleSheet); 0332 } 0333 0334 // static 0335 const QString AssetPanel::getStyleSheet() 0336 { 0337 KColorScheme scheme(QApplication::palette().currentColorGroup(), KColorScheme::View); 0338 QColor selected_bg = scheme.decoration(KColorScheme::FocusColor).color(); 0339 QColor hgh = KColorUtils::mix(QApplication::palette().window().color(), selected_bg, 0.2); 0340 QColor hover_bg = scheme.decoration(KColorScheme::HoverColor).color(); 0341 QColor light_bg = scheme.shade(KColorScheme::LightShade); 0342 QColor alt_bg = scheme.background(KColorScheme::NormalBackground).color(); 0343 // QColor normal_bg = QApplication::palette().window().color(); 0344 0345 QString stylesheet; 0346 0347 // effect background 0348 stylesheet.append(QStringLiteral("QFrame#decoframe {border-bottom:2px solid " 0349 "palette(mid);background: transparent} QFrame#decoframe[active=\"true\"] {background: %1;}") 0350 .arg(hgh.name())); 0351 0352 // effect in group background 0353 stylesheet.append( 0354 QStringLiteral("QFrame#decoframesub {border-top:1px solid palette(light);} QFrame#decoframesub[active=\"true\"] {background: %1;}").arg(hgh.name())); 0355 0356 // group background 0357 stylesheet.append(QStringLiteral("QFrame#decoframegroup {border:2px solid palette(dark);margin:0px;margin-top:2px;} ")); 0358 0359 // effect title bar 0360 stylesheet.append(QStringLiteral("QFrame#frame {margin-bottom:2px;} QFrame#frame[target=\"true\"] " 0361 "{background: palette(highlight);}")); 0362 0363 // group effect title bar 0364 stylesheet.append(QStringLiteral("QFrame#framegroup {background: palette(dark);} " 0365 "QFrame#framegroup[target=\"true\"] {background: palette(highlight);} ")); 0366 0367 // draggable effect bar content 0368 stylesheet.append(QStringLiteral("QProgressBar::chunk:horizontal {background: palette(button);border-top-left-radius: 4px;border-bottom-left-radius: 4px;} " 0369 "QProgressBar::chunk:horizontal#dragOnly {background: %1;border-top-left-radius: 4px;border-bottom-left-radius: 4px;} " 0370 "QProgressBar::chunk:horizontal:hover {background: %2;}") 0371 .arg(alt_bg.name(), selected_bg.name())); 0372 0373 // draggable effect bar 0374 stylesheet.append(QStringLiteral("QProgressBar:horizontal {border: 1px solid palette(dark);border-top-left-radius: 4px;border-bottom-left-radius: " 0375 "4px;border-right:0px;background:%3;padding: 0px;text-align:left center} QProgressBar:horizontal:disabled {border: 1px " 0376 "solid palette(button)} QProgressBar:horizontal#dragOnly {background: %3} QProgressBar:horizontal[inTimeline=\"true\"] { " 0377 "border: 1px solid %1;border-right: 0px;background: %2;padding: 0px;text-align:left center } " 0378 "QProgressBar::chunk:horizontal[inTimeline=\"true\"] {background: %1;}") 0379 .arg(hover_bg.name(), light_bg.name(), alt_bg.name())); 0380 0381 // spin box for draggable widget 0382 stylesheet.append( 0383 QStringLiteral("QAbstractSpinBox#dragBox {border: 1px solid palette(dark);border-top-right-radius: 4px;border-bottom-right-radius: " 0384 "4px;padding-right:0px;} QAbstractSpinBox::down-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox:disabled#dragBox {border: 1px " 0385 "solid palette(button);} QAbstractSpinBox::up-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox[inTimeline=\"true\"]#dragBox { " 0386 "border: 1px solid %1;} QAbstractSpinBox:hover#dragBox {border: 1px solid %2;} ") 0387 .arg(hover_bg.name(), selected_bg.name())); 0388 0389 // minimal double edit 0390 stylesheet.append(QStringLiteral("QAbstractSpinBox#dragMinimal {border: 0px " 0391 ";padding-right:0px; background-color:transparent} QAbstractSpinBox::down-button#dragMinimal {width:0px;padding:0px;} " 0392 "QAbstractSpinBox:disabled#dragMinimal {border: 0px;; background-color:transparent " 0393 ";} QAbstractSpinBox::up-button#dragMinimal {width:0px;padding:0px;}")); 0394 // group editable labels 0395 stylesheet.append(QStringLiteral("MyEditableLabel { background-color: transparent; color: palette(bright-text); border-radius: 2px;border: 1px solid " 0396 "transparent;} MyEditableLabel:hover {border: 1px solid palette(highlight);} ")); 0397 return stylesheet; 0398 } 0399 0400 void AssetPanel::processSplitEffect(bool enable) 0401 { 0402 KdenliveObjectType id = m_effectStackWidget->stackOwner().type; 0403 if (id == KdenliveObjectType::TimelineClip) { 0404 Q_EMIT doSplitEffect(enable); 0405 } else if (id == KdenliveObjectType::BinClip) { 0406 Q_EMIT doSplitBinEffect(enable); 0407 } 0408 } 0409 0410 void AssetPanel::showKeyframes(bool enable) 0411 { 0412 if (m_effectStackWidget->isVisible()) { 0413 pCore->showClipKeyframes(m_effectStackWidget->stackOwner(), enable); 0414 } else if (m_transitionWidget->isVisible()) { 0415 pCore->showClipKeyframes(m_transitionWidget->stackOwner(), enable); 0416 } 0417 } 0418 0419 ObjectId AssetPanel::effectStackOwner() 0420 { 0421 if (m_effectStackWidget->isVisible()) { 0422 return m_effectStackWidget->stackOwner(); 0423 } 0424 if (m_transitionWidget->isVisible()) { 0425 return m_transitionWidget->stackOwner(); 0426 } 0427 if (m_mixWidget->isVisible()) { 0428 return m_mixWidget->stackOwner(); 0429 } 0430 return ObjectId(); 0431 } 0432 0433 bool AssetPanel::addEffect(const QString &effectId) 0434 { 0435 if (!m_effectStackWidget->isVisible()) { 0436 return false; 0437 } 0438 return m_effectStackWidget->addEffect(effectId); 0439 } 0440 0441 void AssetPanel::enableStack(bool enable) 0442 { 0443 if (!m_effectStackWidget->isVisible()) { 0444 return; 0445 } 0446 m_effectStackWidget->enableStack(enable); 0447 } 0448 0449 void AssetPanel::deleteCurrentEffect() 0450 { 0451 if (m_effectStackWidget->isVisible()) { 0452 Q_EMIT m_effectStackWidget->removeCurrentEffect(); 0453 } 0454 } 0455 0456 void AssetPanel::collapseCurrentEffect() 0457 { 0458 if (m_effectStackWidget->isVisible()) { 0459 m_effectStackWidget->switchCollapsed(); 0460 } 0461 } 0462 0463 void AssetPanel::scrollTo(QRect rect) 0464 { 0465 // Ensure the scrollview widget adapted its height to the effectstackview height change 0466 m_sc->widget()->adjustSize(); 0467 if (rect.height() < m_sc->height()) { 0468 m_sc->ensureVisible(0, rect.y() + rect.height(), 0, 0); 0469 } else { 0470 m_sc->ensureVisible(0, rect.y() + m_sc->height(), 0, 0); 0471 } 0472 } 0473 0474 void AssetPanel::slotCheckWheelEventFilter() 0475 { 0476 // If the effect stack widget has no scrollbar, we will not filter the 0477 // mouse wheel events, so that user can easily adjust effect params 0478 bool blockWheel = false; 0479 if (m_sc->verticalScrollBar() && m_sc->verticalScrollBar()->isVisible()) { 0480 // widget has scroll bar, 0481 blockWheel = true; 0482 } 0483 Q_EMIT m_effectStackWidget->blockWheelEvent(blockWheel); 0484 } 0485 0486 void AssetPanel::assetPanelWarning(const QString &service, const QString & /*id*/, const QString &message) 0487 { 0488 QString finalMessage; 0489 if (!service.isEmpty() && EffectsRepository::get()->exists(service)) { 0490 QString effectName = EffectsRepository::get()->getName(service); 0491 if (!effectName.isEmpty()) { 0492 finalMessage = QStringLiteral("<b>") + effectName + QStringLiteral("</b><br />"); 0493 } 0494 } 0495 finalMessage.append(message); 0496 m_infoMessage->setText(finalMessage); 0497 m_infoMessage->setWordWrap(message.length() > 35); 0498 m_infoMessage->setCloseButtonVisible(true); 0499 m_infoMessage->setMessageType(KMessageWidget::Warning); 0500 m_infoMessage->animatedShow(); 0501 } 0502 0503 void AssetPanel::slotAddRemoveKeyframe() 0504 { 0505 if (m_effectStackWidget->isVisible()) { 0506 m_effectStackWidget->addRemoveKeyframe(); 0507 } else if (m_transitionWidget->isVisible()) { 0508 Q_EMIT m_transitionWidget->addRemoveKeyframe(); 0509 } else if (m_mixWidget->isVisible()) { 0510 Q_EMIT m_mixWidget->addRemoveKeyframe(); 0511 } 0512 } 0513 0514 void AssetPanel::slotNextKeyframe() 0515 { 0516 if (m_effectStackWidget->isVisible()) { 0517 m_effectStackWidget->slotGoToKeyframe(true); 0518 } else if (m_transitionWidget->isVisible()) { 0519 Q_EMIT m_transitionWidget->nextKeyframe(); 0520 } else if (m_mixWidget->isVisible()) { 0521 Q_EMIT m_mixWidget->nextKeyframe(); 0522 } 0523 } 0524 0525 void AssetPanel::slotPreviousKeyframe() 0526 { 0527 if (m_effectStackWidget->isVisible()) { 0528 m_effectStackWidget->slotGoToKeyframe(false); 0529 } else if (m_transitionWidget->isVisible()) { 0530 Q_EMIT m_transitionWidget->previousKeyframe(); 0531 } else if (m_mixWidget->isVisible()) { 0532 Q_EMIT m_mixWidget->previousKeyframe(); 0533 } 0534 } 0535 0536 void AssetPanel::updateAssetPosition(int itemId, const QUuid uuid) 0537 { 0538 if (m_effectStackWidget->isVisible()) { 0539 ObjectId id(KdenliveObjectType::TimelineClip, itemId, uuid); 0540 if (m_effectStackWidget->stackOwner() == id) { 0541 Q_EMIT pCore->getMonitor(Kdenlive::ProjectMonitor)->seekPosition(pCore->getMonitorPosition()); 0542 } 0543 } else if (m_transitionWidget->isVisible()) { 0544 ObjectId id(KdenliveObjectType::TimelineComposition, itemId, uuid); 0545 if (m_transitionWidget->stackOwner() == id) { 0546 Q_EMIT pCore->getMonitor(Kdenlive::ProjectMonitor)->seekPosition(pCore->getMonitorPosition()); 0547 } 0548 } 0549 } 0550 0551 void AssetPanel::sendStandardCommand(int command) 0552 { 0553 if (m_effectStackWidget->isVisible()) { 0554 m_effectStackWidget->sendStandardCommand(command); 0555 } else if (m_transitionWidget->isVisible()) { 0556 m_transitionWidget->sendStandardCommand(command); 0557 } 0558 }