处理Mac OS X文件打开事件BEFORE C ++ main()执行 [英] Handling Mac OS X file open event BEFORE C++ main() executes
问题描述
我已经google了很多,但仍然找不到好的解决方案:/
所以,我正在移植一个复杂的Qt5应用程序(某些网络服务的客户端)到Mac OS X(10.7。 0Lion以上)。
I've googled a lot, but still unable to find nice solution :/
So, i'm porting one complicated Qt5 application (client of some network service) to Mac OS X (10.7.0 "Lion" and higher).
我需要处理自定义文件,例如 *。xyz
自定义URL方案如 xyz://
。
好吧,Qt5有 QFileOpenEvent
处理OS X适当的事件。
但:此事件仅在应用程序事件循环开始后到达(显然)!
I need to handle custom file like *.xyz
and custom URL scheme like xyz://
.
Okay, Qt5 has the QFileOpenEvent
class to handle OS X appropriate event.
BUT: this event arrives only after the application event loop starts (obviously)!
我需要捕获和处理OS X'文件打开事件 BEFORE main
启动,因为程序逻辑设计为照顾
And i need to "catch" and handle OS X' file open event BEFORE main
starts, because the program logic was designed to take care of the command line argument handling only.
简化的 main
函数代码:
int main(int argc, char[]* argv)
{
QApplication app( argc, argv );
QStringList arguments = app.arguments();
if( arguments.count() == argc ) arguments.removeFirst();
Logic appLogic( NULL, &app );
app.installMessageHandler( &appLogic );
// The problem:
// **This function will always called earlier than the any event**
if( ! appLogic.start( arguments ) ) return 0;
// Start processing of events
// Only after this call Logic class get the desired event
return app.exec();
}
是否有办法获取OS X文件打开事件之前启动C ++ main
函数,或者在 argv
参数中获取my文件/ ?
也许,一些 Objective-C
黑魔法可以完成这项工作吗?
Is there a way to get an OS X' file opening event before the C++ main
function starts, or to get "my" file/url in the argv
parameter?
Maybe, some Objective-C
black magic does the job?
start
执行许多复杂和异步的事情。事件在执行期间到达,因此当异步东西已经工作时,很难处理它。所以看起来像我只是需要防止开始
执行,如果事件将到达。
NOTE: start
does many complicated - and asynchronous - things. Event arrives during it's execution, so it's hard to handle it when the async stuff is already working. So looks like i just need to prevent start
execution, if the event will arrive.
如果应用程序已经打开,没有问题。
If the application is already opened, there is no problem.
推荐答案
我发现了一个可行的解决方案 - 使用Qt的事件系统。 / p>
I've found one, propably weird, solution - use Qt' event system.
int main(int argc, char[]* argv)
{
QApplication app( argc, argv );
QStringList arguments = app.arguments();
if( arguments.count() == argc ) arguments.removeFirst();
Logic appLogic( NULL, &app );
#ifdef Q_OS_MAC
app.installMessageHandler( &appLogic );
// Here we should alreasy get FileOpenEvent, if it occurs
// NOTE: without this FileOpenEvent will arrive LATER
// than the DryRunEvent!
app.processEvents();
// If there is no file open event in the queue,
// we should just open the blank program window
// NOTE: Qt takes ownership of this event object,
// so you should not delete it manually
DryRunEvent* runEv = new DryRunEvent( p );
a.postEvent( &l, runEv, Qt::LowEventPriority );
#endif
...
#ifndef Q_OS_MAC
if( ! appLogic.start( arguments ) ) return 0;
#endif
return app.exec();
}
自定义事件标题:
class BaseEvent : public QEvent
{
public:
BaseEvent( QEvent::Type& eType ) : QEvent( getEventType( eType ) )
{
}
~BaseEvent() {}
QEvent::Type getEventType( QEvent::Type& eType )
{
if( eType == QEvent::None )
{
eType = static_cast<QEvent::Type>( QEvent::registerEventType() );
}
return eType;
}
};
class DryRunEvent : public BaseEvent
{
QStringList m_params;
public:
DryRunEvent( const Parameters& params ) :
BaseEvent( eventType ), m_params( params )
{
}
~DryRunEvent(){}
QStringList GetCmdLineParams() const { return m_params; }
public:
static QEvent::Type eventType;
};
自定义事件源:
QEvent::Type ViewerDryRunEvent::eventType = QEvent::None;
逻辑类标题:
class Logic : public QObject
{
Q_OBJECT
Q_DISABLE_COPY( Logic )
public:
explicit Logic(QObject *parent, QApplication* application);
virtual ~Logic();
public slots:
bool Start( QStringList parameters );
void ReceiveParameters( QStringList parameters );
void Stop();
#ifdef Q_OS_MAC
bool Logic::WasStarted() const
{
... Determine wether logic was started or not ...
}
#endif
private:
#ifdef OS_MACOSX
// Virtual overrided functions
bool eventFilter( QObject* obj, QEvent* event )
{
if( event->type() == QEvent::FileOpen )
{
QFileOpenEvent* fileEvent = static_cast< QFileOpenEvent* >(event);
Q_ASSERT( fileEvent != NULL );
QString uri;
if( fileEvent->file().isEmpty() == false )
{
uri = fileEvent->file();
}
else if( fileEvent->url().isEmpty() == false )
{
uri = fileEvent->url().toString();
}
if( uri.isEmpty() == false )
{
if( WasStarted() ) ReceiveParameters( uri );
else Start( uri );
}
return false;
}
else if( event->type() == DryRunEvent::eventType )
{
DryRunEvent* myEvent = static_cast< DryRunEvent* >( event );
Q_ASSERT( myEvent != NULL );
QStringList cmdLineParams = myEvent->GetCmdLineParams();
Q_ASSERT( !WasStarted() );
if( WasStarted() ) return false;
if( !Start( cmdLineParams ) ) m_application->exit( 0 );
return false;
}
// Standard event processing
return QObject::eventFilter( obj, event );
}
#endif
};
我希望有人觉得这个东西很有用:)
I hope someone find this stuff useful :)
这篇关于处理Mac OS X文件打开事件BEFORE C ++ main()执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!