sys/veri_detay/#007

Sistem Asistanı (v1.1)

Son Senkronizasyon: 16.12.2025
ana_pencere.py 291 satır • 12.62 KB
# ana_pencere.py

import sys
import os
import subprocess
from PyQt6.QtWidgets import *
from PyQt6.QtCore import Qt, QSize
from PyQt6.QtGui import QIcon, QPixmap, QAction
from PyQt6.QtNetwork import QLocalServer, QLocalSocket

# --- MODÜLLER ---
from sayfalar.genel_bakis import GenelBakisSayfasi
from sayfalar.donanim import DonanimSayfasi
from sayfalar.surec_yonetimi import SurecYonetimiSayfasi
from sayfalar.ag_araclari import AgAraclariSayfasi
from sayfalar.yonetim import YonetimSayfasi
from sayfalar.bakim import BakimSayfasi
from sayfalar.hakkinda import HakkindaSayfasi
from sayfalar.hud_penceresi import HUDPenceresi
from sayfalar.disk_analizi import DiskAnaliziSayfasi
from sayfalar.usb_yazdir import UsbYazdirSayfasi
from sayfalar.acilis_analizi import AcilisAnaliziSayfasi
from sayfalar.sistem_gunlugu import SistemGunluguSayfasi
from sayfalar.disk_sagligi import DiskSagligiSayfasi
from sayfalar.ozel_komutlar import OzelKomutlarSayfasi
from sayfalar.port_yoneticisi import PortYoneticisiSayfasi
from sayfalar.site_engelleyici import SiteEngelleyiciSayfasi
from sayfalar.cron_yoneticisi import CronYoneticisiSayfasi
from sayfalar.ayarlar import AyarlarSayfasi
from sayfalar.temizlik import TemizlikSayfasi
from sayfalar.wifi_analiz import WifiAnalizSayfasi

from gorsel_araclar import BilgiIsleyicisi, SvgIkonOlusturucu, AyarlarYoneticisi
from stil_sayfasi import get_stil

class AnaPencere(QMainWindow):
    def __init__(self, socket_name="SistemAsistaniInstance"):
        super().__init__()
        self.setWindowTitle("Sistem Asistanı")
        
        # *** GÜNCELLENEN BOYUTLAR ***
        self.resize(1100, 780) # Varsayılan boyutu biraz küçülttük
        self.setMinimumSize(950, 680) # Minimum boyutu 700'e yakın bir değere indirdik.
        # ****************************
        
        self.ayarlar = AyarlarYoneticisi()
        
        # --- SÜRÜM SABİTLENDİ ---
        self.SURUM = "v1.1"

        # --- İKON YOLU (DÜZELTİLDİ) ---
        if getattr(sys, 'frozen', False):
            self.base_dir = os.path.dirname(sys.executable)
        else:
            self.base_dir = os.path.dirname(os.path.abspath(__file__))

        self.icons_dir = os.path.join(self.base_dir, "icons")
        self.icon_path_light = os.path.join(self.icons_dir, "sistem-asistani.png")      
        self.icon_path_dark = os.path.join(self.icons_dir, "sistem-asistani-dark.png") 

        # İkonu Yükle
        if os.path.exists(self.icon_path_light):
            self.app_icon = QIcon(self.icon_path_light)
        else:
            self.app_icon = QIcon("icons/sistem-asistani.png")

        self.setWindowIcon(self.app_icon)
        QApplication.setWindowIcon(self.app_icon)

        self.socket_name = socket_name
        self.server = QLocalServer()
        try:
            if sys.platform != "win32":
                if os.path.exists(f"/tmp/{self.socket_name}") or os.path.exists(self.socket_name): QLocalServer.removeServer(self.socket_name)
        except: pass
        self.server.listen(self.socket_name)
        self.server.newConnection.connect(self.yeni_baglanti_geldi)

        self.hud_window = None
        self.logo_label = QLabel() 
        self.arayuzu_kur()
        self.tray_kur() 
        self.backend_baslat()
        self.tema_uygula()
        self.ekran_ortala()

    def ekran_ortala(self):
        qr = self.frameGeometry()
        cp = self.screen().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def yeni_baglanti_geldi(self):
        socket = self.server.nextPendingConnection()
        socket.readyRead.connect(lambda: self.pencereyi_one_getir(socket))

    def pencereyi_one_getir(self, socket):
        """Çalışan uygulamaya tıklandığında pencereyi öne getirir."""
        # Socket'ten gelen SHOW komutunu oku (okunması gerekiyor)
        _ = socket.readAll() 
        
        # HUD modu açıksa kapat
        if self.hud_window and self.hud_window.isVisible(): 
            self.hud_window.close() 
            
        # Ana pencereyi normal boyutta göster (küçültülmüşse normalleştirir)
        self.showNormal() 
        
        # Pencereyi ekranın ortasına getir
        self.ekran_ortala() 
        
        # Pencereyi aktif hale getir (Odakla)
        self.activateWindow() 
        
        # Pencereyi diğerlerinin üstüne çıkar (Linux'ta bazen activateWindow yetmez)
        self.raise_() 

    def tema_uygula(self):
        self.ayarlar.ayarlar = self.ayarlar.yukle()
        secim = self.ayarlar.ayarlar.get("tema", "Otomatik")
        renk = self.ayarlar.ayarlar.get("renk", "#33AADD")
        tema = AyarlarYoneticisi.sistem_temasini_algila() if secim == "Otomatik" else secim
        
        self.setStyleSheet(get_stil(tema, renk))
        
        if tema == "Açık":
            target_icon = self.icon_path_dark if os.path.exists(self.icon_path_dark) else self.icon_path_light
        else:
            target_icon = self.icon_path_light
            
        if os.path.exists(target_icon):
            pixmap = QPixmap(target_icon).scaled(140, 140, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
            self.logo_label.setPixmap(pixmap)
        else:
             self.logo_label.setText("SİSTEM\nASİSTANI")
             self.logo_label.setStyleSheet(f"color: {renk}; font-weight: bold; font-size: 16pt;")

    def arayuzu_kur(self):
        ana_widget = QWidget()
        self.setCentralWidget(ana_widget)
        main_layout = QHBoxLayout(ana_widget)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)

        self.menu_scroll = QScrollArea()
        self.menu_scroll.setObjectName("YanMenuScroll")
        self.menu_scroll.setFixedWidth(280)
        self.menu_scroll.setWidgetResizable(True)
        self.menu_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.menu_scroll.setFrameShape(QFrame.Shape.NoFrame)

        self.menu_panel = QWidget()
        self.menu_panel.setObjectName("YanMenu")
        menu_layout = QVBoxLayout(self.menu_panel)
        menu_layout.setContentsMargins(10, 20, 10, 20)
        menu_layout.setSpacing(5)

        self.logo_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.logo_label.setStyleSheet("background:transparent; border:none; margin-bottom:10px;")
        menu_layout.addWidget(self.logo_label)
        
        t = QLabel("Araçlar & Modüller")
        t.setObjectName("UygulamaBaslik")
        t.setAlignment(Qt.AlignmentFlag.AlignCenter)
        t.setStyleSheet("font-size: 12pt; color: #AAAAAA; font-weight:bold; letter-spacing: 1px;")
        menu_layout.addWidget(t)
        menu_layout.addSpacing(10)

        self.stack = QStackedWidget()
        
        self.pages = [
            ("Genel Bakış", SvgIkonOlusturucu.dashboard_ikonu, GenelBakisSayfasi(parent=self)),
            ("Donanım & Güç", SvgIkonOlusturucu.hardware_ikonu, DonanimSayfasi()),
            ("Süreç Yönetimi", SvgIkonOlusturucu.process_ikonu, SurecYonetimiSayfasi()),
            ("Port Yöneticisi", SvgIkonOlusturucu.port_ikonu, PortYoneticisiSayfasi()), 
            ("Ağ & DNS", SvgIkonOlusturucu.network_ikonu, AgAraclariSayfasi()),
            ("Wi-Fi Analizörü", SvgIkonOlusturucu.network_ikonu, WifiAnalizSayfasi()), 
            ("Site Engelleyici", SvgIkonOlusturucu.block_ikonu, SiteEngelleyiciSayfasi()), 
            ("Zamanlanmış Görevler", SvgIkonOlusturucu.cron_ikonu, CronYoneticisiSayfasi()),
            ("Disk Analizi", SvgIkonOlusturucu.disk_analiz_ikonu, DiskAnaliziSayfasi()),
            ("Disk Sağlığı", SvgIkonOlusturucu.health_ikonu, DiskSagligiSayfasi()),
            ("Sistem Temizliği", SvgIkonOlusturucu.clean_ikonu, TemizlikSayfasi()),
            ("Açılış Analizi", SvgIkonOlusturucu.boot_ikonu, AcilisAnaliziSayfasi()),
            ("Sistem Günlüğü", SvgIkonOlusturucu.log_ikonu, SistemGunluguSayfasi()),
            ("Özel Komutlar", SvgIkonOlusturucu.script_ikonu, OzelKomutlarSayfasi()),
            ("USB Yazdırıcı", SvgIkonOlusturucu.usb_ikonu, UsbYazdirSayfasi()),
            ("Sistem Yönetimi", SvgIkonOlusturucu.anahtar_ikonu, YonetimSayfasi(parent=self)),
            ("Bakım & Onarım", SvgIkonOlusturucu.maintenance_ikonu, BakimSayfasi()),
            ("Ayarlar", SvgIkonOlusturucu.ayarlar_ikonu, AyarlarSayfasi(parent=self)),
            ("Hakkında", SvgIkonOlusturucu.info_ikonu, HakkindaSayfasi(self.SURUM, self.icon_path_light))
        ]

        self.menu_buttons = []

        for i, (ad, ikon_func, w) in enumerate(self.pages):
            b = QPushButton(ad)
            b.setObjectName("MenuDugmesi")
            b.setCheckable(True)
            b.setCursor(Qt.CursorShape.PointingHandCursor)
            b.setIcon(QIcon(ikon_func("#AAAAAA", 24)))
            b.setIconSize(QSize(22, 22))
            
            if i == 0: b.setChecked(True)
            b.clicked.connect(lambda checked, idx=i: self.sayfa_degistir(idx))
            menu_layout.addWidget(b)
            self.stack.addWidget(w)
            self.menu_buttons.append(b)

        menu_layout.addStretch()
        self.menu_scroll.setWidget(self.menu_panel)
        main_layout.addWidget(self.menu_scroll)
        main_layout.addWidget(self.stack)
    
    def hud_moduna_gec(self):
        self.hide()
        if not self.hud_window: self.hud_window = HUDPenceresi(self)
        self.hud_window.show()

    def backend_baslat(self):
        self.thread = BilgiIsleyicisi()
        self.thread.bilgi_guncelle_sinyal.connect(self.veri_dagitici)
        self.thread.bildirim_sinyali.connect(self.bildirim_goster)
        self.thread.disk_degisti_sinyali.connect(self.disk_degisimi_algilandi)
        self.thread.start()

    def disk_degisimi_algilandi(self):
        self.bildirim_goster("Donanım Algılandı", "Disk birimleri değişti, listeler güncelleniyor.")
        for _, _, widget in self.pages:
            if isinstance(widget, UsbYazdirSayfasi): widget.diskleri_getir()
            elif isinstance(widget, DiskSagligiSayfasi): widget.diskleri_bul()
            elif isinstance(widget, DonanimSayfasi): widget.donanim_tara()

    def bildirim_goster(self, baslik, mesaj):
        if hasattr(self, 'tray') and self.tray.isVisible(): self.tray.showMessage(baslik, mesaj, QSystemTrayIcon.MessageIcon.Information, 5000)

    def veri_dagitici(self, veri):
        if self.hud_window and self.hud_window.isVisible(): self.hud_window.guncelle(veri)
        elif self.isVisible():
            cw = self.stack.currentWidget()
            if hasattr(cw, 'guncelle'):
                try: cw.guncelle(veri)
                except: pass

    # --- TRAY (TEPSİ) KURULUMU DÜZELTİLDİ ---
    def tray_kur(self):
        if QSystemTrayIcon.isSystemTrayAvailable():
            self.tray = QSystemTrayIcon(self)
            
            # İkonu kesinleştir
            if not self.app_icon.isNull(): 
                self.tray.setIcon(self.app_icon)
            else:
                # Fallback: Eğer ikon dosyası yoksa sistem ikonunu kullan
                self.tray.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_ComputerIcon))
                
            menu = QMenu()
            show_act = QAction("Göster", self)
            show_act.triggered.connect(self.showNormal)
            quit_act = QAction("Çıkış", self)
            quit_act.triggered.connect(self.uygulamayi_kapat)
            
            menu.addAction(show_act)
            menu.addAction(quit_act)
            self.tray.setContextMenu(menu)
            self.tray.show()
            self.tray.setToolTip(f"Sistem Asistanı {self.SURUM}")
            self.tray.activated.connect(self.tray_tiklandi)
        else:
            print("Hata: Sistem tepsisi kullanılamıyor.")

    def tray_tiklandi(self, reason):
        if reason == QSystemTrayIcon.ActivationReason.Trigger: self.showNormal(); self.activateWindow()

    def closeEvent(self, event):
        if hasattr(self, 'tray') and self.tray.isVisible():
            self.hide()
            if not self.ayarlar.ayarlar.get("tray_bilgisi_verildi"):
                self.tray.showMessage("Sistem Asistanı", "Uygulama tepsiye küçültüldü.", QSystemTrayIcon.MessageIcon.Information, 2000)
                self.ayarlar.kaydet("tray_bilgisi_verildi", True)
            event.ignore()
        else: self.uygulamayi_kapat()

    def uygulamayi_kapat(self):
        if hasattr(self, 'thread') and self.thread.isRunning(): self.thread.requestInterruption(); self.thread.quit(); self.thread.wait(2000)
        self.server.close(); QLocalServer.removeServer(self.socket_name); QApplication.instance().quit()

    def sayfa_degistir(self, index):
        self.stack.setCurrentIndex(index)
        for i, btn in enumerate(self.menu_buttons):
            if i != index: btn.setChecked(False)
            else: btn.setChecked(True)
DATA_PAYLOAD (Açıklama)
Kapak

Sistem temizliği (detaylı ve kullanışlı ve tam kontrol sağlayacak şekilde güncellendi), Usb İso yazdırıcı (Artık kendi penceresinde ve detaylı şekilde dd modda usb'nize iso dosyalarınızı daha güvenle yazdırır) , Uygulama pencere boyutu (700 px altına dolayısı ile notebook vb küçük ekranlar içinde uyumlu olacak şekilde, özellikler güncellendi.

Pardus 25 (Debian 13) ve Pardus 23 (Debian 12) tabanlı Linux dağıtımları için geliştirilmiş; sistem izleme, bakım, onarım ve yönetim işlemlerini tek bir modern arayüzde toplayan gelişmiş bir araçtır.

Pardus 25 uyumlu sürümü indirmek için sağ taraftaki "indir" butonuna tıklayın ve çift tıklayıp kurun. Tüm bağımlılıkları 1 kere indirip internetsiz de çalışabilmektedir.

----

Özellikler

Uygulama modüler bir yapıya sahiptir ve aşağıdaki temel araçları içerir:

Sistem İzleme & Donanım

Genel Bakış: CPU, RAM, Swap kullanımı, anlık ağ trafiği ve harita üzerinde konum bilgisi. HUD Modu: Masaüstünde yüzen, kompakt sistem bilgi penceresi. Donanım Bilgisi: İşlemci, GPU, Batarya sağlığı, BIOS ve Çekirdek bilgileri. Süreç Yöneticisi: Çalışan işlemleri (PID, CPU, RAM) izleme ve sonlandırma.

Ağ & İnternet Ağ Tarayıcı: Wifi ağınızda kaç cihaz bağlı, ip adresleri, isim ve markaları gibi bilgileri görün. Wi-Fi Analizörü: Çevredeki ağları tarama, sinyal gücü grafiği ve kanal önerisi (2.4GHz optimizasyonu). Hız Testi: Çoklu iş parçacığı ile İndirme (Download), Yükleme (Upload) ve Gecikme (Ping) testi. DNS Yönetimi: Tek tıkla Google, Cloudflare, OpenDNS veya Otomatik DNS geçişi. Site Engelleyici: /etc/hosts üzerinden istenmeyen siteleri engelleme. Port Yöneticisi: Açık portları listeleme ve güvenlik duvarı (UFW) üzerinden port açma/kapama.

Bakım & Onarım

Sistem Temizliği: Apt önbelleği, eski kernel logları, tarayıcı çöp dosyaları ve çöp kutusu temizliği. Disk Sağlığı: Disk ömrü analizi ve sağlık raporu. Açılış Analizi: Sistemi yavaşlatan başlangıç servislerinin tespiti. Otomatik Bakım: Paket güncellemeleri, bozuk paket onarımı ve GRUB güncelleme araçları.

Disk & Dosya

Disk Analizcisi: Klasör boyutlarını ağaç yapısında görselleştirme. USB Yazdırıcı: ISO dosyalarını USB belleklere yazdırma (dd arayüzü).

Yönetim & Otomasyon

Cron Yöneticisi: Zamanlanmış görevleri grafik arayüzle ekleme/silme. Özel Komutlar: Sık kullandığınız uzun terminal komutlarını butonlara dönüştürme. Başlangıç Yöneticisi: Sistem açılışında çalışan uygulamaları yönetme.

Kurulum

Bu proje, sistem kütüphanelerindeki farklılıklar nedeniyle Pardus 25 ve Pardus 23 için ayrı paketleme yöntemleri sunar.

Yöntem 1: .deb Paketi ile Kurulum (En Kolay)

GitHub Releases sayfasından sisteminize uygun olan sürümü indirin ve kurun:

Pardus 25 / Debian 13 İçin: sistem-asistani_1.1_amd64.deb

Pardus 23 / Debian 12 İçin: sistem-asistani_1.0_pardus23_amd64.deb

sudo dpkg -i indirilen_paket_adi.deb
sudo apt-get install -f  # Eksik bağımlılık varsa tamamlar

Yöntem 2: Paketleme Sihirbazı ile Kurulum (Önerilen)

Bu yöntem, kaynak kodları indirir, gerekli Python kütüphanelerini internetten çeker ve sizin sisteminize özel, internetsiz çalışabilen bir .deb paketi üretir.

Yan taraftan "Kaynak Kod İndir" tıklayın :

ya da Kaynak Kod İndir Zip

Sisteminize Uygun Scripti Çalıştırın:

Pardus 25 (Debian 13) Kullanıyorsanız:

sudo sh ./paketle_pardus25.sh

Pardus 23 (Debian 12) Kullanıyorsanız:

sudo sh ./paketle_pardus23.sh

Oluşan Paketi Kurun: İşlem bittiğinde oluşan .deb paketini çift tıklayarak kurun ya da : (* yerine paketadiniz.deb)

sudo dpkg -i *.deb

Önemli Notlar

Root Yetkisi: Uygulama, sistem dosyalarına müdahale ettiği için (güncelleme, UFW, hosts vb.) kritik işlemlerde pkexec (veya Pardus 23’te policykit) aracılığıyla root şifrenizi isteyecektir.

Uyumluluk:

Pardus 25 / Debian 12 (Bookworm): Tam uyumlu.

Pardus 23 / Debian 11 (Bullseye): Tam uyumlu (Özel paketleme scripti ile).

Meta Veri (Özet)

Linux Sistem, Yönetim, Takip, Bakım, Kontrol aracı

1,364
Sinyal (Ağ Hiti)
288.29 KB
Kapasite

Ağda Paylaş