sqlshell 0.1.8__py3-none-any.whl → 0.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sqlshell might be problematic. Click here for more details.

sqlshell/splash_screen.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout
2
2
  from PyQt6.QtCore import Qt, QTimer, QPropertyAnimation, QEasingCurve, QPoint, QRect, pyqtProperty
3
- from PyQt6.QtGui import QPainter, QColor, QFont, QMovie, QPainterPath, QLinearGradient
3
+ from PyQt6.QtGui import QPainter, QColor, QFont, QMovie, QPainterPath, QLinearGradient, QPixmap
4
4
  import os
5
5
 
6
6
  class AnimatedSplashScreen(QWidget):
@@ -11,6 +11,7 @@ class AnimatedSplashScreen(QWidget):
11
11
  self._opacity = 0.0
12
12
  self._progress = 0.0
13
13
  self.next_widget = None
14
+ self.use_fallback = False
14
15
 
15
16
  # Set up the window properties
16
17
  self.setWindowFlags(
@@ -34,30 +35,32 @@ class AnimatedSplashScreen(QWidget):
34
35
  (screen_geometry.height() - self.height()) // 2
35
36
  )
36
37
 
38
+ # Create movie label first (background)
39
+ self.movie_label = QLabel(self)
40
+ self.movie_label.setGeometry(0, 0, self.width(), self.height())
41
+
42
+ # Create overlay for fade effect (between movie and content)
43
+ self.overlay = QLabel(self)
44
+ self.overlay.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
45
+ self.overlay.setGeometry(0, 0, self.width(), self.height())
46
+
47
+ # Create text label for animated text
48
+ self.text_label = QLabel(self)
49
+ self.text_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
50
+ self.text_label.setStyleSheet("color: rgba(255, 255, 255, 0); background: transparent;")
51
+ self.text_label.setGeometry(0, 0, self.width(), self.height())
52
+
37
53
  # Create layout
38
54
  layout = QVBoxLayout(self)
39
- layout.setContentsMargins(20, 20, 20, 20)
55
+ layout.setContentsMargins(20, 140, 20, 20) # Increased top margin to accommodate title bar and logo
40
56
  layout.setSpacing(10)
41
57
 
42
- # Create background container for the title and subtitle
58
+ # Create background container for the subtitle
43
59
  self.content_container = QWidget(self)
60
+ self.content_container.setStyleSheet("background: transparent;")
44
61
  content_layout = QVBoxLayout(self.content_container)
45
- content_layout.setContentsMargins(20, 20, 20, 20)
46
- content_layout.setSpacing(10)
47
-
48
- # Create title label
49
- self.title_label = QLabel("SQLShell", self.content_container)
50
- self.title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
51
- self.title_label.setStyleSheet("""
52
- QLabel {
53
- color: #3498DB;
54
- font-size: 32px;
55
- font-weight: bold;
56
- font-family: 'Segoe UI', Arial, sans-serif;
57
- background: transparent;
58
- }
59
- """)
60
- content_layout.addWidget(self.title_label)
62
+ content_layout.setContentsMargins(20, 5, 20, 20)
63
+ content_layout.setSpacing(5)
61
64
 
62
65
  # Create subtitle label
63
66
  self.subtitle_label = QLabel("Loading...", self.content_container)
@@ -75,36 +78,81 @@ class AnimatedSplashScreen(QWidget):
75
78
  # Add content container to main layout
76
79
  layout.addWidget(self.content_container)
77
80
 
78
- # Create movie label (background)
79
- self.movie_label = QLabel(self)
80
- self.movie_label.setGeometry(0, 0, self.width(), self.height())
81
- self.movie_label.lower() # Put it at the back
82
-
83
- # Create overlay for fade effect (between movie and content)
84
- self.overlay = QLabel(self)
85
- self.overlay.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
86
- self.overlay.setGeometry(0, 0, self.width(), self.height())
87
- self.overlay.lower() # Put it behind the content but above the movie
88
-
89
- # Create text label for animated text
90
- self.text_label = QLabel(self)
91
- self.text_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
92
- self.text_label.setStyleSheet("color: rgba(255, 255, 255, 0); background: transparent;")
93
- self.text_label.setGeometry(0, 0, self.width(), self.height())
94
- self.text_label.lower() # Put it behind the content
95
-
96
81
  # Create progress bar (always on top)
97
82
  self.progress_bar = QLabel(self)
98
83
  self.progress_bar.setFixedHeight(4)
99
84
  self.progress_bar.setStyleSheet("background-color: #3498DB; border-radius: 2px;")
100
85
  self.progress_bar.move(100, self.height() - 40)
101
86
  self.progress_bar.setFixedWidth(0)
102
- self.progress_bar.raise_() # Ensure it's on top
87
+
88
+ # Create a top overlay widget that will always be on top
89
+ self.top_overlay = QWidget(self)
90
+ self.top_overlay.setGeometry(0, 0, self.width(), 130) # Covers title and logo area
91
+ self.top_overlay.setStyleSheet("background: transparent;")
92
+
93
+ # Now create the top title and logo elements on the overlay
94
+
95
+ # Create title bar at the very top
96
+ self.title_bar = QLabel(self.top_overlay)
97
+ self.title_bar.setText("SQL Shell") # Set the text
98
+ self.title_bar.setFixedSize(self.width(), 50)
99
+ self.title_bar.move(0, 0)
100
+ self.title_bar.setAlignment(Qt.AlignmentFlag.AlignCenter)
101
+ self.title_bar.setStyleSheet("""
102
+ QLabel {
103
+ color: white;
104
+ font-size: 28px;
105
+ font-weight: bold;
106
+ font-family: 'Segoe UI', Arial, sans-serif;
107
+ background-color: rgba(52, 152, 219, 0.9);
108
+ border-bottom: 2px solid #2980B9;
109
+ border-top-left-radius: 10px;
110
+ border-top-right-radius: 10px;
111
+ }
112
+ """)
113
+
114
+ # Create a dedicated logo container right below the title bar
115
+ self.logo_container = QLabel(self.top_overlay)
116
+ self.logo_container.setFixedSize(self.width(), 80)
117
+ self.logo_container.move(0, 50) # Position right below title bar
118
+ self.logo_container.setAlignment(Qt.AlignmentFlag.AlignCenter)
119
+ self.logo_container.setStyleSheet("background: rgba(255, 255, 255, 0.8); border: 0px;")
120
+
121
+ # Try to load logo directly here
122
+ logo_path = os.path.join(os.path.dirname(__file__), "resources", "logo_medium.png")
123
+ if os.path.exists(logo_path):
124
+ logo_pixmap = QPixmap(logo_path)
125
+ # Scale logo to appropriate size
126
+ scaled_logo = logo_pixmap.scaledToWidth(200, Qt.TransformationMode.SmoothTransformation)
127
+ self.logo_container.setPixmap(scaled_logo)
128
+ print(f"Logo loaded with size: {scaled_logo.width()}x{scaled_logo.height()}")
129
+ print(f"Logo container geometry: {self.logo_container.geometry()}")
130
+ else:
131
+ print(f"Logo not found at path: {logo_path}")
132
+ # Try the small logo as fallback
133
+ logo_path = os.path.join(os.path.dirname(__file__), "resources", "logo_small.png")
134
+ if os.path.exists(logo_path):
135
+ logo_pixmap = QPixmap(logo_path)
136
+ scaled_logo = logo_pixmap.scaledToWidth(150, Qt.TransformationMode.SmoothTransformation)
137
+ self.logo_container.setPixmap(scaled_logo)
138
+ print(f"Fallback logo loaded with size: {scaled_logo.width()}x{scaled_logo.height()}")
139
+ print(f"Logo container geometry: {self.logo_container.geometry()}")
103
140
 
104
- # Set up the loading animation
105
- self.movie = QMovie(os.path.join(os.path.dirname(__file__), "resources", "splash_screen.gif"))
106
- self.movie.setScaledSize(self.size())
107
- self.movie_label.setMovie(self.movie)
141
+ print(f"Title bar geometry: {self.title_bar.geometry()}")
142
+ print(f"Title bar text: {self.title_bar.text()}")
143
+ print(f"Top overlay geometry: {self.top_overlay.geometry()}")
144
+
145
+ # Set appropriate z-order of elements
146
+ self.movie_label.lower() # Background at the very back
147
+ self.overlay.raise_() # Overlay above background
148
+ self.text_label.raise_() # Text above overlay
149
+ self.content_container.raise_() # Content above text
150
+ self.progress_bar.raise_() # Progress bar on top
151
+ self.top_overlay.raise_() # Top overlay with title and logo at the very top
152
+
153
+ # Set up the loading animation - do it immediately in init
154
+ self.movie = None # Initialize to None for safety
155
+ self.load_animation()
108
156
 
109
157
  # Set up fade animation
110
158
  self.fade_anim = QPropertyAnimation(self, b"opacity")
@@ -120,12 +168,151 @@ class AnimatedSplashScreen(QWidget):
120
168
  self.progress_anim.setEndValue(1.0)
121
169
  self.progress_anim.setEasingCurve(QEasingCurve.Type.InOutQuad)
122
170
 
171
+ # Create a dedicated timer to ensure title and logo always stay on top
172
+ self.z_order_timer = QTimer(self)
173
+ self.z_order_timer.timeout.connect(self.ensure_top_elements_visible)
174
+ self.z_order_timer.start(50) # Check every 50ms
175
+
123
176
  # Start animations after everything is initialized
124
177
  QTimer.singleShot(100, self.start_animations) # Small delay to ensure everything is ready
125
178
 
179
+ def load_animation(self):
180
+ """Load the splash screen animation"""
181
+ # Check multiple potential paths for the splash screen GIF
182
+ possible_paths = [
183
+ os.path.join(os.path.dirname(__file__), "resources", "splash_screen.gif"),
184
+ os.path.join(os.path.dirname(os.path.dirname(__file__)), "resources", "splash_screen.gif"),
185
+ os.path.join(os.path.dirname(__file__), "splash_screen.gif"),
186
+ os.path.abspath("sqlshell/resources/splash_screen.gif"),
187
+ os.path.abspath("resources/splash_screen.gif")
188
+ ]
189
+
190
+ # Try each possible path
191
+ for path in possible_paths:
192
+ if os.path.exists(path):
193
+ print(f"Loading splash screen animation from: {path}")
194
+ try:
195
+ self.movie = QMovie(path)
196
+ self.movie.setCacheMode(QMovie.CacheMode.CacheAll) # Cache all frames for smoother playback
197
+ self.movie.setScaledSize(self.size())
198
+
199
+ # Connect frameChanged signal to update the label
200
+ self.movie.frameChanged.connect(self.update_frame)
201
+
202
+ # Ensure the movie label is visible but below other elements
203
+ self.movie_label.lower()
204
+ self.movie_label.setStyleSheet("background: transparent;")
205
+
206
+ # Set the movie to the label
207
+ self.movie_label.setMovie(self.movie)
208
+
209
+ # Test if the movie is valid
210
+ if self.movie.isValid():
211
+ print(f"Successfully loaded animation with {self.movie.frameCount()} frames")
212
+ self.use_fallback = False
213
+
214
+ # Create a timer to ensure animation updates
215
+ self.animation_timer = QTimer(self)
216
+ self.animation_timer.timeout.connect(self.update_animation)
217
+ self.animation_timer.start(50) # Update every 50ms
218
+
219
+ # Force our top overlay to be visible
220
+ self.top_overlay.raise_()
221
+
222
+ return
223
+ else:
224
+ print(f"Warning: Animation file at {path} is not valid")
225
+ self.use_fallback = True
226
+ except Exception as e:
227
+ print(f"Error loading animation from {path}: {e}")
228
+
229
+ # If we get here, no valid animation was found
230
+ print("No valid animation found, using fallback static splash screen")
231
+ self.use_fallback = True
232
+
233
+ def update_frame(self):
234
+ """Handle frame changed in the animation"""
235
+ # Make sure the movie label is refreshed and visible
236
+ self.movie_label.update()
237
+ self.movie_label.show()
238
+
239
+ # Always ensure title and logo stay on top
240
+ self.title_bar.raise_()
241
+ self.logo_container.raise_()
242
+
243
+ def update_animation(self):
244
+ """Ensure animation keeps running"""
245
+ if self.movie and not self.use_fallback:
246
+ # Check if movie is running
247
+ if self.movie.state() != QMovie.MovieState.Running:
248
+ self.movie.start()
249
+
250
+ # Force update of the movie label
251
+ self.movie_label.update()
252
+
253
+ # Always ensure title and logo stay on top
254
+ self.title_bar.raise_()
255
+ self.logo_container.raise_()
256
+
257
+ def paintEvent(self, event):
258
+ """Custom paint event to draw a fallback splash screen if needed"""
259
+ if self.use_fallback:
260
+ painter = QPainter(self)
261
+ painter.setRenderHint(QPainter.RenderHint.Antialiasing)
262
+
263
+ # Draw rounded rectangle background
264
+ gradient = QLinearGradient(0, 0, 0, self.height())
265
+ gradient.setColorAt(0, QColor(44, 62, 80)) # Dark blue-gray
266
+ gradient.setColorAt(1, QColor(52, 152, 219)) # Bright blue
267
+
268
+ painter.setBrush(gradient)
269
+ painter.setPen(Qt.PenStyle.NoPen)
270
+ painter.drawRoundedRect(0, 0, self.width(), self.height(), 10, 10)
271
+
272
+ # Draw title bar at the top
273
+ title_rect = QRect(0, 0, self.width(), 50)
274
+ painter.setBrush(QColor(52, 152, 219)) # Bright blue
275
+ painter.drawRect(title_rect)
276
+
277
+ # Draw title text
278
+ painter.setPen(QColor(255, 255, 255))
279
+ font = QFont("Segoe UI", 24)
280
+ font.setBold(True)
281
+ painter.setFont(font)
282
+ painter.drawText(title_rect, Qt.AlignmentFlag.AlignCenter, "SQL Shell")
283
+
284
+ # Try to draw logo
285
+ logo_path = os.path.join(os.path.dirname(__file__), "resources", "logo_small.png")
286
+ if os.path.exists(logo_path):
287
+ logo_pixmap = QPixmap(logo_path)
288
+ scaled_logo = logo_pixmap.scaledToHeight(70, Qt.TransformationMode.SmoothTransformation)
289
+ logo_x = (self.width() - scaled_logo.width()) // 2
290
+ painter.drawPixmap(logo_x, 60, scaled_logo)
291
+
292
+ # Draw progress bar
293
+ if hasattr(self, '_progress'):
294
+ progress_width = int(200 * self._progress)
295
+ progress_rect = QRect(100, self.height() - 40, progress_width, 4)
296
+ painter.setBrush(QColor(26, 188, 156)) # Teal
297
+ painter.drawRoundedRect(progress_rect, 2, 2)
298
+
299
+ super().paintEvent(event)
300
+
126
301
  def start_animations(self):
127
302
  """Start all animations"""
128
- self.movie.start()
303
+ # Try to start the movie if we have one
304
+ if self.movie and not self.use_fallback:
305
+ self.movie.start()
306
+
307
+ # Check if movie is running after attempt to start
308
+ if not self.movie.state() == QMovie.MovieState.Running:
309
+ print("Warning: Could not start the animation")
310
+ self.use_fallback = True
311
+ else:
312
+ # Ensure the movie label is visible and updated
313
+ self.movie_label.show()
314
+ self.movie_label.update()
315
+
129
316
  self.fade_anim.start()
130
317
  self.progress_anim.start()
131
318
  self.progress_anim.finished.connect(self._on_animation_finished)
@@ -156,8 +343,16 @@ class AnimatedSplashScreen(QWidget):
156
343
  def progress(self, value):
157
344
  self._progress = value
158
345
  # Update progress bar width
159
- self.progress_bar.setFixedWidth(int(200 * value))
346
+ if hasattr(self, 'progress_bar'):
347
+ self.progress_bar.setFixedWidth(int(200 * value))
348
+ # Force repaint if using fallback
349
+ if self.use_fallback:
350
+ self.update()
160
351
 
352
+ def ensure_top_elements_visible(self):
353
+ """Ensure title bar and logo container are always on top"""
354
+ self.top_overlay.raise_()
355
+
161
356
  def _on_animation_finished(self):
162
357
  """Handle animation completion"""
163
358
  if self.next_widget:
@@ -165,13 +360,46 @@ class AnimatedSplashScreen(QWidget):
165
360
 
166
361
  def _finish_splash(self):
167
362
  """Clean up and show the main window"""
168
- self.movie.stop()
169
- self.fade_anim.stop()
170
- self.progress_anim.stop()
363
+ # Stop the animation timer if it exists
364
+ if hasattr(self, 'animation_timer') and self.animation_timer:
365
+ self.animation_timer.stop()
366
+
367
+ # Stop the z-order timer
368
+ if hasattr(self, 'z_order_timer'):
369
+ self.z_order_timer.stop()
370
+
371
+ if self.movie:
372
+ self.movie.stop()
373
+ if self.fade_anim:
374
+ self.fade_anim.stop()
375
+ if self.progress_anim:
376
+ self.progress_anim.stop()
171
377
  self.close()
172
378
  if self.next_widget:
173
379
  self.next_widget.show()
174
380
 
175
381
  def finish(self, widget):
176
382
  """Store the widget to show after animation completes"""
177
- self.next_widget = widget
383
+ self.next_widget = widget
384
+
385
+ # On Windows, we need to explicitly trigger the finish process
386
+ # instead of waiting for the animation to complete
387
+
388
+ # First forcibly stop all animations
389
+ if hasattr(self, 'animation_timer') and self.animation_timer:
390
+ self.animation_timer.stop()
391
+
392
+ # Stop the z-order timer
393
+ if hasattr(self, 'z_order_timer'):
394
+ self.z_order_timer.stop()
395
+
396
+ if self.movie:
397
+ self.movie.stop()
398
+ if self.fade_anim:
399
+ self.fade_anim.stop()
400
+ if self.progress_anim:
401
+ self.progress_anim.stop()
402
+
403
+ # Close the splash screen and show the main window directly
404
+ # Use a very short timer to allow the event loop to process
405
+ QTimer.singleShot(50, self._finish_splash)
@@ -0,0 +1,6 @@
1
+ """UI components for SQLShell application."""
2
+
3
+ from sqlshell.ui.filter_header import FilterHeader
4
+ from sqlshell.ui.bar_chart_delegate import BarChartDelegate
5
+
6
+ __all__ = ['FilterHeader', 'BarChartDelegate']
@@ -0,0 +1,49 @@
1
+ from PyQt6.QtWidgets import QStyledItemDelegate
2
+ from PyQt6.QtCore import Qt, QRect
3
+ from PyQt6.QtGui import QColor
4
+
5
+ class BarChartDelegate(QStyledItemDelegate):
6
+ def __init__(self, parent=None):
7
+ super().__init__(parent)
8
+ self.min_val = 0
9
+ self.max_val = 1
10
+ self.bar_color = QColor("#3498DB")
11
+
12
+ def set_range(self, min_val, max_val):
13
+ self.min_val = min_val
14
+ self.max_val = max_val
15
+
16
+ def paint(self, painter, option, index):
17
+ # Draw the default background
18
+ super().paint(painter, option, index)
19
+
20
+ try:
21
+ text = index.data()
22
+ value = float(text.replace(',', ''))
23
+
24
+ # Calculate normalized value
25
+ range_val = self.max_val - self.min_val if self.max_val != self.min_val else 1
26
+ normalized = (value - self.min_val) / range_val
27
+
28
+ # Define bar dimensions
29
+ bar_height = 16
30
+ max_bar_width = 100
31
+ bar_width = max(5, int(max_bar_width * normalized))
32
+
33
+ # Calculate positions
34
+ text_width = option.fontMetrics.horizontalAdvance(text) + 10
35
+ bar_x = option.rect.left() + text_width + 10
36
+ bar_y = option.rect.center().y() - bar_height // 2
37
+
38
+ # Draw the bar
39
+ bar_rect = QRect(bar_x, bar_y, bar_width, bar_height)
40
+ painter.fillRect(bar_rect, self.bar_color)
41
+
42
+ # Draw the text
43
+ text_rect = QRect(option.rect.left() + 4, option.rect.top(),
44
+ text_width, option.rect.height())
45
+ painter.drawText(text_rect, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter, text)
46
+
47
+ except (ValueError, AttributeError):
48
+ # If not a number, just draw the text
49
+ super().paint(painter, option, index)