diff main/main.cpp @ 365:174ca518546f macness

Use QFileOpenEvent instead of native mac AppleEvent stuff: does the same job, better, neater
author Dan Stowell <dan.stowell@eecs.qmul.ac.uk>
date Mon, 11 Oct 2010 15:47:12 +0100
parents 43205eda54bd
children d0c5831d6528 61111a6a229f
line wrap: on
line diff
--- a/main/main.cpp	Mon Oct 11 14:54:31 2010 +0100
+++ b/main/main.cpp	Mon Oct 11 15:47:12 2010 +0100
@@ -23,11 +23,6 @@
 #include "widgets/TipDialog.h"
 #include "transform/TransformFactory.h"
 
-#ifdef Q_WS_MAC
-#include <ApplicationServices/ApplicationServices.h>
-#include <Carbon/Carbon.h>
-#endif
-
 #include <QMetaType>
 #include <QApplication>
 #include <QDesktopWidget>
@@ -41,6 +36,7 @@
 #include <QSplashScreen>
 #include <QTimer>
 #include <QPainter>
+#include <QFileOpenEvent>
 
 #include "../version.h"
 
@@ -176,7 +172,6 @@
 */
 
 static QMutex cleanupMutex;
-static MainWindow *gui;
 
 static void
 signalHandler(int /* signal */)
@@ -194,7 +189,10 @@
 public:
     SVApplication(int &argc, char **argv) :
         QApplication(argc, argv),
-        m_mainWindow(0) { }
+        m_readyForFiles(false),
+        m_filepathQueue(QStringList()),
+        m_mainWindow(0)
+        { }
     virtual ~SVApplication() { }
 
     void setMainWindow(MainWindow *mw) { m_mainWindow = mw; }
@@ -208,96 +206,15 @@
         if (!success) manager.cancel();
     }
 
-    /** Application-global handler for filepaths passed in, e.g. as command-line arguments or apple events */
-    static void handleFilepathArgument(QString path, QSplashScreen *splash){
-        static bool haveSession = false;
-        static bool haveMainModel = false;
-        static bool havePriorCommandLineModel = false;
-    
-        MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed;
-    
-        if (path.endsWith("sv")) {
-            if (!haveSession) {
-                status = gui->openSessionFile(path);
-                if (status == MainWindow::FileOpenSucceeded) {
-                    haveSession = true;
-                    haveMainModel = true;
-                }
-            } else {
-                std::cerr << "WARNING: Ignoring additional session file argument \"" << path.toStdString() << "\"" << std::endl;
-                status = MainWindow::FileOpenSucceeded;
-            }
-        }
-        if (status != MainWindow::FileOpenSucceeded) {
-            if (!haveMainModel) {
-                status = gui->open(path, MainWindow::ReplaceMainModel);
-                if (status == MainWindow::FileOpenSucceeded) {
-                    haveMainModel = true;
-                }
-            } else {
-                if (haveSession && !havePriorCommandLineModel) {
-                    status = gui->open(path, MainWindow::AskUser);
-                    if (status == MainWindow::FileOpenSucceeded) {
-                        havePriorCommandLineModel = true;
-                    }
-                } else {
-                    status = gui->open(path, MainWindow::CreateAdditionalModel);
-                }
-            }
-        }
-        if (status == MainWindow::FileOpenFailed) {
-            if (splash) splash->hide();
-            QMessageBox::critical
-                (gui, QMessageBox::tr("Failed to open file"),
-                 QMessageBox::tr("File or URL \"%1\" could not be opened").arg(path));
-        } else if (status == MainWindow::FileOpenWrongMode) {
-            if (splash) splash->hide();
-            QMessageBox::critical
-                (gui, QMessageBox::tr("Failed to open file"),
-                 QMessageBox::tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
-        }
-    }
-    
-#ifdef Q_WS_MAC
-    static pascal OSErr HandleOpenDocAE (const AppleEvent * theAppleEvent, AppleEvent * /* reply */, SInt32 /* handlerRefcon */) {
-        AEDescList  docList;
-        FSRef       theFSRef;
-        long        count = 0;
-        OSErr       err;
-     
-        err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
-        err = AECountItems(&docList, &count);
-        if(count == 0){
-            std::cerr << "SV warning: received apple open-documents event with no documents (count==0)" << std::endl;
-            AEDisposeDesc(&docList);
-            return noErr;
-        }
-        // NB we could be passed a list of files - however, SV on Mac currently can only open one at a time, so we simply open the first.
+    void handleFilepathArgument(QString path, QSplashScreen *splash);
 
-        err = AEGetNthPtr(&docList, 1, typeFSRef, NULL, NULL, &theFSRef, sizeof(theFSRef), NULL);
-
-        // Call routine to open document with current reference.
-        if(err == noErr){
-            char uPath[1024];
-            FSRefMakePath(&theFSRef, (UInt8*)uPath, 1023);
-            std::cerr << "SV received Apple Event request to open " << uPath << std::endl;
-            handleFilepathArgument(uPath, NULL);
-        }
-
-        AEDisposeDesc(&docList);
-        return noErr;
-    }
-    static OSErr InstallMacOSEventHandlers(void)
-    {
-        OSErr err;
-        err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(HandleOpenDocAE), 0, false);
-        std::cerr << "HandleOpenDocAE installed. " << err << std::endl;
-        return err;
-    }
-#endif // Q_WS_MAC
+    bool m_readyForFiles;
+    QStringList m_filepathQueue;
 
 protected:
     MainWindow *m_mainWindow;
+    bool event(QEvent *);
+
 };
 
 int
@@ -409,7 +326,7 @@
     qRegisterMetaType<size_t>("size_t");
     qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName");
 
-    gui = new MainWindow(audioOutput, oscSupport);
+    MainWindow *gui = new MainWindow(audioOutput, oscSupport);
     application.setMainWindow(gui);
     if (splash) {
         QObject::connect(gui, SIGNAL(hideSplash()), splash, SLOT(hide()));
@@ -434,10 +351,6 @@
     }
     settings.endGroup();
     
-#ifdef Q_WS_MAC
-    application.InstallMacOSEventHandlers();
-#endif // Q_WS_MAC
-    
     gui->show();
 
     // The MainWindow class seems to have trouble dealing with this if
@@ -445,6 +358,8 @@
     // complete.  As a lazy hack, apply it explicitly from here
     gui->preferenceChanged("Property Box Layout");
 
+    application.m_readyForFiles = true; // Ready to receive files from e.g. Apple Events
+
     for (QStringList::iterator i = args.begin(); i != args.end(); ++i) {
 
         if (i == args.begin()) continue;
@@ -452,7 +367,12 @@
 
         QString path = *i;
 
-        SVApplication::handleFilepathArgument(path, splash);
+        application.handleFilepathArgument(path, splash);
+    }
+    
+    for (QStringList::iterator i = application.m_filepathQueue.begin(); i != application.m_filepathQueue.end(); ++i) {
+        QString path = *i;
+        application.handleFilepathArgument(path, splash);
     }
     
 #ifdef HAVE_FFTW3F
@@ -510,3 +430,68 @@
 
     return rv;
 }
+
+bool SVApplication::event(QEvent *event){
+    QString thePath;
+    switch (event->type()) {
+    case QEvent::FileOpen:
+        thePath = static_cast<QFileOpenEvent *>(event)->file();
+        if(m_readyForFiles)
+            handleFilepathArgument(thePath, NULL);
+        else
+            m_filepathQueue.append(thePath);
+        return true;
+    default:
+        return QApplication::event(event);
+    }
+}
+
+/** Application-global handler for filepaths passed in, e.g. as command-line arguments or apple events */
+void SVApplication::handleFilepathArgument(QString path, QSplashScreen *splash){
+    static bool haveSession = false;
+    static bool haveMainModel = false;
+    static bool havePriorCommandLineModel = false;
+
+    MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed;
+
+    if (path.endsWith("sv")) {
+        if (!haveSession) {
+            status = m_mainWindow->openSessionFile(path);
+            if (status == MainWindow::FileOpenSucceeded) {
+                haveSession = true;
+                haveMainModel = true;
+            }
+        } else {
+            std::cerr << "WARNING: Ignoring additional session file argument \"" << path.toStdString() << "\"" << std::endl;
+            status = MainWindow::FileOpenSucceeded;
+        }
+    }
+    if (status != MainWindow::FileOpenSucceeded) {
+        if (!haveMainModel) {
+            status = m_mainWindow->open(path, MainWindow::ReplaceMainModel);
+            if (status == MainWindow::FileOpenSucceeded) {
+                haveMainModel = true;
+            }
+        } else {
+            if (haveSession && !havePriorCommandLineModel) {
+                status = m_mainWindow->open(path, MainWindow::AskUser);
+                if (status == MainWindow::FileOpenSucceeded) {
+                    havePriorCommandLineModel = true;
+                }
+            } else {
+                status = m_mainWindow->open(path, MainWindow::CreateAdditionalModel);
+            }
+        }
+    }
+    if (status == MainWindow::FileOpenFailed) {
+        if (splash) splash->hide();
+        QMessageBox::critical
+            (m_mainWindow, QMessageBox::tr("Failed to open file"),
+             QMessageBox::tr("File or URL \"%1\" could not be opened").arg(path));
+    } else if (status == MainWindow::FileOpenWrongMode) {
+        if (splash) splash->hide();
+        QMessageBox::critical
+            (m_mainWindow, QMessageBox::tr("Failed to open file"),
+             QMessageBox::tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
+    }
+}