Pardus Gnome 23.4 -- 25 Namaz Vakti Uzantısı

Öncelikle yapması zor gibi fakat izah etmeye çalışacağım elimden geldiğince . Bu uygulama kendi ihtiyacım üzerine geliştirdim Yapay Zeka yardımı ile . Uygulama olarak çokça var fakat göre yöneticisinde hep gözümün önünde hep olmasını istemişimdir . Fikir verirken fikir sahibi oldum . Adımı attım .Yelkenleri açtım . Hamdolsun Allâh’a yelkeni rüzgarla doldurdu sonuç %100 istediğim gibi oldu . Uygulamayı önce Pardus 25 Gnome için yazdım . Sonra 23.4 için yazdım .

Pardus Gnome 25 (Gnome 48.4)

Başlangıç (home) klasörüne girip Gizli Dosyaları Göster diyiniz

Aynı sayfadan Devam .local/share/gnome-shell/extensions içine girelim (extensions dosyası yoksa Gnome-Shell klasörü içine extensions isiminde bir klasör açalım)
extensions klasörünün içine vakit@ahmet.NikBulamadim adında klasör oluşturalım .
vakit@ahmet.NikBulamadim Klasörünün içine 2 tane Metin Belgesi ekleyin .
Bir tanesinin adı extension.js olsun ötekinin adıda metadata.json olsun .
extension.js dosyasının içine Kopyala yapıştır yapın

import St from 'gi://St';
import GLib from 'gi://GLib';
import Clutter from 'gi://Clutter'; // Yeni kütüphane: Mesajı ekrana ortalamak için gerekli
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';

/**
 * AYARLAR
 */
const BILDIRIM_ACIK = true; // Bildirimi kapatmak için false   Bildirimi açmak için true yazım 

/**
 * NAZİLLİ 2026 TÜM YIL NAMAZ VAKİTLERİ
 */
const VAKITLER = {
    // --- OCAK 2026 ---
    "2026-01-13": { "İmsak": "06:49", "Güneş": "08:15", "Öğle": "13:20", "İkindi": "15:54", "Akşam": "18:16", "Yatsı": "19:36" },
    "2026-01-14": { "İmsak": "06:49", "Güneş": "08:15", "Öğle": "13:21", "İkindi": "15:55", "Akşam": "18:17", "Yatsı": "19:37" },
    "2026-01-15": { "İmsak": "06:49", "Güneş": "08:14", "Öğle": "13:21", "İkindi": "15:56", "Akşam": "18:18", "Yatsı": "19:38" },
    "2026-01-16": { "İmsak": "06:49", "Güneş": "08:14", "Öğle": "13:21", "İkindi": "15:57", "Akşam": "18:19", "Yatsı": "19:39" },
    "2026-01-17": { "İmsak": "06:48", "Güneş": "08:14", "Öğle": "13:22", "İkindi": "15:57", "Akşam": "18:20", "Yatsı": "19:40" },
    "2026-01-18": { "İmsak": "06:48", "Güneş": "08:13", "Öğle": "13:22", "İkindi": "15:58", "Akşam": "18:21", "Yatsı": "19:41" },
    "2026-01-19": { "İmsak": "06:48", "Güneş": "08:13", "Öğle": "13:22", "İkindi": "15:59", "Akşam": "18:22", "Yatsı": "19:42" },
    "2026-01-20": { "İmsak": "06:47", "Güneş": "08:12", "Öğle": "13:23", "İkindi": "16:00", "Akşam": "18:23", "Yatsı": "19:43" },
    "2026-01-21": { "İmsak": "06:47", "Güneş": "08:12", "Öğle": "13:23", "İkindi": "16:01", "Akşam": "18:24", "Yatsı": "19:44" },
    "2026-01-22": { "İmsak": "06:47", "Güneş": "08:11", "Öğle": "13:23", "İkindi": "16:02", "Akşam": "18:25", "Yatsı": "19:44" },
    "2026-01-23": { "İmsak": "06:46", "Güneş": "08:11", "Öğle": "13:23", "İkindi": "16:03", "Akşam": "18:26", "Yatsı": "19:45" },
    "2026-01-24": { "İmsak": "06:46", "Güneş": "08:10", "Öğle": "13:24", "İkindi": "16:04", "Akşam": "18:27", "Yatsı": "19:46" },
    "2026-01-25": { "İmsak": "06:45", "Güneş": "08:10", "Öğle": "13:24", "İkindi": "16:05", "Akşam": "18:28", "Yatsı": "19:47" },
    "2026-01-26": { "İmsak": "06:45", "Güneş": "08:09", "Öğle": "13:24", "İkindi": "16:06", "Akşam": "18:29", "Yatsı": "19:48" },
    "2026-01-27": { "İmsak": "06:44", "Güneş": "08:08", "Öğle": "13:24", "İkindi": "16:07", "Akşam": "18:31", "Yatsı": "19:49" },
    "2026-01-28": { "İmsak": "06:44", "Güneş": "08:07", "Öğle": "13:25", "İkindi": "16:08", "Akşam": "18:32", "Yatsı": "19:50" },
    "2026-01-29": { "İmsak": "06:43", "Güneş": "08:07", "Öğle": "13:25", "İkindi": "16:09", "Akşam": "18:33", "Yatsı": "19:51" },
    "2026-01-30": { "İmsak": "06:43", "Güneş": "08:06", "Öğle": "13:25", "İkindi": "16:10", "Akşam": "18:34", "Yatsı": "19:52" },
    "2026-01-31": { "İmsak": "06:42", "Güneş": "08:05", "Öğle": "13:25", "İkindi": "16:11", "Akşam": "18:35", "Yatsı": "19:53" },   
    "2026-12-31": { "İmsak": "06:48", "Güneş": "08:15", "Öğle": "13:14", "İkindi": "15:43", "Akşam": "18:04", "Yatsı": "19:26" } 
};

export default class NazilliVakitExtension extends Extension {
    enable() {
        this._indicator = new PanelMenu.Button(0.5, 'NazilliVakit', false);
        
        this._label = new St.Label({ 
            text: '...',
            style: 'font-family: "Liberation Sans"; font-size: 18px; font-weight: bold; margin: 0 10px; padding-top: 6px;' 
        });
        
        this._indicator.add_child(this._label);
        
        Main.panel.addToStatusArea('nazilli-vakit', this._indicator, 0, 'center');

        this._timerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => {
            this._vaktiGuncelle();
            return GLib.SOURCE_CONTINUE;
        });

        this._vaktiGuncelle();
    }

    _vaktiGuncelle() {
        let simdi = new Date();
        let bugunStr = this._tarihFormatla(simdi);
        let suAnkiToplamSaniye = (simdi.getHours() * 3600) + (simdi.getMinutes() * 60) + simdi.getSeconds();

        let bugunkuListe = VAKITLER[bugunStr];
        let bulundu = false;

        if (bugunkuListe) {
            this._menuGuncelle(bugunkuListe);
              
            let sira = ["İmsak", "Güneş", "Öğle", "İkindi", "Akşam", "Yatsı"];
            for (let vakitAdı of sira) {
                let vTime = bugunkuListe[vakitAdı];
                let vParts = vTime.split(':');
                let vakitSaniye = (parseInt(vParts[0]) * 3600) + (parseInt(vParts[1]) * 60);

                if (vakitSaniye > suAnkiToplamSaniye) {
                    let farkSaniye = vakitSaniye - suAnkiToplamSaniye;
                    let kalanDakika = Math.floor(farkSaniye / 60);
                    let kalanSaniye = farkSaniye % 60;

                    // --- TAM EKRAN ÜSTÜ UYARI TETİKLEYİCİ ---
                    if (BILDIRIM_ACIK && kalanDakika === 20 && kalanSaniye === 0) {
                        this._ekranaBuyukMesajBas("!!! ABDEST VAKTİ !!!", `${vakitAdı} vaktine son 20 dakika kaldı.`);
                        // Paneli de kırmızı yap
                        this._label.set_style('font-family: "Liberation Sans"; font-size: 18px; font-weight: bold; color: #ff0000; padding-top: 6px;');
                    }
                    
                    // 20 dakikanın altına düşünce rengi normale döndür
                    if (kalanDakika < 20) {
                        this._label.set_style('font-family: "Liberation Sans"; font-size: 18px; font-weight: bold; margin: 0 10px; padding-top: 6px;');
                    }
                                        
                    this._ekranaYaz(vakitAdı, vTime, farkSaniye);
                    bulundu = true;
                    break; 
                }
            }
        }

        if (!bulundu) {
            let yarin = new Date(simdi);
            yarin.setDate(simdi.getDate() + 1);
            let yarinStr = this._tarihFormatla(yarin);
            let yarinkiListe = VAKITLER[yarinStr];
            
            if (yarinkiListe) {
                let vParts = yarinkiListe["İmsak"].split(':');
                let yarinİmsakSaniye = (24 * 3600 - suAnkiToplamSaniye) + (parseInt(vParts[0]) * 3600) + (parseInt(vParts[1]) * 60);
                
                // Yarınki imsak için 20 dk uyarısı
                let yKalanDakika = Math.floor(yarinİmsakSaniye / 60);
                let yKalanSaniye = yarinİmsakSaniye % 60;
                if (yKalanDakika === 20 && yKalanSaniye === 0) {
                    this._ekranaBuyukMesajBas("!!! ABDEST VAKTİ !!!", `İmsak vaktine son 20 dakika kaldı.`);
                    this._label.set_style('font-family: "Liberation Sans"; font-size: 18px; font-weight: bold; color: #ff0000; padding-top: 6px;');
                }

                this._ekranaYaz("İmsak", yarinkiListe["İmsak"], yarinİmsakSaniye);
            } else {
                this._label.set_text("Veri Yok");
            }
        }
    }

    // --- YENİ: EKRANIN ORTASINDA ÇIKAN 20 SANİYELİK MESAJ ---
    _ekranaBuyukMesajBas(baslik, icerik) {
        let mesajKutusu = new St.Label({
            text: `${baslik}\n${icerik}`,
            style: 'background-color: rgba(0,0,0,0.85); color: white; font-size: 26px; font-weight: bold; padding: 50px; border-radius: 20px; text-align: center; border: 4px solid #ff0000;',
            x_align: Clutter.ActorAlign.CENTER,
            y_align: Clutter.ActorAlign.CENTER
        });

        // Mesajı en üst katmana ekle
        Main.layoutManager.addChrome(mesajKutusu);
        
        // Ekrana ortala
        let monitor = Main.layoutManager.primaryMonitor;
        mesajKutusu.set_position(
            Math.floor(monitor.width / 2 - mesajKutusu.width / 2),
            Math.floor(monitor.height / 2 - mesajKutusu.height / 2)
        );

        // 20 saniye sonra kendiliğinden sil
        GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 20, () => {
            Main.layoutManager.removeChrome(mesajKutusu);
            mesajKutusu.destroy();
            return GLib.SOURCE_REMOVE;
        });
    }

    _menuGuncelle(vakitler) {
        this._indicator.menu.removeAll();
        for (let [ad, saat] of Object.entries(vakitler)) {
            let madde = new PopupMenu.PopupMenuItem(`${ad}: ${saat}`);
            this._indicator.menu.addMenuItem(madde);
        }
    }

    _ekranaYaz(ad, saat, toplamSaniye) {
        let h = Math.floor(toplamSaniye / 3600);
        let m = Math.floor((toplamSaniye % 3600) / 60);
        let s = toplamSaniye % 60;
        let pad = (n) => String(n).padStart(2, '0');
        this._label.set_text(`${ad}: ${saat} | ${pad(h)}:${pad(m)}:${pad(s)}`);
    }

    _tarihFormatla(tarih) {
        let y = tarih.getFullYear();
        let m = String(tarih.getMonth() + 1).padStart(2, '0');
        let d = String(tarih.getDate()).padStart(2, '0');
        return `${y}-${m}-${d}`;
    }

    disable() {
        if (this._timerId) {
            GLib.Source.remove(this._timerId);
            this._timerId = null;
        }
        if (this._indicator) {
            this._indicator.destroy();
            this._indicator = null;
        }
    }
}

Kaydet diyip çıkış yapın dosyadan .

metadata.json dosyasına girip aşağıdaki kodları kopyalayıp yapıştırın

{
  "name": "Nazilli Vakitleri",
  "description": "Nazilli için çevrimdışı namaz vakitleri",
  "uuid": "vakit@ahmet.NikBulamadim",
  "shell-version": [ "45", "46", "47", "48" ],
  "type": "extension"
}

Kaydet diyip çıkış yapın klasörden .

Şimdi en dikkat edilmesi gereken yer . Çünkü uygulama Ofline hiçbir şekilde internet yada konum ihtiyaç duymaz .

Pardus Mağazaya Girip Word-sys PDF Editor uygulamasını kurun .

Diyanet İşleri Namaz Vakitleri

Şimdi Diyanet Namaz Vakitleri sitesine girip Kendi il ve ilçenizi seçip Yıllık Namaz Vakti ne tıklayın . İndirme Biçimi PDF Masaüsütne atın dosyayı .

Yüklemiş olduğunuz Word-sys PDF Editor uygulamasını açın Dosya Aç İndirmiş olduğun PDF yi seç .

Sağ üst tarafta buluna Üç çizgiyi tıklayıp Farklı Dışarı Çıkart

ve Masaüstünün içine gir ve sağ altta PDF - PDF files seçeneğini tıklayıp TXT - TXT file seçeneğini seçin ve export tuşuna basın sağ üst yukarda

Şimdi 1 yıllık saatler hazı . Bunu yukarda verdiğim kodlara nasıl entegre edeceğiz . İzah ederek anlatmaya çalışacağım . Bunu kod haline döndürcek uygulama yazdım yapay zeka ile . En pratik yolu bu .

Aşağıda vereceğim kodları Ayrıten faydalı bir uygulama paylaşmış oluyorum .

Öncelik olarak sudo apt install python3-pyqt5 -y Termele yazıp kurulum yapın . Bağımlılık gerektiriyor .

Masaüstüne Metin Belgesi açın adı deneme İçine Aşağıdaki kodları yapıştırın

import sys
import csv
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QPushButton, 
                            QTextEdit, QFileDialog, QLabel, QMessageBox)
from PyQt5.QtCore import Qt
from datetime import datetime

class VakitDonusturucu(QWidget):
   def __init__(self):
       super().__init__()
       self.initUI()
   
   def initUI(self):
       self.setWindowTitle('Nazilli 2026 Vakit Dönüştürücü - Gelişmiş Sürüm')
       self.setGeometry(100, 100, 850, 650)
       
       layout = QVBoxLayout()
       
       # BAŞLIK
       self.label = QLabel('📁 Dönüştürülecek dosyayı seçin (.txt veya .csv)')
       self.label.setStyleSheet("font-weight: bold; font-size: 14px; color: #2c3e50;")
       layout.addWidget(self.label)
       
       # BİLGİ ETİKETİ
       self.infoLabel = QLabel('✅ Desteklenen formatlar: TXT, CSV (Excel\'den dışa aktarabilirsiniz)')
       self.infoLabel.setStyleSheet("font-size: 11px; color: #7f8c8d; margin-bottom: 10px;")
       layout.addWidget(self.infoLabel)
       
       # DOSYA SEÇ BUTONU
       self.btnSec = QPushButton('📂 Dosya Seç ve Dönüştür', self)
       self.btnSec.setStyleSheet("""
           QPushButton {
               padding: 12px; 
               background-color: #3498db; 
               color: white; 
               font-weight: bold;
               border-radius: 5px;
               font-size: 13px;
           }
           QPushButton:hover {
               background-color: #2980b9;
           }
       """)
       self.btnSec.clicked.connect(self.dosyaAc)
       layout.addWidget(self.btnSec)
       
       # SONUÇ ALANI
       self.sonucAlan = QTextEdit()
       self.sonucAlan.setPlaceholderText("Dönüştürülen JavaScript kodu buraya gelecek...")
       self.sonucAlan.setLineWrapMode(QTextEdit.NoWrap)
       self.sonucAlan.setStyleSheet("""
           QTextEdit {
               font-family: 'Courier New', monospace;
               font-size: 11px;
               background-color: #ecf0f1;
               border: 2px solid #bdc3c7;
               border-radius: 5px;
               padding: 10px;
           }
       """)
       layout.addWidget(self.sonucAlan)
       
       # KOPYALA BUTONU
       self.btnKopyala = QPushButton('📋 Kodu Panoya Kopyala', self)
       self.btnKopyala.setStyleSheet("""
           QPushButton {
               padding: 12px; 
               background-color: #2ecc71; 
               color: white; 
               font-weight: bold;
               border-radius: 5px;
               font-size: 13px;
           }
           QPushButton:hover {
               background-color: #27ae60;
           }
       """)
       self.btnKopyala.clicked.connect(self.kopyala)
       layout.addWidget(self.btnKopyala)
       
       # KAYDET BUTONU
       self.btnKaydet = QPushButton('💾 JS Dosyası Olarak Kaydet', self)
       self.btnKaydet.setStyleSheet("""
           QPushButton {
               padding: 12px; 
               background-color: #e67e22; 
               color: white; 
               font-weight: bold;
               border-radius: 5px;
               font-size: 13px;
           }
           QPushButton:hover {
               background-color: #d35400;
           }
       """)
       self.btnKaydet.clicked.connect(self.kaydet)
       layout.addWidget(self.btnKaydet)
       
       self.setLayout(layout)
   
   def tarih_duzelt(self, tarih_str):
       """Farklı tarih formatlarını 2026-01-27 formatına dönüştürür"""
       try:
           # String formatı
           tarih_str = str(tarih_str).strip()
           
           # Türkçe ay isimleri
           aylar = {
               'Ocak': '01', 'Şubat': '02', 'Mart': '03', 'Nisan': '04',
               'Mayıs': '05', 'Haziran': '06', 'Temmuz': '07', 'Ağustos': '08',
               'Eylül': '09', 'Ekim': '10', 'Kasım': '11', 'Aralık': '12'
           }
           
           # 01 Ocak 2026 formatı (gün ay_ismi yıl)
           parcalar = tarih_str.split()
           if len(parcalar) >= 3:
               gun = parcalar[0]
               ay_ismi = parcalar[1]
               yil = parcalar[2]
               
               if ay_ismi in aylar:
                   return f"{yil}-{aylar[ay_ismi]}-{gun.zfill(2)}"
           
           # 27.01.2026 formatı
           if "." in tarih_str:
               parcalar = tarih_str.split(".")
               if len(parcalar) == 3:
                   gun, ay, yil = parcalar
                   return f"{yil}-{ay.zfill(2)}-{gun.zfill(2)}"
           
           # 27/01/2026 formatı
           if "/" in tarih_str:
               parcalar = tarih_str.split("/")
               if len(parcalar) == 3:
                   gun, ay, yil = parcalar
                   return f"{yil}-{ay.zfill(2)}-{gun.zfill(2)}"
           
           # 2026-01-27 formatı (zaten doğru)
           if "-" in tarih_str and len(tarih_str.split("-")) == 3:
               return tarih_str
           
       except Exception as e:
           print(f"Tarih dönüştürme hatası: {e}")
       
       return tarih_str
   
   def txt_oku(self, dosya_yolu):
       """TXT dosyasını okur (boşlukla ayrılmış)"""
       cikti = []
       aylar = ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 
                'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık']
       
       with open(dosya_yolu, 'r', encoding='utf-8') as f:
           for satir in f:
               satir = satir.strip()
               if not satir:
                   continue
                   
               p = satir.split()
               
               # "01 Ocak 2026 Perşembe 06:48 08:15..." formatı için
               if len(p) >= 10:
                   # İkinci kelime ay ismi mi kontrol et (Miladi)
                   if p[1] in aylar:
                       tarih_str = f"{p[0]} {p[1]} {p[2]}"  # "01 Ocak 2026"
                       tarih = self.tarih_duzelt(tarih_str)
                       
                       # Gün adını atla, son 6 vakit saatini al
                       cikti.append({
                           'tarih': tarih,
                           'imsak': p[-6],   # Sondan 6. eleman
                           'gunes': p[-5],   # Sondan 5. eleman
                           'ogle': p[-4],    # Sondan 4. eleman
                           'ikindi': p[-3],  # Sondan 3. eleman
                           'aksam': p[-2],   # Sondan 2. eleman
                           'yatsi': p[-1]    # Son eleman
                       })
                   
               # Eski format: "01.01.2026 06:48 08:15..." 
               elif len(p) >= 7:
                   tarih = self.tarih_duzelt(p[0])
                   cikti.append({
                       'tarih': tarih,
                       'imsak': p[1],
                       'gunes': p[2],
                       'ogle': p[3],
                       'ikindi': p[4],
                       'aksam': p[5],
                       'yatsi': p[6]
                   })
       return cikti
   
   def csv_oku(self, dosya_yolu):
       """CSV dosyasını okur (Excel'den dışa aktarılmış)"""
       cikti = []
       
       # Farklı encoding'leri dene
       encodings = ['utf-8', 'utf-8-sig', 'latin-1', 'cp1254']
       
       for encoding in encodings:
           try:
               with open(dosya_yolu, 'r', encoding=encoding) as f:
                   # Delimiter'ı otomatik tespit et
                   sample = f.read(1024)
                   f.seek(0)
                   
                   # Virgül, noktalı virgül veya tab'ı dene
                   if ';' in sample:
                       delimiter = ';'
                   elif '\t' in sample:
                       delimiter = '\t'
                   else:
                       delimiter = ','
                   
                   csv_reader = csv.reader(f, delimiter=delimiter)
                   
                   for i, row in enumerate(csv_reader):
                       # Boş satırları atla
                       if not row or not any(row):
                           continue
                       
                       # İlk satır başlık olabilir (tarih formatında değilse)
                       if i == 0 and row[0] and not any(char.isdigit() for char in str(row[0])):
                           continue
                       
                       if len(row) >= 7 and row[0]:
                           tarih = self.tarih_duzelt(row[0])
                           cikti.append({
                               'tarih': tarih,
                               'imsak': str(row[1]).strip() if row[1] else "",
                               'gunes': str(row[2]).strip() if row[2] else "",
                               'ogle': str(row[3]).strip() if row[3] else "",
                               'ikindi': str(row[4]).strip() if row[4] else "",
                               'aksam': str(row[5]).strip() if row[5] else "",
                               'yatsi': str(row[6]).strip() if row[6] else ""
                           })
               
               # Başarılı olduysa döngüyü kır
               if cikti:
                   break
                   
           except UnicodeDecodeError:
               continue
           except Exception as e:
               print(f"{encoding} ile okuma hatası: {e}")
               continue
       
       return cikti
   
   def dosyaAc(self):
       dosya_yolu, _ = QFileDialog.getOpenFileName(
           self, 
           "Vakit Dosyasını Seç", 
           "", 
           "Desteklenen Dosyalar (*.txt *.csv);;Metin Dosyası (*.txt);;CSV Dosyası (*.csv);;Tüm Dosyalar (*.*)"
       )
       
       if dosya_yolu:
           try:
               # Dosya uzantısını kontrol et
               uzanti = dosya_yolu.lower().split('.')[-1]
               
               if uzanti == 'txt':
                   veriler = self.txt_oku(dosya_yolu)
                   kaynak = "TXT"
               elif uzanti == 'csv':
                   veriler = self.csv_oku(dosya_yolu)
                   kaynak = "CSV"
               else:
                   QMessageBox.warning(self, "Uyarı", "Desteklenmeyen dosya formatı!\nSadece .txt ve .csv dosyaları destekleniyor.")
                   return
               
               if not veriler:
                   QMessageBox.warning(self, "Uyarı", "Dosyada geçerli veri bulunamadı!\n\nDosya formatı:\nTarih İmsak Güneş Öğle İkindi Akşam Yatsı")
                   return
               
               # JavaScript kodunu oluştur
               cikti = ["const VAKITLER = {"]
               
               for v in veriler:
                   formatli = f'    "{v["tarih"]}": {{ "İmsak": "{v["imsak"]}", "Güneş": "{v["gunes"]}", "Öğle": "{v["ogle"]}", "İkindi": "{v["ikindi"]}", "Akşam": "{v["aksam"]}", "Yatsı": "{v["yatsi"]}" }},'
                   cikti.append(formatli)
               
               cikti.append("};")
               
               # Sonucu göster - UTF-8 ile encode et
               sonuc_metni = "\n".join(cikti)
               self.sonucAlan.setText(sonuc_metni)
               self.label.setText(f"✅ Dönüştürme Başarılı! ({kaynak} dosyasından {len(veriler)} kayıt)")
               self.label.setStyleSheet("font-weight: bold; font-size: 14px; color: #27ae60;")
               
           except Exception as e:
               QMessageBox.critical(self, "Hata", f"Dosya işlenirken hata oluştu:\n{str(e)}")
               self.label.setText("❌ Hata oluştu!")
               self.label.setStyleSheet("font-weight: bold; font-size: 14px; color: #e74c3c;")
   
   def kopyala(self):
       """Metin alanındaki kodu panoya kopyalar"""
       icerik = self.sonucAlan.toPlainText()
       if icerik and icerik != "":
           self.sonucAlan.selectAll()
           self.sonucAlan.copy()
           QMessageBox.information(self, "Başarılı", "✅ Kod panoya kopyalandı!")
       else:
           QMessageBox.warning(self, "Uyarı", "Kopyalanacak kod yok!")
   
   def kaydet(self):
       """Kodu .js dosyası olarak kaydeder"""
       icerik = self.sonucAlan.toPlainText()
       if icerik and icerik != "":
           dosya_yolu, _ = QFileDialog.getSaveFileName(
               self, 
               "JavaScript Dosyası Olarak Kaydet", 
               "vakitler.js", 
               "JavaScript Dosyası (*.js);;Tüm Dosyalar (*.*)"
           )
           
           if dosya_yolu:
               try:
                   with open(dosya_yolu, 'w', encoding='utf-8') as f:
                       f.write(icerik)
                   QMessageBox.information(self, "Başarılı", f"✅ Dosya kaydedildi:\n{dosya_yolu}")
               except Exception as e:
                   QMessageBox.critical(self, "Hata", f"Dosya kaydedilirken hata:\n{str(e)}")
       else:
           QMessageBox.warning(self, "Uyarı", "Kaydedilecek kod yok!")

if __name__ == '__main__':
   app = QApplication(sys.argv)
   ex = VakitDonusturucu()
   ex.show()
   sys.exit(app.exec_())

Kaydet ve çık

Masaüstünde iken Fare Sağ tıklama yapın Uç Birim Aç Diyin Terminale şu komutu yazın python3 deneme enter . Uygulama açılması lazım doğru yaptıysanız .

Dosya Seç Ve Dönüştür tıklayıp Dışa Aktardığınız Txt dosyasını seçiniz ve oluşan Kodları resimdeki gibi seçin en sona kadar . 1 yıllık Namaz Vakit verisi bunlar .


Şimdi asıl mesele bunu düzgünce yapıştırmak ilgili dosyamıza .

extension.js dosyasına giriş yapın . Kopyaladığınız kodları Göstereceğim yere yapıştırın . Bu kısım önemli Resim ile göstersem iyi olur ,

Aynı Resimdeki gibi seçin ve kopyaladığınız kodları buraya yapıştır yapın .

Kaydet ve çık .

Kopyalanmış Hali Resimde

Bu kısımı tam hatırlamıyorum Fazladan Oturum Aç Kapa yaptırabilirim

İşlemler bitince Oturum Kapat Tekar giriş Yap

Uzantılar Açalım

Sanırım Tekrar oturum aç kapat gerekiyordu . emin değilim .

Uzantı gelmezse Dash To Panel / Konum / OrTa Kutu Görünür yap . Ekranın uygun yerine döşmek için yukarı aşağı yön tuşları ile yerdeğiştirebilirsin . sağa sola ekranı ortala seçenekleri var orası sizde . Elimden geldiğince anlattım .

Balık tutmayı değil Olta yapmayı öğrendik hep beraber . Tüketen değil üreten olduk . Bütün bu düzen Yapay Zeka ile yardımı ile yapıldı . Yapay zeka sadece kodları yazdı , hataları düzeltti . neyi nereye koyacağımı gösterdi . Bu projedeki uygulamalar tamamen kendi fikrim .

Ekrana son 20 Dk kala inatçı bir bildirim gelebilir :slight_smile: İstemiyorsanız bildirimi extension.js dosyasına girip Ctrl F yapıp arama kutucuğuna const BILDIRIM_ACIK = true; // Bildirimi kapatmak için false yazın . true yazam yere false yazın kaydet çık ve Oturum Kapat Tekrar Giriş Yap .

Pardus 23.4 olanı sonra yapacağım İnşâalâh . Çok geç oldu saat .

Not : Hep Kendi isimimde ve İlçeme ait isimler oldu . İstiyen değiştirebilir fakat bu şekilde kullanmanızda hiç sakınca yok . Önemli olan burada kendi il veya ilçenize ait olan veriler .

Uzantıyı istiyen geliştirebilir. Daha zahmetsiz hale getirebilir ve dağıtabilir . Bayadır böyle birşey istiyordum . Bir arkadaşın konusuna fikir olarak yazdım . Proje oluverdi kalbime düştü. %100 işimi gören bir uzantı oldu .

1 Beğeni

Pardus 23.4 Gnome için

Pardus 23 Sürümlerinde e çalışabilir Çünkü Gnome sürümleri uyuyor . Fakat Pardus 23.4 sürümünde testi edilmiştir .

extension.js içine aşağıdaki kodları yapıştırın

const St = imports.gi.St;
const GLib = imports.gi.GLib;
const Clutter = imports.gi.Clutter;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;

// --- AYAR BURASI ---
// Bildirimi kapatmak için false, açmak için true yapın.
const BILDIRIM_ACIK = true; 

const VAKITLER = {
    "2026-01-14": { "İmsak": "06:49", "Güneş": "08:15", "Öğle": "13:21", "İkindi": "15:55", "Akşam": "18:17", "Yatsı": "19:37" },
    "2026-01-15": { "İmsak": "06:49", "Güneş": "08:14", "Öğle": "13:21", "İkindi": "15:56", "Akşam": "18:18", "Yatsı": "19:38" },
    "2026-01-16": { "İmsak": "06:49", "Güneş": "08:14", "Öğle": "13:21", "İkindi": "15:57", "Akşam": "18:19", "Yatsı": "19:39" },
    "2026-01-17": { "İmsak": "06:48", "Güneş": "08:14", "Öğle": "13:22", "İkindi": "15:57", "Akşam": "18:20", "Yatsı": "19:40" },
    "2026-01-18": { "İmsak": "06:48", "Güneş": "08:13", "Öğle": "13:22", "İkindi": "15:58", "Akşam": "18:21", "Yatsı": "19:41" },
    "2026-01-19": { "İmsak": "06:48", "Güneş": "08:13", "Öğle": "13:22", "İkindi": "15:59", "Akşam": "18:22", "Yatsı": "19:42" },
    "2026-01-20": { "İmsak": "06:47", "Güneş": "08:12", "Öğle": "13:23", "İkindi": "16:00", "Akşam": "18:23", "Yatsı": "19:43" },
    "2026-01-21": { "İmsak": "06:47", "Güneş": "08:12", "Öğle": "13:23", "İkindi": "16:01", "Akşam": "18:24", "Yatsı": "19:44" },
    "2026-01-22": { "İmsak": "06:47", "Güneş": "08:11", "Öğle": "13:23", "İkindi": "16:02", "Akşam": "18:25", "Yatsı": "19:44" },
    "2026-01-23": { "İmsak": "06:46", "Güneş": "08:11", "Öğle": "13:23", "İkindi": "16:03", "Akşam": "18:26", "Yatsı": "19:45" },
    "2026-01-24": { "İmsak": "06:46", "Güneş": "08:10", "Öğle": "13:24", "İkindi": "16:04", "Akşam": "18:27", "Yatsı": "19:46" },
    "2026-01-25": { "İmsak": "06:45", "Güneş": "08:10", "Öğle": "13:24", "İkindi": "16:05", "Akşam": "18:28", "Yatsı": "19:47" },
    "2026-01-26": { "İmsak": "06:45", "Güneş": "08:09", "Öğle": "13:24", "İkindi": "16:06", "Akşam": "18:29", "Yatsı": "19:48" },
    "2026-01-27": { "İmsak": "06:44", "Güneş": "08:08", "Öğle": "13:24", "İkindi": "16:07", "Akşam": "18:31", "Yatsı": "19:49" },
    "2026-01-28": { "İmsak": "06:44", "Güneş": "08:07", "Öğle": "13:25", "İkindi": "16:08", "Akşam": "18:32", "Yatsı": "19:50" },
    "2026-01-29": { "İmsak": "06:43", "Güneş": "08:07", "Öğle": "13:25", "İkindi": "16:09", "Akşam": "18:33", "Yatsı": "19:51" },
    "2026-01-30": { "İmsak": "06:43", "Güneş": "08:06", "Öğle": "13:25", "İkindi": "16:10", "Akşam": "18:34", "Yatsı": "19:52" },
    "2026-01-31": { "İmsak": "06:42", "Güneş": "08:05", "Öğle": "13:25", "İkindi": "16:11", "Akşam": "18:35", "Yatsı": "19:53" },
};

class NazilliVakitExtension {
    constructor() {
        this._indicator = null;
        this._label = null;
        this._timerId = null;
    }

    enable() {
        this._indicator = new PanelMenu.Button(0.5, 'NazilliVakit', false);
        
        this._label = new St.Label({
            text: '...',
            style: 'font-family: "Liberation Sans"; font-size: 18px; font-weight: bold; margin: 0 10px;',
            y_align: Clutter.ActorAlign.CENTER
        });
        
        this._indicator.add_child(this._label);
        Main.panel.addToStatusArea('nazilli-vakit', this._indicator, 0, 'center');

        this._timerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => {
            this._vaktiGuncelle();
            return GLib.SOURCE_CONTINUE;
        });
        this._vaktiGuncelle();
    }

    _vaktiGuncelle() {
        let simdi = new Date();
        let bugunStr = this._tarihFormatla(simdi);
        let suAnkiToplamSaniye = (simdi.getHours() * 3600) + (simdi.getMinutes() * 60) + simdi.getSeconds();
        let bugunkuListe = VAKITLER[bugunStr];

        if (bugunkuListe) {
            this._menuGuncelle(bugunkuListe);
            let sira = ["İmsak", "Güneş", "Öğle", "İkindi", "Akşam", "Yatsı"];
            for (let vakitAdı of sira) {
                let vTime = bugunkuListe[vakitAdı];
                let vParts = vTime.split(':');
                let vakitSaniye = (parseInt(vParts[0]) * 3600) + (parseInt(vParts[1]) * 60);

                if (vakitSaniye > suAnkiToplamSaniye) {
                    let farkSaniye = vakitSaniye - suAnkiToplamSaniye;
                    let kalanDakika = Math.floor(farkSaniye / 60);
                    
                    // Bildirim kontrolü burada yapılıyor
                    if (BILDIRIM_ACIK && kalanDakika === 20 && (farkSaniye % 60) === 0) {
                        this._ekranaBuyukMesajBas("!!! ABDEST VAKTİ !!!", `${vakitAdı} vaktine son 20 dakika kaldı.`);
                        this._label.set_style('font-family: "Liberation Sans"; font-size: 18px; font-weight: bold; color: #ff0000;');
                    }
                    if (kalanDakika < 20) {
                        this._label.set_style('font-family: "Liberation Sans"; font-size: 18px; font-weight: bold; margin: 0 10px;');
                    }
                    this._ekranaYaz(vakitAdı, vTime, farkSaniye);
                    return;
                }
            }
        }
    }

    _ekranaBuyukMesajBas(baslik, icerik) {
        let mesajKutusu = new St.Label({
            text: `${baslik}\n${icerik}`,
            style: 'background-color: rgba(0,0,0,0.85); color: white; font-size: 26px; font-weight: bold; padding: 50px; border-radius: 20px; text-align: center; border: 4px solid #ff0000;',
            x_align: Clutter.ActorAlign.CENTER,
            y_align: Clutter.ActorAlign.CENTER
        });
        Main.layoutManager.addChrome(mesajKutusu);
        let monitor = Main.layoutManager.primaryMonitor;
        mesajKutusu.set_position(Math.floor(monitor.width / 2 - mesajKutusu.width / 2), Math.floor(monitor.height / 2 - mesajKutusu.height / 2));
        GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 20, () => {
            Main.layoutManager.removeChrome(mesajKutusu);
            mesajKutusu.destroy();
            return GLib.SOURCE_REMOVE;
        });
    }

    _menuGuncelle(vakitler) {
        this._indicator.menu.removeAll();
        for (let [ad, saat] of Object.entries(vakitler)) {
            this._indicator.menu.addMenuItem(new PopupMenu.PopupMenuItem(`${ad}: ${saat}`));
        }
    }

    _ekranaYaz(ad, saat, toplamSaniye) {
        let h = Math.floor(toplamSaniye / 3600), m = Math.floor((toplamSaniye % 3600) / 60), s = toplamSaniye % 60;
        let pad = (n) => String(n).padStart(2, '0');
        this._label.set_text(`${ad}: ${saat} | ${pad(h)}:${pad(m)}:${pad(s)}`);
    }

    _tarihFormatla(tarih) {
        return `${tarih.getFullYear()}-${String(tarih.getMonth() + 1).padStart(2, '0')}-${String(tarih.getDate()).padStart(2, '0')}`;
    }

    disable() {
        if (this._timerId) GLib.Source.remove(this._timerId);
        if (this._indicator) this._indicator.destroy();
        this._indicator = null;
    }
}

function init() {
    return new NazilliVakitExtension();
}

metadata.json içine aşağıdaki kodları kopyalayın

{
  "name": "Nazilli Vakitleri",
  "description": "Nazilli için çevrimdışı namaz vakitleri",
  "uuid": "vakit@ahmet.NikBulamadim",
  "shell-version": [ "43" ],
  "type": "extension"
}

İşlem sırasını yukarıdaki konuya bakarak yapın .