-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Remove from disk: add to deck track menu, fix undeleted message #4560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b32addd
fda4ed1
b9d5a4c
e89aedf
23b9581
3c6e33d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -535,8 +535,7 @@ void WTrackMenu::setupActions() { | |
| } | ||
| } | ||
|
|
||
| if (featureIsEnabled(Feature::RemoveFromDisk) && | ||
| m_pTrackModel->hasCapabilities(TrackModel::Capability::RemoveFromDisk)) { | ||
| if (featureIsEnabled(Feature::RemoveFromDisk)) { | ||
| m_pRemoveFromDiskMenu->addAction(m_pRemoveFromDiskAct); | ||
| addMenu(m_pRemoveFromDiskMenu); | ||
| } | ||
|
|
@@ -790,9 +789,11 @@ void WTrackMenu::updateMenus() { | |
| } | ||
|
|
||
| if (featureIsEnabled(Feature::RemoveFromDisk)) { | ||
| bool locked = m_pTrackModel->hasCapabilities(TrackModel::Capability::Locked); | ||
| if (m_pTrackModel->hasCapabilities(TrackModel::Capability::RemoveFromDisk)) { | ||
| m_pRemoveFromDiskAct->setEnabled(!locked); | ||
| if (m_pTrackModel) { | ||
| bool locked = m_pTrackModel->hasCapabilities(TrackModel::Capability::Locked); | ||
| if (m_pTrackModel->hasCapabilities(TrackModel::Capability::RemoveFromDisk)) { | ||
| m_pRemoveFromDiskAct->setEnabled(!locked); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -1704,14 +1705,21 @@ class RemoveTrackFilesFromDiskTrackPointerOperation : public mixxx::TrackPointer | |
| } // anonymous namespace | ||
|
|
||
| void WTrackMenu::slotRemoveFromDisk() { | ||
| const auto trackRefs = getTrackRefs(); | ||
| QStringList locations; | ||
| locations.reserve(trackRefs.size()); | ||
| for (const auto& trackRef : trackRefs) { | ||
| QString location = trackRef.getLocation(); | ||
| if (m_pTrackModel) { | ||
| const auto trackRefs = getTrackRefs(); | ||
| locations.reserve(trackRefs.size()); | ||
| for (const auto& trackRef : trackRefs) { | ||
| QString location = trackRef.getLocation(); | ||
| locations.append(location); | ||
| } | ||
| locations.removeDuplicates(); | ||
| } else if (m_pTrack) { | ||
| QString location = m_pTrack->getLocation(); | ||
| locations.append(location); | ||
| } else { | ||
| return; | ||
| } | ||
| locations.removeDuplicates(); | ||
|
|
||
| { | ||
| // Prepare the delete confirmation dialog | ||
|
|
@@ -1724,15 +1732,24 @@ void WTrackMenu::slotRemoveFromDisk() { | |
| delListWidget->setFocusPolicy(Qt::ClickFocus); | ||
| delListWidget->addItems(locations); | ||
| mixxx::widgethelper::growListWidget(*delListWidget, *this); | ||
| // Warning text | ||
|
|
||
| QString delWarningText; | ||
| if (m_pTrackModel) { | ||
| delWarningText = tr("Permanently delete these files from disk?") + | ||
| QStringLiteral("<br><br><b>") + | ||
| tr("This can not be undone!") + QStringLiteral("</b>"); | ||
| } else { | ||
| delWarningText = | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On Linux you can delete the file while playing. |
||
| tr("Stop the deck and permanently delete this track file from disk?") + | ||
| QStringLiteral("<br><br><b>") + | ||
| tr("This can not be undone!") + QStringLiteral("</b>"); | ||
| } | ||
| QLabel* delWarning = new QLabel(); | ||
| delWarning->setText(tr("Permanently delete these files from disk?") + | ||
| QString("<br><br><b>") + | ||
| tr("This can not be undone!") + QString("</b>")); | ||
| delWarning->setText(delWarningText); | ||
| delWarning->setTextFormat(Qt::RichText); | ||
| delWarning->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, | ||
| QSizePolicy::Minimum)); | ||
| // Buttons | ||
|
|
||
| QDialogButtonBox* delButtons = new QDialogButtonBox(); | ||
| QPushButton* cancelBtn = delButtons->addButton( | ||
| tr("Cancel"), | ||
|
|
@@ -1762,6 +1779,13 @@ void WTrackMenu::slotRemoveFromDisk() { | |
| } | ||
| } | ||
|
|
||
| // If the operation was initiated from a deck's track menu | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code drags dependencies into WTrackMenu that don't belong here. Another example of the spaghetti control flow in Mixxx, unmaintainable. Is this side-effect even synchronous? Can we guarantee that the track is ejected immediately? Probably not, because decoding is done concurrently in a separate thread -> CachingReaderWorker. I suppose this doesn't work as intended.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only supposed to have a clean UX: it would be confusing if the deleted track was still loaded and could still be played. Please clarify your technical concerns (for example the libmad issue) and give an estimation if this can be solved at all (by me, with guidance, of course). Because, if there are issues to be expected they apply to the delete and purge action in general, not just to the deck option, since we're not checking if a track queued for deletion is analyzed or loaded anywhere. If there are serious concerns it'd be sad they pop up just now because we'd then have wasted quite some time implementing the feature in the first place :\ (what I've learned along the way would be persist, but still..)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't imagine an easy fix considering the current state of the code base. Merging the code for deleting files directly from within Mixxx without any chance to detect if those files are still accessed by Mixxx probably was a mistake. We didn't consider all the consequences. I don't veto against merging this PR, but on the other hand I won't merge it myself. Someone else may decide.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, that's unfortunate. I still don't overlook the potential consequences:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could only delete the entire review or keep the rejection. Both are not an option for me. "Disagree and merge" or "Disagree and let others merge" (for a second opinion). I don't really care enough and I also don't have a better proposal. The code is just ugly with the entanglement of the control proxies for triggering a side-effect in another component directly. It works somehow, but probably not always.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, then thanks for your review! |
||
| // we'll first stop the deck and eject the track. | ||
| if (m_pTrack) { | ||
| ControlObject::set(ConfigKey(m_deckGroup, "stop"), 1.0); | ||
| ControlObject::set(ConfigKey(m_deckGroup, "eject"), 1.0); | ||
| } | ||
|
|
||
| // Set up and initiate the track batch operation | ||
| const auto progressLabelText = | ||
| tr("Removing %1 track file(s) from disk...", | ||
|
|
@@ -1782,14 +1806,25 @@ void WTrackMenu::slotRemoveFromDisk() { | |
| // Show purge summary message | ||
| QMessageBox msgBoxPurgeTracks; | ||
| msgBoxPurgeTracks.setIcon(QMessageBox::Information); | ||
| msgBoxPurgeTracks.setWindowTitle(tr("Track Files Deleted")); | ||
| msgBoxPurgeTracks.setText( | ||
| tr("%1 track files were deleted from disk and purged " | ||
| "from the Mixxx database.") | ||
| .arg(QString::number(tracksToPurge.length())) + | ||
| QString("<br><br>") + | ||
| tr("Note: if you are in Browse or Recording you need to " | ||
| "click the current view again to see changes.")); | ||
| QString msgTitle; | ||
| QString msgText; | ||
| if (m_pTrackModel) { | ||
| msgTitle = tr("Track Files Deleted"); | ||
| msgText = | ||
| tr("%1 track files were deleted from disk and purged " | ||
| "from the Mixxx database.") | ||
| .arg(QString::number(tracksToPurge.length())) + | ||
| QStringLiteral("<br><br>") + | ||
| tr("Note: if you are in Browse or Recording you need to " | ||
| "click the current view again to see changes."); | ||
| } else { | ||
| msgTitle = tr("Track File Deleted"); | ||
| msgText = tr( | ||
| "Track file was deleted from disk and purged " | ||
| "from the Mixxx database."); | ||
| } | ||
| msgBoxPurgeTracks.setWindowTitle(msgTitle); | ||
| msgBoxPurgeTracks.setText(msgText); | ||
| msgBoxPurgeTracks.setTextFormat(Qt::RichText); | ||
| msgBoxPurgeTracks.setStandardButtons(QMessageBox::Ok); | ||
| msgBoxPurgeTracks.exec(); | ||
|
|
@@ -1802,10 +1837,16 @@ void WTrackMenu::slotRemoveFromDisk() { | |
| } | ||
| // Else show a message with a list of tracks that could not be deleted. | ||
| QLabel* notDeletedLabel = new QLabel; | ||
| notDeletedLabel->setText( | ||
| tr("The following %1 files could not be deleted from disk") | ||
| .arg(QString::number( | ||
| tracksToKeep.length()))); | ||
| QString msgText; | ||
| if (m_pTrackModel) { | ||
| msgText = | ||
| tr("The following %1 file(s) could not be deleted from disk") | ||
| .arg(QString::number( | ||
| tracksToKeep.length())); | ||
| } else { | ||
| msgText = tr("This track file could not be deleted from disk"); | ||
| } | ||
| notDeletedLabel->setText(msgText); | ||
| notDeletedLabel->setTextFormat(Qt::RichText); | ||
|
|
||
| QListWidget* notDeletedListWidget = new QListWidget; | ||
|
|
@@ -1825,7 +1866,7 @@ void WTrackMenu::slotRemoveFromDisk() { | |
|
|
||
| QDialog dlgNotDeleted; | ||
| dlgNotDeleted.setModal(true); | ||
| dlgNotDeleted.setWindowTitle(tr("Remaining Track Files")); | ||
| dlgNotDeleted.setWindowTitle(tr("Remaining Track File(s)")); | ||
| dlgNotDeleted.setLayout(notDeletedLayout); | ||
| // Required for being able to close the dialog | ||
| connect(closeBtn, &QPushButton::clicked, &dlgNotDeleted, &QDialog::close); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.