99from AnyQt .QtWidgets import (
1010 QPlainTextEdit , QListView , QSizePolicy , QMenu , QSplitter , QLineEdit ,
1111 QAction , QToolButton , QFileDialog , QStyledItemDelegate ,
12- QStyleOptionViewItem , QPlainTextDocumentLayout
13- )
12+ QStyleOptionViewItem , QPlainTextDocumentLayout ,
13+ QMessageBox )
1414from AnyQt .QtGui import (
1515 QColor , QBrush , QPalette , QFont , QTextDocument ,
1616 QSyntaxHighlighter , QTextCharFormat , QTextCursor , QKeySequence ,
1717)
1818from AnyQt .QtCore import Qt , QRegExp , QByteArray , QItemSelectionModel
1919
20+ from Orange .canvas .gui .utils import OSX_NSURL_toLocalFile
2021from Orange .data import Table
2122from Orange .base import Learner , Model
2223from 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+
3874class 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
142207class 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
724805if __name__ == "__main__" : # pragma: no cover
725806 WidgetPreview (OWPythonScript ).run ()
0 commit comments