clapp-pm 1.0.43__py3-none-any.whl → 1.0.45__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.43.data → clapp_pm-1.0.45.data}/data/version.json +1 -1
- {clapp_pm-1.0.43.dist-info → clapp_pm-1.0.45.dist-info}/METADATA +1 -1
- {clapp_pm-1.0.43.dist-info → clapp_pm-1.0.45.dist-info}/RECORD +12 -24
- package_runner.py +1 -0
- packages/luaozgur-moba/README.md +159 -0
- packages/luaozgur-moba/manifest.json +8 -0
- publish_command.py +41 -39
- version.py +1 -1
- packages/pycloudos/README.md +0 -279
- packages/pycloudos/main.py +0 -193
- packages/pycloudos/manifest.json +0 -15
- packages/pycloudos/rain/__init__.py +0 -7
- packages/pycloudos/rain/dock.py +0 -722
- packages/pycloudos/rain/flet_html_widgets.py +0 -0
- packages/pycloudos/rain/theme.py +0 -930
- 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.43.dist-info → clapp_pm-1.0.45.dist-info}/WHEEL +0 -0
- {clapp_pm-1.0.43.dist-info → clapp_pm-1.0.45.dist-info}/entry_points.txt +0 -0
- {clapp_pm-1.0.43.dist-info → clapp_pm-1.0.45.dist-info}/licenses/LICENSE +0 -0
- {clapp_pm-1.0.43.dist-info → clapp_pm-1.0.45.dist-info}/top_level.txt +0 -0
@@ -1,605 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Rain Window Manager - Uygulama Pencere Yöneticisi
|
3
|
-
PyCloud OS için window management sistemi
|
4
|
-
"""
|
5
|
-
|
6
|
-
import logging
|
7
|
-
import time
|
8
|
-
from enum import Enum
|
9
|
-
from typing import Dict, List, Optional, Tuple, Callable
|
10
|
-
from dataclasses import dataclass, field
|
11
|
-
import json
|
12
|
-
from pathlib import Path
|
13
|
-
from functools import wraps
|
14
|
-
|
15
|
-
try:
|
16
|
-
from PyQt6.QtWidgets import (QApplication, QWidget, QMainWindow, QMdiArea,
|
17
|
-
QMdiSubWindow, QVBoxLayout, QHBoxLayout,
|
18
|
-
QPushButton, QLabel, QFrame)
|
19
|
-
from PyQt6.QtCore import Qt, QRect, QPoint, QSize, QTimer, pyqtSignal, QObject, QMetaObject, Q_ARG, QThread
|
20
|
-
from PyQt6.QtGui import QPixmap, QIcon, QFont
|
21
|
-
PYQT_AVAILABLE = True
|
22
|
-
except ImportError:
|
23
|
-
PYQT_AVAILABLE = False
|
24
|
-
# Dummy classes for fallback
|
25
|
-
class QObject:
|
26
|
-
def __init__(self): pass
|
27
|
-
class pyqtSignal:
|
28
|
-
def __init__(self, *args): pass
|
29
|
-
def emit(self, *args): pass
|
30
|
-
|
31
|
-
def ensure_main_thread(func):
|
32
|
-
"""UI işlemlerini main thread'de çalıştırmak için dekoratör"""
|
33
|
-
@wraps(func)
|
34
|
-
def wrapper(self, *args, **kwargs):
|
35
|
-
if not PYQT_AVAILABLE:
|
36
|
-
return func(self, *args, **kwargs)
|
37
|
-
|
38
|
-
# Ana thread kontrolü
|
39
|
-
app = QApplication.instance()
|
40
|
-
if app:
|
41
|
-
current_thread = QThread.currentThread()
|
42
|
-
main_thread = app.thread()
|
43
|
-
|
44
|
-
if current_thread != main_thread:
|
45
|
-
# Farklı thread'deyiz, main thread'e yönlendir
|
46
|
-
# QTimer kullanarak main thread'de çalıştır
|
47
|
-
def delayed_call():
|
48
|
-
try:
|
49
|
-
return func(self, *args, **kwargs)
|
50
|
-
except Exception as e:
|
51
|
-
self.logger.error(f"Main thread call failed: {e}")
|
52
|
-
|
53
|
-
QTimer.singleShot(0, delayed_call)
|
54
|
-
return None
|
55
|
-
else:
|
56
|
-
# Ana thread'deyiz, doğrudan çalıştır
|
57
|
-
return func(self, *args, **kwargs)
|
58
|
-
else:
|
59
|
-
# QApplication yok, doğrudan çalıştır
|
60
|
-
return func(self, *args, **kwargs)
|
61
|
-
|
62
|
-
return wrapper
|
63
|
-
|
64
|
-
class WindowState(Enum):
|
65
|
-
"""Pencere durumları"""
|
66
|
-
NORMAL = "normal"
|
67
|
-
MINIMIZED = "minimized"
|
68
|
-
MAXIMIZED = "maximized"
|
69
|
-
FULLSCREEN = "fullscreen"
|
70
|
-
HIDDEN = "hidden"
|
71
|
-
|
72
|
-
class WindowType(Enum):
|
73
|
-
"""Pencere türleri"""
|
74
|
-
APPLICATION = "application"
|
75
|
-
SYSTEM = "system"
|
76
|
-
DIALOG = "dialog"
|
77
|
-
POPUP = "popup"
|
78
|
-
WIDGET = "widget"
|
79
|
-
|
80
|
-
@dataclass
|
81
|
-
class WindowInfo:
|
82
|
-
"""Pencere bilgi yapısı"""
|
83
|
-
window_id: str
|
84
|
-
app_id: str
|
85
|
-
title: str
|
86
|
-
window_type: WindowType
|
87
|
-
state: WindowState
|
88
|
-
geometry: QRect = field(default_factory=lambda: QRect(100, 100, 800, 600))
|
89
|
-
z_order: int = 0
|
90
|
-
is_active: bool = False
|
91
|
-
is_visible: bool = True
|
92
|
-
created_time: float = field(default_factory=time.time)
|
93
|
-
last_focus_time: float = field(default_factory=time.time)
|
94
|
-
icon_path: Optional[str] = None
|
95
|
-
metadata: Dict = field(default_factory=dict)
|
96
|
-
|
97
|
-
@dataclass
|
98
|
-
class WindowConfig:
|
99
|
-
"""Pencere yöneticisi yapılandırması"""
|
100
|
-
enable_animations: bool = True
|
101
|
-
enable_transparency: bool = True
|
102
|
-
enable_shadows: bool = True
|
103
|
-
default_window_size: Tuple[int, int] = (800, 600)
|
104
|
-
minimum_window_size: Tuple[int, int] = (300, 200)
|
105
|
-
taskbar_height: int = 40
|
106
|
-
titlebar_height: int = 30
|
107
|
-
snap_threshold: int = 10
|
108
|
-
animation_duration: int = 200
|
109
|
-
|
110
|
-
class WindowManager(QObject):
|
111
|
-
"""Ana pencere yöneticisi sınıfı"""
|
112
|
-
|
113
|
-
# Sinyaller
|
114
|
-
window_created = pyqtSignal(str) # window_id
|
115
|
-
window_destroyed = pyqtSignal(str) # window_id
|
116
|
-
window_state_changed = pyqtSignal(str, str) # window_id, new_state
|
117
|
-
window_focus_changed = pyqtSignal(str) # window_id
|
118
|
-
|
119
|
-
def __init__(self, kernel=None):
|
120
|
-
super().__init__()
|
121
|
-
self.kernel = kernel
|
122
|
-
self.logger = logging.getLogger("WindowManager")
|
123
|
-
|
124
|
-
# Pencere kayıtları
|
125
|
-
self.windows: Dict[str, WindowInfo] = {}
|
126
|
-
self.window_widgets: Dict[str, QWidget] = {}
|
127
|
-
self.active_window_id: Optional[str] = None
|
128
|
-
self.window_counter = 0
|
129
|
-
|
130
|
-
# Topbar entegrasyonu
|
131
|
-
self.topbar = None
|
132
|
-
|
133
|
-
# Yapılandırma
|
134
|
-
self.config = WindowConfig()
|
135
|
-
self.config_file = Path("system/config/window_manager.json")
|
136
|
-
|
137
|
-
# UI bileşenleri
|
138
|
-
self.mdi_area: Optional[QMdiArea] = None
|
139
|
-
self.taskbar: Optional[QWidget] = None
|
140
|
-
|
141
|
-
# Timer'lar
|
142
|
-
self.focus_timer = QTimer()
|
143
|
-
self.focus_timer.timeout.connect(self._check_window_focus)
|
144
|
-
self.focus_timer.start(100) # 100ms
|
145
|
-
|
146
|
-
# İstatistikler
|
147
|
-
self.stats = {
|
148
|
-
"total_windows_created": 0,
|
149
|
-
"active_windows": 0,
|
150
|
-
"window_switches": 0,
|
151
|
-
"last_activity": time.time()
|
152
|
-
}
|
153
|
-
|
154
|
-
self._load_config()
|
155
|
-
self._setup_ui()
|
156
|
-
|
157
|
-
self.logger.info("Window Manager initialized")
|
158
|
-
|
159
|
-
def _load_config(self):
|
160
|
-
"""Yapılandırmayı yükle"""
|
161
|
-
try:
|
162
|
-
if self.config_file.exists():
|
163
|
-
with open(self.config_file, 'r', encoding='utf-8') as f:
|
164
|
-
config_data = json.load(f)
|
165
|
-
|
166
|
-
# Config güncelle
|
167
|
-
for key, value in config_data.items():
|
168
|
-
if hasattr(self.config, key):
|
169
|
-
setattr(self.config, key, value)
|
170
|
-
|
171
|
-
self.logger.info("Window manager config loaded")
|
172
|
-
except Exception as e:
|
173
|
-
self.logger.error(f"Failed to load window manager config: {e}")
|
174
|
-
|
175
|
-
def _save_config(self):
|
176
|
-
"""Yapılandırmayı kaydet"""
|
177
|
-
try:
|
178
|
-
self.config_file.parent.mkdir(parents=True, exist_ok=True)
|
179
|
-
|
180
|
-
config_data = {
|
181
|
-
"enable_animations": self.config.enable_animations,
|
182
|
-
"enable_transparency": self.config.enable_transparency,
|
183
|
-
"enable_shadows": self.config.enable_shadows,
|
184
|
-
"default_window_size": self.config.default_window_size,
|
185
|
-
"minimum_window_size": self.config.minimum_window_size,
|
186
|
-
"taskbar_height": self.config.taskbar_height,
|
187
|
-
"titlebar_height": self.config.titlebar_height,
|
188
|
-
"snap_threshold": self.config.snap_threshold,
|
189
|
-
"animation_duration": self.config.animation_duration
|
190
|
-
}
|
191
|
-
|
192
|
-
with open(self.config_file, 'w', encoding='utf-8') as f:
|
193
|
-
json.dump(config_data, f, indent=2, ensure_ascii=False)
|
194
|
-
|
195
|
-
self.logger.info("Window manager config saved")
|
196
|
-
except Exception as e:
|
197
|
-
self.logger.error(f"Failed to save window manager config: {e}")
|
198
|
-
|
199
|
-
def _setup_ui(self):
|
200
|
-
"""UI bileşenlerini kur"""
|
201
|
-
if not PYQT_AVAILABLE:
|
202
|
-
return
|
203
|
-
|
204
|
-
try:
|
205
|
-
# MDI Area oluştur (ana pencere alanı)
|
206
|
-
self.mdi_area = QMdiArea()
|
207
|
-
self.mdi_area.setViewMode(QMdiArea.ViewMode.TabbedView)
|
208
|
-
self.mdi_area.setTabsClosable(True)
|
209
|
-
self.mdi_area.setTabsMovable(True)
|
210
|
-
self.mdi_area.setDocumentMode(True)
|
211
|
-
|
212
|
-
# Stil ayarları
|
213
|
-
self.mdi_area.setStyleSheet("""
|
214
|
-
QMdiArea {
|
215
|
-
background-color: #2d2d2d;
|
216
|
-
border: none;
|
217
|
-
}
|
218
|
-
QMdiSubWindow {
|
219
|
-
background-color: #3d3d3d;
|
220
|
-
border: 1px solid #555;
|
221
|
-
border-radius: 8px;
|
222
|
-
}
|
223
|
-
QMdiSubWindow::title {
|
224
|
-
background-color: #404040;
|
225
|
-
color: #ffffff;
|
226
|
-
padding: 4px 8px;
|
227
|
-
font-size: 13px;
|
228
|
-
}
|
229
|
-
""")
|
230
|
-
|
231
|
-
self.logger.info("Window manager UI setup completed")
|
232
|
-
|
233
|
-
except Exception as e:
|
234
|
-
self.logger.error(f"Failed to setup window manager UI: {e}")
|
235
|
-
|
236
|
-
@ensure_main_thread
|
237
|
-
def create_window(self, app_id: str, title: str,
|
238
|
-
window_type: WindowType = WindowType.APPLICATION,
|
239
|
-
geometry: Optional[QRect] = None,
|
240
|
-
icon_path: Optional[str] = None,
|
241
|
-
metadata: Optional[Dict] = None) -> str:
|
242
|
-
"""Yeni pencere oluştur"""
|
243
|
-
|
244
|
-
# Benzersiz window ID oluştur
|
245
|
-
self.window_counter += 1
|
246
|
-
window_id = f"{app_id}_{self.window_counter}_{int(time.time())}"
|
247
|
-
|
248
|
-
# Geometry ayarla
|
249
|
-
if geometry is None:
|
250
|
-
geometry = QRect(
|
251
|
-
100 + (len(self.windows) * 30),
|
252
|
-
100 + (len(self.windows) * 30),
|
253
|
-
self.config.default_window_size[0],
|
254
|
-
self.config.default_window_size[1]
|
255
|
-
)
|
256
|
-
|
257
|
-
# WindowInfo oluştur
|
258
|
-
window_info = WindowInfo(
|
259
|
-
window_id=window_id,
|
260
|
-
app_id=app_id,
|
261
|
-
title=title,
|
262
|
-
window_type=window_type,
|
263
|
-
state=WindowState.NORMAL,
|
264
|
-
geometry=geometry,
|
265
|
-
z_order=len(self.windows),
|
266
|
-
is_active=True,
|
267
|
-
is_visible=True,
|
268
|
-
icon_path=icon_path,
|
269
|
-
metadata=metadata or {}
|
270
|
-
)
|
271
|
-
|
272
|
-
# Kaydet
|
273
|
-
self.windows[window_id] = window_info
|
274
|
-
|
275
|
-
# İstatistikleri güncelle
|
276
|
-
self.stats["total_windows_created"] += 1
|
277
|
-
self.stats["active_windows"] = len(self.windows)
|
278
|
-
self.stats["last_activity"] = time.time()
|
279
|
-
|
280
|
-
# Aktif pencereyi ayarla
|
281
|
-
self._set_active_window(window_id)
|
282
|
-
|
283
|
-
# UI widget oluştur
|
284
|
-
self._create_window_widget(window_id)
|
285
|
-
|
286
|
-
# Desktop'tan window view'a geç (eğer varsa)
|
287
|
-
if hasattr(self, 'show_windows'):
|
288
|
-
self.show_windows()
|
289
|
-
|
290
|
-
# Sinyal gönder
|
291
|
-
self.window_created.emit(window_id)
|
292
|
-
|
293
|
-
self.logger.info(f"Window created: {window_id} ({title})")
|
294
|
-
return window_id
|
295
|
-
|
296
|
-
@ensure_main_thread
|
297
|
-
def _create_window_widget(self, window_id: str):
|
298
|
-
"""Pencere için UI widget oluştur"""
|
299
|
-
if not PYQT_AVAILABLE or not self.mdi_area:
|
300
|
-
return
|
301
|
-
|
302
|
-
try:
|
303
|
-
window_info = self.windows.get(window_id)
|
304
|
-
if not window_info:
|
305
|
-
return
|
306
|
-
|
307
|
-
# Main thread kontrol et
|
308
|
-
app = QApplication.instance()
|
309
|
-
if not app or app.thread() != QObject().thread():
|
310
|
-
# Ana thread'de değiliz, işlemi ertele
|
311
|
-
QTimer.singleShot(100, lambda: self._create_window_widget(window_id))
|
312
|
-
return
|
313
|
-
|
314
|
-
# Sub window oluştur
|
315
|
-
sub_window = QMdiSubWindow(self.mdi_area)
|
316
|
-
sub_window.setWindowTitle(window_info.title)
|
317
|
-
sub_window.resize(window_info.geometry.size())
|
318
|
-
|
319
|
-
# İçerik widget'ı oluştur
|
320
|
-
content_widget = QWidget()
|
321
|
-
content_widget.setStyleSheet("""
|
322
|
-
QWidget {
|
323
|
-
background-color: #2d2d2d;
|
324
|
-
color: #ffffff;
|
325
|
-
}
|
326
|
-
""")
|
327
|
-
|
328
|
-
# Basit layout
|
329
|
-
layout = QVBoxLayout(content_widget)
|
330
|
-
|
331
|
-
# Başlık
|
332
|
-
title_label = QLabel(window_info.title)
|
333
|
-
title_label.setFont(QFont("Arial", 14, QFont.Weight.Bold))
|
334
|
-
title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
335
|
-
layout.addWidget(title_label)
|
336
|
-
|
337
|
-
# App ID bilgisi
|
338
|
-
app_label = QLabel(f"App: {window_info.app_id}")
|
339
|
-
app_label.setFont(QFont("Arial", 10))
|
340
|
-
app_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
341
|
-
app_label.setStyleSheet("color: #888;")
|
342
|
-
layout.addWidget(app_label)
|
343
|
-
|
344
|
-
# Window ID bilgisi
|
345
|
-
id_label = QLabel(f"Window ID: {window_id}")
|
346
|
-
id_label.setFont(QFont("Arial", 9))
|
347
|
-
id_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
348
|
-
id_label.setStyleSheet("color: #666;")
|
349
|
-
layout.addWidget(id_label)
|
350
|
-
|
351
|
-
# Pencere kontrolleri
|
352
|
-
controls_layout = QHBoxLayout()
|
353
|
-
|
354
|
-
minimize_btn = QPushButton("−")
|
355
|
-
minimize_btn.setFixedSize(30, 30)
|
356
|
-
minimize_btn.clicked.connect(lambda: self.minimize_window(window_id))
|
357
|
-
controls_layout.addWidget(minimize_btn)
|
358
|
-
|
359
|
-
maximize_btn = QPushButton("□")
|
360
|
-
maximize_btn.setFixedSize(30, 30)
|
361
|
-
maximize_btn.clicked.connect(lambda: self.toggle_maximize_window(window_id))
|
362
|
-
controls_layout.addWidget(maximize_btn)
|
363
|
-
|
364
|
-
close_btn = QPushButton("×")
|
365
|
-
close_btn.setFixedSize(30, 30)
|
366
|
-
close_btn.clicked.connect(lambda: self.close_window(window_id))
|
367
|
-
controls_layout.addWidget(close_btn)
|
368
|
-
|
369
|
-
layout.addLayout(controls_layout)
|
370
|
-
layout.addStretch()
|
371
|
-
|
372
|
-
# Sub window'a içeriği ayarla
|
373
|
-
sub_window.setWidget(content_widget)
|
374
|
-
|
375
|
-
# MDI area'ya ekle
|
376
|
-
self.mdi_area.addSubWindow(sub_window)
|
377
|
-
sub_window.show()
|
378
|
-
|
379
|
-
# Widget'ı kaydet
|
380
|
-
self.window_widgets[window_id] = sub_window
|
381
|
-
|
382
|
-
self.logger.info(f"Window widget created for: {window_id}")
|
383
|
-
|
384
|
-
except Exception as e:
|
385
|
-
self.logger.error(f"Failed to create window widget for {window_id}: {e}")
|
386
|
-
# Hata durumunda retry dene
|
387
|
-
QTimer.singleShot(1000, lambda: self._create_window_widget(window_id))
|
388
|
-
|
389
|
-
@ensure_main_thread
|
390
|
-
def close_window(self, window_id: str) -> bool:
|
391
|
-
"""Pencereyi kapat"""
|
392
|
-
try:
|
393
|
-
window_info = self.windows.get(window_id)
|
394
|
-
if not window_info:
|
395
|
-
return False
|
396
|
-
|
397
|
-
# UI widget'ı kaldır
|
398
|
-
if window_id in self.window_widgets:
|
399
|
-
widget = self.window_widgets[window_id]
|
400
|
-
if widget and self.mdi_area:
|
401
|
-
self.mdi_area.removeSubWindow(widget)
|
402
|
-
widget.close()
|
403
|
-
del self.window_widgets[window_id]
|
404
|
-
|
405
|
-
# Pencere kaydını sil
|
406
|
-
del self.windows[window_id]
|
407
|
-
|
408
|
-
# Aktif pencere kontrolü
|
409
|
-
if self.active_window_id == window_id:
|
410
|
-
self.active_window_id = None
|
411
|
-
# Bir sonraki pencereyi aktif yap
|
412
|
-
if self.windows:
|
413
|
-
next_window_id = list(self.windows.keys())[-1]
|
414
|
-
self._set_active_window(next_window_id)
|
415
|
-
else:
|
416
|
-
# Hiç pencere kalmadıysa topbar'ı temizle
|
417
|
-
if self.topbar and hasattr(self.topbar, 'on_app_focus_changed'):
|
418
|
-
self.topbar.on_app_focus_changed(None)
|
419
|
-
|
420
|
-
# İstatistikleri güncelle
|
421
|
-
self.stats["active_windows"] = len(self.windows)
|
422
|
-
self.stats["last_activity"] = time.time()
|
423
|
-
|
424
|
-
# Eğer hiç pencere kalmadıysa desktop'a dön
|
425
|
-
if len(self.windows) == 0 and hasattr(self, 'show_desktop'):
|
426
|
-
self.show_desktop()
|
427
|
-
|
428
|
-
# Sinyal gönder
|
429
|
-
self.window_destroyed.emit(window_id)
|
430
|
-
|
431
|
-
self.logger.info(f"Window closed: {window_id}")
|
432
|
-
return True
|
433
|
-
|
434
|
-
except Exception as e:
|
435
|
-
self.logger.error(f"Failed to close window {window_id}: {e}")
|
436
|
-
return False
|
437
|
-
|
438
|
-
def minimize_window(self, window_id: str) -> bool:
|
439
|
-
"""Pencereyi küçült"""
|
440
|
-
return self._change_window_state(window_id, WindowState.MINIMIZED)
|
441
|
-
|
442
|
-
def maximize_window(self, window_id: str) -> bool:
|
443
|
-
"""Pencereyi büyüt"""
|
444
|
-
return self._change_window_state(window_id, WindowState.MAXIMIZED)
|
445
|
-
|
446
|
-
def toggle_maximize_window(self, window_id: str) -> bool:
|
447
|
-
"""Pencere büyütme/normal arası geçiş"""
|
448
|
-
window_info = self.windows.get(window_id)
|
449
|
-
if not window_info:
|
450
|
-
return False
|
451
|
-
|
452
|
-
new_state = (WindowState.NORMAL if window_info.state == WindowState.MAXIMIZED
|
453
|
-
else WindowState.MAXIMIZED)
|
454
|
-
return self._change_window_state(window_id, new_state)
|
455
|
-
|
456
|
-
def _change_window_state(self, window_id: str, new_state: WindowState) -> bool:
|
457
|
-
"""Pencere durumunu değiştir"""
|
458
|
-
try:
|
459
|
-
window_info = self.windows.get(window_id)
|
460
|
-
if not window_info:
|
461
|
-
return False
|
462
|
-
|
463
|
-
old_state = window_info.state
|
464
|
-
window_info.state = new_state
|
465
|
-
window_info.last_focus_time = time.time()
|
466
|
-
|
467
|
-
# UI widget'ı güncelle
|
468
|
-
if window_id in self.window_widgets:
|
469
|
-
widget = self.window_widgets[window_id]
|
470
|
-
if widget:
|
471
|
-
if new_state == WindowState.MINIMIZED:
|
472
|
-
widget.showMinimized()
|
473
|
-
elif new_state == WindowState.MAXIMIZED:
|
474
|
-
widget.showMaximized()
|
475
|
-
elif new_state == WindowState.NORMAL:
|
476
|
-
widget.showNormal()
|
477
|
-
elif new_state == WindowState.HIDDEN:
|
478
|
-
widget.hide()
|
479
|
-
|
480
|
-
# Sinyal gönder
|
481
|
-
self.window_state_changed.emit(window_id, new_state.value)
|
482
|
-
|
483
|
-
self.logger.info(f"Window {window_id} state changed: {old_state.value} -> {new_state.value}")
|
484
|
-
return True
|
485
|
-
|
486
|
-
except Exception as e:
|
487
|
-
self.logger.error(f"Failed to change window state for {window_id}: {e}")
|
488
|
-
return False
|
489
|
-
|
490
|
-
def _set_active_window(self, window_id: str):
|
491
|
-
"""Aktif pencereyi ayarla"""
|
492
|
-
try:
|
493
|
-
if window_id not in self.windows:
|
494
|
-
return
|
495
|
-
|
496
|
-
# Önceki aktif pencereyi güncelle
|
497
|
-
if self.active_window_id and self.active_window_id in self.windows:
|
498
|
-
self.windows[self.active_window_id].is_active = False
|
499
|
-
|
500
|
-
# Yeni aktif pencereyi ayarla
|
501
|
-
self.active_window_id = window_id
|
502
|
-
self.windows[window_id].is_active = True
|
503
|
-
self.windows[window_id].last_focus_time = time.time()
|
504
|
-
|
505
|
-
# Z-order güncelle
|
506
|
-
max_z = max(w.z_order for w in self.windows.values()) if self.windows else 0
|
507
|
-
self.windows[window_id].z_order = max_z + 1
|
508
|
-
|
509
|
-
# Topbar'ı bilgilendir
|
510
|
-
if self.topbar and hasattr(self.topbar, 'on_app_focus_changed'):
|
511
|
-
app_id = self.windows[window_id].app_id
|
512
|
-
self.topbar.on_app_focus_changed(app_id)
|
513
|
-
|
514
|
-
# İstatistikler
|
515
|
-
self.stats["window_switches"] += 1
|
516
|
-
self.stats["last_activity"] = time.time()
|
517
|
-
|
518
|
-
# Sinyal gönder
|
519
|
-
self.window_focus_changed.emit(window_id)
|
520
|
-
|
521
|
-
self.logger.debug(f"Active window set to: {window_id}")
|
522
|
-
|
523
|
-
except Exception as e:
|
524
|
-
self.logger.error(f"Failed to set active window {window_id}: {e}")
|
525
|
-
|
526
|
-
def _check_window_focus(self):
|
527
|
-
"""Pencere focus durumunu kontrol et"""
|
528
|
-
if not PYQT_AVAILABLE or not self.mdi_area:
|
529
|
-
return
|
530
|
-
|
531
|
-
try:
|
532
|
-
active_sub_window = self.mdi_area.activeSubWindow()
|
533
|
-
if active_sub_window:
|
534
|
-
# Aktif sub window'u bul
|
535
|
-
for window_id, widget in self.window_widgets.items():
|
536
|
-
if widget == active_sub_window and window_id != self.active_window_id:
|
537
|
-
self._set_active_window(window_id)
|
538
|
-
break
|
539
|
-
except Exception as e:
|
540
|
-
self.logger.debug(f"Focus check error: {e}")
|
541
|
-
|
542
|
-
def get_window_info(self, window_id: str) -> Optional[WindowInfo]:
|
543
|
-
"""Pencere bilgisini al"""
|
544
|
-
return self.windows.get(window_id)
|
545
|
-
|
546
|
-
def get_all_windows(self) -> Dict[str, WindowInfo]:
|
547
|
-
"""Tüm pencereleri al"""
|
548
|
-
return self.windows.copy()
|
549
|
-
|
550
|
-
def get_windows_by_app(self, app_id: str) -> List[WindowInfo]:
|
551
|
-
"""Uygulamaya ait pencereleri al"""
|
552
|
-
return [w for w in self.windows.values() if w.app_id == app_id]
|
553
|
-
|
554
|
-
def get_active_window(self) -> Optional[WindowInfo]:
|
555
|
-
"""Aktif pencereyi al"""
|
556
|
-
if self.active_window_id:
|
557
|
-
return self.windows.get(self.active_window_id)
|
558
|
-
return None
|
559
|
-
|
560
|
-
def get_mdi_area(self) -> Optional[QMdiArea]:
|
561
|
-
"""MDI Area widget'ını al"""
|
562
|
-
return self.mdi_area
|
563
|
-
|
564
|
-
def get_stats(self) -> Dict:
|
565
|
-
"""İstatistikleri al"""
|
566
|
-
return self.stats.copy()
|
567
|
-
|
568
|
-
def shutdown(self):
|
569
|
-
"""Modül kapatma"""
|
570
|
-
try:
|
571
|
-
# Tüm pencereleri kapat
|
572
|
-
window_ids = list(self.windows.keys())
|
573
|
-
for window_id in window_ids:
|
574
|
-
self.close_window(window_id)
|
575
|
-
|
576
|
-
# Timer'ları durdur
|
577
|
-
if hasattr(self, 'focus_timer'):
|
578
|
-
self.focus_timer.stop()
|
579
|
-
|
580
|
-
# Config kaydet
|
581
|
-
self._save_config()
|
582
|
-
|
583
|
-
self.logger.info("Window manager shutdown completed")
|
584
|
-
|
585
|
-
except Exception as e:
|
586
|
-
self.logger.error(f"Error during window manager shutdown: {e}")
|
587
|
-
|
588
|
-
def set_topbar(self, topbar):
|
589
|
-
"""Topbar referansını ayarla"""
|
590
|
-
self.topbar = topbar
|
591
|
-
self.logger.info("Topbar reference set in window manager")
|
592
|
-
|
593
|
-
# Global window manager instance
|
594
|
-
_window_manager = None
|
595
|
-
|
596
|
-
def init_window_manager(kernel=None) -> WindowManager:
|
597
|
-
"""Window manager'ı başlat"""
|
598
|
-
global _window_manager
|
599
|
-
if _window_manager is None:
|
600
|
-
_window_manager = WindowManager(kernel)
|
601
|
-
return _window_manager
|
602
|
-
|
603
|
-
def get_window_manager() -> Optional[WindowManager]:
|
604
|
-
"""Window manager'ı al"""
|
605
|
-
return _window_manager
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# PyCloud OS Development Requirements
|
2
|
-
# Önce production requirements'ları yükle
|
3
|
-
-r requirements.txt
|
4
|
-
|
5
|
-
# Development ve Testing araçları
|
6
|
-
pytest>=7.0.0
|
7
|
-
pytest-cov>=4.0.0
|
8
|
-
pytest-mock>=3.0.0
|
9
|
-
|
10
|
-
# Code formatting ve linting
|
11
|
-
black>=22.0.0
|
12
|
-
flake8>=5.0.0
|
13
|
-
isort>=5.0.0
|
14
|
-
mypy>=1.0.0
|
15
|
-
|
16
|
-
# Type stubs
|
17
|
-
types-requests>=2.28.0
|
18
|
-
types-setuptools>=65.0.0
|
19
|
-
|
20
|
-
# Documentation
|
21
|
-
sphinx>=5.0.0
|
22
|
-
sphinx-rtd-theme>=1.0.0
|
23
|
-
sphinx-autodoc-typehints>=1.19.0
|
24
|
-
|
25
|
-
# Build tools
|
26
|
-
wheel>=0.37.0
|
27
|
-
setuptools>=65.0.0
|
28
|
-
build>=0.8.0
|
29
|
-
|
30
|
-
# Development utilities
|
31
|
-
ipython>=8.0.0
|
32
|
-
jupyterlab>=3.4.0
|
33
|
-
|
34
|
-
# Performance profiling
|
35
|
-
memory-profiler>=0.60.0
|
36
|
-
line-profiler>=4.0.0
|
37
|
-
|
38
|
-
# Security analysis
|
39
|
-
bandit>=1.7.0
|
40
|
-
safety>=2.0.0
|
41
|
-
|
42
|
-
# Git hooks
|
43
|
-
pre-commit>=2.20.0
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# PyCloud OS Requirements
|
2
|
-
# Ana GUI ve Web Framework
|
3
|
-
PyQt6>=6.4.0
|
4
|
-
PyQt6-WebEngine>=6.4.0
|
5
|
-
|
6
|
-
# Resim işleme
|
7
|
-
Pillow>=9.0.0
|
8
|
-
|
9
|
-
# Sistem izleme
|
10
|
-
psutil>=5.9.0
|
11
|
-
|
12
|
-
# HTTP istekleri (Clapp repo sistemi için)
|
13
|
-
requests>=2.28.0
|
14
|
-
|
15
|
-
# Seri port desteği (Terminal için)
|
16
|
-
pyserial>=3.5
|
17
|
-
|
18
|
-
# Flask (PyIDE şablonlarında kullanılıyor)
|
19
|
-
Flask>=2.2.0
|
20
|
-
|
21
|
-
# JSON Schema validation (opsiyonel)
|
22
|
-
jsonschema>=4.0.0
|
23
|
-
|
24
|
-
# Standart kütüphaneler (Python ile birlikte gelir):
|
25
|
-
# - zipfile (AppKit ve Clapp için)
|
26
|
-
# - urllib (Browser için)
|
27
|
-
# - json, os, sys, pathlib, typing, datetime, logging
|
28
|
-
# - threading, time, subprocess, shutil
|
29
|
-
# - hashlib, uuid, enum, dataclasses
|
30
|
-
# - functools, contextlib, collections
|
31
|
-
|
32
|
-
# Ek geliştirme araçları (opsiyonel)
|
33
|
-
# wheel>=0.37.0
|
34
|
-
# setuptools>=65.0.0
|
35
|
-
|
36
|
-
# Testing ve linting (geliştirme için)
|
37
|
-
# pytest>=7.0.0
|
38
|
-
# black>=22.0.0
|
39
|
-
# flake8>=5.0.0
|
40
|
-
|
41
|
-
# Dokümantasyon (geliştirme için)
|
42
|
-
# sphinx>=5.0.0
|
43
|
-
# sphinx-rtd-theme>=1.0.0
|