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
@@ -1,688 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
PyCloud OS Rain Widgets
|
3
|
-
Kullanıcının masaüstüne etkileşimli widget'lar eklemesini sağlayan sistem
|
4
|
-
"""
|
5
|
-
|
6
|
-
import os
|
7
|
-
import json
|
8
|
-
import logging
|
9
|
-
import threading
|
10
|
-
from pathlib import Path
|
11
|
-
from typing import Dict, List, Optional, Any, Callable
|
12
|
-
from datetime import datetime, timedelta
|
13
|
-
from dataclasses import dataclass, asdict
|
14
|
-
from enum import Enum
|
15
|
-
|
16
|
-
try:
|
17
|
-
from PyQt6.QtWidgets import (QWidget, QLabel, QVBoxLayout, QHBoxLayout,
|
18
|
-
QPushButton, QFrame, QScrollArea, QGridLayout,
|
19
|
-
QSlider, QSpinBox, QComboBox, QTextEdit, QProgressBar)
|
20
|
-
from PyQt6.QtCore import Qt, QTimer, QThread, pyqtSignal, QRect, QPoint, QSize
|
21
|
-
from PyQt6.QtGui import QFont, QPixmap, QPainter, QColor, QPalette
|
22
|
-
PYQT_AVAILABLE = True
|
23
|
-
except ImportError:
|
24
|
-
PYQT_AVAILABLE = False
|
25
|
-
|
26
|
-
class WidgetType(Enum):
|
27
|
-
"""Widget türleri"""
|
28
|
-
CLOCK = "clock"
|
29
|
-
CALENDAR = "calendar"
|
30
|
-
WEATHER = "weather"
|
31
|
-
SYSTEM_INFO = "system_info"
|
32
|
-
CPU_MONITOR = "cpu_monitor"
|
33
|
-
MEMORY_MONITOR = "memory_monitor"
|
34
|
-
NOTES = "notes"
|
35
|
-
CALCULATOR = "calculator"
|
36
|
-
RSS_READER = "rss_reader"
|
37
|
-
TODO_LIST = "todo_list"
|
38
|
-
|
39
|
-
class WidgetState(Enum):
|
40
|
-
"""Widget durumları"""
|
41
|
-
ACTIVE = "active"
|
42
|
-
MINIMIZED = "minimized"
|
43
|
-
HIDDEN = "hidden"
|
44
|
-
LOADING = "loading"
|
45
|
-
ERROR = "error"
|
46
|
-
|
47
|
-
@dataclass
|
48
|
-
class WidgetConfig:
|
49
|
-
"""Widget yapılandırması"""
|
50
|
-
widget_id: str
|
51
|
-
widget_type: WidgetType
|
52
|
-
title: str
|
53
|
-
position: tuple = (100, 100)
|
54
|
-
size: tuple = (200, 150)
|
55
|
-
state: WidgetState = WidgetState.ACTIVE
|
56
|
-
settings: Dict = None
|
57
|
-
refresh_interval: int = 30 # saniye
|
58
|
-
always_on_top: bool = False
|
59
|
-
transparency: float = 1.0
|
60
|
-
theme: str = "auto"
|
61
|
-
|
62
|
-
def __post_init__(self):
|
63
|
-
if self.settings is None:
|
64
|
-
self.settings = {}
|
65
|
-
|
66
|
-
def to_dict(self) -> Dict:
|
67
|
-
"""Dict'e çevir"""
|
68
|
-
data = asdict(self)
|
69
|
-
data['widget_type'] = self.widget_type.value
|
70
|
-
data['state'] = self.state.value
|
71
|
-
return data
|
72
|
-
|
73
|
-
@classmethod
|
74
|
-
def from_dict(cls, data: Dict) -> 'WidgetConfig':
|
75
|
-
"""Dict'ten oluştur"""
|
76
|
-
data['widget_type'] = WidgetType(data.get('widget_type', 'clock'))
|
77
|
-
data['state'] = WidgetState(data.get('state', 'active'))
|
78
|
-
return cls(**data)
|
79
|
-
|
80
|
-
class BaseWidget(QWidget if PYQT_AVAILABLE else object):
|
81
|
-
"""Temel widget sınıfı"""
|
82
|
-
|
83
|
-
def __init__(self, config: WidgetConfig, widget_manager=None):
|
84
|
-
if PYQT_AVAILABLE:
|
85
|
-
super().__init__()
|
86
|
-
|
87
|
-
self.config = config
|
88
|
-
self.widget_manager = widget_manager
|
89
|
-
self.logger = logging.getLogger(f"Widget-{config.widget_id}")
|
90
|
-
|
91
|
-
# Widget durumu
|
92
|
-
self.is_running = False
|
93
|
-
self.last_update = None
|
94
|
-
self.update_timer = None
|
95
|
-
self.data_sources = {}
|
96
|
-
|
97
|
-
# UI bileşenleri
|
98
|
-
if PYQT_AVAILABLE:
|
99
|
-
self.init_ui()
|
100
|
-
self.setup_timer()
|
101
|
-
|
102
|
-
def init_ui(self):
|
103
|
-
"""UI'yı başlat"""
|
104
|
-
self.setWindowTitle(self.config.title)
|
105
|
-
self.setGeometry(*self.config.position, *self.config.size)
|
106
|
-
|
107
|
-
# Ana layout
|
108
|
-
self.layout = QVBoxLayout()
|
109
|
-
self.setLayout(self.layout)
|
110
|
-
|
111
|
-
# Başlık çubuğu
|
112
|
-
self.title_bar = self.create_title_bar()
|
113
|
-
self.layout.addWidget(self.title_bar)
|
114
|
-
|
115
|
-
# İçerik alanı
|
116
|
-
self.content_widget = QWidget()
|
117
|
-
self.content_layout = QVBoxLayout()
|
118
|
-
self.content_widget.setLayout(self.content_layout)
|
119
|
-
self.layout.addWidget(self.content_widget)
|
120
|
-
|
121
|
-
# Widget-specific UI
|
122
|
-
self.setup_content()
|
123
|
-
|
124
|
-
# Stil uygula
|
125
|
-
self.apply_theme()
|
126
|
-
|
127
|
-
def create_title_bar(self) -> QWidget:
|
128
|
-
"""Başlık çubuğu oluştur"""
|
129
|
-
title_bar = QFrame()
|
130
|
-
title_bar.setFixedHeight(30)
|
131
|
-
title_bar.setStyleSheet("background-color: #2b2b2b; border-radius: 5px;")
|
132
|
-
|
133
|
-
layout = QHBoxLayout()
|
134
|
-
layout.setContentsMargins(5, 0, 5, 0)
|
135
|
-
|
136
|
-
# Başlık
|
137
|
-
title_label = QLabel(self.config.title)
|
138
|
-
title_label.setStyleSheet("color: white; font-weight: bold;")
|
139
|
-
layout.addWidget(title_label)
|
140
|
-
|
141
|
-
layout.addStretch()
|
142
|
-
|
143
|
-
# Ayarlar butonu
|
144
|
-
settings_btn = QPushButton("⚙")
|
145
|
-
settings_btn.setFixedSize(20, 20)
|
146
|
-
settings_btn.setStyleSheet("background-color: #404040; border: none; color: white;")
|
147
|
-
settings_btn.clicked.connect(self.show_settings)
|
148
|
-
layout.addWidget(settings_btn)
|
149
|
-
|
150
|
-
# Kapat butonu
|
151
|
-
close_btn = QPushButton("✕")
|
152
|
-
close_btn.setFixedSize(20, 20)
|
153
|
-
close_btn.setStyleSheet("background-color: #ff5555; border: none; color: white;")
|
154
|
-
close_btn.clicked.connect(self.close_widget)
|
155
|
-
layout.addWidget(close_btn)
|
156
|
-
|
157
|
-
title_bar.setLayout(layout)
|
158
|
-
return title_bar
|
159
|
-
|
160
|
-
def setup_content(self):
|
161
|
-
"""Widget içeriğini ayarla (alt sınıflarda override edilir)"""
|
162
|
-
label = QLabel("Temel Widget")
|
163
|
-
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
164
|
-
self.content_layout.addWidget(label)
|
165
|
-
|
166
|
-
def setup_timer(self):
|
167
|
-
"""Güncelleme timer'ını ayarla"""
|
168
|
-
if self.config.refresh_interval > 0:
|
169
|
-
self.update_timer = QTimer()
|
170
|
-
self.update_timer.timeout.connect(self.update_data)
|
171
|
-
self.update_timer.start(self.config.refresh_interval * 1000)
|
172
|
-
|
173
|
-
def apply_theme(self):
|
174
|
-
"""Tema uygula"""
|
175
|
-
# Temel stil
|
176
|
-
style = """
|
177
|
-
QWidget {
|
178
|
-
background-color: #3c3c3c;
|
179
|
-
color: white;
|
180
|
-
border: 1px solid #555;
|
181
|
-
border-radius: 8px;
|
182
|
-
}
|
183
|
-
QLabel {
|
184
|
-
border: none;
|
185
|
-
padding: 2px;
|
186
|
-
}
|
187
|
-
"""
|
188
|
-
|
189
|
-
if self.config.transparency < 1.0:
|
190
|
-
self.setWindowOpacity(self.config.transparency)
|
191
|
-
|
192
|
-
self.setStyleSheet(style)
|
193
|
-
|
194
|
-
def update_data(self):
|
195
|
-
"""Veriyi güncelle"""
|
196
|
-
try:
|
197
|
-
self.last_update = datetime.now()
|
198
|
-
# Alt sınıflarda implement edilir
|
199
|
-
self.on_data_update()
|
200
|
-
except Exception as e:
|
201
|
-
self.logger.error(f"Data update error: {e}")
|
202
|
-
|
203
|
-
def on_data_update(self):
|
204
|
-
"""Veri güncellemesi (alt sınıflarda override edilir)"""
|
205
|
-
pass
|
206
|
-
|
207
|
-
def show_settings(self):
|
208
|
-
"""Ayarları göster"""
|
209
|
-
if self.widget_manager:
|
210
|
-
self.widget_manager.show_widget_settings(self.config.widget_id)
|
211
|
-
|
212
|
-
def close_widget(self):
|
213
|
-
"""Widget'ı kapat"""
|
214
|
-
if self.widget_manager:
|
215
|
-
self.widget_manager.remove_widget(self.config.widget_id)
|
216
|
-
self.close()
|
217
|
-
|
218
|
-
def get_settings_schema(self) -> Dict:
|
219
|
-
"""Ayar şemasını döndür"""
|
220
|
-
return {
|
221
|
-
"refresh_interval": {
|
222
|
-
"type": "int",
|
223
|
-
"label": "Yenileme Aralığı (saniye)",
|
224
|
-
"default": 30,
|
225
|
-
"min": 5,
|
226
|
-
"max": 3600
|
227
|
-
},
|
228
|
-
"transparency": {
|
229
|
-
"type": "float",
|
230
|
-
"label": "Şeffaflık",
|
231
|
-
"default": 1.0,
|
232
|
-
"min": 0.1,
|
233
|
-
"max": 1.0
|
234
|
-
}
|
235
|
-
}
|
236
|
-
|
237
|
-
def apply_settings(self, settings: Dict):
|
238
|
-
"""Ayarları uygula"""
|
239
|
-
if "refresh_interval" in settings:
|
240
|
-
self.config.refresh_interval = settings["refresh_interval"]
|
241
|
-
if self.update_timer:
|
242
|
-
self.update_timer.setInterval(self.config.refresh_interval * 1000)
|
243
|
-
|
244
|
-
if "transparency" in settings:
|
245
|
-
self.config.transparency = settings["transparency"]
|
246
|
-
self.setWindowOpacity(self.config.transparency)
|
247
|
-
|
248
|
-
class ClockWidget(BaseWidget):
|
249
|
-
"""Saat widget'ı"""
|
250
|
-
|
251
|
-
def setup_content(self):
|
252
|
-
"""Saat içeriğini ayarla"""
|
253
|
-
self.time_label = QLabel()
|
254
|
-
self.time_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
255
|
-
self.time_label.setFont(QFont("Arial", 16, QFont.Weight.Bold))
|
256
|
-
self.content_layout.addWidget(self.time_label)
|
257
|
-
|
258
|
-
self.date_label = QLabel()
|
259
|
-
self.date_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
260
|
-
self.date_label.setFont(QFont("Arial", 10))
|
261
|
-
self.content_layout.addWidget(self.date_label)
|
262
|
-
|
263
|
-
def on_data_update(self):
|
264
|
-
"""Saat verilerini güncelle"""
|
265
|
-
now = datetime.now()
|
266
|
-
|
267
|
-
# Locale manager'dan format al
|
268
|
-
if self.widget_manager and self.widget_manager.kernel:
|
269
|
-
locale_manager = self.widget_manager.kernel.get_module("locale")
|
270
|
-
if locale_manager:
|
271
|
-
time_str = locale_manager.format_time(now)
|
272
|
-
date_str = locale_manager.format_date(now)
|
273
|
-
else:
|
274
|
-
time_str = now.strftime("%H:%M")
|
275
|
-
date_str = now.strftime("%d.%m.%Y")
|
276
|
-
else:
|
277
|
-
time_str = now.strftime("%H:%M")
|
278
|
-
date_str = now.strftime("%d.%m.%Y")
|
279
|
-
|
280
|
-
self.time_label.setText(time_str)
|
281
|
-
self.date_label.setText(date_str)
|
282
|
-
|
283
|
-
class SystemInfoWidget(BaseWidget):
|
284
|
-
"""Sistem bilgisi widget'ı"""
|
285
|
-
|
286
|
-
def setup_content(self):
|
287
|
-
"""Sistem bilgisi içeriğini ayarla"""
|
288
|
-
self.cpu_label = QLabel("CPU: -")
|
289
|
-
self.memory_label = QLabel("RAM: -")
|
290
|
-
self.uptime_label = QLabel("Uptime: -")
|
291
|
-
|
292
|
-
for label in [self.cpu_label, self.memory_label, self.uptime_label]:
|
293
|
-
label.setFont(QFont("Arial", 9))
|
294
|
-
self.content_layout.addWidget(label)
|
295
|
-
|
296
|
-
def on_data_update(self):
|
297
|
-
"""Sistem bilgilerini güncelle"""
|
298
|
-
try:
|
299
|
-
if self.widget_manager and self.widget_manager.kernel:
|
300
|
-
# CPU bilgisi
|
301
|
-
process_manager = self.widget_manager.kernel.get_module("process")
|
302
|
-
if process_manager:
|
303
|
-
cpu_percent = process_manager.get_system_cpu_usage()
|
304
|
-
self.cpu_label.setText(f"CPU: {cpu_percent:.1f}%")
|
305
|
-
|
306
|
-
# Bellek bilgisi
|
307
|
-
memory_manager = self.widget_manager.kernel.get_module("memory")
|
308
|
-
if memory_manager:
|
309
|
-
memory_info = memory_manager.get_memory_info()
|
310
|
-
used_mb = memory_info.get("used_mb", 0)
|
311
|
-
total_mb = memory_info.get("total_mb", 0)
|
312
|
-
percent = (used_mb / total_mb * 100) if total_mb > 0 else 0
|
313
|
-
self.memory_label.setText(f"RAM: {percent:.1f}% ({used_mb:.0f}MB)")
|
314
|
-
|
315
|
-
# Uptime
|
316
|
-
uptime = self.widget_manager.kernel.get_uptime()
|
317
|
-
hours = int(uptime // 3600)
|
318
|
-
minutes = int((uptime % 3600) // 60)
|
319
|
-
self.uptime_label.setText(f"Uptime: {hours:02d}:{minutes:02d}")
|
320
|
-
|
321
|
-
except Exception as e:
|
322
|
-
self.logger.error(f"System info update error: {e}")
|
323
|
-
|
324
|
-
class NotesWidget(BaseWidget):
|
325
|
-
"""Not widget'ı"""
|
326
|
-
|
327
|
-
def setup_content(self):
|
328
|
-
"""Not içeriğini ayarla"""
|
329
|
-
self.notes_edit = QTextEdit()
|
330
|
-
self.notes_edit.setPlaceholderText("Notlarınızı buraya yazın...")
|
331
|
-
self.notes_edit.textChanged.connect(self.save_notes)
|
332
|
-
self.content_layout.addWidget(self.notes_edit)
|
333
|
-
|
334
|
-
# Kayıtlı notları yükle
|
335
|
-
self.load_notes()
|
336
|
-
|
337
|
-
def load_notes(self):
|
338
|
-
"""Notları yükle"""
|
339
|
-
notes_file = Path(f"users/widgets/{self.config.widget_id}.txt")
|
340
|
-
if notes_file.exists():
|
341
|
-
try:
|
342
|
-
with open(notes_file, 'r', encoding='utf-8') as f:
|
343
|
-
content = f.read()
|
344
|
-
self.notes_edit.setPlainText(content)
|
345
|
-
except Exception as e:
|
346
|
-
self.logger.error(f"Failed to load notes: {e}")
|
347
|
-
|
348
|
-
def save_notes(self):
|
349
|
-
"""Notları kaydet"""
|
350
|
-
notes_file = Path(f"users/widgets/{self.config.widget_id}.txt")
|
351
|
-
notes_file.parent.mkdir(parents=True, exist_ok=True)
|
352
|
-
|
353
|
-
try:
|
354
|
-
with open(notes_file, 'w', encoding='utf-8') as f:
|
355
|
-
f.write(self.notes_edit.toPlainText())
|
356
|
-
except Exception as e:
|
357
|
-
self.logger.error(f"Failed to save notes: {e}")
|
358
|
-
|
359
|
-
class WeatherWidget(BaseWidget):
|
360
|
-
"""Hava durumu widget'ı"""
|
361
|
-
|
362
|
-
def setup_content(self):
|
363
|
-
"""Hava durumu içeriğini ayarla"""
|
364
|
-
self.location_label = QLabel("📍 Konum belirsiz")
|
365
|
-
self.temp_label = QLabel("🌡️ --°C")
|
366
|
-
self.condition_label = QLabel("☁️ Bekleniyor...")
|
367
|
-
|
368
|
-
for label in [self.location_label, self.temp_label, self.condition_label]:
|
369
|
-
label.setFont(QFont("Arial", 9))
|
370
|
-
self.content_layout.addWidget(label)
|
371
|
-
|
372
|
-
def on_data_update(self):
|
373
|
-
"""Hava durumu verilerini güncelle (demo)"""
|
374
|
-
# Demo veri (gerçek API entegrasyonu yapılabilir)
|
375
|
-
import random
|
376
|
-
temp = random.randint(15, 35)
|
377
|
-
conditions = ["☀️ Güneşli", "☁️ Bulutlu", "🌧️ Yağmurlu", "❄️ Karlı"]
|
378
|
-
condition = random.choice(conditions)
|
379
|
-
|
380
|
-
self.location_label.setText("📍 İstanbul")
|
381
|
-
self.temp_label.setText(f"🌡️ {temp}°C")
|
382
|
-
self.condition_label.setText(condition)
|
383
|
-
|
384
|
-
class WidgetFactory:
|
385
|
-
"""Widget fabrikası"""
|
386
|
-
|
387
|
-
@staticmethod
|
388
|
-
def create_widget(config: WidgetConfig, widget_manager=None) -> Optional[BaseWidget]:
|
389
|
-
"""Widget oluştur"""
|
390
|
-
if not PYQT_AVAILABLE:
|
391
|
-
return None
|
392
|
-
|
393
|
-
widget_classes = {
|
394
|
-
WidgetType.CLOCK: ClockWidget,
|
395
|
-
WidgetType.SYSTEM_INFO: SystemInfoWidget,
|
396
|
-
WidgetType.NOTES: NotesWidget,
|
397
|
-
WidgetType.WEATHER: WeatherWidget,
|
398
|
-
}
|
399
|
-
|
400
|
-
widget_class = widget_classes.get(config.widget_type)
|
401
|
-
if widget_class:
|
402
|
-
return widget_class(config, widget_manager)
|
403
|
-
|
404
|
-
return None
|
405
|
-
|
406
|
-
class WidgetManager:
|
407
|
-
"""Widget yöneticisi"""
|
408
|
-
|
409
|
-
def __init__(self, kernel=None):
|
410
|
-
self.kernel = kernel
|
411
|
-
self.logger = logging.getLogger("WidgetManager")
|
412
|
-
|
413
|
-
# Widget verileri
|
414
|
-
self.widgets: Dict[str, BaseWidget] = {}
|
415
|
-
self.widget_configs: Dict[str, WidgetConfig] = {}
|
416
|
-
|
417
|
-
# Dosya yolları
|
418
|
-
self.widgets_dir = Path("users/widgets")
|
419
|
-
self.widgets_dir.mkdir(parents=True, exist_ok=True)
|
420
|
-
self.config_file = self.widgets_dir / "widgets.json"
|
421
|
-
|
422
|
-
# Widget ayarları
|
423
|
-
self.max_widgets = 20
|
424
|
-
self.default_refresh_interval = 30
|
425
|
-
|
426
|
-
# Başlangıç
|
427
|
-
self.load_widget_configs()
|
428
|
-
self.restore_widgets()
|
429
|
-
|
430
|
-
def create_widget(self, widget_type: WidgetType, title: str = None,
|
431
|
-
position: tuple = None, **kwargs) -> Optional[str]:
|
432
|
-
"""Yeni widget oluştur"""
|
433
|
-
try:
|
434
|
-
if len(self.widgets) >= self.max_widgets:
|
435
|
-
self.logger.warning("Maximum widget limit reached")
|
436
|
-
return None
|
437
|
-
|
438
|
-
# Widget ID oluştur
|
439
|
-
import uuid
|
440
|
-
widget_id = str(uuid.uuid4())[:8]
|
441
|
-
|
442
|
-
# Varsayılan değerler
|
443
|
-
if title is None:
|
444
|
-
title = widget_type.value.replace("_", " ").title()
|
445
|
-
|
446
|
-
if position is None:
|
447
|
-
position = (100 + len(self.widgets) * 50, 100 + len(self.widgets) * 50)
|
448
|
-
|
449
|
-
# Konfigürasyon oluştur
|
450
|
-
config = WidgetConfig(
|
451
|
-
widget_id=widget_id,
|
452
|
-
widget_type=widget_type,
|
453
|
-
title=title,
|
454
|
-
position=position,
|
455
|
-
**kwargs
|
456
|
-
)
|
457
|
-
|
458
|
-
# Widget oluştur
|
459
|
-
widget = WidgetFactory.create_widget(config, self)
|
460
|
-
if not widget:
|
461
|
-
self.logger.error(f"Failed to create widget: {widget_type}")
|
462
|
-
return None
|
463
|
-
|
464
|
-
# Kaydet
|
465
|
-
self.widgets[widget_id] = widget
|
466
|
-
self.widget_configs[widget_id] = config
|
467
|
-
self.save_widget_configs()
|
468
|
-
|
469
|
-
# Göster
|
470
|
-
widget.show()
|
471
|
-
widget.update_data()
|
472
|
-
|
473
|
-
self.logger.info(f"Widget created: {widget_id} ({widget_type.value})")
|
474
|
-
return widget_id
|
475
|
-
|
476
|
-
except Exception as e:
|
477
|
-
self.logger.error(f"Failed to create widget: {e}")
|
478
|
-
return None
|
479
|
-
|
480
|
-
def remove_widget(self, widget_id: str) -> bool:
|
481
|
-
"""Widget'ı kaldır"""
|
482
|
-
try:
|
483
|
-
if widget_id not in self.widgets:
|
484
|
-
return False
|
485
|
-
|
486
|
-
# Widget'ı kapat
|
487
|
-
widget = self.widgets[widget_id]
|
488
|
-
if hasattr(widget, 'update_timer') and widget.update_timer:
|
489
|
-
widget.update_timer.stop()
|
490
|
-
|
491
|
-
widget.close()
|
492
|
-
|
493
|
-
# Veriyi temizle
|
494
|
-
del self.widgets[widget_id]
|
495
|
-
del self.widget_configs[widget_id]
|
496
|
-
|
497
|
-
# Widget dosyasını sil
|
498
|
-
widget_file = self.widgets_dir / f"{widget_id}.txt"
|
499
|
-
if widget_file.exists():
|
500
|
-
widget_file.unlink()
|
501
|
-
|
502
|
-
self.save_widget_configs()
|
503
|
-
|
504
|
-
self.logger.info(f"Widget removed: {widget_id}")
|
505
|
-
return True
|
506
|
-
|
507
|
-
except Exception as e:
|
508
|
-
self.logger.error(f"Failed to remove widget {widget_id}: {e}")
|
509
|
-
return False
|
510
|
-
|
511
|
-
def get_widget(self, widget_id: str) -> Optional[BaseWidget]:
|
512
|
-
"""Widget'ı al"""
|
513
|
-
return self.widgets.get(widget_id)
|
514
|
-
|
515
|
-
def list_widgets(self) -> List[Dict]:
|
516
|
-
"""Widget listesi"""
|
517
|
-
return [config.to_dict() for config in self.widget_configs.values()]
|
518
|
-
|
519
|
-
def update_widget_config(self, widget_id: str, **kwargs) -> bool:
|
520
|
-
"""Widget konfigürasyonunu güncelle"""
|
521
|
-
try:
|
522
|
-
if widget_id not in self.widget_configs:
|
523
|
-
return False
|
524
|
-
|
525
|
-
config = self.widget_configs[widget_id]
|
526
|
-
|
527
|
-
# Güncelle
|
528
|
-
for key, value in kwargs.items():
|
529
|
-
if hasattr(config, key):
|
530
|
-
setattr(config, key, value)
|
531
|
-
|
532
|
-
# Widget'a uygula
|
533
|
-
if widget_id in self.widgets:
|
534
|
-
widget = self.widgets[widget_id]
|
535
|
-
if hasattr(widget, 'apply_settings'):
|
536
|
-
widget.apply_settings(kwargs)
|
537
|
-
|
538
|
-
self.save_widget_configs()
|
539
|
-
return True
|
540
|
-
|
541
|
-
except Exception as e:
|
542
|
-
self.logger.error(f"Failed to update widget config {widget_id}: {e}")
|
543
|
-
return False
|
544
|
-
|
545
|
-
def show_widget_settings(self, widget_id: str):
|
546
|
-
"""Widget ayarlarını göster"""
|
547
|
-
# Bu bir dialog açacak (widget ayar penceresi)
|
548
|
-
self.logger.info(f"Opening settings for widget: {widget_id}")
|
549
|
-
# TODO: Ayar dialogu implementasyonu
|
550
|
-
|
551
|
-
def save_widget_configs(self):
|
552
|
-
"""Widget konfigürasyonlarını kaydet"""
|
553
|
-
try:
|
554
|
-
configs_data = {
|
555
|
-
widget_id: config.to_dict()
|
556
|
-
for widget_id, config in self.widget_configs.items()
|
557
|
-
}
|
558
|
-
|
559
|
-
with open(self.config_file, 'w', encoding='utf-8') as f:
|
560
|
-
json.dump(configs_data, f, indent=2, ensure_ascii=False)
|
561
|
-
|
562
|
-
except Exception as e:
|
563
|
-
self.logger.error(f"Failed to save widget configs: {e}")
|
564
|
-
|
565
|
-
def load_widget_configs(self):
|
566
|
-
"""Widget konfigürasyonlarını yükle"""
|
567
|
-
try:
|
568
|
-
if not self.config_file.exists():
|
569
|
-
return
|
570
|
-
|
571
|
-
with open(self.config_file, 'r', encoding='utf-8') as f:
|
572
|
-
configs_data = json.load(f)
|
573
|
-
|
574
|
-
for widget_id, config_data in configs_data.items():
|
575
|
-
try:
|
576
|
-
config = WidgetConfig.from_dict(config_data)
|
577
|
-
self.widget_configs[widget_id] = config
|
578
|
-
except Exception as e:
|
579
|
-
self.logger.error(f"Failed to load widget config {widget_id}: {e}")
|
580
|
-
|
581
|
-
self.logger.info(f"Loaded {len(self.widget_configs)} widget configurations")
|
582
|
-
|
583
|
-
except Exception as e:
|
584
|
-
self.logger.error(f"Failed to load widget configs: {e}")
|
585
|
-
|
586
|
-
def restore_widgets(self):
|
587
|
-
"""Widget'ları geri yükle"""
|
588
|
-
try:
|
589
|
-
for widget_id, config in self.widget_configs.items():
|
590
|
-
if config.state == WidgetState.ACTIVE:
|
591
|
-
widget = WidgetFactory.create_widget(config, self)
|
592
|
-
if widget:
|
593
|
-
self.widgets[widget_id] = widget
|
594
|
-
widget.show()
|
595
|
-
widget.update_data()
|
596
|
-
|
597
|
-
self.logger.info(f"Restored {len(self.widgets)} widgets")
|
598
|
-
|
599
|
-
except Exception as e:
|
600
|
-
self.logger.error(f"Failed to restore widgets: {e}")
|
601
|
-
|
602
|
-
def get_available_widget_types(self) -> List[Dict]:
|
603
|
-
"""Mevcut widget türleri"""
|
604
|
-
return [
|
605
|
-
{
|
606
|
-
"type": WidgetType.CLOCK.value,
|
607
|
-
"name": "Saat",
|
608
|
-
"description": "Dijital saat ve tarih göstergesi",
|
609
|
-
"icon": "🕐"
|
610
|
-
},
|
611
|
-
{
|
612
|
-
"type": WidgetType.SYSTEM_INFO.value,
|
613
|
-
"name": "Sistem Bilgisi",
|
614
|
-
"description": "CPU, RAM ve uptime izleme",
|
615
|
-
"icon": "💻"
|
616
|
-
},
|
617
|
-
{
|
618
|
-
"type": WidgetType.WEATHER.value,
|
619
|
-
"name": "Hava Durumu",
|
620
|
-
"description": "Anlık hava durumu bilgisi",
|
621
|
-
"icon": "🌤️"
|
622
|
-
},
|
623
|
-
{
|
624
|
-
"type": WidgetType.NOTES.value,
|
625
|
-
"name": "Notlar",
|
626
|
-
"description": "Hızlı not alma aracı",
|
627
|
-
"icon": "📝"
|
628
|
-
}
|
629
|
-
]
|
630
|
-
|
631
|
-
def hide_all_widgets(self):
|
632
|
-
"""Tüm widget'ları gizle"""
|
633
|
-
for widget in self.widgets.values():
|
634
|
-
widget.hide()
|
635
|
-
|
636
|
-
def show_all_widgets(self):
|
637
|
-
"""Tüm widget'ları göster"""
|
638
|
-
for widget in self.widgets.values():
|
639
|
-
widget.show()
|
640
|
-
|
641
|
-
def refresh_all_widgets(self):
|
642
|
-
"""Tüm widget'ları yenile"""
|
643
|
-
for widget in self.widgets.values():
|
644
|
-
widget.update_data()
|
645
|
-
|
646
|
-
def shutdown(self):
|
647
|
-
"""Widget manager'ı kapat"""
|
648
|
-
try:
|
649
|
-
# Tüm widget'ları kapat
|
650
|
-
for widget_id in list(self.widgets.keys()):
|
651
|
-
self.remove_widget(widget_id)
|
652
|
-
|
653
|
-
# Konfigürasyonları kaydet
|
654
|
-
self.save_widget_configs()
|
655
|
-
|
656
|
-
self.logger.info("Widget manager shutdown completed")
|
657
|
-
|
658
|
-
except Exception as e:
|
659
|
-
self.logger.error(f"Widget manager shutdown failed: {e}")
|
660
|
-
|
661
|
-
# Kolaylık fonksiyonları
|
662
|
-
_widget_manager = None
|
663
|
-
|
664
|
-
def init_widget_manager(kernel=None) -> WidgetManager:
|
665
|
-
"""Widget manager'ı başlat"""
|
666
|
-
global _widget_manager
|
667
|
-
_widget_manager = WidgetManager(kernel)
|
668
|
-
return _widget_manager
|
669
|
-
|
670
|
-
def get_widget_manager() -> Optional[WidgetManager]:
|
671
|
-
"""Widget manager'ı al"""
|
672
|
-
return _widget_manager
|
673
|
-
|
674
|
-
def create_widget(widget_type: str, **kwargs) -> Optional[str]:
|
675
|
-
"""Widget oluştur (kısayol)"""
|
676
|
-
if _widget_manager:
|
677
|
-
try:
|
678
|
-
widget_type_enum = WidgetType(widget_type)
|
679
|
-
return _widget_manager.create_widget(widget_type_enum, **kwargs)
|
680
|
-
except ValueError:
|
681
|
-
return None
|
682
|
-
return None
|
683
|
-
|
684
|
-
def remove_widget(widget_id: str) -> bool:
|
685
|
-
"""Widget kaldır (kısayol)"""
|
686
|
-
if _widget_manager:
|
687
|
-
return _widget_manager.remove_widget(widget_id)
|
688
|
-
return False
|