Skip to content

Commit 4a8539a

Browse files
committed
OWPythonScript: dropping and pasting of python scripts
1 parent 1e2d311 commit 4a8539a

File tree

1 file changed

+83
-2
lines changed

1 file changed

+83
-2
lines changed

Orange/widgets/data/owpythonscript.py

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
from AnyQt.QtWidgets import (
1010
QPlainTextEdit, QListView, QSizePolicy, QMenu, QSplitter, QLineEdit,
1111
QAction, QToolButton, QFileDialog, QStyledItemDelegate,
12-
QStyleOptionViewItem, QPlainTextDocumentLayout
13-
)
12+
QStyleOptionViewItem, QPlainTextDocumentLayout,
13+
QMessageBox)
1414
from AnyQt.QtGui import (
1515
QColor, QBrush, QPalette, QFont, QTextDocument,
1616
QSyntaxHighlighter, QTextCharFormat, QTextCursor, QKeySequence,
1717
)
1818
from AnyQt.QtCore import Qt, QRegExp, QByteArray, QItemSelectionModel
1919

20+
from Orange.canvas.gui.utils import OSX_NSURL_toLocalFile
2021
from Orange.data import Table
2122
from Orange.base import Learner, Model
2223
from Orange.widgets import widget, gui
@@ -35,6 +36,41 @@ def text_format(foreground=Qt.black, weight=QFont.Normal):
3536
return fmt
3637

3738

39+
def to_local_file(url):
40+
return OSX_NSURL_toLocalFile(url) or url.toLocalFile()
41+
42+
43+
def read_file_content(url, limit=None):
44+
filename = to_local_file(url)
45+
try:
46+
with open(filename, encoding="utf-8", errors='strict') as f:
47+
text = f.read(limit)
48+
return text
49+
except (OSError, UnicodeDecodeError):
50+
return None
51+
52+
53+
def dialog_replace_append(filename):
54+
dlg = QMessageBox(
55+
QMessageBox.Information,
56+
"Add script",
57+
"Adding script from {}\n\n"
58+
"Replace the current script or append to it?".format(filename))
59+
role = QMessageBox.AcceptRole
60+
replace = dlg.addButton("Replace", role)
61+
append = dlg.addButton("Append", role)
62+
cancel = dlg.addButton("Cancel", role)
63+
dlg.setEscapeButton(cancel)
64+
dlg.setDefaultButton(replace)
65+
dlg.exec()
66+
if dlg.clickedButton() == replace:
67+
return True
68+
elif dlg.clickedButton() == append:
69+
return False
70+
else:
71+
return None
72+
73+
3874
class PythonSyntaxHighlighter(QSyntaxHighlighter):
3975
def __init__(self, parent=None):
4076

@@ -138,6 +174,35 @@ def keyPressEvent(self, event):
138174
else:
139175
super().keyPressEvent(event)
140176

177+
def insertFromMimeData(self, source):
178+
"""
179+
Reimplemented from QPlainTextEdit.insertFromMimeData.
180+
"""
181+
urls = source.urls()
182+
if urls:
183+
self.pasteFile(urls[0])
184+
else:
185+
super().insertFromMimeData(source)
186+
187+
def pasteFile(self, url):
188+
new = read_file_content(url)
189+
if new:
190+
filename = os.path.basename(to_local_file(url))
191+
replace = True
192+
current_text = self.toPlainText()
193+
if current_text.strip(): # only ask if there is current script
194+
replace = dialog_replace_append(filename)
195+
if replace is None: # cancel
196+
return
197+
if replace: # replace
198+
self.document().setPlainText(new)
199+
else: # append
200+
self.document().setPlainText(
201+
current_text +
202+
("\n" if not current_text.endswith("\n") else "") +
203+
new)
204+
self.document().setModified(True)
205+
141206

142207
class PythonConsole(QPlainTextEdit, code.InteractiveConsole):
143208
def __init__(self, locals=None, parent=None):
@@ -533,6 +598,8 @@ def __init__(self):
533598
if self.splitterState is not None:
534599
self.splitCanvas.restoreState(QByteArray(self.splitterState))
535600

601+
self.setAcceptDrops(True)
602+
536603
self.splitCanvas.splitterMoved[int, int].connect(self.onSpliterMoved)
537604
self.controlArea.layout().addStretch(1)
538605
self.resize(800, 600)
@@ -720,6 +787,20 @@ def commit(self):
720787
out_var = None
721788
getattr(self.Outputs, signal).send(out_var)
722789

790+
def dragEnterEvent(self, event):
791+
urls = event.mimeData().urls()
792+
if urls:
793+
# try reading the file as text
794+
c = read_file_content(urls[0], limit=1000)
795+
if c is not None:
796+
event.acceptProposedAction()
797+
798+
def dropEvent(self, event):
799+
"""Handle file drops"""
800+
urls = event.mimeData().urls()
801+
if urls:
802+
self.text.pasteFile(urls[0])
803+
723804

724805
if __name__ == "__main__": # pragma: no cover
725806
WidgetPreview(OWPythonScript).run()

0 commit comments

Comments
 (0)