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[])

Reply via email to