Skip to content

Commit

Permalink
Add win32 native implementation, and new openFileExplorerAndSelectFile
Browse files Browse the repository at this point in the history
method to QgsNative

Opens the desktop file explorer at the folder containing path,
and (if possible) scrolls to and pre-selects the file at path itself.

The default implementation just calls the QDesktopServices method to open the folder,
without selecting the specified file.

Use this to automatically select the exported layout file
when clicking the message bar success message in layouts (on Windows)
  • Loading branch information
nyalldawson committed Jul 31, 2018
1 parent 1fea03f commit 762099b
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 12 deletions.
10 changes: 4 additions & 6 deletions src/app/layout/qgslayoutdesignerdialog.cpp
Expand Up @@ -1971,14 +1971,13 @@ void QgsLayoutDesignerDialog::exportToPdf()
// force a refresh, to e.g. update data defined properties, tables, etc
mLayout->refresh();

QFileInfo fi( outputFileName );
QgsLayoutExporter exporter( mLayout );
switch ( exporter.exportToPdf( outputFileName, pdfSettings ) )
{
case QgsLayoutExporter::Success:
{
mMessageBar->pushMessage( tr( "Export layout" ),
tr( "Successfully exported layout to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( fi.path() ).toString(), QDir::toNativeSeparators( outputFileName ) ),
tr( "Successfully exported layout to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( outputFileName ).toString(), QDir::toNativeSeparators( outputFileName ) ),
Qgis::Success, 0 );
break;
}
Expand Down Expand Up @@ -2078,14 +2077,13 @@ void QgsLayoutDesignerDialog::exportToSvg()
// force a refresh, to e.g. update data defined properties, tables, etc
mLayout->refresh();

QFileInfo fi( outputFileName );
QgsLayoutExporter exporter( mLayout );
switch ( exporter.exportToSvg( outputFileName, svgSettings ) )
{
case QgsLayoutExporter::Success:
{
mMessageBar->pushMessage( tr( "Export layout" ),
tr( "Successfully exported layout to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( fi.path() ).toString(), QDir::toNativeSeparators( outputFileName ) ),
tr( "Successfully exported layout to <a href=\"%1\">%2</a>" ).arg( outputFileName, QDir::toNativeSeparators( outputFileName ) ),
Qgis::Success, 0 );
break;
}
Expand Down Expand Up @@ -2892,7 +2890,7 @@ void QgsLayoutDesignerDialog::exportAtlasToPdf()
if ( singleFile )
{
mMessageBar->pushMessage( tr( "Export atlas" ),
tr( "Successfully exported atlas to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( fi.path() ).toString(), QDir::toNativeSeparators( outputFileName ) ),
tr( "Successfully exported atlas to <a href=\"%1\">%2</a>" ).arg( outputFileName, QDir::toNativeSeparators( outputFileName ) ),
Qgis::Success, 0 );
}
else
Expand Down Expand Up @@ -3251,7 +3249,7 @@ void QgsLayoutDesignerDialog::exportReportToPdf()
case QgsLayoutExporter::Success:
{
mMessageBar->pushMessage( tr( "Export report" ),
tr( "Successfully exported report to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( fi.path() ).toString(), QDir::toNativeSeparators( outputFileName ) ),
tr( "Successfully exported report to <a href=\"%1\">%2</a>" ).arg( outputFileName, QDir::toNativeSeparators( outputFileName ) ),
Qgis::Success, 0 );
break;
}
Expand Down
6 changes: 3 additions & 3 deletions src/app/qgsprojectproperties.cpp
Expand Up @@ -26,9 +26,11 @@
#include "qgsdatumtransformtablewidget.h"
#include "qgslayoutmanager.h"
#include "qgslogger.h"
#include "qgsgui.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayer.h"
#include "qgsproject.h"
#include "qgsnative.h"
#include "qgsprojectlayergroupdialog.h"
#include "qgsrasterlayer.h"
#include "qgsvectorlayer.h"
Expand Down Expand Up @@ -246,9 +248,7 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *pa

connect( mButtonOpenProjectFolder, &QToolButton::clicked, this, [ = ]
{
QFileInfo fi( QgsProject::instance()->fileName() );
QString folder = fi.path();
QDesktopServices::openUrl( QUrl::fromLocalFile( folder ) );
QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( QgsProject::instance()->fileName() );
} );

// get the manner in which the number of decimal places in the mouse
Expand Down
3 changes: 3 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -956,6 +956,9 @@ GENERATE_EXPORT_HEADER(
SET(QGIS_GUI_HDRS ${QGIS_GUI_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_gui.h)

IF(NOT APPLE)
IF (WIN32 )
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/native/win)
ENDIF (WIN32)
INSTALL(FILES ${QGIS_GUI_HDRS} ${QGIS_GUI_MOC_HDRS} DESTINATION ${QGIS_INCLUDE_DIR})
ELSE(NOT APPLE)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/native/mac)
Expand Down
4 changes: 4 additions & 0 deletions src/gui/qgsgui.cpp
Expand Up @@ -25,6 +25,8 @@
#include "qgslayoutviewrubberband.h"
#ifdef Q_OS_MACX
#include "qgsmacnative.h"
#elif defined (Q_OS_WIN)
#include "qgswinnative.h"
#else
#include "qgsnative.h"
#endif
Expand Down Expand Up @@ -112,6 +114,8 @@ QgsGui::QgsGui()
{
#ifdef Q_OS_MAC
mNative = new QgsMacNative();
#elif defined (Q_OS_WIN)
mNative = new QgsWinNative();
#else
mNative = new QgsNative();
#endif
Expand Down
10 changes: 8 additions & 2 deletions src/gui/qgsmessagebaritem.cpp
Expand Up @@ -18,11 +18,13 @@
#include "qgsapplication.h"
#include "qgsmessagebaritem.h"
#include "qgsmessagebar.h"

#include "qgsgui.h"
#include "qgsnative.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QTextBrowser>
#include <QDesktopServices>
#include <QFile>

QgsMessageBarItem::QgsMessageBarItem( const QString &text, Qgis::MessageLevel level, int duration, QWidget *parent )
: QWidget( parent )
Expand Down Expand Up @@ -269,5 +271,9 @@ QgsMessageBarItem *QgsMessageBarItem::setDuration( int duration )

void QgsMessageBarItem::urlClicked( const QUrl &url )
{
QDesktopServices::openUrl( url );
const bool isFile = QFile::exists( url.toLocalFile() );
if ( isFile )
QgsGui::instance()->nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
else
QDesktopServices::openUrl( url );
}
25 changes: 24 additions & 1 deletion src/native/CMakeLists.txt
Expand Up @@ -24,6 +24,7 @@ IF(APPLE)
ENDFOREACH(_lib ${APPLE_LIB_LIST})
ENDIF(APPLE)


#############################################################
# sources

Expand All @@ -44,6 +45,15 @@ IF(APPLE)
)
ENDIF(APPLE)

IF(WIN32)
SET(QGIS_APP_WIN32_SRCS
win/qgswinnative.cpp
)
SET(QGIS_NATIVE_SRCS ${QGIS_NATIVE_SRCS}
${QGIS_APP_WIN32_SRCS}
)
ENDIF(WIN32)

SET(QGIS_NATIVE_HDRS
qgsnative.h
)
Expand All @@ -57,6 +67,12 @@ IF(APPLE)
)
ENDIF(APPLE)

IF(WIN32)
SET (QGIS_NATIVE_HDRS ${QGIS_NATIVE_HDRS}
win/qgswinnative.h
)
ENDIF(WIN32)

INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
Expand Down Expand Up @@ -100,8 +116,15 @@ IF(NOT ANDROID)
)
ENDIF(NOT ANDROID)

TARGET_LINK_LIBRARIES(qgis_native "${NATIVE_LINK_LIBS}")
TARGET_LINK_LIBRARIES(qgis_native
${Qt5Core_LIBRARIES}
${Qt5Gui_LIBRARIES}
"${NATIVE_LINK_LIBS}"
)

IF (WIN32)
TARGET_LINK_LIBRARIES(qgis_native shell32)
ENDIF (WIN32)
# install

INSTALL(TARGETS qgis_native
Expand Down
11 changes: 11 additions & 0 deletions src/native/qgsnative.cpp
Expand Up @@ -16,7 +16,18 @@
***************************************************************************/

#include "qgsnative.h"
#include <QString>
#include <QDesktopServices>
#include <QUrl>
#include <QFileInfo>

void QgsNative::currentAppActivateIgnoringOtherApps()
{
}

void QgsNative::openFileExplorerAndSelectFile( const QString &path )
{
QFileInfo fi( path );
QString folder = fi.path();
QDesktopServices::openUrl( QUrl::fromLocalFile( folder ) );
}
13 changes: 13 additions & 0 deletions src/native/qgsnative.h
Expand Up @@ -20,6 +20,8 @@

#include "qgis_native.h"

class QString;

/**
* \class QgsNative
* \ingroup native
Expand All @@ -37,6 +39,17 @@ class NATIVE_EXPORT QgsNative
* Brings the QGIS app to front. The default implementation does nothing.
*/
virtual void currentAppActivateIgnoringOtherApps();

/**
* Opens the desktop file explorer at the folder containing \a path,
* and (if possible) scrolls to and pre-selects the file at \a path itself.
*
* The default implementation just calls the QDesktopServices method to open the folder,
* without selecting the specified file.
*
* \since QGIS 3.4
*/
virtual void openFileExplorerAndSelectFile( const QString &path );
};

#endif // QGSNATIVE_H
31 changes: 31 additions & 0 deletions src/native/win/qgswinnative.cpp
@@ -0,0 +1,31 @@
/***************************************************************************
qgswinnative.cpp - abstracted interface to native system calls
-------------------
begin : January 2017
copyright : (C) 2017 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgswinnative.h"
#include <QString>
#include <QDir>

void QgsWinNative::openFileExplorerAndSelectFile( const QString &path )
{
const QString nativePath = QDir::toNativeSeparators( path );
ITEMIDLIST *pidl = ILCreateFromPath( nativePath.toUtf8().constData() );
if ( pidl )
{
SHOpenFolderAndSelectItems( pidl, 0, 0, 0 );
ILFree( pidl );
}
}
32 changes: 32 additions & 0 deletions src/native/win/qgswinnative.h
@@ -0,0 +1,32 @@
/***************************************************************************
qgswinnative.h - abstracted interface to native Mac objective-c
-------------------
begin : January 2014
copyright : (C) 2014 by Larry Shaffer
email : larrys at dakotacarto dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMACNATIVE_H
#define QGSMACNATIVE_H

#include "qgsnative.h"
#include <windows.h>
#include <shlobj.h>
#pragma comment(lib,"Shell32.lib")

class NATIVE_EXPORT QgsWinNative : public QgsNative
{
public:
void openFileExplorerAndSelectFile( const QString &path ) override;
};

#endif // QGSMACNATIVE_H

0 comments on commit 762099b

Please sign in to comment.