1+ import os
2+
13from PyQt5 .QtCore import (
24 Qt ,
35 pyqtSignal ,
911 QPushButton ,
1012 QVBoxLayout ,
1113 QTextEdit ,
14+ QSpinBox ,
1215)
1316
1417
@@ -22,6 +25,11 @@ def __init__(self, parent=None):
2225 self .parent = parent
2326 self .setWindowTitle (self .tr ("Batch Process All Images" ))
2427 self .setMinimumWidth (450 )
28+
29+ self .cpu_count = os .cpu_count () or 1
30+ self .max_concurrency = max (1 , int (self .cpu_count * 0.95 ))
31+ self .default_concurrency = max (1 , int (self .cpu_count * 0.8 ))
32+
2533 self .setup_ui ()
2634
2735 def setup_ui (self ):
@@ -98,6 +106,61 @@ def setup_ui(self):
98106 )
99107 dialog_layout .addWidget (self .batch_message_input )
100108
109+ # Concurrency setting
110+ settings_container = QHBoxLayout ()
111+ settings_container .setContentsMargins (0 , 0 , 0 , 0 )
112+ settings_container .setSpacing (8 )
113+ settings_container .addStretch ()
114+
115+ concurrency_label = QLabel (self .tr ("Concurrency:" ))
116+ concurrency_label .setStyleSheet (
117+ """
118+ QLabel {
119+ font-size: 12px;
120+ color: #6B7280;
121+ font-weight: 400;
122+ }
123+ """
124+ )
125+ settings_container .addWidget (concurrency_label )
126+
127+ self .concurrency_spinbox = QSpinBox ()
128+ self .concurrency_spinbox .setMinimum (1 )
129+ self .concurrency_spinbox .setMaximum (self .max_concurrency )
130+ self .concurrency_spinbox .setValue (self .default_concurrency )
131+ tooltip_text = self .tr ("Max: {}" ).format (self .max_concurrency )
132+ self .concurrency_spinbox .setToolTip (tooltip_text )
133+ self .concurrency_spinbox .setSuffix (f" / { self .max_concurrency } " )
134+ self .concurrency_spinbox .setStyleSheet (
135+ """
136+ QSpinBox {
137+ border: 1px solid #E5E7EB;
138+ border-radius: 4px;
139+ background-color: #FFFFFF;
140+ color: #1F2937;
141+ font-size: 12px;
142+ padding: 4px 8px;
143+ min-width: 80px;
144+ max-width: 80px;
145+ }
146+ QSpinBox:focus {
147+ border: 1px solid #6366F1;
148+ background-color: #F9FAFB;
149+ }
150+ QSpinBox::up-button, QSpinBox::down-button {
151+ width: 16px;
152+ border: none;
153+ background: transparent;
154+ }
155+ QSpinBox::up-button:hover, QSpinBox::down-button:hover {
156+ background-color: #F3F4F6;
157+ }
158+ """
159+ )
160+ settings_container .addWidget (self .concurrency_spinbox )
161+
162+ dialog_layout .addLayout (settings_container )
163+
101164 # Button layout
102165 button_layout = QHBoxLayout ()
103166 button_layout .setContentsMargins (0 , 8 , 0 , 0 )
@@ -178,6 +241,10 @@ def get_prompt(self):
178241 """Get the user input prompt"""
179242 return self .batch_message_input .toPlainText ().strip ()
180243
244+ def get_concurrency (self ):
245+ """Get the concurrency setting"""
246+ return self .concurrency_spinbox .value ()
247+
181248 def exec_ (self ):
182249 """Override exec_ method to adjust position before showing the dialog"""
183250 self .adjustSize ()
@@ -186,7 +253,8 @@ def exec_(self):
186253
187254 if result == QDialog .Accepted :
188255 prompt = self .get_prompt ()
256+ concurrency = self .get_concurrency ()
189257 if prompt :
190258 self .promptReady .emit (prompt )
191- return prompt
192- return ""
259+ return ( prompt , concurrency )
260+ return None
0 commit comments