clapp-pm 1.0.44__py3-none-any.whl → 1.0.46__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.
- {clapp_pm-1.0.44.data → clapp_pm-1.0.46.data}/data/version.json +1 -1
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/METADATA +1 -1
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/RECORD +13 -29
- manifest_schema.py +1 -1
- manifest_validator.py +1 -1
- package_runner.py +1 -0
- packages/luaozgur-moba/README.md +159 -0
- packages/luaozgur-moba/manifest.json +8 -0
- version.py +1 -1
- packages/pycloudos/README.md +0 -279
- packages/pycloudos/core/appmon.py +0 -0
- packages/pycloudos/main.py +0 -193
- packages/pycloudos/manifest.json +0 -15
- packages/pycloudos/rain/__init__.py +0 -7
- packages/pycloudos/rain/contextmenu.py +0 -1370
- packages/pycloudos/rain/desktop.py +0 -556
- packages/pycloudos/rain/dock.py +0 -722
- packages/pycloudos/rain/flet_html_widgets.py +0 -1448
- packages/pycloudos/rain/theme.py +0 -930
- packages/pycloudos/rain/topbar.py +0 -1421
- packages/pycloudos/rain/ui.py +0 -381
- packages/pycloudos/rain/wallpaper.py +0 -830
- packages/pycloudos/rain/widgets.py +0 -688
- packages/pycloudos/rain/windowmanager.py +0 -605
- packages/pycloudos/requirements-dev.txt +0 -43
- packages/pycloudos/requirements.txt +0 -43
- packages/pycloudos/setup_deps.py +0 -422
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/WHEEL +0 -0
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/entry_points.txt +0 -0
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/licenses/LICENSE +0 -0
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/top_level.txt +0 -0
packages/pycloudos/rain/dock.py
DELETED
@@ -1,722 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Rain Dock - Modern Dock Sistemi
|
3
|
-
Kullanıcıya sabit uygulamalara hızlı erişim sağlayan modern dock yapısı
|
4
|
-
macOS Big Sur/Monterey tarzında glassmorphism efektleri ile
|
5
|
-
"""
|
6
|
-
|
7
|
-
import logging
|
8
|
-
import math
|
9
|
-
from typing import List, Dict, Optional
|
10
|
-
from pathlib import Path
|
11
|
-
|
12
|
-
try:
|
13
|
-
from PyQt6.QtWidgets import (QWidget, QHBoxLayout, QVBoxLayout, QLabel,
|
14
|
-
QPushButton, QFrame, QScrollArea, QMenu,
|
15
|
-
QGraphicsDropShadowEffect, QSizePolicy, QGraphicsBlurEffect)
|
16
|
-
from PyQt6.QtCore import (Qt, QSize, QPropertyAnimation, QEasingCurve, pyqtSignal,
|
17
|
-
QTimer, QRect, QPoint, QParallelAnimationGroup, QSequentialAnimationGroup)
|
18
|
-
from PyQt6.QtGui import (QFont, QPixmap, QAction, QPainter, QColor, QBrush, QIcon,
|
19
|
-
QPainterPath, QLinearGradient, QRadialGradient, QPen)
|
20
|
-
PYQT_AVAILABLE = True
|
21
|
-
except ImportError:
|
22
|
-
PYQT_AVAILABLE = False
|
23
|
-
|
24
|
-
class ModernDockIcon(QPushButton):
|
25
|
-
"""Modern Dock simgesi widget'ı - glassmorphism efektleri ile"""
|
26
|
-
|
27
|
-
# Sinyaller
|
28
|
-
app_launch_requested = pyqtSignal(str) # app_id
|
29
|
-
context_menu_requested = pyqtSignal(str, object) # app_id, position
|
30
|
-
|
31
|
-
def __init__(self, app_id: str, app_name: str, icon_path: str = None, icon_text: str = "📱", is_running: bool = False):
|
32
|
-
super().__init__()
|
33
|
-
|
34
|
-
self.app_id = app_id
|
35
|
-
self.app_name = app_name
|
36
|
-
self.icon_path = icon_path
|
37
|
-
self.icon_text = icon_text
|
38
|
-
self.is_running = is_running
|
39
|
-
self.is_hovered = False
|
40
|
-
|
41
|
-
# Animasyon değişkenleri
|
42
|
-
self.base_size = 64
|
43
|
-
self.hover_size = 80
|
44
|
-
self.current_scale = 1.0
|
45
|
-
|
46
|
-
self.setup_ui()
|
47
|
-
self.setup_animations()
|
48
|
-
self.setup_effects()
|
49
|
-
|
50
|
-
def setup_ui(self):
|
51
|
-
"""UI kurulumu"""
|
52
|
-
self.setFixedSize(self.base_size, self.base_size)
|
53
|
-
self.setObjectName("ModernDockIcon")
|
54
|
-
|
55
|
-
# İkon yükleme - daha yüksek kalite
|
56
|
-
if self.icon_path and Path(self.icon_path).exists():
|
57
|
-
# PNG ikon kullan
|
58
|
-
pixmap = QPixmap(self.icon_path)
|
59
|
-
if not pixmap.isNull():
|
60
|
-
# İkonu ultra yüksek kalitede boyutlandır
|
61
|
-
icon_size = int(self.base_size * 0.75) # %75 boyut
|
62
|
-
scaled_pixmap = pixmap.scaled(
|
63
|
-
icon_size, icon_size,
|
64
|
-
Qt.AspectRatioMode.KeepAspectRatio,
|
65
|
-
Qt.TransformationMode.SmoothTransformation
|
66
|
-
)
|
67
|
-
|
68
|
-
# Şeffaf arka plan ile temiz ikon oluştur
|
69
|
-
clean_pixmap = QPixmap(icon_size, icon_size)
|
70
|
-
clean_pixmap.fill(Qt.GlobalColor.transparent)
|
71
|
-
|
72
|
-
painter = QPainter(clean_pixmap)
|
73
|
-
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
74
|
-
painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform)
|
75
|
-
|
76
|
-
# İkonu ortala
|
77
|
-
x = (icon_size - scaled_pixmap.width()) // 2
|
78
|
-
y = (icon_size - scaled_pixmap.height()) // 2
|
79
|
-
painter.drawPixmap(x, y, scaled_pixmap)
|
80
|
-
painter.end()
|
81
|
-
|
82
|
-
self.setIcon(QIcon(clean_pixmap))
|
83
|
-
self.setIconSize(QSize(icon_size, icon_size))
|
84
|
-
|
85
|
-
# Metin temizle (sadece ikon göster)
|
86
|
-
self.setText("")
|
87
|
-
else:
|
88
|
-
# Fallback: emoji
|
89
|
-
self.setText(self.icon_text)
|
90
|
-
self.setStyleSheet("font-size: 32px;")
|
91
|
-
else:
|
92
|
-
# Fallback: emoji veya metin
|
93
|
-
self.setText(self.icon_text)
|
94
|
-
self.setStyleSheet("font-size: 32px;")
|
95
|
-
|
96
|
-
# Modern stil
|
97
|
-
self.setStyleSheet(self._get_modern_style())
|
98
|
-
|
99
|
-
# Tooltip
|
100
|
-
self.setToolTip(self.app_name)
|
101
|
-
|
102
|
-
def _get_modern_style(self) -> str:
|
103
|
-
"""Modern glassmorphism stil"""
|
104
|
-
return f"""
|
105
|
-
QPushButton {{
|
106
|
-
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
107
|
-
stop:0 rgba(255, 255, 255, 0.3),
|
108
|
-
stop:0.5 rgba(255, 255, 255, 0.2),
|
109
|
-
stop:1 rgba(255, 255, 255, 0.1));
|
110
|
-
border: 1px solid rgba(255, 255, 255, 0.3);
|
111
|
-
border-radius: {self.base_size // 4}px;
|
112
|
-
margin: 2px;
|
113
|
-
padding: 0px;
|
114
|
-
}}
|
115
|
-
|
116
|
-
QPushButton:hover {{
|
117
|
-
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
118
|
-
stop:0 rgba(255, 255, 255, 0.4),
|
119
|
-
stop:0.5 rgba(255, 255, 255, 0.25),
|
120
|
-
stop:1 rgba(255, 255, 255, 0.15));
|
121
|
-
border: 1px solid rgba(255, 255, 255, 0.5);
|
122
|
-
}}
|
123
|
-
|
124
|
-
QPushButton:pressed {{
|
125
|
-
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
126
|
-
stop:0 rgba(255, 255, 255, 0.2),
|
127
|
-
stop:0.5 rgba(255, 255, 255, 0.1),
|
128
|
-
stop:1 rgba(255, 255, 255, 0.05));
|
129
|
-
border: 1px solid rgba(255, 255, 255, 0.4);
|
130
|
-
}}
|
131
|
-
"""
|
132
|
-
|
133
|
-
def setup_animations(self):
|
134
|
-
"""Modern animasyonları kur"""
|
135
|
-
# Hover scale animasyonu
|
136
|
-
self.scale_animation = QPropertyAnimation(self, b"geometry")
|
137
|
-
self.scale_animation.setDuration(200)
|
138
|
-
self.scale_animation.setEasingCurve(QEasingCurve.Type.OutCubic)
|
139
|
-
|
140
|
-
# Bounce animasyonu
|
141
|
-
self.bounce_animation = QSequentialAnimationGroup()
|
142
|
-
|
143
|
-
# Yukarı bounce
|
144
|
-
bounce_up = QPropertyAnimation(self, b"geometry")
|
145
|
-
bounce_up.setDuration(150)
|
146
|
-
bounce_up.setEasingCurve(QEasingCurve.Type.OutQuad)
|
147
|
-
|
148
|
-
# Aşağı bounce
|
149
|
-
bounce_down = QPropertyAnimation(self, b"geometry")
|
150
|
-
bounce_down.setDuration(150)
|
151
|
-
bounce_down.setEasingCurve(QEasingCurve.Type.InQuad)
|
152
|
-
|
153
|
-
self.bounce_animation.addAnimation(bounce_up)
|
154
|
-
self.bounce_animation.addAnimation(bounce_down)
|
155
|
-
|
156
|
-
def setup_effects(self):
|
157
|
-
"""Görsel efektleri kur"""
|
158
|
-
# Gölge efekti
|
159
|
-
self.shadow_effect = QGraphicsDropShadowEffect()
|
160
|
-
self.shadow_effect.setBlurRadius(15)
|
161
|
-
self.shadow_effect.setColor(QColor(0, 0, 0, 80))
|
162
|
-
self.shadow_effect.setOffset(0, 4)
|
163
|
-
self.setGraphicsEffect(self.shadow_effect)
|
164
|
-
|
165
|
-
def enterEvent(self, event):
|
166
|
-
"""Mouse hover başlangıcı - devre dışı"""
|
167
|
-
super().enterEvent(event)
|
168
|
-
# Hover efekti kaldırıldı
|
169
|
-
pass
|
170
|
-
|
171
|
-
def leaveEvent(self, event):
|
172
|
-
"""Mouse hover bitişi - devre dışı"""
|
173
|
-
super().leaveEvent(event)
|
174
|
-
# Hover efekti kaldırıldı
|
175
|
-
pass
|
176
|
-
|
177
|
-
def animate_hover(self, hover: bool):
|
178
|
-
"""Hover animasyonu - devre dışı bırakıldı"""
|
179
|
-
# Hover efekti tamamen kaldırıldı
|
180
|
-
# Sadece tıklama animasyonu aktif
|
181
|
-
pass
|
182
|
-
|
183
|
-
def animate_click(self):
|
184
|
-
"""Tıklama animasyonu - yukarı zıplama efekti"""
|
185
|
-
if self.bounce_animation.state() == QSequentialAnimationGroup.State.Running:
|
186
|
-
return
|
187
|
-
|
188
|
-
current_rect = self.geometry()
|
189
|
-
|
190
|
-
# Daha belirgin yukarı zıplama (20px yukarı)
|
191
|
-
bounce_height = 20
|
192
|
-
bounce_up_rect = QRect(
|
193
|
-
current_rect.x(),
|
194
|
-
current_rect.y() - bounce_height,
|
195
|
-
current_rect.width(),
|
196
|
-
current_rect.height()
|
197
|
-
)
|
198
|
-
|
199
|
-
# Aşağı bounce (orijinal pozisyon)
|
200
|
-
bounce_down_rect = current_rect
|
201
|
-
|
202
|
-
# Animasyonları ayarla
|
203
|
-
bounce_up = self.bounce_animation.animationAt(0)
|
204
|
-
bounce_down = self.bounce_animation.animationAt(1)
|
205
|
-
|
206
|
-
# Yukarı zıplama - hızlı ve etkili
|
207
|
-
bounce_up.setDuration(120) # Daha hızlı
|
208
|
-
bounce_up.setEasingCurve(QEasingCurve.Type.OutQuart) # Daha etkili easing
|
209
|
-
bounce_up.setStartValue(current_rect)
|
210
|
-
bounce_up.setEndValue(bounce_up_rect)
|
211
|
-
|
212
|
-
# Aşağı zıplama - yumuşak iniş
|
213
|
-
bounce_down.setDuration(180) # Biraz daha yavaş iniş
|
214
|
-
bounce_down.setEasingCurve(QEasingCurve.Type.InQuart) # Yumuşak iniş
|
215
|
-
bounce_down.setStartValue(bounce_up_rect)
|
216
|
-
bounce_down.setEndValue(bounce_down_rect)
|
217
|
-
|
218
|
-
self.bounce_animation.start()
|
219
|
-
|
220
|
-
def set_running_state(self, is_running: bool):
|
221
|
-
"""Çalışma durumunu ayarla"""
|
222
|
-
if self.is_running != is_running:
|
223
|
-
self.is_running = is_running
|
224
|
-
self.update_running_indicator()
|
225
|
-
|
226
|
-
def update_running_indicator(self):
|
227
|
-
"""Çalışma göstergesini güncelle"""
|
228
|
-
# Bu özellik paintEvent'te implement edilecek
|
229
|
-
self.update()
|
230
|
-
|
231
|
-
def paintEvent(self, event):
|
232
|
-
"""Özel çizim - çalışma göstergesi için"""
|
233
|
-
super().paintEvent(event)
|
234
|
-
|
235
|
-
if self.is_running:
|
236
|
-
painter = QPainter(self)
|
237
|
-
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
238
|
-
|
239
|
-
# Çalışma göstergesi (alt kısımda küçük nokta)
|
240
|
-
indicator_size = 6
|
241
|
-
indicator_x = (self.width() - indicator_size) // 2
|
242
|
-
indicator_y = self.height() - 8
|
243
|
-
|
244
|
-
# Gradient nokta
|
245
|
-
gradient = QRadialGradient(
|
246
|
-
indicator_x + indicator_size // 2,
|
247
|
-
indicator_y + indicator_size // 2,
|
248
|
-
indicator_size // 2
|
249
|
-
)
|
250
|
-
gradient.setColorAt(0, QColor(255, 255, 255, 255))
|
251
|
-
gradient.setColorAt(1, QColor(200, 200, 200, 200))
|
252
|
-
|
253
|
-
painter.setBrush(QBrush(gradient))
|
254
|
-
painter.setPen(Qt.PenStyle.NoPen)
|
255
|
-
painter.drawEllipse(indicator_x, indicator_y, indicator_size, indicator_size)
|
256
|
-
|
257
|
-
painter.end()
|
258
|
-
|
259
|
-
def mousePressEvent(self, event):
|
260
|
-
"""Fare tıklama olayı"""
|
261
|
-
if event.button() == Qt.MouseButton.LeftButton:
|
262
|
-
self.animate_click()
|
263
|
-
self.app_launch_requested.emit(self.app_id)
|
264
|
-
elif event.button() == Qt.MouseButton.RightButton:
|
265
|
-
# PyQt6'da globalPosition() kullan
|
266
|
-
try:
|
267
|
-
global_pos = event.globalPosition().toPoint()
|
268
|
-
except AttributeError:
|
269
|
-
# Fallback
|
270
|
-
global_pos = self.mapToGlobal(event.pos())
|
271
|
-
|
272
|
-
self.context_menu_requested.emit(self.app_id, global_pos)
|
273
|
-
|
274
|
-
super().mousePressEvent(event)
|
275
|
-
|
276
|
-
class ModernRainDock(QWidget):
|
277
|
-
"""Modern Rain UI Dock bileşeni - glassmorphism efektleri ile"""
|
278
|
-
|
279
|
-
def __init__(self, kernel):
|
280
|
-
super().__init__()
|
281
|
-
self.kernel = kernel
|
282
|
-
self.logger = logging.getLogger("ModernRainDock")
|
283
|
-
|
284
|
-
if not PYQT_AVAILABLE:
|
285
|
-
return
|
286
|
-
|
287
|
-
self.dock_icons: List[ModernDockIcon] = []
|
288
|
-
self.pinned_apps: List[Dict] = []
|
289
|
-
self.running_apps: List[str] = []
|
290
|
-
|
291
|
-
# Dock pozisyon ve boyut ayarları
|
292
|
-
self.dock_height = 80
|
293
|
-
self.dock_margin = 20
|
294
|
-
self.icon_spacing = 12
|
295
|
-
|
296
|
-
self.setup_ui()
|
297
|
-
self.load_pinned_apps()
|
298
|
-
self.setup_connections()
|
299
|
-
self.setup_update_timer()
|
300
|
-
|
301
|
-
def setup_ui(self):
|
302
|
-
"""Modern arayüzü kur"""
|
303
|
-
self.setFixedHeight(self.dock_height + self.dock_margin)
|
304
|
-
self.setStyleSheet("""
|
305
|
-
QWidget {
|
306
|
-
background-color: transparent;
|
307
|
-
border: none;
|
308
|
-
}
|
309
|
-
""")
|
310
|
-
|
311
|
-
# Ana layout
|
312
|
-
main_layout = QHBoxLayout(self)
|
313
|
-
main_layout.setContentsMargins(0, 0, 0, self.dock_margin)
|
314
|
-
main_layout.setSpacing(0)
|
315
|
-
|
316
|
-
# Sol spacer
|
317
|
-
main_layout.addStretch()
|
318
|
-
|
319
|
-
# Modern dock container
|
320
|
-
self.dock_container = QWidget()
|
321
|
-
self.dock_layout = QHBoxLayout(self.dock_container)
|
322
|
-
self.dock_layout.setSpacing(self.icon_spacing)
|
323
|
-
self.dock_layout.setContentsMargins(20, 10, 20, 10)
|
324
|
-
|
325
|
-
# Modern glassmorphism dock container stili
|
326
|
-
self.dock_container.setStyleSheet(f"""
|
327
|
-
QWidget {{
|
328
|
-
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
329
|
-
stop:0 rgba(255, 255, 255, 0.2),
|
330
|
-
stop:0.5 rgba(255, 255, 255, 0.15),
|
331
|
-
stop:1 rgba(255, 255, 255, 0.1));
|
332
|
-
border: 1px solid rgba(255, 255, 255, 0.3);
|
333
|
-
border-radius: {self.dock_height // 3}px;
|
334
|
-
}}
|
335
|
-
""")
|
336
|
-
|
337
|
-
# Modern gölge efekti
|
338
|
-
shadow_effect = QGraphicsDropShadowEffect()
|
339
|
-
shadow_effect.setBlurRadius(25)
|
340
|
-
shadow_effect.setColor(QColor(0, 0, 0, 60))
|
341
|
-
shadow_effect.setOffset(0, 8)
|
342
|
-
self.dock_container.setGraphicsEffect(shadow_effect)
|
343
|
-
|
344
|
-
main_layout.addWidget(self.dock_container)
|
345
|
-
|
346
|
-
# Sağ spacer
|
347
|
-
main_layout.addStretch()
|
348
|
-
|
349
|
-
def load_pinned_apps(self):
|
350
|
-
"""Sabitlenmiş uygulamaları yükle"""
|
351
|
-
try:
|
352
|
-
# Varsayılan sabitlenmiş uygulamalar
|
353
|
-
default_apps = [
|
354
|
-
{"id": "cloud_files", "name": "Dosyalar", "icon": "📁"},
|
355
|
-
{"id": "cloud_terminal", "name": "Terminal", "icon": "💻"},
|
356
|
-
{"id": "cloud_notepad", "name": "Notepad", "icon": "📝"},
|
357
|
-
{"id": "cloud_browser", "name": "Tarayıcı", "icon": "🌐"},
|
358
|
-
{"id": "cloud_pyide", "name": "Python IDE", "icon": "🐍"},
|
359
|
-
]
|
360
|
-
|
361
|
-
# AppExplorer'dan gerçek uygulama bilgilerini al
|
362
|
-
if self.kernel:
|
363
|
-
app_explorer = self.kernel.get_module("appexplorer")
|
364
|
-
if app_explorer:
|
365
|
-
for app_config in default_apps:
|
366
|
-
app_info = app_explorer.get_app_by_id(app_config["id"])
|
367
|
-
if app_info:
|
368
|
-
# PNG ikon yolunu al
|
369
|
-
icon_path = None
|
370
|
-
if app_info.app_path:
|
371
|
-
potential_icon = Path(app_info.app_path) / "icon.png"
|
372
|
-
if potential_icon.exists():
|
373
|
-
icon_path = str(potential_icon)
|
374
|
-
|
375
|
-
self.pinned_apps.append({
|
376
|
-
"id": app_config["id"],
|
377
|
-
"name": app_info.name,
|
378
|
-
"icon": app_config["icon"],
|
379
|
-
"icon_path": icon_path
|
380
|
-
})
|
381
|
-
else:
|
382
|
-
# Fallback
|
383
|
-
self.pinned_apps.append(app_config)
|
384
|
-
else:
|
385
|
-
self.pinned_apps = default_apps
|
386
|
-
else:
|
387
|
-
self.pinned_apps = default_apps
|
388
|
-
|
389
|
-
self.update_dock_icons()
|
390
|
-
|
391
|
-
except Exception as e:
|
392
|
-
self.logger.error(f"Failed to load pinned apps: {e}")
|
393
|
-
|
394
|
-
def update_dock_icons(self):
|
395
|
-
"""Dock simgelerini güncelle"""
|
396
|
-
# Mevcut simgeleri temizle
|
397
|
-
for icon in self.dock_icons:
|
398
|
-
icon.setParent(None)
|
399
|
-
icon.deleteLater()
|
400
|
-
|
401
|
-
self.dock_icons.clear()
|
402
|
-
|
403
|
-
# Yeni simgeleri oluştur
|
404
|
-
for app_info in self.pinned_apps:
|
405
|
-
is_running = app_info["id"] in self.running_apps
|
406
|
-
|
407
|
-
icon = ModernDockIcon(
|
408
|
-
app_id=app_info["id"],
|
409
|
-
app_name=app_info["name"],
|
410
|
-
icon_path=app_info.get("icon_path"),
|
411
|
-
icon_text=app_info["icon"],
|
412
|
-
is_running=is_running
|
413
|
-
)
|
414
|
-
|
415
|
-
# Sinyal bağlantıları
|
416
|
-
icon.app_launch_requested.connect(self.launch_app)
|
417
|
-
icon.context_menu_requested.connect(self.show_app_context_menu)
|
418
|
-
|
419
|
-
self.dock_layout.addWidget(icon)
|
420
|
-
self.dock_icons.append(icon)
|
421
|
-
|
422
|
-
self.logger.info(f"Updated dock with {len(self.dock_icons)} icons")
|
423
|
-
|
424
|
-
def setup_connections(self):
|
425
|
-
"""Sinyal bağlantıları"""
|
426
|
-
if self.kernel:
|
427
|
-
# Event sistemi ile bağlantı kur
|
428
|
-
events = self.kernel.get_module("events")
|
429
|
-
if events:
|
430
|
-
events.subscribe("app_launched", self.on_app_launched)
|
431
|
-
events.subscribe("app_closed", self.on_app_closed)
|
432
|
-
|
433
|
-
def setup_update_timer(self):
|
434
|
-
"""Güncelleme zamanlayıcısı"""
|
435
|
-
self.update_timer = QTimer()
|
436
|
-
self.update_timer.timeout.connect(self.update_running_apps)
|
437
|
-
self.update_timer.start(2000) # Her 2 saniyede güncelle
|
438
|
-
|
439
|
-
def update_running_apps(self):
|
440
|
-
"""Çalışan uygulamaları güncelle"""
|
441
|
-
try:
|
442
|
-
if self.kernel:
|
443
|
-
launcher = self.kernel.get_module("launcher")
|
444
|
-
if launcher:
|
445
|
-
running_apps = list(launcher.get_all_running_apps().keys())
|
446
|
-
|
447
|
-
if running_apps != self.running_apps:
|
448
|
-
self.running_apps = running_apps
|
449
|
-
self.update_dock_running_states()
|
450
|
-
|
451
|
-
except Exception as e:
|
452
|
-
self.logger.error(f"Failed to update running apps: {e}")
|
453
|
-
|
454
|
-
def update_dock_running_states(self):
|
455
|
-
"""Dock simgelerinin çalışma durumlarını güncelle"""
|
456
|
-
for icon in self.dock_icons:
|
457
|
-
is_running = icon.app_id in self.running_apps
|
458
|
-
icon.set_running_state(is_running)
|
459
|
-
|
460
|
-
def launch_app(self, app_id: str):
|
461
|
-
"""Uygulama başlat"""
|
462
|
-
try:
|
463
|
-
self.logger.info(f"Launching app: {app_id}")
|
464
|
-
|
465
|
-
if self.kernel:
|
466
|
-
launcher = self.kernel.get_module("launcher")
|
467
|
-
if launcher:
|
468
|
-
success = launcher.launch_app(app_id)
|
469
|
-
if success:
|
470
|
-
self.logger.info(f"App {app_id} launch requested successfully")
|
471
|
-
else:
|
472
|
-
self.logger.warning(f"Failed to launch app {app_id}")
|
473
|
-
self._fallback_launch(app_id)
|
474
|
-
else:
|
475
|
-
self.logger.warning("Launcher module not available")
|
476
|
-
self._fallback_launch(app_id)
|
477
|
-
else:
|
478
|
-
self.logger.warning("Kernel not available")
|
479
|
-
self._fallback_launch(app_id)
|
480
|
-
|
481
|
-
except Exception as e:
|
482
|
-
self.logger.error(f"Failed to launch app {app_id}: {e}")
|
483
|
-
self._fallback_launch(app_id)
|
484
|
-
|
485
|
-
def _fallback_launch(self, app_id: str):
|
486
|
-
"""Fallback uygulama başlatma"""
|
487
|
-
try:
|
488
|
-
import subprocess
|
489
|
-
import os
|
490
|
-
|
491
|
-
# Uygulama dizinini bul
|
492
|
-
app_path = Path("apps") / app_id
|
493
|
-
if app_path.exists():
|
494
|
-
main_py = app_path / "main.py"
|
495
|
-
if main_py.exists():
|
496
|
-
# Python ile başlat
|
497
|
-
subprocess.Popen([
|
498
|
-
"python3", str(main_py)
|
499
|
-
], cwd=str(app_path))
|
500
|
-
|
501
|
-
self.logger.info(f"Fallback launch successful for {app_id}")
|
502
|
-
else:
|
503
|
-
self.logger.error(f"main.py not found for {app_id}")
|
504
|
-
else:
|
505
|
-
self.logger.error(f"App directory not found: {app_path}")
|
506
|
-
|
507
|
-
except Exception as e:
|
508
|
-
self.logger.error(f"Fallback launch failed for {app_id}: {e}")
|
509
|
-
|
510
|
-
def show_app_context_menu(self, app_id: str, position):
|
511
|
-
"""Uygulama bağlam menüsünü göster"""
|
512
|
-
try:
|
513
|
-
self.logger.info(f"Showing context menu for app: {app_id}")
|
514
|
-
|
515
|
-
menu = QMenu(self)
|
516
|
-
menu.setStyleSheet("""
|
517
|
-
QMenu {
|
518
|
-
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
519
|
-
stop:0 rgba(45, 45, 45, 0.95),
|
520
|
-
stop:1 rgba(35, 35, 35, 0.95));
|
521
|
-
border: 1px solid rgba(80, 80, 80, 0.8);
|
522
|
-
border-radius: 12px;
|
523
|
-
padding: 8px;
|
524
|
-
color: #ffffff;
|
525
|
-
}
|
526
|
-
|
527
|
-
QMenu::item {
|
528
|
-
background-color: transparent;
|
529
|
-
padding: 12px 20px;
|
530
|
-
border-radius: 8px;
|
531
|
-
margin: 2px;
|
532
|
-
color: #ffffff;
|
533
|
-
font-size: 14px;
|
534
|
-
}
|
535
|
-
|
536
|
-
QMenu::item:selected {
|
537
|
-
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
538
|
-
stop:0 rgba(70, 70, 70, 0.8),
|
539
|
-
stop:1 rgba(60, 60, 60, 0.8));
|
540
|
-
color: #ffffff;
|
541
|
-
}
|
542
|
-
|
543
|
-
QMenu::separator {
|
544
|
-
height: 1px;
|
545
|
-
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
546
|
-
stop:0 transparent,
|
547
|
-
stop:0.5 rgba(100, 100, 100, 0.6),
|
548
|
-
stop:1 transparent);
|
549
|
-
margin: 6px 16px;
|
550
|
-
}
|
551
|
-
""")
|
552
|
-
|
553
|
-
# Menü öğeleri
|
554
|
-
if app_id in self.running_apps:
|
555
|
-
# Çalışan uygulama menüsü
|
556
|
-
show_action = QAction("🔍 Göster", self)
|
557
|
-
show_action.triggered.connect(lambda: self.show_app(app_id))
|
558
|
-
menu.addAction(show_action)
|
559
|
-
|
560
|
-
close_action = QAction("❌ Kapat", self)
|
561
|
-
close_action.triggered.connect(lambda: self.close_app(app_id))
|
562
|
-
menu.addAction(close_action)
|
563
|
-
|
564
|
-
menu.addSeparator()
|
565
|
-
|
566
|
-
restart_action = QAction("🔄 Yeniden Başlat", self)
|
567
|
-
restart_action.triggered.connect(lambda: self.restart_app(app_id))
|
568
|
-
menu.addAction(restart_action)
|
569
|
-
else:
|
570
|
-
# Çalışmayan uygulama menüsü
|
571
|
-
launch_action = QAction("🚀 Başlat", self)
|
572
|
-
launch_action.triggered.connect(lambda: self.launch_app(app_id))
|
573
|
-
menu.addAction(launch_action)
|
574
|
-
|
575
|
-
menu.addSeparator()
|
576
|
-
|
577
|
-
# Dock işlemleri
|
578
|
-
unpin_action = QAction("📌 Dock'tan Kaldır", self)
|
579
|
-
unpin_action.triggered.connect(lambda: self.unpin_app(app_id))
|
580
|
-
menu.addAction(unpin_action)
|
581
|
-
|
582
|
-
info_action = QAction("ℹ️ Uygulama Bilgileri", self)
|
583
|
-
info_action.triggered.connect(lambda: self.show_app_info(app_id))
|
584
|
-
menu.addAction(info_action)
|
585
|
-
|
586
|
-
menu.exec(position)
|
587
|
-
|
588
|
-
except Exception as e:
|
589
|
-
self.logger.error(f"Failed to show context menu: {e}")
|
590
|
-
import traceback
|
591
|
-
self.logger.error(traceback.format_exc())
|
592
|
-
|
593
|
-
def show_app(self, app_id: str):
|
594
|
-
"""Uygulamayı göster/öne getir"""
|
595
|
-
try:
|
596
|
-
if self.kernel:
|
597
|
-
window_manager = self.kernel.get_module("windowmanager")
|
598
|
-
if window_manager:
|
599
|
-
windows = window_manager.get_windows_by_app(app_id)
|
600
|
-
if windows:
|
601
|
-
window_manager.focus_window(windows[0].window_id)
|
602
|
-
except Exception as e:
|
603
|
-
self.logger.error(f"Failed to show app {app_id}: {e}")
|
604
|
-
|
605
|
-
def close_app(self, app_id: str):
|
606
|
-
"""Uygulamayı kapat"""
|
607
|
-
try:
|
608
|
-
if self.kernel:
|
609
|
-
launcher = self.kernel.get_module("launcher")
|
610
|
-
if launcher:
|
611
|
-
launcher.stop_app(app_id)
|
612
|
-
except Exception as e:
|
613
|
-
self.logger.error(f"Failed to close app {app_id}: {e}")
|
614
|
-
|
615
|
-
def restart_app(self, app_id: str):
|
616
|
-
"""Uygulamayı yeniden başlat"""
|
617
|
-
try:
|
618
|
-
if self.kernel:
|
619
|
-
launcher = self.kernel.get_module("launcher")
|
620
|
-
if launcher:
|
621
|
-
launcher.restart_app(app_id)
|
622
|
-
except Exception as e:
|
623
|
-
self.logger.error(f"Failed to restart app {app_id}: {e}")
|
624
|
-
|
625
|
-
def unpin_app(self, app_id: str):
|
626
|
-
"""Uygulamayı dock'tan kaldır"""
|
627
|
-
try:
|
628
|
-
self.pinned_apps = [app for app in self.pinned_apps if app["id"] != app_id]
|
629
|
-
self.update_dock_icons()
|
630
|
-
self.logger.info(f"Unpinned app: {app_id}")
|
631
|
-
except Exception as e:
|
632
|
-
self.logger.error(f"Failed to unpin app {app_id}: {e}")
|
633
|
-
|
634
|
-
def pin_app(self, app_id: str, app_name: str, icon: str):
|
635
|
-
"""Uygulamayı dock'a sabitle"""
|
636
|
-
try:
|
637
|
-
# Zaten sabitlenmiş mi kontrol et
|
638
|
-
if any(app["id"] == app_id for app in self.pinned_apps):
|
639
|
-
return
|
640
|
-
|
641
|
-
# PNG ikon yolunu bul
|
642
|
-
icon_path = None
|
643
|
-
if self.kernel:
|
644
|
-
app_explorer = self.kernel.get_module("appexplorer")
|
645
|
-
if app_explorer:
|
646
|
-
app_info = app_explorer.get_app_by_id(app_id)
|
647
|
-
if app_info and app_info.app_path:
|
648
|
-
potential_icon = Path(app_info.app_path) / "icon.png"
|
649
|
-
if potential_icon.exists():
|
650
|
-
icon_path = str(potential_icon)
|
651
|
-
|
652
|
-
self.pinned_apps.append({
|
653
|
-
"id": app_id,
|
654
|
-
"name": app_name,
|
655
|
-
"icon": icon,
|
656
|
-
"icon_path": icon_path
|
657
|
-
})
|
658
|
-
|
659
|
-
self.update_dock_icons()
|
660
|
-
self.logger.info(f"Pinned app: {app_id}")
|
661
|
-
|
662
|
-
except Exception as e:
|
663
|
-
self.logger.error(f"Failed to pin app {app_id}: {e}")
|
664
|
-
|
665
|
-
def show_app_info(self, app_id: str):
|
666
|
-
"""Uygulama bilgilerini göster"""
|
667
|
-
self.logger.info(f"Show app info for: {app_id}")
|
668
|
-
# TODO: Uygulama bilgi dialogu implementasyonu
|
669
|
-
|
670
|
-
def on_app_launched(self, event):
|
671
|
-
"""Uygulama başlatıldı olayı"""
|
672
|
-
try:
|
673
|
-
app_id = event.get("app_id")
|
674
|
-
if app_id and app_id not in self.running_apps:
|
675
|
-
self.running_apps.append(app_id)
|
676
|
-
self.update_dock_running_states()
|
677
|
-
except Exception as e:
|
678
|
-
self.logger.error(f"Failed to handle app launched event: {e}")
|
679
|
-
|
680
|
-
def on_app_closed(self, event):
|
681
|
-
"""Uygulama kapatıldı olayı"""
|
682
|
-
try:
|
683
|
-
app_id = event.get("app_id")
|
684
|
-
if app_id and app_id in self.running_apps:
|
685
|
-
self.running_apps.remove(app_id)
|
686
|
-
self.update_dock_running_states()
|
687
|
-
except Exception as e:
|
688
|
-
self.logger.error(f"Failed to handle app closed event: {e}")
|
689
|
-
|
690
|
-
def get_dock_config(self) -> Dict:
|
691
|
-
"""Dock konfigürasyonunu al"""
|
692
|
-
return {
|
693
|
-
"pinned_apps": self.pinned_apps,
|
694
|
-
"dock_height": self.dock_height,
|
695
|
-
"dock_margin": self.dock_margin,
|
696
|
-
"icon_spacing": self.icon_spacing
|
697
|
-
}
|
698
|
-
|
699
|
-
def apply_dock_config(self, config: Dict):
|
700
|
-
"""Dock konfigürasyonunu uygula"""
|
701
|
-
try:
|
702
|
-
if "pinned_apps" in config:
|
703
|
-
self.pinned_apps = config["pinned_apps"]
|
704
|
-
self.update_dock_icons()
|
705
|
-
|
706
|
-
if "dock_height" in config:
|
707
|
-
self.dock_height = config["dock_height"]
|
708
|
-
self.setFixedHeight(self.dock_height + self.dock_margin)
|
709
|
-
|
710
|
-
if "dock_margin" in config:
|
711
|
-
self.dock_margin = config["dock_margin"]
|
712
|
-
|
713
|
-
if "icon_spacing" in config:
|
714
|
-
self.icon_spacing = config["icon_spacing"]
|
715
|
-
self.dock_layout.setSpacing(self.icon_spacing)
|
716
|
-
|
717
|
-
except Exception as e:
|
718
|
-
self.logger.error(f"Failed to apply dock config: {e}")
|
719
|
-
|
720
|
-
# Geriye uyumluluk için alias
|
721
|
-
ModernDock = ModernRainDock
|
722
|
-
RainDock = ModernRainDock # Eski isim için de alias
|