[QGIS Commit] r15410 - in trunk/qgis/src: app core

svn_qgis at osgeo.org svn_qgis at osgeo.org
Wed Mar 9 21:01:37 EST 2011


Author: telwertowski
Date: 2011-03-09 18:01:37 -0800 (Wed, 09 Mar 2011)
New Revision: 15410

Modified:
   trunk/qgis/src/app/main.cpp
   trunk/qgis/src/app/qgisapp.cpp
   trunk/qgis/src/app/qgisapp.h
   trunk/qgis/src/core/qgsapplication.cpp
   trunk/qgis/src/core/qgsapplication.h
Log:
Use QFileOpenEvent to handle double clicking a file icon in the Mac OS X Finder. This works for both Cocoa and Carbon. Remove Carbon-only OpenDocument code.


Modified: trunk/qgis/src/app/main.cpp
===================================================================
--- trunk/qgis/src/app/main.cpp	2011-03-09 21:40:48 UTC (rev 15409)
+++ trunk/qgis/src/app/main.cpp	2011-03-10 02:01:37 UTC (rev 15410)
@@ -129,70 +129,6 @@
 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 @@
   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" ) );

Modified: trunk/qgis/src/app/qgisapp.cpp
===================================================================
--- trunk/qgis/src/app/qgisapp.cpp	2011-03-09 21:40:48 UTC (rev 15409)
+++ trunk/qgis/src/app/qgisapp.cpp	2011-03-10 02:01:37 UTC (rev 15410)
@@ -570,6 +570,9 @@
   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 @@
   deletePrintComposers();
   removeAnnotationItems();
 
+  // cancel request for FileOpen events
+  QgsApplication::setFileOpenEventReceiver( nil );
+
   // delete map layer registry and provider registry
   QgsApplication::exitQgis();
 }
@@ -646,24 +652,31 @@
     // 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 @@
   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() )

Modified: trunk/qgis/src/app/qgisapp.h
===================================================================
--- trunk/qgis/src/app/qgisapp.h	2011-03-09 21:40:48 UTC (rev 15409)
+++ trunk/qgis/src/app/qgisapp.h	2011-03-10 02:01:37 UTC (rev 15410)
@@ -140,22 +140,23 @@
     //! 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 @@
     //! layer selection changed
     void legendLayerSelectionChanged( void );
 
+    //! Watch for QFileOpenEvent.
+    virtual bool event( QEvent * event );
+
   protected:
 
     //! Handle state changes (WindowTitleChange)

Modified: trunk/qgis/src/core/qgsapplication.cpp
===================================================================
--- trunk/qgis/src/core/qgsapplication.cpp	2011-03-09 21:40:48 UTC (rev 15409)
+++ trunk/qgis/src/core/qgsapplication.cpp	2011-03-10 02:01:37 UTC (rev 15410)
@@ -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 @@
 {
 }
 
+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 @@
   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;

Modified: trunk/qgis/src/core/qgsapplication.h
===================================================================
--- trunk/qgis/src/core/qgsapplication.h	2011-03-09 21:40:48 UTC (rev 15409)
+++ trunk/qgis/src/core/qgsapplication.h	2011-03-10 02:01:37 UTC (rev 15410)
@@ -17,6 +17,7 @@
 #define QGSAPPLICATION_H
 
 #include <QApplication>
+#include <QEvent>
 
 #include <qgis.h>
 
@@ -32,9 +33,15 @@
     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 @@
     static QString relativePathToAbsolutePath( QString rpath, QString targetPath );
 
   private:
+    static QObject* mFileOpenEventReceiver;
+    static QStringList mFileOpenEventList;
+
     static QString mPrefixPath;
     static QString mPluginPath;
     static QString mPkgDataPath;



More information about the QGIS-commit mailing list