From 2aea19fff13f0aa326fd6bee1eb570d4bec009ba Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 14 Apr 2020 14:45:08 +0200 Subject: [PATCH 1/3] Add "Open containing folder" (#5453) Add functionality to open the containing folder of a file that's selected in LMMS' file browser. Technical details ------------------ Add a new private method openContainingFolder to FileBrowser. Add a new action to the context menu of a selected file. This action in turn calls the added method. The current implementation of openContainingFolder delegates to QDesktopServices::openUrl with the directory of the selected file. Please note that this will only open the directory but not select the file as this is much more complicated due to different implementations that are needed for the different platforms (Linux/Windows/MacOS). Using QDesktopServices::openUrl seems to be the most simple cross platform way which uses functionality that's already available in Qt. --- include/FileBrowser.h | 1 + src/gui/FileBrowser.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/FileBrowser.h b/include/FileBrowser.h index b84ba5e54..0e8ce7bf3 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -125,6 +125,7 @@ private slots: void activateListItem( QTreeWidgetItem * item, int column ); void openInNewInstrumentTrackBBE( void ); void openInNewInstrumentTrackSE( void ); + void openContainingFolder(); void sendToActiveInstrumentTrack( void ); void updateDirectory( QTreeWidgetItem * item ); diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 809518683..52641a73d 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -24,6 +24,7 @@ */ +#include #include #include #include @@ -380,6 +381,11 @@ void FileBrowserTreeWidget::contextMenuEvent(QContextMenuEvent * e ) "B+B Editor" ), this, SLOT( openInNewInstrumentTrackBBE() ) ); + contextMenu.addSeparator(); + contextMenu.addAction( QIcon(embed::getIconPixmap( "folder" )), + tr( "Open containing folder" ), + this, + SLOT( openContainingFolder() ) ); contextMenu.exec( e->globalPos() ); m_contextMenuItem = NULL; } @@ -671,6 +677,16 @@ void FileBrowserTreeWidget::openInNewInstrumentTrackSE( void ) +void FileBrowserTreeWidget::openContainingFolder() +{ + if (m_contextMenuItem) + { + QFileInfo fileInfo(m_contextMenuItem->fullName()); + QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.dir().path())); + } +} + + void FileBrowserTreeWidget::sendToActiveInstrumentTrack( void ) { From b85aef2f33794eb6bd7fa1153f7c411ef14c5b7c Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 19 Apr 2020 22:08:09 +0200 Subject: [PATCH 2/3] Code review changes Move openContainingFolder to the end of the method block. Adjust FileBrowserTreeWidget::contextMenuEvent to the coding conventions and also make the code more readable by splitting up some conditions. Add comments to clarify as to why the member m_contextMenuItem is set to nullptr at the end of the execution of contextMenuEvent. Please note that this implementation is not exception safe and should be changed in the future, e.g. by passing the FileItem as a parameter of the slot. --- include/FileBrowser.h | 2 +- src/gui/FileBrowser.cpp | 53 +++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/include/FileBrowser.h b/include/FileBrowser.h index 0e8ce7bf3..d36eacf07 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -125,9 +125,9 @@ private slots: void activateListItem( QTreeWidgetItem * item, int column ); void openInNewInstrumentTrackBBE( void ); void openInNewInstrumentTrackSE( void ); - void openContainingFolder(); void sendToActiveInstrumentTrack( void ); void updateDirectory( QTreeWidgetItem * item ); + void openContainingFolder(); } ; diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 52641a73d..29f25ec30 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -364,30 +364,41 @@ QList FileBrowserTreeWidget::expandedDirs( QTreeWidgetItem * item ) con void FileBrowserTreeWidget::contextMenuEvent(QContextMenuEvent * e ) { - FileItem * f = dynamic_cast( itemAt( e->pos() ) ); - if( f != NULL && ( f->handling() == FileItem::LoadAsPreset || - f->handling() == FileItem::LoadByPlugin ) ) + FileItem * f = dynamic_cast(itemAt(e->pos())); + if (f == nullptr) { + return; + } + + if (f->handling() == FileItem::LoadAsPreset || f->handling() == FileItem::LoadByPlugin) + { + // Set the member to the current FileItem so that it is available during the + // execution of the slots of the context menu we are about to create and execute. m_contextMenuItem = f; - QMenu contextMenu( this ); - contextMenu.addAction( tr( "Send to active instrument-track" ), - this, - SLOT( sendToActiveInstrumentTrack() ) ); - contextMenu.addAction( tr( "Open in new instrument-track/" - "Song Editor" ), - this, - SLOT( openInNewInstrumentTrackSE() ) ); - contextMenu.addAction( tr( "Open in new instrument-track/" - "B+B Editor" ), - this, - SLOT( openInNewInstrumentTrackBBE() ) ); - contextMenu.addSeparator(); - contextMenu.addAction( QIcon(embed::getIconPixmap( "folder" )), - tr( "Open containing folder" ), + + QMenu contextMenu(this); + + contextMenu.addAction(tr("Send to active instrument-track"), this, - SLOT( openContainingFolder() ) ); - contextMenu.exec( e->globalPos() ); - m_contextMenuItem = NULL; + SLOT(sendToActiveInstrumentTrack())); + contextMenu.addAction(tr("Open in new instrument-track/Song Editor"), + this, + SLOT(openInNewInstrumentTrackSE())); + contextMenu.addAction(tr("Open in new instrument-track/B+B Editor"), + this, + SLOT(openInNewInstrumentTrackBBE())); + + contextMenu.addSeparator(); + + contextMenu.addAction(QIcon(embed::getIconPixmap("folder")), + tr("Open containing folder"), + this, + SLOT(openContainingFolder())); + + contextMenu.exec(e->globalPos()); + + // The context menu has been executed so we can reset this member back to nullptr. + m_contextMenuItem = nullptr; } } From c37fdd005529f1fbc19d974c62d617fe89dfe988 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 21 Apr 2020 20:12:50 +0200 Subject: [PATCH 3/3] Code review changes (comment added) Add a comment which describes that only the folder is opened without selecting any file. Also explain why it is only done like this for now. --- src/gui/FileBrowser.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 29f25ec30..c976c39f6 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -692,6 +692,12 @@ void FileBrowserTreeWidget::openContainingFolder() { if (m_contextMenuItem) { + // Delegate to QDesktopServices::openUrl with the directory of the selected file. Please note that + // this will only open the directory but not select the file as this is much more complicated due + // to different implementations that are needed for different platforms (Linux/Windows/MacOS). + + // Using QDesktopServices::openUrl seems to be the most simple cross platform way which uses + // functionality that's already available in Qt. QFileInfo fileInfo(m_contextMenuItem->fullName()); QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.dir().path())); }