Skip to content

Commit

Permalink
[AU4] Clips actions: delete
Browse files Browse the repository at this point in the history
  • Loading branch information
grliszas14 committed Jul 3, 2024
1 parent 76e5fe0 commit 4f4eb2d
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 11 deletions.
2 changes: 1 addition & 1 deletion au4/src/appshell/view/appmenumodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ MenuItem* AppMenuModel::makeEditMenu()
makeMenuItem("cut"),
makeMenuItem("copy"),
makeMenuItem("paste"),
makeMenuItem("delete"),
makeMenuItem("clip-delete-selected"),
makeSeparator(),
makeMenuItem("cut-and-close-gap"),
makeMenuItem("duplicate"),
Expand Down
47 changes: 47 additions & 0 deletions au4/src/au3wrap/internal/processinginteraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,50 @@ bool ProcessingInteraction::changeClipTitle(const processing::ClipKey& clipKey,

return true;
}

bool ProcessingInteraction::removeClip(const processing::ClipKey& clipKey)
{
WaveTrack* waveTrack = DomAccessor::findWaveTrack(projectRef(), TrackId(clipKey.trackId));
IF_ASSERT_FAILED(waveTrack) {
return false;
}

std::shared_ptr<WaveClip> clip = DomAccessor::findWaveClip(waveTrack, clipKey.index);
IF_ASSERT_FAILED(clip) {
return false;
}

clip->Clear(clip->Start(), clip->End());

processing::ProcessingProjectPtr prj = globalContext()->currentProcessingProject();
prj->onClipRemoved(DomConverter::clip(waveTrack, clip.get(), clipKey.index));

return true;
}

bool ProcessingInteraction::removeClipData(const processing::ClipKey& clipKey, double begin, double end)
{
WaveTrack* waveTrack = DomAccessor::findWaveTrack(projectRef(), TrackId(clipKey.trackId));
IF_ASSERT_FAILED(waveTrack) {
return false;
}

std::shared_ptr<WaveClip> clip = DomAccessor::findWaveClip(waveTrack, clipKey.index);
IF_ASSERT_FAILED(clip) {
return false;
}

processing::secs_t initialClipStart = clip->Start();
processing::secs_t initialClipEnd = clip->End();

clip->Clear(begin, end);

processing::ProcessingProjectPtr prj = globalContext()->currentProcessingProject();
if (begin <= initialClipStart && end >= initialClipEnd) {
prj->onClipRemoved(DomConverter::clip(waveTrack, clip.get(), clipKey.index));
} else {
prj->onClipChanged(DomConverter::clip(waveTrack, clip.get(), clipKey.index));
}

return true;
}
2 changes: 2 additions & 0 deletions au4/src/au3wrap/internal/processinginteraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class ProcessingInteraction : public processing::IProcessingInteraction

bool changeClipStartTime(const processing::ClipKey& clipKey, double sec) override;
bool changeClipTitle(const processing::ClipKey& clipKey, const muse::String& newTitle) override;
bool removeClip(const processing::ClipKey& clipKey) override;
bool removeClipData(const processing::ClipKey& clipKey, double begin, double end) override;

private:
AudacityProject& projectRef() const;
Expand Down
19 changes: 15 additions & 4 deletions au4/src/processing/dom/processingproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,29 @@ async::NotifyList<Track> ProcessingProject::trackList() const
return m_au3->trackList();
}

Clip ProcessingProject::clip(const ClipKey& key) const
{
return m_au3->clipList(key.trackId)[key.index];
}

async::NotifyList<Clip> ProcessingProject::clipList(const TrackId& trackId) const
{
async::NotifyList<Clip> clips = m_au3->clipList(trackId);
async::ChangedNotifier<Clip>& notifer = m_clipsChanged[trackId];
clips.setNotify(notifer.notify());
async::ChangedNotifier<Clip>& notifier = m_clipsChanged[trackId];
clips.setNotify(notifier.notify());
return clips;
}

void ProcessingProject::onClipChanged(const Clip& clip)
{
async::ChangedNotifier<Clip>& notifer = m_clipsChanged[clip.key.trackId];
notifer.itemChanged(clip);
async::ChangedNotifier<Clip>& notifier = m_clipsChanged[clip.key.trackId];
notifier.itemChanged(clip);
}

void ProcessingProject::onClipRemoved(const Clip& clip)
{
async::ChangedNotifier<Clip>& notifier = m_clipsChanged[clip.key.trackId];
notifier.itemRemoved(clip);
}

TimeSignature ProcessingProject::timeSignature() const
Expand Down
2 changes: 2 additions & 0 deletions au4/src/processing/dom/processingproject.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ class ProcessingProject

std::vector<TrackId> trackIdList() const;
muse::async::NotifyList<Track> trackList() const;
Clip clip(const ClipKey& key) const;
muse::async::NotifyList<Clip> clipList(const TrackId& trackId) const;

void onClipChanged(const Clip& clip);
void onClipRemoved(const Clip& clip);

processing::TimeSignature timeSignature() const;
void setTimeSignature(const processing::TimeSignature& timeSignature);
Expand Down
61 changes: 61 additions & 0 deletions au4/src/processing/internal/processingactionscontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@
* Audacity: A Digital Audio Editor
*/
#include "processingactionscontroller.h"
#include "project/internal/audacityproject.h"

using namespace muse;
using namespace au::processing;
using namespace muse::async;
using namespace muse::actions;

static const ActionCode CLIP_CUT_CODE("clip-cut");
static const ActionCode CLIP_COPY_CODE("clip-copy");
static const ActionCode CLIP_DELETE_CODE("clip-delete");
static const ActionCode CLIP_DELETE_SELECTED_CODE("clip-delete-selected");

void ProcessingActionsController::init()
{
dispatcher()->reg(this, CLIP_CUT_CODE, this, &ProcessingActionsController::clipCut);
dispatcher()->reg(this, CLIP_COPY_CODE, this, &ProcessingActionsController::clipCopy);
dispatcher()->reg(this, CLIP_DELETE_CODE, this, &ProcessingActionsController::clipDelete);
dispatcher()->reg(this, CLIP_DELETE_SELECTED_CODE, this, &ProcessingActionsController::clipDeleteSelected);
dispatcher()->reg(this, "toggle-loop-region", this, &ProcessingActionsController::toggleLoopRegion);
dispatcher()->reg(this, "clear-loop-region", this, &ProcessingActionsController::clearLoopRegion);
dispatcher()->reg(this, "set-loop-region-to-selection", this, &ProcessingActionsController::setLoopRegionToSelection);
Expand All @@ -23,6 +33,57 @@ void ProcessingActionsController::notifyActionCheckedChanged(const ActionCode& a
m_actionCheckedChanged.send(actionCode);
}

void ProcessingActionsController::clipCut()
{
NOT_IMPLEMENTED;
}

void ProcessingActionsController::clipCopy()
{
NOT_IMPLEMENTED;
}

// called from clips context menu
void ProcessingActionsController::clipDelete()
{
NOT_IMPLEMENTED;
}

// called from app menu / del shortcut
void ProcessingActionsController::clipDeleteSelected()
{
project::IAudacityProjectPtr project = globalContext()->currentProject();
auto selectedTracks = selectionController()->dataSelectedOnTracks();
auto selectedStartTime = selectionController()->dataSelectedStartTime();
auto selectedEndTime = selectionController()->dataSelectedEndTime();
auto tracks = project->processingProject()->trackList();
auto selectedClipKey = selectionController()->selectedClip();

//! TODO AU4: improve for deleting multiple selected clips
// remove single clip when selected via header click
if (selectedClipKey.index != nidx) {
processingInteraction()->removeClip(selectedClipKey);
}

// remove multiple clips in selected region
for (const auto& track : tracks) {
if (std::find(selectedTracks.begin(), selectedTracks.end(), track.id) == selectedTracks.end()) {
continue;
}

auto clips = project->processingProject()->clipList(track.id);
for (const auto& clip: clips) {
if (selectedStartTime > clip.endTime || selectedEndTime < clip.startTime) {
continue;
}

processingInteraction()->removeClipData(clip.key, selectedStartTime, selectedEndTime);
}
}

//! TODO AU4: add history of user actions
}

void ProcessingActionsController::toggleLoopRegion()
{
NOT_IMPLEMENTED;
Expand Down
8 changes: 8 additions & 0 deletions au4/src/processing/internal/processingactionscontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef AU_PROCESSING_PROCESSINGACTIONSCONTROLLER_H
#define AU_PROCESSING_PROCESSINGACTIONSCONTROLLER_H

#include "iprocessinginteraction.h"
#include "iselectioncontroller.h"
#include "modularity/ioc.h"
#include "async/asyncable.h"
#include "actions/iactionsdispatcher.h"
Expand All @@ -19,6 +21,8 @@ class ProcessingActionsController : public IProcessingActionsController, public
INJECT_STATIC(muse::actions::IActionsDispatcher, dispatcher)
INJECT_STATIC(au::context::IGlobalContext, globalContext)
INJECT_STATIC(muse::IInteractive, interactive)
muse::Inject<processing::ISelectionController> selectionController;
muse::Inject<processing::IProcessingInteraction> processingInteraction;

public:
void init();
Expand All @@ -30,6 +34,10 @@ class ProcessingActionsController : public IProcessingActionsController, public
private:
void notifyActionCheckedChanged(const muse::actions::ActionCode& actionCode);

void clipCut();
void clipCopy();
void clipDelete();
void clipDeleteSelected();
void toggleLoopRegion();
void clearLoopRegion();
void setLoopRegionToSelection();
Expand Down
6 changes: 6 additions & 0 deletions au4/src/processing/internal/processinguiactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ const UiActionList ProcessingUiActions::m_actions = {
TranslatableString("action", "Delete"),
TranslatableString("action", "Delete clip")
),
UiAction("clip-delete-selected",
au::context::UiCtxAny,
au::context::CTX_ANY,
TranslatableString("action", "Delete"),
TranslatableString("action", "Delete clip")
),
UiAction("clip-cut-close-gap",
au::context::UiCtxAny,
au::context::CTX_ANY,
Expand Down
2 changes: 2 additions & 0 deletions au4/src/processing/iprocessinginteraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ class IProcessingInteraction : MODULE_EXPORT_INTERFACE

virtual bool changeClipStartTime(const ClipKey& clipKey, double sec) = 0;
virtual bool changeClipTitle(const ClipKey& clipKey, const muse::String& newTitle) = 0;
virtual bool removeClip(const ClipKey& clipKey) = 0;
virtual bool removeClipData(const ClipKey& clipKey, double begin, double end) = 0;
};
}
6 changes: 0 additions & 6 deletions au4/src/project/internal/projectuiactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,6 @@ const UiActionList ProjectUiActions::m_actions = {
TranslatableString("action", "&Paste"),
TranslatableString("action", "Paste")
),
UiAction("delete",
au::context::UiCtxAny,
au::context::CTX_ANY,
TranslatableString("action", "&Delete"),
TranslatableString("action", "Delete")
),
UiAction("cut-and-close-gap",
au::context::UiCtxAny,
au::context::CTX_ANY,
Expand Down
10 changes: 10 additions & 0 deletions au4/src/projectscene/view/clipsview/clipslistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ void ClipsListModel::reload()
}
});

m_allClipList.onItemRemoved(this, [this](const Clip& clip) {
for (auto it = m_allClipList.begin(); it != m_allClipList.end(); ++it) {
if (it->key == clip.key) {
m_allClipList.erase(it);
update();
break;
}
}
});

update();
}

Expand Down

0 comments on commit 4f4eb2d

Please sign in to comment.