clapp-pm 1.0.42__py3-none-any.whl → 1.0.43__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.
@@ -0,0 +1,605 @@
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
@@ -0,0 +1,43 @@
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
@@ -0,0 +1,43 @@
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