一、背景介紹
用Qt開發的應用程序要實現文件關聯,雙擊時用默認關聯的程序打開文件,在Windows上這個功能非常容易實現。Windows應用程序在安裝的時候可以在注冊表中寫入相關的鍵值對。打開文件的時候,Windows Explorer會將文件完整的路徑作為參數傳遞給關聯的應用程序。這樣就可以在啟動程序后將這個文件作為目標進行處理。
如上述代碼所示,接着我們就可以在main函數的argv中獲取到文件路徑,完成文件的關聯打開。但是在macOS上卻不是這么做的。首先macOS上沒有類似Windows注冊表,不會寫入這些信息;其次,macOS上常見的安裝包格式pkg也不提供這些功能。那么,在macOS上我們應該怎么來實現這樣的功能呢?我們馬上來看看。
首先,要實現雙擊用關聯程序打開文件這個功能,要分兩個步驟:(1)通過某種方式來聲明我們的應用程序支持哪些文檔類型;(2)要接收從窗口管理系統傳遞過來的文件路徑。滿足了這兩點,才能正常實現目標功能。
(1)文件格式關聯聲明
在macOS上,每個應用程序里面都會包含一個info.plist文件。這個文件以XML格式來組織一些鍵值對。每個鍵值對都包含聲明了一個特定的信息,如版本號、文檔類型、簽名信息和標識符等。應用程序支持哪些文檔格式也是在這個文件里面進行聲明的。
可以看到,這個info.plist文件里面我們添加了三種文檔格式。每當嘗試使用應用程序來打開一個文檔時,都會根據這些信息來確定是否支持打開。
(2)接收目標文檔路徑
在macOS上打開一個文檔時,macOS Finder不會像Windows Explorer一樣將文件名作為關聯程序的啟動參數。我們測試的時候也可以發現,程序啟動的時候main函數的argc參數值永遠是1,除了程序名之外不會有其他參數存在。事實上,在macOS上我們用Qt開發的程序可以監聽QFileOpenEvent這樣一個事件,來實現對文件路徑的捕獲。
在Qt文檔中我們可以看到這樣一個示例:
1 #include <QApplication> 2 #include <QFileOpenEvent> 3 #include <QtDebug> 4 5 class MyApplication : public QApplication 6 { 7 public: 8 MyApplication(int &argc, char **argv) 9 : QApplication(argc, argv) 10 { 11 } 12 13 bool event(QEvent *event) 14 { 15 if (event->type() == QEvent::FileOpen) { 16 QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event); 17 qDebug() << "Open file" << openEvent->file(); 18 } 19 20 return QApplication::event(event); 21 } 22 };
示例中繼承了QApplication類,並在event函數中處理了QFileOpenEvent事件。這個事件可以直接獲取到正在打開的文件名和文件路徑,也就實現了我們的目的了。這里我們在QApplication里面處理了這個事件,根據需要我們也可以將這個文件路徑傳到主窗口類中進行后續的打開操作。至此,結合上面的這方面的設置,我們這個功能就完成了。
二、參考鏈接
1. https://forum.qt.io/topic/80205/open-file-with-double-click-on-mac/8
2. https://stackoverflow.com/questions/26849866/unable-to-open-file-with-qt-app-on-mac
3. https://doc.qt.io/qt-5/qfileopenevent.html