Skip to content
Permalink
Browse files

Use QFileOpenEvent to handle double clicking a file icon in the Mac O…

…S X Finder. This works for both Cocoa and Carbon. Remove Carbon-only OpenDocument code.

git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@15410 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
telwertowski
telwertowski committed Mar 10, 2011
1 parent 10dee12 commit eb25ec510676835bdd482a7af92b919ab3eda125
Showing with 113 additions and 90 deletions.
  1. +0 −71 src/app/main.cpp
  2. +44 −12 src/app/qgisapp.cpp
  3. +11 −7 src/app/qgisapp.h
  4. +48 −0 src/core/qgsapplication.cpp
  5. +10 −0 src/core/qgsapplication.h
@@ -129,70 +129,6 @@ static QString myProjectFileName = "";
static QStringList myFileList;


#ifdef Q_OS_MACX
/* Mac OS OpenDocuments AppleEvent handler called when files are double-clicked.
* May be called at startup before application is initialized as well as
* at any time while the application is running.
*/
OSErr openDocumentsAEHandler( const AppleEvent *event, AppleEvent *reply, SRefCon refCon )
{
AEDescList docs;
if ( AEGetParamDesc( event, keyDirectObject, typeAEList, &docs ) == noErr )
{
// Get count of files to open
long count = 0;
AECountItems( &docs, &count );

// Examine files and load first project file followed by all other non-project files
myProjectFileName.truncate( 0 );
myFileList.clear();
for ( int i = 0; i < count; i++ )
{
FSRef ref;
UInt8 strBuffer[256];
if ( AEGetNthPtr( &docs, i + 1, typeFSRef, 0, 0, &ref, sizeof( ref ), 0 ) == noErr &&
FSRefMakePath( &ref, strBuffer, 256 ) == noErr )
{
QString fileName( QString::fromUtf8( reinterpret_cast<char *>( strBuffer ) ) );
if ( fileName.endsWith( ".qgs" ) )
{
// Load first project file and ignore all other project files
if ( myProjectFileName.isEmpty() )
{
myProjectFileName = fileName;
}
}
else
{
// Load all non-project files
myFileList.append( fileName );
}
}
}

// Open files now if application has been fully initialized (has objectName).
// Otherwise (if this routine is called by processEvents inside the QgisApp constructor
// at startup) wait for the command line file loader to notice these files.
QgisApp *qgis = QgisApp::instance();
if ( qgis && qgis->objectName() == "QgisApp" )
{
if ( !myProjectFileName.isEmpty() )
{
qgis->openProject( myProjectFileName );
}
for ( QStringList::Iterator myIterator = myFileList.begin();
myIterator != myFileList.end(); ++myIterator )
{
QString fileName = *myIterator;
qgis->openLayer( fileName );
}
}
}
return noErr;
}
#endif


/* Test to determine if this program was started on Mac OS X by double-clicking
* the application bundle rather then from a command line. If clicked, argv[1]
* contains a process serial number in the form -psn_0_1234567. Don't process
@@ -512,13 +448,6 @@ int main( int argc, char *argv[] )
QCoreApplication::setApplicationName( "QGIS" );
QCoreApplication::setAttribute( Qt::AA_DontShowIconsInMenus, false );
#ifdef Q_OS_MACX
// Install OpenDocuments AppleEvent handler after application object is initialized
// but before any other event handling (including dialogs or splash screens) occurs.
// If an OpenDocuments event has been created before the application was launched,
// it must be handled before some other event handler runs and dismisses it as unknown.
// If run at startup, the handler will set either or both of myProjectFileName and myFileList.
AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments, openDocumentsAEHandler, 0, false );

// If the GDAL plugins are bundled with the application and GDAL_DRIVER_PATH
// is not already defined, use the GDAL plugins in the application bundle.
QString gdalPlugins( QCoreApplication::applicationDirPath().append( "/lib/gdalplugins" ) );
@@ -570,6 +570,9 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
QgsDebugMsg( QgsApplication::showSettings() );
QgsDebugMsg( "\n--------------------------\n\n\n" );

// request notification of FileOpen events (double clicking a file icon in Mac OS X Finder)
QgsApplication::setFileOpenEventReceiver( this );

} // QgisApp ctor


@@ -622,6 +625,9 @@ QgisApp::~QgisApp()
deletePrintComposers();
removeAnnotationItems();

// cancel request for FileOpen events
QgsApplication::setFileOpenEventReceiver( nil );

// delete map layer registry and provider registry
QgsApplication::exitQgis();
}
@@ -646,23 +652,30 @@ void QgisApp::dropEvent( QDropEvent *event )
// so we test for length to make sure we have something
if ( !fileName.isEmpty() )
{
// check to see if we are opening a project file
QFileInfo fi( fileName );
if ( fi.completeSuffix() == "qgs" )
{
QgsDebugMsg( "Opening project " + fileName );
openProject( fileName );
}
else
{
QgsDebugMsg( "Adding " + fileName + " to the map canvas" );
openLayer( fileName, true );
}
openFile( fileName );
}
}
event->acceptProposedAction();
}

bool QgisApp::event( QEvent * event )
{
bool done = false;
if ( event->type() == QEvent::FileOpen )
{
// handle FileOpen event (double clicking a file icon in Mac OS X Finder)
QFileOpenEvent *foe = static_cast<QFileOpenEvent *>( event );
openFile( foe->file() );
done = true;
}
else
{
// pass other events to base class
done = QMainWindow::event( event );
}
return done;
}


// restore any application settings stored in QSettings
void QgisApp::readSettings()
@@ -2970,6 +2983,25 @@ bool QgisApp::openLayer( const QString & fileName, bool allowInteractive )
return ok;
}


// Open a file specified by a commandline argument, Drop or FileOpen event.
void QgisApp::openFile( const QString & fileName )
{
// check to see if we are opening a project file
QFileInfo fi( fileName );
if ( fi.completeSuffix() == "qgs" )
{
QgsDebugMsg( "Opening project " + fileName );
openProject( fileName );
}
else
{
QgsDebugMsg( "Adding " + fileName + " to the map canvas" );
openLayer( fileName, true );
}
}


void QgisApp::newPrintComposer()
{
if ( mMapCanvas && mMapCanvas->isDrawing() )
@@ -140,22 +140,23 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
//! Remove all layers from the map and legend - reimplements same method from qgisappbase
void removeAllLayers();
/** Open a raster or vector file; ignore other files.
Used to process a commandline argument or OpenDocument AppleEvent.
Used to process a commandline argument, FileOpen or Drop event.
Set interactive to true if it is ok to ask the user for information (mostly for
when a vector layer has sublayers and we want to ask which sublayers to use).
@returns true if the file is successfully opened
*/
bool openLayer( const QString & fileName, bool allowInteractive = false );
/** Open the specified file (project, vector, or raster); prompt to save
previous project if necessary.
Used to process a commandline argument, OpenDocument AppleEvent, or a
file drag/drop event. Set interactive to true if it is ok to ask the
user for information (mostly for when a vector layer has sublayers and
we want to ask which sublayers to use).
/** Open the specified project file; prompt to save previous project if necessary.
Used to process a commandline argument, FileOpen or Drop event.
*/
void openProject( const QString & fileName );
/** opens a qgis project file
@returns false if unable to open the project
*/
bool addProject( QString projectFile );
/** Convenience function to open either a project or a layer file.
*/
void openFile( const QString & fileName );
//!Overloaded version of the private function with same name that takes the imagename as a parameter
void saveMapAsImage( QString, QPixmap * );
/** Get the mapcanvas object from the app */
@@ -431,6 +432,9 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
//! layer selection changed
void legendLayerSelectionChanged( void );

//! Watch for QFileOpenEvent.
virtual bool event( QEvent * event );

protected:

//! Handle state changes (WindowTitleChange)
@@ -20,6 +20,7 @@
#include "qgsexception.h"

#include <QDir>
#include <QFileOpenEvent>
#include <QMessageBox>
#include <QPalette>
#include <QSettings>
@@ -34,6 +35,8 @@

#include <ogr_api.h>

QObject * QgsApplication::mFileOpenEventReceiver;
QStringList QgsApplication::mFileOpenEventList;
QString QgsApplication::mPrefixPath;
QString QgsApplication::mPluginPath;
QString QgsApplication::mPkgDataPath;
@@ -79,6 +82,34 @@ QgsApplication::~QgsApplication()
{
}

bool QgsApplication::event( QEvent * event )
{
bool done = false;
if ( event->type() == QEvent::FileOpen )
{
// handle FileOpen event (double clicking a file icon in Mac OS X Finder)
if ( mFileOpenEventReceiver )
{
// Forward event to main window.
done = notify( mFileOpenEventReceiver, event );
}
else
{
// Store filename because receiver has not registered yet.
// If QGIS has been launched by double clicking a file icon, FileOpen will be
// the first event; the main window is not yet ready to handle the event.
mFileOpenEventList.append( static_cast<QFileOpenEvent *>( event )->file() );
done = true;
}
}
else
{
// pass other events to base class
done = QApplication::event( event );
}
return done;
}

bool QgsApplication::notify( QObject * receiver, QEvent * event )
{
// Send event to receiver and catch unhandled exceptions
@@ -102,6 +133,23 @@ bool QgsApplication::notify( QObject * receiver, QEvent * event )
return done;
}

void QgsApplication::setFileOpenEventReceiver( QObject * receiver )
{
// Set receiver for FileOpen events
mFileOpenEventReceiver = receiver;
// Propagate any events collected before the receiver has registered.
if ( mFileOpenEventList.count() > 0 )
{
QStringListIterator i( mFileOpenEventList );
while ( i.hasNext() )
{
QFileOpenEvent foe( i.next() );
QgsApplication::sendEvent( mFileOpenEventReceiver, &foe );
}
mFileOpenEventList.clear();
}
}

void QgsApplication::setPrefixPath( const QString thePrefixPath, bool useDefaultPaths )
{
mPrefixPath = thePrefixPath;
@@ -17,6 +17,7 @@
#define QGSAPPLICATION_H

#include <QApplication>
#include <QEvent>

#include <qgis.h>

@@ -32,9 +33,15 @@ class CORE_EXPORT QgsApplication: public QApplication
QgsApplication( int & argc, char ** argv, bool GUIenabled, QString customConfigPath = QString() );
virtual ~QgsApplication();

//! Watch for QFileOpenEvent.
virtual bool event( QEvent * event );

//! Catch exceptions when sending event to receiver.
virtual bool notify( QObject * receiver, QEvent * event );

//! Set the FileOpen event receiver
static void setFileOpenEventReceiver( QObject * receiver );

/** Set the active theme to the specified theme.
* The theme name should be a single word e.g. 'default','classic'.
* The theme search path usually will be pkgDataPath + "/themes/" + themName + "/"
@@ -195,6 +202,9 @@ class CORE_EXPORT QgsApplication: public QApplication
static QString relativePathToAbsolutePath( QString rpath, QString targetPath );

private:
static QObject* mFileOpenEventReceiver;
static QStringList mFileOpenEventList;

static QString mPrefixPath;
static QString mPluginPath;
static QString mPkgDataPath;

0 comments on commit eb25ec5

Please sign in to comment.
You can’t perform that action at this time.