Bug 114911 - allow drag'n'drop into Kile
Summary: allow drag'n'drop into Kile
Status: RESOLVED FIXED
Alias: None
Product: kile
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Debian testing Linux
: NOR wishlist
Target Milestone: ---
Assignee: Jeroen Wijnhout
URL:
Keywords:
: 121467 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-10-23 01:14 UTC by Oliver Grimm
Modified: 2006-08-17 16:52 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Oliver Grimm 2005-10-23 01:14:12 UTC
Version:           1.8.1 (using KDE KDE 3.4.1)
Installed from:    Debian testing/unstable Packages
OS:                Linux

Kile v 1.8.1 does not allow dragging files from Konqueror or Krusader into the edit space. Please add such a feature to Kile.
Comment 1 Thomas Braun 2006-02-06 19:52:46 UTC
*** Bug 121467 has been marked as a duplicate of this bug. ***
Comment 2 Michel Ludwig 2006-08-17 16:52:34 UTC
SVN commit 573922 by mludwig:

Add drag-and-drop functionality as proposed in bug 114911.

The sensitive areas for URL drops are the edit space (tab widget, editor) and the project view.

(changes approved by Thomas Braun)

FEATURE: 114911



 M  +15 -4     kiledocmanager.cpp  
 M  +5 -2      kiledocmanager.h  
 M  +10 -0     kileprojectview.cpp  
 M  +5 -0      kileprojectview.h  
 M  +71 -5     kileviewmanager.cpp  
 M  +30 -1     kileviewmanager.h  


--- trunk/extragear/office/kile/kile/kiledocmanager.cpp #573921:573922
@@ -5,6 +5,7 @@
 //
 //
 // Author: Jeroen Wijnhout <Jeroen.Wijnhout@kdemail.net>, (C) 2004
+//         Michel Ludwig <michel.ludwig@kdemail.net>, (C) 2006
 //
 
 /***************************************************************************
@@ -35,6 +36,7 @@
 #include <kio/netaccess.h>
 #include <kpushbutton.h>
 #include <kurl.h>
+#include <kurldrag.h>
 
 #include "kileuntitled.h"
 #include "templates.h"
@@ -525,7 +527,7 @@
 	return view;
 }
 
-Kate::View* Manager::load(const KURL &url , const QString & encoding /* = QString::null */, bool create /* = true */, const QString & highlight /* = QString::null */, const QString & text /* = QString::null */)
+Kate::View* Manager::load(const KURL &url , const QString & encoding /* = QString::null */, bool create /* = true */, const QString & highlight /* = QString::null */, const QString & text /* = QString::null */, int index /* = - 1 */)
 {
 	kdDebug() << "==load(" << url.url() << ")=================" << endl;
 	//if doc already opened, update the structure view and return the view
@@ -542,7 +544,7 @@
 
 	//FIXME: use signal/slot
 	if (doc && create)
-		return m_ki->viewManager()->createView(doc);
+		return m_ki->viewManager()->createView(doc, index);
 
 	kdDebug() << "just after createView()" << endl;
 	kdDebug() << "\tdocinfo = " << docinfo << " doc = " << docinfo->getDoc() << " docfor = " << docFor(docinfo->url().path()) << endl;
@@ -784,7 +786,7 @@
 	}
 }
 
-void Manager::fileOpen(const KURL & url, const QString & encoding)
+void Manager::fileOpen(const KURL & url, const QString & encoding, int index)
 {
 	kdDebug() << "==Kile::fileOpen==========================" << endl;
 	
@@ -798,7 +800,7 @@
 	
 	bool isopen = m_ki->isOpen(realurl);
 
-	Kate::View *view = load(realurl, encoding);
+	Kate::View *view = load(realurl, encoding, true, QString::null, QString::null, index);
 	KileProjectItem *item = itemFor(realurl);
 
 	if(!isopen)
@@ -1528,6 +1530,15 @@
 	docinfo->cleanTempFiles(extlist);
 }
 
+void Manager::openDroppedUris(QDropEvent *e) {
+	KURL::List urls;
+	if(KURLDrag::decode(e, urls)) {
+		for(KURL::List::iterator i = urls.begin(); i != urls.end(); ++i) {
+			fileOpen(*i);
+		}
+	}
+}
+
 // Show all opened projects and switch to another one, if you want
 
 void Manager::projectShow()
--- trunk/extragear/office/kile/kile/kiledocmanager.h #573921:573922
@@ -5,6 +5,7 @@
 //
 //
 // Author: Jeroen Wijnhout <Jeroen.Wijnhout@kdemail.net>, (C) 2004
+//         Michel Ludwig <michel.ludwig@kdemail.net>, (C) 2006
 //
 // Copyright: See COPYING file that comes with this distribution
 //
@@ -57,7 +58,7 @@
 
 	Kate::View* createDocumentWithText(const QString & text);
 
-	Kate::View* load( const KURL &url , const QString & encoding = QString::null, bool create = true, const QString & highlight  = QString::null, const QString &text = QString::null);
+	Kate::View* load( const KURL &url , const QString & encoding = QString::null, bool create = true, const QString & highlight  = QString::null, const QString &text = QString::null, int index = -1);
 	Kate::View* loadItem(KileProjectItem *item, const QString & text = QString::null);
 
 	void setHighlightMode(Kate::Document * doc, const QString & highlight = QString::null);
@@ -72,7 +73,7 @@
 	void fileSelected(const KFileItem *file);
 
 	void fileOpen();
-	void fileOpen(const KURL& url, const QString & encoding = QString::null);
+	void fileOpen(const KURL& url, const QString & encoding = QString::null, int index = -1);
 
 	void saveURL(const KURL &);
 	void fileSaveAll(bool amAutoSaving = false, bool disUntitled = false);
@@ -127,6 +128,8 @@
 
 	void cleanUpTempFiles(KileDocument::Info *docinfo = 0, bool silent = false);
 
+	void openDroppedUris(QDropEvent *e);
+
 signals:
 	void projectTreeChanged(const KileProject *);
 	void closingDocument(KileDocument::Info *);
--- trunk/extragear/office/kile/kile/kileprojectview.cpp #573921:573922
@@ -1,7 +1,9 @@
 /***************************************************************************
     begin                : Tue Aug 12 2003
     copyright            : (C) 2003 by Jeroen Wijnhout
+                           (C) 2006 by Michel Ludwig
     email                : Jeroen.Wijnhout@kdemail.net
+                           michel.ludwig@kdemail.net
  ***************************************************************************/
 
 /***************************************************************************
@@ -22,6 +24,7 @@
 #include <kurl.h>
 #include <krun.h>
 #include <kmimetype.h>
+#include <kurldrag.h>
 
 #include "kileinfo.h"
 #include "kiledocumentinfo.h"
@@ -89,6 +92,8 @@
 	connect(this, SIGNAL(contextMenu(KListView *, QListViewItem *, const QPoint & )), this,SLOT(popup(KListView *, QListViewItem * , const QPoint & )));
 
 	connect(this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotClicked(QListViewItem*)));
+	setAcceptDrops(true);
+	connect(this, SIGNAL(dropped(QDropEvent *, QListViewItem *)), m_ki->docManager(), SLOT(openDroppedUris(QDropEvent *)));
 }
 
 void KileProjectView::slotClicked(QListViewItem *item)
@@ -613,4 +618,9 @@
 
 }
 
+bool KileProjectView::acceptDrag(QDropEvent *e) const
+{
+	return KURLDrag::canDecode(e); // only accept URL drops
+}
+
 #include "kileprojectview.moc"
--- trunk/extragear/office/kile/kile/kileprojectview.h #573921:573922
@@ -1,7 +1,9 @@
 /***************************************************************************
     begin                : Tue Aug 12 2003
     copyright            : (C) 2003 by Jeroen Wijnhout
+                           (C) 2006 by Michel Ludwig
     email                : Jeroen.Wijnhout@kdemail.net
+                           michel.ludwig@kdemail.net
  ***************************************************************************/
 
 /***************************************************************************
@@ -129,6 +131,9 @@
 	KileProjectViewItem* itemFor(const KURL &);
 	KileProjectViewItem* parentFor(const KileProjectItem *projitem, KileProjectViewItem *projvi);
 
+protected:
+	virtual bool acceptDrag(QDropEvent *e) const;
+
 private slots:
 	void popup(KListView *, QListViewItem *, const QPoint &);
 
--- trunk/extragear/office/kile/kile/kileviewmanager.cpp #573921:573922
@@ -5,6 +5,7 @@
 //
 //
 // Author: Jeroen Wijnhout <Jeroen.Wijnhout@kdemail.net>, (C) 2004
+//         Michel Ludwig <michel.ludwig@kdemail.net>, (C) 2006
 
 /***************************************************************************
  *                                                                         *
@@ -32,6 +33,7 @@
 #include <klocale.h>
 #include <ktexteditor/editinterfaceext.h>
 #include <kapplication.h>
+#include <kurldrag.h>
 
 #include "kileinfo.h"
 #include "kiledocmanager.h"
@@ -50,7 +52,9 @@
 	m_ki(info),
 	m_activeView(0L),
 // 	m_projectview(0L),
-	m_tabs(0L)
+	m_tabs(0L),
+	m_widgetStack(0L),
+	m_emptyDropWidget(0L)
 {
 }
 
@@ -76,7 +80,13 @@
 
 void Manager::createTabs(QWidget *parent)
 {
+	m_widgetStack = new QWidgetStack(parent);
+	m_emptyDropWidget = new DropWidget(parent);
+	m_widgetStack->addWidget(m_emptyDropWidget);
+	connect(m_emptyDropWidget, SIGNAL(testCanDecode(const QDragMoveEvent *,  bool &)), this, SLOT(testCanDecodeURLs(const QDragMoveEvent *, bool &)));
+	connect(m_emptyDropWidget, SIGNAL(receivedDropEvent(QDropEvent *)), m_ki->docManager(), SLOT(openDroppedUris(QDropEvent *)));
 	m_tabs = new KTabWidget(parent);
+	m_widgetStack->addWidget(m_tabs);
 	m_tabs->setFocusPolicy(QWidget::ClickFocus);
 	m_tabs->setTabReorderingEnabled(true);
 	m_tabs->setHoverCloseButton(true);
@@ -86,6 +96,10 @@
 	connect( m_tabs, SIGNAL( currentChanged( QWidget * ) ), m_receiver, SLOT(activateView( QWidget * )) );
 	connect( m_tabs, SIGNAL( currentChanged( QWidget * ) ), m_receiver, SLOT(updateModeStatus()) );
 	connect( m_tabs, SIGNAL( closeRequest(QWidget *) ), this, SLOT(closeWidget(QWidget *)));
+	connect( m_tabs, SIGNAL( testCanDecode( const QDragMoveEvent *,  bool & ) ), this, SLOT(testCanDecodeURLs( const QDragMoveEvent *, bool & )) );
+	connect( m_tabs, SIGNAL( receivedDropEvent( QDropEvent * ) ), m_ki->docManager(), SLOT(openDroppedUris( QDropEvent * )) );
+	connect( m_tabs, SIGNAL( receivedDropEvent( QWidget*, QDropEvent * ) ), this, SLOT(replaceLoadedUri( QWidget *, QDropEvent * )) );
+	m_widgetStack->raiseWidget(m_emptyDropWidget); // there are no tabs, so show the DropWidget
 }
 
 void Manager::closeWidget(QWidget *widget)
@@ -97,7 +111,7 @@
 	}
 }
 
-Kate::View* Manager::createView(Kate::Document *doc)
+Kate::View* Manager::createView(Kate::Document *doc, int index)
 {
 	Kate::View *view = (Kate::View*) doc->createView (m_tabs, 0L);
 
@@ -105,13 +119,14 @@
 	view->focusProxy()->installEventFilter(m_ki->eventFilter());
 
 	//insert the view in the tab widget
-	m_tabs->addTab( view, m_ki->getShortName(doc) );
+	m_tabs->insertTab( view, m_ki->getShortName(doc), index );
 	m_tabs->setTabToolTip(view, doc->url().url() );
 	m_tabs->showPage( view );
-	m_viewList.append(view);
+	m_viewList.insert((index < 0 || (uint)index >= m_viewList.count()) ? m_viewList.count() : index, view);
 
 	connect(view, SIGNAL(viewStatusMsg(const QString&)), m_receiver, SLOT(newStatus(const QString&)));
 	connect(view, SIGNAL(newStatus()), m_receiver, SLOT(newCaption()));
+	connect(view, SIGNAL(dropEventPass(QDropEvent *)), m_ki->docManager(), SLOT(openDroppedUris(QDropEvent *)));
 
 	connect( doc,  SIGNAL(charactersInteractivelyInserted (int,int,const QString&)), m_ki->editorExtension()->complete(),  SLOT(slotCharactersInserted(int,int,const QString&)) );
 	connect( view, SIGNAL(completionDone(KTextEditor::CompletionEntry)), m_ki->editorExtension()->complete(),  SLOT( slotCompletionDone(KTextEditor::CompletionEntry)) );
@@ -154,6 +169,8 @@
 		action->unplugAll();
 	}
 
+	m_widgetStack->raiseWidget(m_tabs); // there is at least one tab, so show the KTabWidget now
+
 	return view;
 }
 
@@ -168,7 +185,11 @@
 		delete view;
 		
 		QTimer::singleShot(0, m_receiver, SLOT(newCaption())); //make sure the caption gets updated
-		if (views().isEmpty()) m_ki->structureWidget()->clear();
+		if (views().isEmpty()) {
+			m_ki->structureWidget()->clear();
+			m_widgetStack->raiseWidget(m_emptyDropWidget); // there are no tabs left, so show
+			                                               // the DropWidget
+		}
 	}
 }
 
@@ -399,6 +420,51 @@
 		editInterfaceExt->editEnd();
 }
 
+
+void Manager::testCanDecodeURLs(const QDragMoveEvent *e, bool &accept)
+{
+	accept = KURLDrag::canDecode(e); // only accept URL drops
 }
 
+void Manager::replaceLoadedUri(QWidget *w, QDropEvent *e)
+{
+	KURL::List urls;
+	if(!KURLDrag::decode(e, urls)) {
+		return;
+	}
+	int index = m_tabs->indexOf(w);
+	closeWidget(w);
+	for(KURL::List::iterator i = urls.begin(); i != urls.end(); ++i) {
+		if(i == urls.begin()) {
+			m_ki->docManager()->fileOpen(*i, QString::null, index);
+		}
+		else {
+			m_ki->docManager()->fileOpen(*i);
+		}
+	}
+}
+
+DropWidget::DropWidget(QWidget * parent, const char * name, WFlags f) : QWidget(parent, name, f)
+{
+	setAcceptDrops(true);
+}
+
+DropWidget::~DropWidget()
+{
+}
+
+void DropWidget::dragMoveEvent(QDragMoveEvent *e)
+{
+	bool b;
+	emit testCanDecode(e, b);
+	e->accept(b);
+}
+
+void DropWidget::dropEvent(QDropEvent *e)
+{
+	emit receivedDropEvent(e);
+}
+
+}
+
 #include "kileviewmanager.moc"
--- trunk/extragear/office/kile/kile/kileviewmanager.h #573921:573922
@@ -5,6 +5,7 @@
 //
 //
 // Author: Jeroen Wijnhout <Jeroen.Wijnhout@kdemail.net>, (C) 2004
+//         Michel Ludwig <michel.ludwig@kdemail.net>, (C) 2006
 //
 
 /***************************************************************************
@@ -20,6 +21,7 @@
 #define KILEVIEWKILEVIEWMANAGER_H
 
 #include <qobject.h>
+#include <qwidgetstack.h>
 
 #include <ktabwidget.h>
 
@@ -61,7 +63,7 @@
 	Kate::View* view(int i) { return m_viewList.at(i); }
 
 	void createTabs(QWidget *);
-	Kate::View* createView(Kate::Document *doc);
+	Kate::View* createView(Kate::Document *doc, int index = -1);
 	KTabWidget* tabs() { return m_tabs; }
 
 // 	void setProjectView(KileProjectView *view) { m_projectview = view; }
@@ -87,6 +89,10 @@
 	void convertSelectionToLaTeX(void);
 	void pasteAsLaTeX(void);
 
+protected slots:
+	void testCanDecodeURLs(const QDragMoveEvent *e, bool &accept);
+	void replaceLoadedUri(QWidget *w, QDropEvent *e);
+
 signals:
 	void activateView(QWidget *, bool);
 	void prepareForPart(const QString &);
@@ -100,8 +106,31 @@
 	KTabWidget 			*m_tabs;
 	QObject				*m_receiver;
 	KXMLGUIClient		*m_client;
+	QWidgetStack			*m_widgetStack;
+	QWidget				*m_emptyDropWidget;
+
 };
 
+/**
+ * Little helper widget to overcome the limitation that KTabWidget doesn't honour drop events when
+ * there are no tabs: the DropWidget is shown instead of KTabWidget when there are no tabs.
+ */
+class DropWidget : public QWidget {
+	Q_OBJECT
+
+	public:
+		DropWidget(QWidget * parent = 0, const char * name = 0, WFlags f = 0);
+		virtual ~DropWidget();
+
+		virtual void dragMoveEvent(QDragMoveEvent *e);
+
+		virtual void dropEvent(QDropEvent *e);
+
+	signals:
+		void testCanDecode(const QDragMoveEvent *, bool &);
+		void receivedDropEvent(QDropEvent *);
+};
+
 }
 
 #endif