Commit 2f7f7c5b authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Allow creating multiple Project bin widgets

parent 3aa01a85
......@@ -888,9 +888,10 @@ void ClipWidget::init(QDockWidget* m_DockClipWidget)
ClipCreationDialog::clipWidget(m_DockClipWidget);
}
Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent, bool isMainBin)
: QWidget(parent)
, isLoading(false)
, m_isMainBin(isMainBin)
, m_itemModel(std::move(model))
, m_itemView(nullptr)
, m_binTreeViewDelegate(nullptr)
......@@ -958,16 +959,6 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
connect(leventEater, &LineEventEater::showClearButton, this, &Bin::showClearButton);
setFocusPolicy(Qt::ClickFocus);
connect(m_itemModel.get(), &ProjectItemModel::refreshPanel, this, &Bin::refreshPanel);
connect(m_itemModel.get(), &ProjectItemModel::refreshClip, this, &Bin::refreshClip);
connect(m_itemModel.get(), static_cast<void (ProjectItemModel::*)(const QStringList &, const QModelIndex &)>(&ProjectItemModel::itemDropped), this,
static_cast<void (Bin::*)(const QStringList &, const QModelIndex &)>(&Bin::slotItemDropped));
connect(m_itemModel.get(), static_cast<void (ProjectItemModel::*)(const QList<QUrl> &, const QModelIndex &)>(&ProjectItemModel::itemDropped), this,
static_cast<const QString (Bin::*)(const QList<QUrl> &, const QModelIndex &)>(&Bin::slotItemDropped));
connect(m_itemModel.get(), &ProjectItemModel::effectDropped, this, &Bin::slotEffectDropped);
connect(m_itemModel.get(), &ProjectItemModel::addTag, this, &Bin::slotTagDropped);
connect(m_itemModel.get(), &QAbstractItemModel::dataChanged, this, &Bin::slotItemEdited);
connect(this, &Bin::refreshPanel, this, &Bin::doRefreshPanel);
// Zoom slider
......@@ -1003,6 +994,9 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
listType->setCurrentAction(treeViewAction);
}
pCore->window()->actionCollection()->addAction(QStringLiteral("bin_view_mode_tree"), treeViewAction);
QAction *profileAction = new QAction(i18n("Adjust Profile to Current Clip"), this);
connect(profileAction, &QAction::triggered, this, &Bin::adjustProjectProfileToItem);
pCore->window()->actionCollection()->addAction(QStringLiteral("project_adjust_profile"), profileAction);
QAction *iconViewAction = listType->addAction(QIcon::fromTheme(QStringLiteral("view-list-icons")), i18n("Icon View"));
iconViewAction->setData(BinIconView);
......@@ -1119,11 +1113,15 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
m_showRating->setCheckable(true);
m_showRating->setData(7);
connect(m_showRating, &QAction::triggered, this, &Bin::slotShowColumn);
QAction *duplicateBin = new QAction(i18n("New Project Bin"), this);
connect(duplicateBin, &QAction::triggered, pCore.get(), &Core::addBin);
settingsMenu->addAction(m_showDate);
settingsMenu->addAction(m_showDesc);
settingsMenu->addAction(m_showRating);
settingsMenu->addAction(disableEffects);
settingsMenu->addAction(hoverPreview);
settingsMenu->addAction(duplicateBin);
// Show tags panel
m_tagAction = new QAction(QIcon::fromTheme(QStringLiteral("tag")), i18n("Tags Panel"), this);
......@@ -1248,39 +1246,40 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
button->setPopupMode(QToolButton::InstantPopup);
m_toolbar->addWidget(button);
// small info button for pending jobs
m_infoLabel = new SmallJobLabel(this);
m_infoLabel->setStyleSheet(SmallJobLabel::getStyleSheet(palette()));
connect(&pCore->taskManager, &TaskManager::jobCount, m_infoLabel, &SmallJobLabel::slotSetJobCount);
QAction *infoAction = m_toolbar->addWidget(m_infoLabel);
m_jobsMenu = new QMenu(this);
// connect(m_jobsMenu, &QMenu::aboutToShow, this, &Bin::slotPrepareJobsMenu);
m_cancelJobs = new QAction(i18n("Cancel All Jobs"), this);
m_cancelJobs->setCheckable(false);
m_discardCurrentClipJobs = new QAction(i18n("Cancel Current Clip Jobs"), this);
m_discardCurrentClipJobs->setCheckable(false);
m_discardPendingJobs = new QAction(i18n("Cancel Pending Jobs"), this);
m_discardPendingJobs->setCheckable(false);
m_jobsMenu->addAction(m_cancelJobs);
m_jobsMenu->addAction(m_discardCurrentClipJobs);
m_jobsMenu->addAction(m_discardPendingJobs);
m_infoLabel->setMenu(m_jobsMenu);
m_infoLabel->setAction(infoAction);
connect(m_discardCurrentClipJobs, &QAction::triggered, this, [&]() {
const QString currentId = m_monitor->activeClipId();
if (!currentId.isEmpty()) {
pCore->taskManager.discardJobs({ObjectType::BinClip,currentId.toInt()}, AbstractTask::NOJOBTYPE, true);
}
});
connect(m_cancelJobs, &QAction::triggered, [&]() {
pCore->taskManager.slotCancelJobs();
});
connect(m_discardPendingJobs, &QAction::triggered, [&]() {
// TODO: implement pending only deletion
pCore->taskManager.slotCancelJobs();
});
if (m_isMainBin) {
// small info button for pending jobs
m_infoLabel = new SmallJobLabel(this);
m_infoLabel->setStyleSheet(SmallJobLabel::getStyleSheet(palette()));
connect(&pCore->taskManager, &TaskManager::jobCount, m_infoLabel, &SmallJobLabel::slotSetJobCount);
QAction *infoAction = m_toolbar->addWidget(m_infoLabel);
m_jobsMenu = new QMenu(this);
// connect(m_jobsMenu, &QMenu::aboutToShow, this, &Bin::slotPrepareJobsMenu);
m_cancelJobs = new QAction(i18n("Cancel All Jobs"), this);
m_cancelJobs->setCheckable(false);
m_discardCurrentClipJobs = new QAction(i18n("Cancel Current Clip Jobs"), this);
m_discardCurrentClipJobs->setCheckable(false);
m_discardPendingJobs = new QAction(i18n("Cancel Pending Jobs"), this);
m_discardPendingJobs->setCheckable(false);
m_jobsMenu->addAction(m_cancelJobs);
m_jobsMenu->addAction(m_discardCurrentClipJobs);
m_jobsMenu->addAction(m_discardPendingJobs);
m_infoLabel->setMenu(m_jobsMenu);
m_infoLabel->setAction(infoAction);
connect(m_discardCurrentClipJobs, &QAction::triggered, this, [&]() {
const QString currentId = m_monitor->activeClipId();
if (!currentId.isEmpty()) {
pCore->taskManager.discardJobs({ObjectType::BinClip,currentId.toInt()}, AbstractTask::NOJOBTYPE, true);
}
});
connect(m_cancelJobs, &QAction::triggered, [&]() {
pCore->taskManager.slotCancelJobs();
});
connect(m_discardPendingJobs, &QAction::triggered, [&]() {
// TODO: implement pending only deletion
pCore->taskManager.slotCancelJobs();
});
}
// Hack, create toolbar spacer
QWidget *spacer = new QWidget();
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
......@@ -1311,13 +1310,20 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
Bin::~Bin()
{
pCore->taskManager.slotCancelJobs();
blockSignals(true);
m_proxyModel->selectionModel()->blockSignals(true);
setEnabled(false);
m_propertiesPanel = nullptr;
abortOperations();
m_itemModel->clean();
if (m_isMainBin) {
pCore->taskManager.slotCancelJobs();
blockSignals(true);
m_proxyModel->selectionModel()->blockSignals(true);
setEnabled(false);
delete m_propertiesDock;
m_propertiesPanel = nullptr;
abortOperations();
m_itemModel->clean();
} else {
blockSignals(true);
setEnabled(false);
delete m_propertiesDock;
}
}
QDockWidget *Bin::clipPropertiesDock()
......@@ -1771,7 +1777,9 @@ void Bin::cleanDocument()
void Bin::setDocument(KdenliveDoc *project)
{
m_doc = project;
m_infoLabel->slotSetJobCount(0);
if (m_isMainBin) {
m_infoLabel->slotSetJobCount(0);
}
int iconHeight = int(QFontInfo(font()).pixelSize() * 3.5);
m_iconSize = QSize(int(iconHeight * pCore->getCurrentDar()), iconHeight);
setEnabled(true);
......
......@@ -196,7 +196,7 @@ class Bin : public QWidget
enum BinViewType { BinTreeView, BinIconView };
public:
explicit Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent = nullptr);
explicit Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent = nullptr, bool isMainBin = true);
~Bin() override;
bool isLoading;
......@@ -364,11 +364,6 @@ private slots:
void slotSetIconSize(int size);
void selectProxyModel(const QModelIndex &id);
void slotSaveHeaders();
void slotItemDropped(const QStringList &ids, const QModelIndex &parent);
const QString slotItemDropped(const QList<QUrl> &urls, const QModelIndex &parent);
void slotEffectDropped(const QStringList &effectData, const QModelIndex &parent);
void slotTagDropped(const QString &tag, const QModelIndex &parent);
void slotItemEdited(const QModelIndex &, const QModelIndex &, const QVector<int> &);
/** @brief Reset all text and log data from info message widget. */
void slotResetInfoMessage();
......@@ -419,6 +414,11 @@ public slots:
/** @brief Start a filter job requested by a filter applied in timeline */
void slotStartFilterJob(const ItemInfo &info, const QString &id, QMap<QString, QString> &filterParams, QMap<QString, QString> &consumerParams,
QMap<QString, QString> &extraParams);
void slotItemDropped(const QStringList &ids, const QModelIndex &parent);
const QString slotItemDropped(const QList<QUrl> &urls, const QModelIndex &parent);
void slotEffectDropped(const QStringList &effectData, const QModelIndex &parent);
void slotTagDropped(const QString &tag, const QModelIndex &parent);
void slotItemEdited(const QModelIndex &, const QModelIndex &, const QVector<int> &);
/** @brief Open current clip in an external editing application */
void slotOpenClip();
void slotDuplicateClip();
......@@ -463,6 +463,7 @@ protected:
QSize sizeHint() const override;
private:
bool m_isMainBin;
std::shared_ptr<ProjectItemModel> m_itemModel;
QAbstractItemView *m_itemView;
BinItemDelegate *m_binTreeViewDelegate;
......
......@@ -61,7 +61,6 @@ Core::~Core()
if (m_monitorManager) {
delete m_monitorManager;
}
// delete m_binWidget;
if (m_projectManager) {
delete m_projectManager;
}
......@@ -130,13 +129,26 @@ void Core::initGUI(bool isAppImage, const QString &MltPath, const QUrl &Url, con
connect(this, &Core::showConfigDialog, m_mainWindow, &MainWindow::slotPreferences);
m_projectManager = new ProjectManager(this);
m_binWidget = new Bin(m_projectItemModel, m_mainWindow);
std::shared_ptr<Bin> bin(new Bin(m_projectItemModel, m_mainWindow));
m_mainWindow->addBin(bin);
connect(m_projectItemModel.get(), &ProjectItemModel::refreshPanel, m_mainWindow->activeBin().get(), &Bin::refreshPanel);
connect(m_projectItemModel.get(), &ProjectItemModel::refreshClip, m_mainWindow->activeBin().get(), &Bin::refreshClip);
connect(m_projectItemModel.get(), static_cast<void (ProjectItemModel::*)(const QStringList &, const QModelIndex &)>(&ProjectItemModel::itemDropped), m_mainWindow->activeBin().get(),
static_cast<void (Bin::*)(const QStringList &, const QModelIndex &)>(&Bin::slotItemDropped));
connect(m_projectItemModel.get(), static_cast<void (ProjectItemModel::*)(const QList<QUrl> &, const QModelIndex &)>(&ProjectItemModel::itemDropped), m_mainWindow->activeBin().get(),
static_cast<const QString (Bin::*)(const QList<QUrl> &, const QModelIndex &)>(&Bin::slotItemDropped));
connect(m_projectItemModel.get(), &ProjectItemModel::effectDropped, m_mainWindow->activeBin().get(), &Bin::slotEffectDropped);
connect(m_projectItemModel.get(), &ProjectItemModel::addTag, m_mainWindow->activeBin().get(), &Bin::slotTagDropped);
connect(m_projectItemModel.get(), &QAbstractItemModel::dataChanged, m_mainWindow->activeBin().get(), &Bin::slotItemEdited);
qDebug()<<"::::::::: ADDED NEW FIRST BIN";
m_library = new LibraryWidget(m_projectManager, m_mainWindow);
m_subtitleWidget = new SubtitleEdit(m_mainWindow);
m_mixerWidget = new MixerManager(m_mainWindow);
m_textEditWidget = new TextBasedEdit(m_mainWindow);
m_timeRemapWidget = new TimeRemap(m_mainWindow);
connect(m_library, SIGNAL(addProjectClips(QList<QUrl>)), m_binWidget, SLOT(droppedUrls(QList<QUrl>)));
connect(m_library, SIGNAL(addProjectClips(QList<QUrl>)), m_mainWindow->getBin().get(), SLOT(droppedUrls(QList<QUrl>)));
connect(this, &Core::updateLibraryPath, m_library, &LibraryWidget::slotUpdateLibraryPath);
connect(m_capture.get(), &MediaCapture::recordStateChanged, m_mixerWidget, &MixerManager::recordStateChanged);
connect(m_mixerWidget, &MixerManager::updateRecVolume, m_capture.get(), &MediaCapture::setAudioVolume);
......@@ -316,12 +328,12 @@ Monitor *Core::getMonitor(int id)
Bin *Core::bin()
{
return m_binWidget;
return m_mainWindow->getBin().get();
}
void Core::selectBinClip(const QString &clipId, bool activateMonitor, int frame, const QPoint &zone)
{
m_binWidget->selectClipById(clipId, frame, zone, activateMonitor);
m_mainWindow->getBin()->selectClipById(clipId, frame, zone, activateMonitor);
}
void Core::selectTimelineItem(int id)
......@@ -467,8 +479,8 @@ void Core::checkProfileValidity()
int offset = (getCurrentProfile()->profile().width() % 2) + (getCurrentProfile()->profile().height() % 2);
if (offset > 0) {
// Profile is broken, warn user
if (m_binWidget) {
emit m_binWidget->displayBinMessage(i18n("Your project profile is invalid, rendering might fail."), KMessageWidget::Warning);
if (m_mainWindow->getBin()) {
emit m_mainWindow->getBin()->displayBinMessage(i18n("Your project profile is invalid, rendering might fail."), KMessageWidget::Warning);
}
}
}
......@@ -599,7 +611,7 @@ PlaylistState::ClipState Core::getItemState(const ObjectId &id)
case ObjectType::TimelineComposition:
return PlaylistState::VideoOnly;
case ObjectType::BinClip:
return m_binWidget->getClipState(id.second);
return m_mainWindow->getBin()->getClipState(id.second);
case ObjectType::TimelineTrack:
return m_mainWindow->getCurrentTimeline()->controller()->getModel()->isAudioTrack(id.second) ? PlaylistState::AudioOnly : PlaylistState::VideoOnly;
case ObjectType::Master:
......@@ -626,7 +638,7 @@ int Core::getItemDuration(const ObjectId &id)
}
break;
case ObjectType::BinClip:
return int(m_binWidget->getClipDuration(id.second));
return int(m_mainWindow->getBin()->getClipDuration(id.second));
case ObjectType::TimelineTrack:
case ObjectType::Master:
return m_mainWindow->getCurrentTimeline()->controller()->duration() - 1;
......@@ -653,7 +665,7 @@ QSize Core::getItemFrameSize(const ObjectId &id)
}
break;
case ObjectType::BinClip:
return m_binWidget->getFrameSize(id.second);
return m_mainWindow->getBin()->getFrameSize(id.second);
case ObjectType::TimelineTrack:
case ObjectType::Master:
case ObjectType::TimelineComposition:
......@@ -787,12 +799,12 @@ void Core::loadingClips(int count)
void Core::displayBinMessage(const QString &text, int type, const QList<QAction *> &actions, bool showClose, BinMessage::BinCategory messageCategory)
{
m_binWidget->doDisplayMessage(text, KMessageWidget::MessageType(type), actions, showClose, messageCategory);
m_mainWindow->getBin()->doDisplayMessage(text, KMessageWidget::MessageType(type), actions, showClose, messageCategory);
}
void Core::displayBinLogMessage(const QString &text, int type, const QString &logInfo)
{
m_binWidget->doDisplayMessage(text, KMessageWidget::MessageType(type), logInfo);
m_mainWindow->getBin()->doDisplayMessage(text, KMessageWidget::MessageType(type), logInfo);
}
void Core::clearAssetPanel(int itemId)
......@@ -809,7 +821,7 @@ std::shared_ptr<EffectStackModel> Core::getItemEffectStack(int itemType, int ite
case int(ObjectType::TimelineTrack):
return m_mainWindow->getCurrentTimeline()->controller()->getModel()->getTrackEffectStackModel(itemId);
case int(ObjectType::BinClip):
return m_binWidget->getClipEffectStack(itemId);
return m_mainWindow->getBin()->getClipEffectStack(itemId);
case int(ObjectType::Master):
return m_mainWindow->getCurrentTimeline()->controller()->getModel()->getMasterEffectStackModel();
default:
......@@ -868,7 +880,7 @@ void Core::invalidateItem(ObjectId itemId)
m_mainWindow->getCurrentTimeline()->controller()->invalidateTrack(itemId.second);
break;
case ObjectType::BinClip:
m_binWidget->invalidateClip(QString::number(itemId.second));
m_mainWindow->getBin()->invalidateClip(QString::number(itemId.second));
break;
case ObjectType::Master:
m_mainWindow->getCurrentTimeline()->controller()->invalidateZone(0, -1);
......@@ -1137,9 +1149,9 @@ void Core::testProxies()
dialog->exec();
}
void Core::resizeMix(int cid, int duration, MixAlignment align, int leftFrames)
void Core::resizeMix(int cid, int duration, MixAlignment align, int rightFrames)
{
m_mainWindow->getCurrentTimeline()->controller()->resizeMix(cid, duration, align, leftFrames);
m_mainWindow->getCurrentTimeline()->controller()->resizeMix(cid, duration, align, rightFrames);
}
MixAlignment Core::getMixAlign(int cid) const
......@@ -1165,3 +1177,14 @@ int Core::getNewStuff(const QString &config)
{
return m_mainWindow->getNewStuff(config);
}
void Core::addBin()
{
std::shared_ptr<Bin> bin(new Bin(m_projectItemModel, m_mainWindow, false));
bin->setupMenu();
bin->setMonitor(m_monitorManager->clipMonitor());
bin->setDocument(pCore->currentDoc());
int ix = m_mainWindow->binCount() + 1;
QDockWidget *binDock = m_mainWindow->addDock(i18n("Project Bin %1", ix), QString("project_bin_%1").arg(ix), bin.get());
m_mainWindow->addBin(bin);
}
......@@ -255,7 +255,7 @@ public:
/** @brief The number of clip load jobs changed */
void loadingClips(int);
/** @brief Resize current mix item */
void resizeMix(int cid, int duration, MixAlignment align, int leftFrames = -1);
void resizeMix(int cid, int duration, MixAlignment align, int rightFrames = -1);
/** @brief Get Mix cut pos (the duration of the mix on the right clip) */
int getMixCutPos(int cid) const;
/** @brief Get alignment info for a mix item */
......@@ -280,7 +280,6 @@ private:
ProjectManager *m_projectManager{nullptr};
MonitorManager *m_monitorManager{nullptr};
std::shared_ptr<ProjectItemModel> m_projectItemModel;
Bin *m_binWidget{nullptr};
LibraryWidget *m_library{nullptr};
SubtitleEdit *m_subtitleWidget{nullptr};
TextBasedEdit *m_textEditWidget{nullptr};
......@@ -329,6 +328,8 @@ public slots:
void testProxies();
/** @brief Refresh the monitor profile when project profile changes. */
void updateMonitorProfile();
/** @brief Add a new Bin Widget. */
void addBin();
signals:
void coreIsReady();
......
......@@ -266,6 +266,7 @@ void MainWindow::init(const QString &mltPath)
ctnLay->addWidget(fr);
setupActions();
auto *layoutManager = new LayoutManagement(this);
pCore->bin()->setupMenu();
QDockWidget *libraryDock = addDock(i18n("Library"), QStringLiteral("library"), pCore->library());
QDockWidget *subtitlesDock = addDock(i18n("Subtitles"), QStringLiteral("Subtitles"), pCore->subtitleWidget());
......@@ -285,12 +286,6 @@ void MainWindow::init(const QString &mltPath)
connect(m_clipMonitor, &Monitor::seekToPreviousSnap, this, &MainWindow::slotSnapRewind);
connect(m_clipMonitor, &Monitor::seekToNextSnap, this, &MainWindow::slotSnapForward);
connect(pCore->bin(), &Bin::findInTimeline, this, &MainWindow::slotClipInTimeline, Qt::DirectConnection);
connect(pCore->bin(), &Bin::setupTargets, this, [&] (bool hasVideo, QMap <int, QString> audioStreams) {
getCurrentTimeline()->controller()->setTargetTracks(hasVideo, audioStreams);
}
);
// TODO deprecated, replace with Bin methods if necessary
/*connect(m_projectList, SIGNAL(loadingIsOver()), this, SLOT(slotElapsedTime()));
connect(m_projectList, SIGNAL(updateRenderStatus()), this, SLOT(slotCheckRenderStatus()));
......@@ -409,7 +404,6 @@ void MainWindow::init(const QString &mltPath)
});
connect(m_timelineTabs, &TimelineTabs::updateZoom, this, &MainWindow::updateZoomSlider);
connect(pCore->bin(), &Bin::requestShowEffectStack, m_assetPanel, &AssetPanel::showEffectStack);
connect(pCore->bin(), &Bin::requestShowEffectStack, [&] () {
// Don't raise effect stack on clip bin in case it is docked with bin or clip monitor
// m_effectStackDock->raise();
......@@ -1434,8 +1428,6 @@ void MainWindow::setupActions()
slotRestart(true);
});
addAction("project_adjust_profile", i18n("Adjust Profile to Current Clip"), pCore->bin(), SLOT(adjustProjectProfileToItem()));
m_playZone = addAction(QStringLiteral("monitor_play_zone"), i18n("Play Zone"), pCore->monitorManager(), SLOT(slotPlayZone()),
QIcon::fromTheme(QStringLiteral("media-playback-start")), Qt::CTRL + Qt::Key_Space);
m_loopZone = addAction(QStringLiteral("monitor_loop_zone"), i18n("Loop Zone"), pCore->monitorManager(), SLOT(slotLoopZone()),
......@@ -1918,8 +1910,6 @@ void MainWindow::setupActions()
addAction(QString("activate_target_%1").arg(i), ac3, QKeySequence(Qt::CTRL, keysequence[i-1]), timelineActions);
}
pCore->bin()->setupMenu();
// Setup effects and transitions actions.
KActionCategory *transitionActions = new KActionCategory(i18n("Transitions"), actionCollection());
// m_transitions = new QAction*[transitions.count()];
......@@ -2637,9 +2627,15 @@ void MainWindow::slotShowTimelineTags()
void MainWindow::slotDeleteItem()
{
if (QApplication::focusWidget() != nullptr && pCore->bin()->isAncestorOf(QApplication::focusWidget())) {
pCore->bin()->slotDeleteClip();
} if (QApplication::focusWidget() != nullptr && pCore->textEditWidget()->isAncestorOf(QApplication::focusWidget())) {
if (QApplication::focusWidget() != nullptr) {
for (auto &bin : m_binWidgets) {
if (bin->isAncestorOf(QApplication::focusWidget())) {
bin->slotDeleteClip();
return;
}
}
}
if (QApplication::focusWidget() != nullptr && pCore->textEditWidget()->isAncestorOf(QApplication::focusWidget())) {
qDebug()<<"===============\nDELETE TEXT BASED ITEM";
pCore->textEditWidget()->deleteItem();
} else {
......@@ -2842,9 +2838,13 @@ void MainWindow::slotSelectTrack()
void MainWindow::slotSelectAllTracks()
{
if (QApplication::focusWidget() != nullptr) {
if (QApplication::focusWidget()->parentWidget() != nullptr && QApplication::focusWidget()->parentWidget() == pCore->bin()) {
pCore->bin()->selectAll();
return;
if (QApplication::focusWidget()->parentWidget() != nullptr) {
for (auto &bin : m_binWidgets) {
if (bin->isAncestorOf(QApplication::focusWidget())) {
bin->selectAll();
return;
}
}
}
if (QApplication::focusWidget()->objectName() == QLatin1String("markers_list")) {
emit pCore->bin()->selectMarkers();
......@@ -3715,6 +3715,11 @@ void MainWindow::buildDynamicActions()
kdenliveCategoryMap.insert(QStringLiteral("transcoderslist"), ts);
kdenliveCategoryMap.insert(QStringLiteral("audiotranscoderslist"), ats);
updateDockMenu();
}
void MainWindow::updateDockMenu()
{
// Populate View menu with show / hide actions for dock widgets
KActionCategory *guiActions = nullptr;
if (kdenliveCategoryMap.contains(QStringLiteral("interface"))) {
......@@ -4552,6 +4557,48 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event)
return QObject::eventFilter(object, event);
}
void MainWindow::addBin(std::shared_ptr<Bin> bin)
{
connect(bin.get(), &Bin::findInTimeline, this, &MainWindow::slotClipInTimeline, Qt::DirectConnection);
connect(bin.get(), &Bin::setupTargets, this, [&] (bool hasVideo, QMap <int, QString> audioStreams) {
getCurrentTimeline()->controller()->setTargetTracks(hasVideo, audioStreams);
}
);
connect(bin.get(), &Bin::requestShowEffectStack, m_assetPanel, &AssetPanel::showEffectStack);
m_binWidgets << bin;
if (m_binWidgets.count() > 1) {
// Update dock list
updateDockMenu();
loadDockActions();
}
}
std::shared_ptr<Bin> MainWindow::getBin()
{
if (m_binWidgets.isEmpty()) {
return nullptr;
}
return m_binWidgets.first();
}
std::shared_ptr<Bin> MainWindow::activeBin()
{
for (auto &bin : m_binWidgets) {
if (bin->isAncestorOf(QApplication::focusWidget())) {
return bin;
}
}
return m_binWidgets.first();
}
int MainWindow::binCount() const
{
if (m_binWidgets.isEmpty()) {
return 0;
}
return m_binWidgets.count();
}
#ifdef DEBUG_MAINW
#undef DEBUG_MAINW
#endif
......@@ -134,6 +134,13 @@ public:
/** @brief Raise (show) the project bin*/
void raiseBin();
/** @brief Add a bin widget*/
void addBin(std::shared_ptr<Bin> bin);
/** @brief Get the main (first) bin*/
std::shared_ptr<Bin> getBin();
/** @brief Get the active (focused) bin or first one if none is active*/
std::shared_ptr<Bin> activeBin();
int binCount() const;
/** @brief Hide subtitle track */
void resetSubtitles();
......@@ -176,6 +183,8 @@ protected:
private:
/** @brief Sets up all the actions and attaches them to the collection. */
void setupActions();
/** @brief Rebuild the dock menu according to existing dock widgets. */
void updateDockMenu();
OtioConvertions m_otioConvertions;
KColorSchemeManager *m_colorschemes;
......@@ -205,6 +214,7 @@ private:
KSelectAction *m_compositeAction;
TimelineTabs *m_timelineTabs{nullptr};
QVector <std::shared_ptr<Bin> >m_binWidgets;
/** This list holds all the scopes used in Kdenlive, allowing to manage some global settings */
QList<QDockWidget *> m_gfxScopesList;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment