11from PySide6 .QtWidgets import (QDialog , QVBoxLayout , QHBoxLayout , QLabel ,
22 QComboBox , QPushButton , QRadioButton , QButtonGroup ,
33 QLineEdit , QGroupBox , QFileDialog , QProgressDialog , QMessageBox )
4- from PySide6 .QtCore import Qt
5- from binaryninja import log_info , log_error
4+ from PySide6 .QtCore import Qt , QThread , Signal
5+ from binaryninja import log_info , log_error , log_warn
6+
7+ class ModelLoadThread (QThread ):
8+ finished = Signal (set ) # Signal emitting the loaded models
9+ error = Signal (str ) # Signal for error handling
10+
11+ def __init__ (self , uploader ):
12+ super ().__init__ ()
13+ self .uploader = uploader
14+
15+ def run (self ):
16+ try :
17+ models = self .uploader .get_models ()
18+ self .finished .emit (models )
19+ except Exception as e :
20+ log_error (f"RevEng.AI | Failed to load models: { str (e )} " )
21+ self .error .emit (str (e ))
22+
23+ class UploadBinaryThread (QThread ):
24+ finished = Signal (bool , str ) # Signal for success/failure and error message
25+
26+ def __init__ (self , uploader , bv , options ):
27+ super ().__init__ ()
28+ self .uploader = uploader
29+ self .bv = bv
30+ self .options = options
31+
32+ def run (self ):
33+ try :
34+ success = self .uploader .upload_binary (self .bv , self .options )
35+ if success :
36+ self .finished .emit (True , "" )
37+ else :
38+ self .finished .emit (False , "Failed to upload binary" )
39+ except Exception as e :
40+ self .finished .emit (False , str (e ))
641
742class UploadDialog (QDialog ):
843 def __init__ (self , config , uploader , bv ):
944 super ().__init__ ()
1045 self .config = config
1146 self .uploader = uploader
1247 self .bv = bv
48+ self .model_thread = None
49+ self .upload_thread = None
50+ self .progress = None
51+ self .load_models ()
1352 self .init_ui ()
1453
54+
1555 def init_ui (self ):
1656 self .setWindowTitle ("RevEng.AI: Process Binary" )
1757 self .setMinimumWidth (500 )
@@ -42,8 +82,6 @@ def init_ui(self):
4282 model_layout = QHBoxLayout ()
4383 model_label = QLabel ("AI Model:" )
4484 self .model_combo = QComboBox ()
45- for model in self .uploader .get_models ():
46- self .model_combo .addItem (model )
4785 model_layout .addWidget (model_label )
4886 model_layout .addWidget (self .model_combo )
4987 layout .addLayout (model_layout )
@@ -77,65 +115,135 @@ def init_ui(self):
77115
78116 self .setLayout (layout )
79117
118+ def load_models (self ):
119+ """Start loading models in background"""
120+ # Create and show progress dialog
121+ self .progress = QProgressDialog ("Loading available models..." , None , 0 , 0 , self )
122+ self .progress .setWindowTitle ("RevEng.AI" )
123+ self .progress .setWindowModality (Qt .WindowModal )
124+ self .progress .setCancelButton (None )
125+ self .progress .setMinimumWidth (400 )
126+ self .progress .setMinimumHeight (100 )
127+ self .progress .setStyleSheet ("""
128+ QProgressDialog {
129+ background-color: white;
130+ color: black;
131+ }
132+ QProgressBar {
133+ border: 1px solid #cccccc;
134+ border-radius: 4px;
135+ text-align: center;
136+ background-color: #f0f0f0;
137+ min-width: 250px;
138+ min-height: 20px;
139+ }
140+ QProgressBar::chunk {
141+ background-color: #007bff;
142+ border-radius: 3px;
143+ }
144+ QLabel {
145+ color: black;
146+ font-size: 13px;
147+ padding: 10px;
148+ }
149+ """ )
150+
151+ self .model_thread = ModelLoadThread (self .uploader )
152+ self .model_thread .finished .connect (self ._on_models_loaded )
153+ self .model_thread .error .connect (self ._on_model_load_error )
154+ self .model_thread .start ()
155+
156+ self .progress .show ()
157+
158+ def _on_models_loaded (self , models ):
159+ """Handle successful model loading"""
160+ self .progress .close ()
161+ self .model_combo .clear ()
162+ for model in sorted (models ):
163+ self .model_combo .addItem (model )
164+
165+ def _on_model_load_error (self , error_msg ):
166+ """Handle model loading error"""
167+ self .progress .close ()
168+ log_error (f"RevEng.AI | Failed to load models: { error_msg } " )
169+ QMessageBox .critical (
170+ self ,
171+ "RevEng.AI Model Loading Error" ,
172+ f"Failed to load available models: { error_msg } " ,
173+ QMessageBox .Ok
174+ )
80175
81176 def upload_binary (self ):
82- try :
83- progress = QProgressDialog ("Uploading binary to RevEng.AI..." , None , 0 , 0 )
84- progress .setWindowTitle ("RevEng.AI Upload" )
85- progress .setWindowModality (Qt .WindowModal )
86- progress .setCancelButton (None )
87- progress .setMinimumWidth (400 )
88- progress .setMinimumHeight (100 )
89- progress .setStyleSheet ("""
90- QProgressDialog {
91- background-color: white;
92- color: black;
93- }
94- QProgressBar {
95- border: 1px solid #cccccc;
96- border-radius: 4px;
97- text-align: center;
98- background-color: #f0f0f0;
99- min-width: 250px;
100- min-height: 20px;
101- }
102- QProgressBar::chunk {
103- background-color: #007bff;
104- border-radius: 3px;
105- }
106- QLabel {
107- color: black;
108- font-size: 13px;
109- padding: 10px;
110- }
111- """ )
112-
113- progress .show ()
114-
115- upload_try = self .uploader .upload_binary (self .bv , self .get_upload_options ())
177+ """Start binary upload process"""
178+ # Validate model selection
179+ if not self .model_combo .currentText ():
180+ log_warn ("RevEng.AI | Model selection is required" )
181+ QMessageBox .warning (
182+ self ,
183+ "RevEng.AI Upload" ,
184+ "Please select a model for analysis." ,
185+ QMessageBox .Ok
186+ )
187+ return
116188
117- progress .close ()
118-
119- if not upload_try :
120- raise Exception ("Failed to upload binary" )
121-
189+ # Create and show progress dialog
190+ self .progress = QProgressDialog ("Uploading binary to RevEng.AI..." , None , 0 , 0 , self )
191+ self .progress .setWindowTitle ("RevEng.AI Upload" )
192+ self .progress .setWindowModality (Qt .WindowModal )
193+ self .progress .setCancelButton (None )
194+ self .progress .setMinimumWidth (400 )
195+ self .progress .setMinimumHeight (100 )
196+ self .progress .setStyleSheet ("""
197+ QProgressDialog {
198+ background-color: white;
199+ color: black;
200+ }
201+ QProgressBar {
202+ border: 1px solid #cccccc;
203+ border-radius: 4px;
204+ text-align: center;
205+ background-color: #f0f0f0;
206+ min-width: 250px;
207+ min-height: 20px;
208+ }
209+ QProgressBar::chunk {
210+ background-color: #007bff;
211+ border-radius: 3px;
212+ }
213+ QLabel {
214+ color: black;
215+ font-size: 13px;
216+ padding: 10px;
217+ }
218+ """ )
219+
220+ # Create and start upload thread
221+ self .upload_thread = UploadBinaryThread (self .uploader , self .bv , self .get_upload_options ())
222+ self .upload_thread .finished .connect (self ._on_upload_finished )
223+ self .upload_thread .start ()
224+
225+ self .progress .show ()
226+
227+ def _on_upload_finished (self , success , error_message ):
228+ """Handle upload completion"""
229+ self .progress .close ()
230+
231+ if success :
122232 QMessageBox .information (
123- None ,
233+ self ,
124234 "RevEng.AI Upload" ,
125235 "Binary uploaded successfully!\n You can now view the analysis on RevEng.AI" ,
126236 QMessageBox .Ok
127237 )
128238 self .accept ()
129-
130- except Exception as e :
131- log_error (f"Failed to upload binary: { str (e )} " )
239+ else :
240+ log_error (f"RevEng.AI | Failed to upload binary: { error_message } " )
132241 QMessageBox .critical (
133- None ,
242+ self ,
134243 "RevEng.AI Upload Error" ,
135- f"Failed to upload binary: { str ( e ) } " ,
244+ f"Failed to upload binary: { error_message } " ,
136245 QMessageBox .Ok
137246 )
138-
139247
140248 def browse_debug_info (self ):
141249 file_path , _ = QFileDialog .getOpenFileName (
@@ -147,7 +255,6 @@ def browse_debug_info(self):
147255 if file_path :
148256 self .debug_combo .setCurrentText (file_path )
149257
150-
151258 def get_upload_options (self ):
152259 return {
153260 'debug_info' : self .debug_combo .currentText (),
0 commit comments