Skip to content

Commit

Permalink
Merge pull request mantidproject#20650 from mantidproject/20643-fix-o…
Browse files Browse the repository at this point in the history
…sx-drag-and-drop

Fix dragging and dropping files into Mantid on OSX
  • Loading branch information
martyngigg authored Oct 3, 2017
2 parents d978086 + 3429c06 commit d783c7a
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 60 deletions.
21 changes: 3 additions & 18 deletions MantidPlot/src/Mantid/MantidUI.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Python header must go first
#include "MantidQtWidgets/Common/PythonThreading.h"
#include "MantidQtWidgets/Common/DropEventHelper.h"

#include "AlgorithmDockWidget.h"
#include "AlgorithmHistoryWindow.h"
Expand Down Expand Up @@ -1562,8 +1563,8 @@ bool MantidUI::drop(QDropEvent *e) {
foreach (const auto &wsName, wsNames) { importWorkspace(wsName, false); }
return true;
} else if (e->mimeData()->hasUrls()) {
QStringList pyFiles = extractPyFiles(e->mimeData()->urls());
if (pyFiles.size() > 0) {
const auto pyFiles = DropEventHelper::extractPythonFiles(e);
if (!pyFiles.empty()) {
try {
MantidQt::API::ProjectSerialiser serialiser(m_appWindow);
serialiser.openScriptWindow(pyFiles);
Expand Down Expand Up @@ -1597,22 +1598,6 @@ bool MantidUI::drop(QDropEvent *e) {
return false;
}

/// extracts the files from a mimedata object that have a .py extension
QStringList MantidUI::extractPyFiles(const QList<QUrl> &urlList) const {
QStringList filenames;
for (int i = 0; i < urlList.size(); ++i) {
QString fName = urlList[i].toLocalFile();
if (fName.size() > 0) {
QFileInfo fi(fName);

if (fi.suffix().toUpper() == "PY") {
filenames.append(fName);
}
}
}
return filenames;
}

/**
Executes the Save Nexus dialogue from the right click context menu.
Expand Down
3 changes: 0 additions & 3 deletions MantidPlot/src/Mantid/MantidUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -620,9 +620,6 @@ private slots:
bool useAbsoluteDate,
Mantid::Kernel::DateAndTime start);

/// extracts the files from a mimedata object that have a .py extension
QStringList extractPyFiles(const QList<QUrl> &urlList) const;

// Whether new plots shoul re-use the same plot instance (for every
// different
// type of plot).
Expand Down
29 changes: 9 additions & 20 deletions MantidPlot/src/ScriptingWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "ScriptingWindow.h"
#include "ApplicationWindow.h"
#include "MantidQtWidgets/Common/TSVSerialiser.h"
#include "MantidQtWidgets/Common/DropEventHelper.h"
#include "MultiTabScriptInterpreter.h"
#include "ScriptFileInterpreter.h"
#include "ScriptingEnv.h"
Expand Down Expand Up @@ -37,6 +38,7 @@

using namespace Mantid;
using namespace MantidQt::API;
namespace DropEventHelper = MantidQt::MantidWidgets::DropEventHelper;

namespace {
/// static logger
Expand Down Expand Up @@ -516,7 +518,8 @@ void ScriptingWindow::customEvent(QEvent *event) {
void ScriptingWindow::dragEnterEvent(QDragEnterEvent *de) {
const QMimeData *mimeData = de->mimeData();
if (mimeData->hasUrls()) {
if (extractPyFiles(mimeData->urls()).size() > 0) {
const auto pythonFilenames = DropEventHelper::extractPythonFiles(de);
if (!pythonFilenames.empty()) {
de->acceptProposedAction();
}
}
Expand All @@ -529,7 +532,8 @@ void ScriptingWindow::dragEnterEvent(QDragEnterEvent *de) {
void ScriptingWindow::dragMoveEvent(QDragMoveEvent *de) {
const QMimeData *mimeData = de->mimeData();
if (mimeData->hasUrls()) {
if (extractPyFiles(mimeData->urls()).size() > 0) {
const auto pythonFilenames = DropEventHelper::extractPythonFiles(de);
if (!pythonFilenames.empty()) {
de->accept();
}
}
Expand All @@ -542,11 +546,11 @@ void ScriptingWindow::dragMoveEvent(QDragMoveEvent *de) {
void ScriptingWindow::dropEvent(QDropEvent *de) {
const QMimeData *mimeData = de->mimeData();
if (mimeData->hasUrls()) {
QStringList filenames = extractPyFiles(mimeData->urls());
const auto filenames = DropEventHelper::extractPythonFiles(de);
de->acceptProposedAction();

for (int i = 0; i < filenames.size(); ++i) {
m_manager->openInNewTab(filenames[i]);
for (const auto &name : filenames) {
m_manager->openInNewTab(name);
}
}
}
Expand Down Expand Up @@ -894,18 +898,3 @@ Script::ExecutionMode ScriptingWindow::getExecutionMode() const {
else
return Script::Serialised;
}

QStringList ScriptingWindow::extractPyFiles(const QList<QUrl> &urlList) const {
QStringList filenames;
for (int i = 0; i < urlList.size(); ++i) {
QString fName = urlList[i].toLocalFile();
if (fName.size() > 0) {
QFileInfo fi(fName);

if (fi.suffix().toUpper() == "PY") {
filenames.append(fName);
}
}
}
return filenames;
}
3 changes: 0 additions & 3 deletions MantidPlot/src/ScriptingWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,6 @@ private slots:
/// Returns the current execution mode
Script::ExecutionMode getExecutionMode() const;

/// Extract py files from urllist
QStringList extractPyFiles(const QList<QUrl> &urlList) const;

private:
/// The script editors' manager
MultiTabScriptInterpreter *m_manager;
Expand Down
2 changes: 2 additions & 0 deletions docs/source/release/v3.11.0/ui.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ UI & Usability Changes
User Interface
--------------

- Fixed the ability to drag & drop files into Mantid OSX >=10.10
- The First use dialog has been redesigned to use less of the screen to fit better onto laptops with small high resolution screens that use screen scaling.
- The welcome dialog has been redesigned to use less of the screen to fit better onto laptops with small high resolution screens that use screen scaling.

Scanning workspaces
Expand Down
10 changes: 9 additions & 1 deletion qt/widgets/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
src/AlgorithmRunner.cpp
src/BatchAlgorithmRunner.cpp
src/BoolPropertyWidget.cpp
src/DropEventHelper.cpp
src/FileDialogHandler.cpp
src/FilePropertyWidget.cpp
src/GenericDialog.cpp
Expand Down Expand Up @@ -261,7 +262,8 @@ set ( INC_FILES
inc/MantidQtWidgets/Common/AlgorithmRunner.h
inc/MantidQtWidgets/Common/BatchAlgorithmRunner.h
inc/MantidQtWidgets/Common/DllOption.h
inc/MantidQtWidgets/Common/FileDialogHandler.h
inc/MantidQtWidgets/Common/DropEventHelper.h
inc/MantidQtWidgets/Common/FileDialogHandler.h
inc/MantidQtWidgets/Common/FlowLayout.h
inc/MantidQtWidgets/Common/GraphOptions.h
inc/MantidQtWidgets/Common/DistributionOptions.h
Expand Down Expand Up @@ -574,13 +576,19 @@ add_library ( MantidQtWidgetsCommon ${ALL_SRC} ${INC_FILES} ${UI_HDRS} )

set_target_properties ( MantidQtWidgetsCommon PROPERTIES COMPILE_DEFINITIONS IN_MANTIDQT_COMMON )

# Add support for OSX system libraries if this is an OSX machine
if ( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET( APPLE_SYSTEM_LIBRARIES "-framework CoreFoundation")
endif()

if (OSX_VERSION VERSION_GREATER 10.8)
set_target_properties ( MantidQtWidgetsCommon PROPERTIES INSTALL_RPATH "@loader_path/../MacOS;@loader_path/../Libraries")
endif ()

target_link_libraries ( MantidQtWidgetsCommon LINK_PRIVATE ${TCMALLOC_LIBRARIES_LINKTIME}
${CORE_MANTIDLIBS} ${QT_LIBRARIES} ${QWT_LIBRARIES}
${POCO_LIBRARIES} ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${QSCINTILLA_LIBRARIES}
${APPLE_SYSTEM_LIBRARIES}
)

if(MAKE_VATES AND ParaView_FOUND)
Expand Down
23 changes: 23 additions & 0 deletions qt/widgets/common/inc/MantidQtWidgets/Common/DropEventHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef MANTIDQT_MANTIDWIDGETS_DROPEVENTHELPER_H
#define MANTIDQT_MANTIDWIDGETS_DROPEVENTHELPER_H

#include "MantidQtWidgets/Common/DllOption.h"

#include <QDropEvent>
#include <vector>

namespace MantidQt {
namespace MantidWidgets {

namespace DropEventHelper {
/// Get all filenames from a QDropEvent
EXPORT_OPT_MANTIDQT_COMMON QStringList getFileNames(const QDropEvent *event);
/// Get all python files from q QDropEvent
EXPORT_OPT_MANTIDQT_COMMON QStringList
extractPythonFiles(const QDropEvent *event);
}

} // namespace MantidWidgets
} // namespace MantidQt

#endif
105 changes: 105 additions & 0 deletions qt/widgets/common/src/DropEventHelper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@

#include "MantidQtWidgets/Common/DropEventHelper.h"

#include <QStringList>
#include <QUrl>
#include <QFileInfo>

// Compile on OSX only.
#if defined(__APPLE__)
#include <CoreFoundation/CoreFoundation.h>
#endif // defined(__APPLE__)

using namespace MantidQt::MantidWidgets;

/** Workaround for file path bug on OSX >=10.10 with Qt4
*
* On Windows/Linux this simply returns the URL unchanged.
*
* For more information see this bug report:
* https://bugreports.qt.io/browse/QTBUG-40449
*
* @param url :: the url to correct the path for
* @returns a valid url to a file path
*/
QUrl fixupURL(const QUrl &url) {
#if defined(__APPLE__)
QString localFileQString = url.toLocalFile();
// Compile on OSX only.
if (localFileQString.startsWith("/.file/id=")) {
CFStringRef relCFStringRef = CFStringCreateWithCString(
kCFAllocatorDefault, localFileQString.toUtf8().constData(),
kCFStringEncodingUTF8);
CFURLRef relCFURL = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault, relCFStringRef, kCFURLPOSIXPathStyle,
false // isDirectory
);
CFErrorRef error = 0;
CFURLRef absCFURL =
CFURLCreateFilePathURL(kCFAllocatorDefault, relCFURL, &error);
if (!error) {
static const CFIndex maxAbsPathCStrBufLen = 4096;
char absPathCStr[maxAbsPathCStrBufLen];
if (CFURLGetFileSystemRepresentation(
absCFURL,
true, // resolveAgainstBase
reinterpret_cast<UInt8 *>(&absPathCStr[0]),
maxAbsPathCStrBufLen)) {
localFileQString = QString(absPathCStr);
}
}
CFRelease(absCFURL);
CFRelease(relCFURL);
CFRelease(relCFStringRef);
}
return QUrl(localFileQString);
#else
return url;
#endif // defined(__APPLE__)
}

/** Extract a list of file names from a drop event.
*
* This is a special OSX version because the OSX broke the way Qt decoded
* the file path in OSX 10.10. This is fixed in Qt5 but not backported to Qt4.
*
* @param event :: the event to extract file names from
* @return a list of file names as a QStringList
*/
QStringList DropEventHelper::getFileNames(const QDropEvent *event) {
QStringList filenames;
const auto mimeData = event->mimeData();
if (mimeData->hasUrls()) {
const auto urlList = mimeData->urls();
for (const auto &url : urlList) {
const auto fileUrl = fixupURL(url);
const auto fName = fileUrl.toLocalFile();
if (fName.size() > 0) {
filenames.append(fName);
}
}
}
return filenames;
}

/** Extract python file names from a drop event
*
* This will filter the list of file names extracted from a QDropEvent that
* end with the extension .py
*
* @param event :: the QDropEvent to filter filenames from
* @return a list of python file names
*/
QStringList DropEventHelper::extractPythonFiles(const QDropEvent *event) {
QStringList filenames;

for (const auto &name : getFileNames(event)) {
QFileInfo fi(name);

if (fi.suffix().toUpper() == "PY") {
filenames.append(name);
}
}

return filenames;
}
8 changes: 5 additions & 3 deletions qt/widgets/common/src/MWRunFiles.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "MantidQtWidgets/Common/MWRunFiles.h"
#include "MantidQtWidgets/Common/DropEventHelper.h"

#include "MantidKernel/ConfigService.h"
#include "MantidKernel/FacilityInfo.h"
Expand Down Expand Up @@ -26,6 +27,7 @@
using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace MantidQt::API;
namespace DropEventHelper = MantidQt::MantidWidgets::DropEventHelper;

////////////////////////////////////////////////////////////////////
// FindFilesThread
Expand Down Expand Up @@ -1064,9 +1066,9 @@ void MWRunFiles::checkEntry() {
*/
void MWRunFiles::dropEvent(QDropEvent *de) {
const QMimeData *mimeData = de->mimeData();
if (mimeData->hasUrls()) {
auto url_list = mimeData->urls();
m_uiForm.fileEditor->setText(url_list[0].toLocalFile());
const auto filenames = DropEventHelper::getFileNames(de);
if (!filenames.empty()) {
m_uiForm.fileEditor->setText(filenames[0]);
de->acceptProposedAction();
} else if (mimeData->hasText()) {
QString text = mimeData->text();
Expand Down
14 changes: 2 additions & 12 deletions qt/widgets/common/src/MantidTreeWidget.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include "MantidQtWidgets/Common/MantidTreeWidget.h"
#include <MantidQtWidgets/Common/WorkspacePresenter/QWorkspaceDockView.h>

#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidQtWidgets/Common/DropEventHelper.h"
#include "MantidQtWidgets/Common/MantidDisplayBase.h"

#include <QApplication>
Expand Down Expand Up @@ -56,17 +56,7 @@ void MantidTreeWidget::dragEnterEvent(QDragEnterEvent *de) {
* @param de :: The drag drop event
*/
void MantidTreeWidget::dropEvent(QDropEvent *de) {
QStringList filenames;
const QMimeData *mimeData = de->mimeData();
if (mimeData->hasUrls()) {
QList<QUrl> urlList = mimeData->urls();
for (int i = 0; i < urlList.size(); ++i) {
QString fName = urlList[i].toLocalFile();
if (fName.size() > 0) {
filenames.append(fName);
}
}
}
const auto filenames = DropEventHelper::getFileNames(de);
de->acceptProposedAction();

for (int i = 0; i < filenames.size(); ++i) {
Expand Down

0 comments on commit d783c7a

Please sign in to comment.