Since nobody read my previous patch for dnd support in lyx/qt, here is a second one that adds support for AppleEvent OpenDocuments. Basically, with this one can double-click a file in the finder and have the file open in a running LyX.
This second patch has been written by Ronald Florence, who found some example code on the net and managed to make it work for LyX. The patch is not too large, but it has a slightly ugly hack: in QWorkArea.C, a plain C function has to know what the current workarea is, and thus uses a global variable wa_ptr (already used in some X11 event handler) to call dispatch. I'd be glad to change this scheme if somebody has a better idea (John?). If nobody complains, this will go in 1.3.4cvs soon, and Ronald will adapt it to 1.4.0cvs later. JMarc
Index: src/BufferView_pimpl.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.C,v retrieving revision 1.322 diff -u -p -r1.322 BufferView_pimpl.C --- src/BufferView_pimpl.C 23 Jan 2003 16:23:35 -0000 1.322 +++ src/BufferView_pimpl.C 8 Dec 2003 13:42:19 -0000 @@ -93,6 +93,7 @@ unsigned int const saved_positions_num = // (Lgb) boost::signals::connection dispatchcon; +boost::signals::connection viewdispatchcon; boost::signals::connection timecon; boost::signals::connection doccon; boost::signals::connection resizecon; @@ -119,6 +120,8 @@ BufferView::Pimpl::Pimpl(BufferView * bv .connect(boost::bind(&BufferView::Pimpl::workAreaResize, this)); dispatchcon = workarea().dispatch .connect(boost::bind(&BufferView::Pimpl::dispatch, this, _1)); + viewdispatchcon = workarea().viewDispatch + .connect(boost::bind(&BufferView::Pimpl::viewDispatch, this, _1)); kpresscon = workarea().workAreaKeyPress .connect(boost::bind(&BufferView::Pimpl::workAreaKeyPress, this, _1, _2)); selectioncon = workarea().selectionRequested @@ -912,6 +915,13 @@ void BufferView::Pimpl::MenuInsertLyXFil #endif owner_->message(STRCONV(str.str())); } +} + + +bool BufferView::Pimpl::viewDispatch(FuncRequest const & ev) +{ + owner_->dispatch(ev); + return true; } Index: src/BufferView_pimpl.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.h,v retrieving revision 1.81 diff -u -p -r1.81 BufferView_pimpl.h --- src/BufferView_pimpl.h 21 Oct 2002 00:15:48 -0000 1.81 +++ src/BufferView_pimpl.h 8 Dec 2003 13:42:19 -0000 @@ -102,6 +102,9 @@ struct BufferView::Pimpl : public boost: void updateInset(Inset * inset, bool mark_dirty); /// bool dispatch(FuncRequest const & ev); + /// + bool viewDispatch(FuncRequest const & ev); + private: /// friend class BufferView; Index: src/ChangeLog =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ChangeLog,v retrieving revision 1.1021.2.23 diff -u -p -r1.1021.2.23 ChangeLog --- src/ChangeLog 20 Nov 2003 14:13:03 -0000 1.1021.2.23 +++ src/ChangeLog 8 Dec 2003 13:42:21 -0000 @@ -1,3 +1,8 @@ +2003-12-04 Jean-Marc Lasgouttes <[EMAIL PROTECTED]> + + * BufferView_pimpl.C (viewDispatch): new method, called by the qt + drag-and-drop code. + 2003-11-19 Angus Leeming <[EMAIL PROTECTED]> * lyxtextclass.C (LyXTextClass): fix warning about variable Index: src/frontends/WorkArea.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/WorkArea.h,v retrieving revision 1.17 diff -u -p -r1.17 WorkArea.h --- src/frontends/WorkArea.h 21 Oct 2002 17:38:07 -0000 1.17 +++ src/frontends/WorkArea.h 8 Dec 2003 13:42:21 -0000 @@ -72,6 +72,8 @@ public: boost::signal2<void, LyXKeySymPtr, key_modifier::state> workAreaKeyPress; /// some mouse event boost::signal1<void, FuncRequest> dispatch; + /// used by drag-and-drop + boost::signal1<bool, FuncRequest> viewDispatch; /// emitted when an X client has requested our selection boost::signal0<void> selectionRequested; /// emitted when another X client has stolen our selection Index: src/frontends/qt2/ChangeLog =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/ChangeLog,v retrieving revision 1.389.2.40 diff -u -p -r1.389.2.40 ChangeLog --- src/frontends/qt2/ChangeLog 5 Dec 2003 10:00:18 -0000 1.389.2.40 +++ src/frontends/qt2/ChangeLog 8 Dec 2003 13:42:21 -0000 @@ -1,3 +1,16 @@ +2003-12-08 Ronald Florence <[EMAIL PROTECTED]> + + * QWorkArea.C (checkAppleEventForMissingParams) + (handleOpenDocuments): add support for OpenDocuments apple event + + * lyx_gui.C (macEventFilter): handle apple events + +2003-12-04 Jean-Marc Lasgouttes <[EMAIL PROTECTED]> + + * QWorkArea.C (QWorkArea): + (dragEnterEvent): + (dropEvent): add support for drag and drop of URIs + 2003-12-05 Juergen Spitzmueller <[EMAIL PROTECTED]> * QDocument.C: use geometry on custom, A3, B3 and B4 Index: src/frontends/qt2/QWorkArea.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/QWorkArea.C,v retrieving revision 1.11 diff -u -p -r1.11 QWorkArea.C --- src/frontends/qt2/QWorkArea.C 17 Dec 2002 20:37:10 -0000 1.11 +++ src/frontends/qt2/QWorkArea.C 8 Dec 2003 13:42:21 -0000 @@ -27,6 +27,7 @@ #include <qapplication.h> #include <qevent.h> +#include <qdragobject.h> #include <qpainter.h> #include <qmainwindow.h> #include <qlayout.h> @@ -36,6 +37,10 @@ #include <X11/Xlib.h> #endif +#ifdef Q_OS_MAC +#include <Carbon/Carbon.h> +#endif + #include <cmath> #include <cctype> @@ -44,6 +49,10 @@ using std::abs; using std::hex; +namespace { +QWorkArea const * wa_ptr = 0; +} + QWorkArea::QWorkArea(int, int, int, int) : WorkArea(), QWidget(qApp->mainWidget()), painter_(*this) { @@ -53,6 +62,7 @@ QWorkArea::QWorkArea(int, int, int, int) (static_cast<QMainWindow*>(qApp->mainWidget()))->setCentralWidget(this); setFocusProxy(content_); + setAcceptDrops(true); content_->show(); @@ -62,6 +72,9 @@ QWorkArea::QWorkArea(int, int, int, int) vl->addWidget(content_, 5); vl->addWidget(scrollbar_, 0); +#ifdef Q_OS_MAC + wa_ptr = this; +#endif show(); } @@ -84,9 +97,6 @@ void QWorkArea::setScrollbarParams(int h scrollbar_->setPageStep(height()); } -namespace { -QWorkArea const * wa_ptr = 0; -} #ifdef Q_WS_X11 bool lyxX11EventFilter(XEvent * xev) @@ -107,6 +117,72 @@ bool lyxX11EventFilter(XEvent * xev) } #endif +#ifdef Q_OS_MAC +namespace{ +OSErr checkAppleEventForMissingParams(const AppleEvent& theAppleEvent) +{ + DescType returnedType; + Size actualSize; + OSErr err = AEGetAttributePtr(&theAppleEvent, keyMissedKeywordAttr, + typeWildCard, &returnedType, nil, 0, + &actualSize); + switch (err) { + case errAEDescNotFound: + return noErr; + case noErr: + return errAEEventNotHandled; + default: + return err; + } +} +} + +pascal OSErr handleOpenDocuments(const AppleEvent* inEvent, + AppleEvent* /*reply*/, long /*refCon*/) +{ + QString s_arg; + AEDescList documentList; + OSErr err = AEGetParamDesc(inEvent, keyDirectObject, typeAEList, + &documentList); + if (err != noErr) + return err; + + err = checkAppleEventForMissingParams(*inEvent); + if (err == noErr) { + long documentCount; + err = AECountItems(&documentList, &documentCount); + for (long documentIndex = 1; + err == noErr && documentIndex <= documentCount; + documentIndex++) { + DescType returnedType; + Size actualSize; + AEKeyword keyword; + FSRef ref; + char qstr_buf[1024]; + err = AESizeOfNthItem(&documentList, documentIndex, + &returnedType, &actualSize); + if (err == noErr) { + err = AEGetNthPtr(&documentList, documentIndex, + typeFSRef, &keyword, + &returnedType, (Ptr)&ref, + sizeof(FSRef), &actualSize); + if (err == noErr) { + FSRefMakePath(&ref, (UInt8*)qstr_buf, + 1024); + s_arg=QString::fromUtf8(qstr_buf); + wa_ptr->viewDispatch( + FuncRequest(LFUN_FILE_OPEN, + fromqstr(s_arg))); + break; + } + } + } // for ... + } + AEDisposeDesc(&documentList); + return err; +} +#endif // Q_OS_MAC + void QWorkArea::haveSelection(bool own) const { wa_ptr = this; @@ -143,4 +219,25 @@ void QWorkArea::putClipboard(string cons QApplication::clipboard()->setSelectionMode(true); #endif QApplication::clipboard()->setText(toqstr(str)); +} + + +void QWorkArea::dragEnterEvent(QDragEnterEvent * event) +{ + event->accept(QUriDrag::canDecode(event)); +} + + +void QWorkArea::dropEvent(QDropEvent* event) +{ + QStringList files; + + if (QUriDrag::decodeLocalFiles(event, files)) { + lyxerr[Debug::GUI] << "QWorkArea::dropEvent: got URIs!" + << endl; + for (QStringList::Iterator i = files.begin(); + i!=files.end(); ++i) + viewDispatch(FuncRequest(LFUN_FILE_OPEN, fromqstr(*i))); +// lyxerr << "got file: " << fromqstr(*i) << endl; + } } Index: src/frontends/qt2/QWorkArea.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/QWorkArea.h,v retrieving revision 1.8 diff -u -p -r1.8 QWorkArea.h --- src/frontends/qt2/QWorkArea.h 20 Oct 2002 01:48:28 -0000 1.8 +++ src/frontends/qt2/QWorkArea.h 8 Dec 2003 13:42:21 -0000 @@ -56,6 +56,11 @@ public: /// virtual void putClipboard(string const &) const; + /// + virtual void dragEnterEvent(QDragEnterEvent * event); + /// + virtual void dropEvent(QDropEvent* event); + /// get the pixmap we paint on to QPixmap * getPixmap() const { return content_->pixmap(); } Index: src/frontends/qt2/lyx_gui.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/lyx_gui.C,v retrieving revision 1.30.2.2 diff -u -p -r1.30.2.2 lyx_gui.C --- src/frontends/qt2/lyx_gui.C 4 Nov 2003 11:52:03 -0000 1.30.2.2 +++ src/frontends/qt2/lyx_gui.C 8 Dec 2003 13:42:21 -0000 @@ -46,6 +46,10 @@ #include "qfont_loader.h" #include "io_callback.h" +#ifdef Q_OS_MAC +#include <Carbon/Carbon.h> +#endif + #include <qapplication.h> #include <qwidget.h> #include <qpaintdevicemetrics.h> @@ -87,6 +91,12 @@ extern void initEncodings(); extern bool lyxX11EventFilter(XEvent * xev); #endif +#ifdef Q_OS_MAC +extern bool macEventFilter(EventRef event); +extern pascal OSErr +handleOpenDocuments(const AppleEvent* inEvent, AppleEvent* /*reply*/, + long /*refCon*/); +#endif class LQApplication : public QApplication { @@ -96,16 +106,39 @@ public: #ifdef Q_WS_X11 bool x11EventFilter (XEvent * ev) { return lyxX11EventFilter(ev); } #endif +#ifdef Q_OS_MAC + bool macEventFilter(EventRef event); +#endif }; - LQApplication::LQApplication(int & argc, char ** argv) : QApplication(argc, argv) -{} +{ +#ifdef Q_OS_MAC + AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, + NewAEEventHandlerUPP(handleOpenDocuments), + 0, false); +#endif +} LQApplication::~LQApplication() {} + + +#ifdef Q_OS_MAC +bool LQApplication::macEventFilter(EventRef event) +{ + if (GetEventClass(event) == kEventClassAppleEvent) { + EventRecord eventrec; + ConvertEventRefToEventRecord(event, &eventrec); + AEProcessAppleEvent(&eventrec); + + return false; + } + return false; +} +#endif void lyx_gui::parse_init(int & argc, char * argv[])