era*_*lan 6 c++ macos events qt qt5
我已经google了很多,但仍然找不到好的解决方案:/
所以,我将一个复杂的Qt5应用程序(某些网络服务的客户端)移植到Mac OS X(10.7.0"Lion"及更高版本).
我需要处理自定义文件*.xyz和自定义URL方案xyz://.
好的,Qt5有QFileOpenEvent类来处理OS X适当的事件.
但是:此事件仅在应用程序事件循环开始后才会到达(显然)!
我需要"捕获"并在 main启动之前处理OS X'文件打开事件,因为程序逻辑仅用于处理命令行参数处理.
简化的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();
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在C++ 函数启动之前获取OS X'文件打开事件main,或者在argv参数中获取"my"文件/ url ?
也许,一些Objective-C黑魔法能胜任这项工作?
注意:start做许多复杂的 - 异步的 - 事情.事件在执行期间到达,因此当异步内容已经工作时很难处理它.所以看起来我只需要阻止start执行,如果事件将到来.
如果应用程序已经打开,则没有问题.
我发现了一个可能很奇怪的解决方案 - 使用Qt'事件系统.
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();
}
Run Code Online (Sandbox Code Playgroud)
自定义事件标题:
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;
};
Run Code Online (Sandbox Code Playgroud)
自定义事件源:
QEvent::Type ViewerDryRunEvent::eventType = QEvent::None;
Run Code Online (Sandbox Code Playgroud)
逻辑类标题:
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
};
Run Code Online (Sandbox Code Playgroud)
我希望有人发现这个东西很有用:)