1- """ Import the necessary modules for the program to work """
21import sys
32import os
43import requests
1514
1615
1716
18- """ Thread for handling file-related operations """
1917class FileHandler (QThread ):
2018 file_content_loaded = pyqtSignal (str , str )
2119 file_saved = pyqtSignal (bool )
@@ -46,7 +44,6 @@ def run(self):
4644
4745
4846
49- """ Utility function to load icons """
5047def load_icon (icon_name ):
5148 icon_path = os .path .join (os .path .dirname (__file__ ), icon_name )
5249 if getattr (sys , 'frozen' , False ):
@@ -57,7 +54,6 @@ def load_icon(icon_name):
5754
5855
5956
60- """ Utility function to load plugins """
6157def load_plugins (app_context ):
6258 user_home = os .path .expanduser ("~" )
6359 plugins_dir = os .path .join (user_home , "spplugins" )
@@ -81,7 +77,6 @@ def load_plugins(app_context):
8177
8278
8379
84- """ Utility function to load CSS stylesheet """
8580def loadStyle ():
8681 user_css_path = os .path .join (os .path .expanduser ("~" ), "spstyle.css" )
8782 stylesheet = None
@@ -124,63 +119,83 @@ def get_preferred_font():
124119
125120
126121
127- """ Dialog for Find and Replace functionality """
128122class FindReplaceDialog (QDialog ):
129- def __init__ (self , text_edit ):
130- super ().__init__ ()
131- self .text_edit = text_edit
132- self .setWindowTitle ("Find and Replace" )
133- self .setWindowIcon (load_icon ('scratchpad.png' ))
134- self .layout = QVBoxLayout (self )
135- self .find_label = QLabel ("Find:" )
136- self .find_input = QLineEdit (self )
137- self .layout .addWidget (self .find_label )
138- self .layout .addWidget (self .find_input )
139- self .replace_label = QLabel ("Replace with:" )
140- self .replace_input = QLineEdit (self )
141- self .layout .addWidget (self .replace_label )
142- self .layout .addWidget (self .replace_input )
143- self .button_layout = QHBoxLayout ()
144- self .find_button = QPushButton ("Find Next" , self )
145- self .replace_button = QPushButton ("Replace" , self )
146- self .replace_all_button = QPushButton ("Replace All" , self )
147- self .button_layout .addWidget (self .find_button )
148- self .button_layout .addWidget (self .replace_button )
149- self .button_layout .addWidget (self .replace_all_button )
150- self .layout .addLayout (self .button_layout )
151- self .find_button .clicked .connect (self .find_next )
152- self .replace_button .clicked .connect (self .replace )
153- self .replace_all_button .clicked .connect (self .replace_all )
154- self .setLayout (self .layout )
155- self .current_index = 0
156-
157- def find_next (self ):
158- text_to_find = self .find_input .text ().strip ()
159- if text_to_find :
160- options = QTextDocument .FindFlags ()
161- found = self .text_edit .find (text_to_find , options )
162- if not found :
163- QMessageBox .information (self , "Not Found" , "No more occurrences found." )
164- else :
165- QMessageBox .warning (self , "Empty Search" , "Please enter text to find." )
166-
167- def replace (self ):
168- text_to_find = self .find_input .text ()
169- text_to_replace = self .replace_input .text ()
170- if text_to_find and text_to_replace :
171- content = self .text_edit .toPlainText ()
172- self .text_edit .setPlainText (content .replace (text_to_find , text_to_replace , 1 ))
173-
174- def replace_all (self ):
175- text_to_find = self .find_input .text ()
176- text_to_replace = self .replace_input .text ()
177- if text_to_find and text_to_replace :
178- content = self .text_edit .toPlainText ()
179- self .text_edit .setPlainText (content .replace (text_to_find , text_to_replace ))
123+ def __init__ (self , editor , parent = None ):
124+ super ().__init__ (parent )
125+ self .editor = editor
126+ self .setWindowTitle ("Find and Replace" )
127+ icon = load_icon ('scratchpad.png' )
128+ self .setWindowIcon (icon if isinstance (icon , QIcon ) else QIcon ())
129+ self .layout = QVBoxLayout (self )
130+ self .find_label = QLabel ("Find:" )
131+ self .find_input = QLineEdit (self )
132+ self .layout .addWidget (self .find_label )
133+ self .layout .addWidget (self .find_input )
134+ self .replace_label = QLabel ("Replace with:" )
135+ self .replace_input = QLineEdit (self )
136+ self .layout .addWidget (self .replace_label )
137+ self .layout .addWidget (self .replace_input )
138+ self .button_layout = QHBoxLayout ()
139+ self .find_button = QPushButton ("Find Next" , self )
140+ self .replace_button = QPushButton ("Replace" , self )
141+ self .replace_all_button = QPushButton ("Replace All" , self )
142+ self .button_layout .addWidget (self .find_button )
143+ self .button_layout .addWidget (self .replace_button )
144+ self .button_layout .addWidget (self .replace_all_button )
145+ self .layout .addLayout (self .button_layout )
146+ self .find_button .clicked .connect (self .find_next )
147+ self .replace_button .clicked .connect (self .replace )
148+ self .replace_all_button .clicked .connect (self .replace_all )
149+ self .setLayout (self .layout )
150+
151+ def find_next (self ):
152+ ed = self .editor
153+ text = self .find_input .text ().strip ()
154+ if not text :
155+ QMessageBox .warning (self , "Empty Search" , "Please enter text to find." )
156+ return
157+ found = ed .findFirst (text , False , False , False , True , True )
158+ if not found :
159+ QMessageBox .information (self , "Not Found" , "No more occurrences found." )
160+
161+ def replace (self ):
162+ ed = self .editor
163+ find_text = self .find_input .text ()
164+ replace_text = self .replace_input .text ()
165+ if not find_text :
166+ return
167+ if ed .hasSelectedText () and ed .selectedText () == find_text :
168+ ed .replaceSelectedText (replace_text )
169+ ed .findFirst (find_text , False , False , False , True , True )
170+ return
171+ if not ed .findFirst (find_text , False , False , False , True , True ):
172+ return
173+ ed .replaceSelectedText (replace_text )
174+ ed .findFirst (find_text , False , False , False , True , True )
175+
176+ def replace_all (self ):
177+ ed = self .editor
178+ find_text = self .find_input .text ()
179+ replace_text = self .replace_input .text ()
180+ if not find_text :
181+ return
182+ ed .beginUndoAction ()
183+ try :
184+ line , index = 0 , 0
185+ count_guard = 0
186+ max_iters = 1_000_000
187+ while count_guard < max_iters :
188+ found = ed .findFirst (find_text , False , False , False , False , True , line , index , True , False )
189+ if not found :
190+ break
191+ ed .replaceSelectedText (replace_text )
192+ line , index = ed .getCursorPosition ()
193+ count_guard += 1
194+ finally :
195+ ed .endUndoAction ()
180196
181197
182198
183- """ Dialog for importing content from the web """
184199class ImportFromWebDialog (QDialog ):
185200 def __init__ (self , text_edit ):
186201 super ().__init__ ()
@@ -217,7 +232,6 @@ def is_valid_url(self, url):
217232
218233
219234
220- """ Dialog for unsaved changes warning """
221235class UnsavedWorkDialog (QDialog ):
222236 def __init__ (self , parent = None ):
223237 super ().__init__ ()
@@ -305,7 +319,6 @@ def adjust_scroll_bar_policy(self):
305319
306320
307321
308- """ Main window """
309322class Scratchpad (QMainWindow ):
310323 def __init__ (self , file_to_open = None ):
311324 super ().__init__ ()
@@ -589,7 +602,6 @@ def clearRecentFiles(self):
589602
590603
591604
592- """ Start the program """
593605if __name__ == '__main__' :
594606 app = QApplication (sys .argv )
595607 loadStyle ()
@@ -598,4 +610,4 @@ def clearRecentFiles(self):
598610 file_to_open = sys .argv [1 ]
599611 scratchpad = Scratchpad (file_to_open )
600612 scratchpad .show ()
601- sys .exit (app .exec_ ())
613+ sys .exit (app .exec_ ())
0 commit comments