mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-28 13:57:22 +00:00
GUI: headers: reordering tracks by dragging & dropping
Part of the implementation of #3227.
This commit is contained in:
parent
d815f46156
commit
a68fa879b2
2
NEWS.md
2
NEWS.md
@ -20,6 +20,8 @@
|
||||
* MKVToolNix GUI: header editor: a new column has been added to the tree view
|
||||
showing the status of the "track enabled" flag. The information is also
|
||||
shown on the track overview page on the right. Implements #3228.
|
||||
* MKVToolNix GUI: header editor: users can now reorder tracks by dragging &
|
||||
dropping. Implements #3227.
|
||||
|
||||
## Bug fixes
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mkvtoolnix-gui/header_editor/page_base.h"
|
||||
#include "mkvtoolnix-gui/header_editor/page_model.h"
|
||||
#include "mkvtoolnix-gui/header_editor/top_level_page.h"
|
||||
#include "mkvtoolnix-gui/header_editor/track_type_page.h"
|
||||
#include "mkvtoolnix-gui/util/model.h"
|
||||
|
||||
namespace mtx::gui::HeaderEditor {
|
||||
@ -25,6 +26,9 @@ PageModel::~PageModel() {
|
||||
PageBase *
|
||||
PageModel::selectedPage(QModelIndex const &idx)
|
||||
const {
|
||||
if (!idx.isValid())
|
||||
return {};
|
||||
|
||||
auto selectedItem = itemFromIndex(idx.sibling(idx.row(), 0));
|
||||
if (!selectedItem)
|
||||
return {};
|
||||
@ -189,20 +193,20 @@ PageModel::canDropMimeData(QMimeData const *data,
|
||||
const {
|
||||
if ( !data
|
||||
|| (Qt::MoveAction != action)
|
||||
|| !parent.isValid()
|
||||
|| !m_lastSelectedIdx.isValid()
|
||||
|| (0 > row))
|
||||
return false;
|
||||
|
||||
auto draggedPage = selectedPage(m_lastSelectedIdx);
|
||||
if (!draggedPage || !dynamic_cast<AttachedFilePage *>(draggedPage))
|
||||
return false;
|
||||
auto parentPage = selectedPage(parent);
|
||||
|
||||
auto parentPage = selectedPage(parent);
|
||||
if (!parentPage || !dynamic_cast<AttachmentsPage *>(parentPage))
|
||||
return false;
|
||||
if (dynamic_cast<AttachedFilePage *>(draggedPage))
|
||||
return dynamic_cast<AttachmentsPage *>(parentPage);
|
||||
|
||||
return true;
|
||||
if (dynamic_cast<TrackTypePage *>(draggedPage))
|
||||
return !parentPage && (row > 0) && (row < rowCount());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -214,13 +218,30 @@ PageModel::dropMimeData(QMimeData const *data,
|
||||
if (!canDropMimeData(data, action, row, column, parent))
|
||||
return false;
|
||||
|
||||
auto draggedPage = selectedPage(m_lastSelectedIdx);
|
||||
|
||||
auto result = QStandardItemModel::dropMimeData(data, action, row, 0, parent);
|
||||
|
||||
Util::requestAllItems(*this);
|
||||
|
||||
Q_EMIT attachmentsReordered();
|
||||
if (dynamic_cast<AttachedFilePage *>(draggedPage))
|
||||
Q_EMIT attachmentsReordered();
|
||||
|
||||
else if (dynamic_cast<TrackTypePage *>(draggedPage))
|
||||
Q_EMIT tracksReordered();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
PageModel::rereadTopLevelPageIndexes() {
|
||||
auto rootItem = invisibleRootItem();
|
||||
|
||||
for (int row = 0, numRows = rootItem->rowCount(); row < numRows; ++row) {
|
||||
auto topLevelItem = rootItem->child(row);
|
||||
auto pageId = topLevelItem->data(Util::HeaderEditorPageIdRole).value<int>();
|
||||
m_pages[pageId]->m_pageIdx = topLevelItem->index();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,6 +48,10 @@ public:
|
||||
|
||||
Q_SIGNALS:
|
||||
void attachmentsReordered();
|
||||
void tracksReordered();
|
||||
|
||||
public Q_SLOTS:
|
||||
void rereadTopLevelPageIndexes();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ Tab::resetData() {
|
||||
m_eTracks.reset();
|
||||
m_model->reset();
|
||||
m_segmentinfoPage = nullptr;
|
||||
m_tracksReordered = false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -196,7 +197,7 @@ Tab::save() {
|
||||
tracksModified = true;
|
||||
}
|
||||
|
||||
if (!segmentinfoModified && !tracksModified && !attachmentsModified) {
|
||||
if (!segmentinfoModified && !tracksModified && !attachmentsModified && !m_tracksReordered) {
|
||||
Util::MessageBox::information(this)->title(QY("File has not been modified")).text(QY("The header values have not been modified. There is nothing to save.")).exec();
|
||||
return;
|
||||
}
|
||||
@ -226,7 +227,9 @@ Tab::save() {
|
||||
}
|
||||
}
|
||||
|
||||
if (ok && tracksModified && m_eTracks) {
|
||||
if (ok && m_eTracks && (tracksModified || m_tracksReordered)) {
|
||||
updateTracksElementToMatchTrackOrder();
|
||||
|
||||
auto result = m_analyzer->update_element(m_eTracks, true);
|
||||
if (kax_analyzer_c::uer_success != result) {
|
||||
Util::KaxAnalyzer::displayUpdateElementResult(this, result, QY("Saving the modified track headers failed."));
|
||||
@ -314,6 +317,13 @@ Tab::setupUi() {
|
||||
connect(m_replaceAttachmentContentAction, &QAction::triggered, [this]() { replaceAttachmentContent(false); });
|
||||
connect(m_replaceAttachmentContentSetValuesAction, &QAction::triggered, [this]() { replaceAttachmentContent(true); });
|
||||
connect(m_model, &PageModel::attachmentsReordered, [this]() { m_attachmentsPage->rereadChildren(*m_model); });
|
||||
connect(m_model, &PageModel::tracksReordered, this, &Tab::handleReorderedTracks);
|
||||
}
|
||||
|
||||
void
|
||||
Tab::handleReorderedTracks() {
|
||||
m_tracksReordered = true;
|
||||
m_model->rereadTopLevelPageIndexes();
|
||||
}
|
||||
|
||||
void
|
||||
@ -874,13 +884,15 @@ Tab::isClosingOrReloadingOkIfModified(ModifiedConfirmationMode mode) {
|
||||
return true;
|
||||
|
||||
auto modifiedPage = hasBeenModified();
|
||||
if (!modifiedPage)
|
||||
if (!modifiedPage && !m_tracksReordered)
|
||||
return true;
|
||||
|
||||
auto tool = MainWindow::headerEditorTool();
|
||||
MainWindow::get()->switchToTool(tool);
|
||||
tool->showTab(*this);
|
||||
focusPage(modifiedPage);
|
||||
|
||||
if (modifiedPage)
|
||||
focusPage(modifiedPage);
|
||||
|
||||
auto closing = mode == ModifiedConfirmationMode::Closing;
|
||||
auto text = closing ? QY("The file \"%1\" has been modified. Do you really want to close? All changes will be lost.")
|
||||
@ -898,4 +910,15 @@ Tab::isClosingOrReloadingOkIfModified(ModifiedConfirmationMode mode) {
|
||||
return answer == QMessageBox::Yes;
|
||||
}
|
||||
|
||||
void
|
||||
Tab::updateTracksElementToMatchTrackOrder() {
|
||||
auto &tracks = static_cast<libebml::EbmlMaster &>(*m_eTracks);
|
||||
|
||||
RemoveChildren<libmatroska::KaxTrackEntry>(tracks);
|
||||
|
||||
for (auto page : m_model->topLevelPages())
|
||||
if (dynamic_cast<TrackTypePage *>(page))
|
||||
tracks.PushElement(static_cast<TrackTypePage &>(*page).m_master);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ protected:
|
||||
PageModel *m_model;
|
||||
PageBase *m_segmentinfoPage{};
|
||||
AttachmentsPage *m_attachmentsPage{};
|
||||
bool m_ignoreSelectionChanges{};
|
||||
bool m_ignoreSelectionChanges{}, m_tracksReordered{};
|
||||
|
||||
QMenu *m_treeContextMenu;
|
||||
QAction *m_expandAllAction, *m_collapseAllAction, *m_addAttachmentsAction, *m_removeAttachmentAction, *m_removeAllAttachmentsAction, *m_saveAttachmentContentAction;
|
||||
@ -86,6 +86,7 @@ public Q_SLOTS:
|
||||
virtual void replaceAttachmentContent(bool deriveNameAndMimeType);
|
||||
virtual void handleDroppedFiles(QStringList const &fileNames, Qt::MouseButtons mouseButtons);
|
||||
virtual void focusPage(PageBase *page);
|
||||
virtual void handleReorderedTracks();
|
||||
|
||||
protected:
|
||||
void setupUi();
|
||||
@ -107,6 +108,8 @@ protected:
|
||||
void pruneEmptyMastersForTrack(TrackTypePage &page);
|
||||
void pruneEmptyMastersForAllTracks();
|
||||
|
||||
void updateTracksElementToMatchTrackOrder();
|
||||
|
||||
public:
|
||||
static memory_cptr readFileData(QWidget *parent, QString const &fileName);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user