Forum: D Programlama Dili RSS
Gtkd kullanıcı giriş metnini değiştirdiğinde verilerin süzülmesi
erdem (Moderatör) #1
Üye Tem 2009 tarihinden beri · 958 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Gtkd kullanıcı giriş metnini değiştirdiğinde verilerin süzülmesi
Bir tane giriş kutumuz var. İçerisindeki metin değiştiğinde verileri süzmek istiyoruz ama bir türlü bu setVisibleFunc işlevine ne göndereceğimizi bulamadım.

Örneğin buradaki örnekte TreeModel geçmiş ama ben daha önce C örneğini de kodlamıştım.
typedef struct
{
    GtkListStore * mallar;
    GtkTreeModelSort * siralanmis;
    GtkTreeModelFilter * suzulmus;
    gdouble enYuksekFiyat;
}Depo;
 
/* ... */
    gtk_tree_model_filter_set_visible_func (depo->suzulmus,
                                            (GtkTreeModelFilterVisibleFunc) satirGorunurMu,
                                            depo, NULL);
 
static gboolean satirGorunurMu (GtkTreeModel * model, GtkTreeIter * erisici, Depo * depo)
{
    gdouble fiyat;
 
    gtk_tree_model_get (model, erisici, FIYAT_SUTUNU, &fiyat, -1);
    return fiyat <= depo->enYuksekFiyat;
}

C örneğinde TreeModel yerine TreeModelFilter geçiyorum kabul ediyor ama D kabul etmiyor. Ya da bir yerlerde gözümden kaçan bir şey olabilir.

Sizin bu konuda fikriniz var mı acaba.
import gtk.Main;
import gtk.MainWindow;
import gtk.Box;
import gtk.Entry;
import gtk.EditableIF;
import gtk.TreeModelFilter;
import gtk.TreeView;
import gtk.HBox;
import gtk.VBox;
import gtk.Label;
import gtk.ListStore;
import gtk.TreeViewColumn;
import gtk.CellRendererText;
import gtk.TreeModel;
import gtk.TreeIter;
 
import std.conv;
import std.stdio;
 
class Pencere: MainWindow
{
    Box anaKutu;
    Entry giriş;
    TreeModelFilter süz;
    TreeIter erişici;
    
    this()
    {
        super("Ağaç örneği 3");
        setSizeRequest(500, 200);
        giriş = new Entry();
        // giriş.addOnChanged((giriş) {metinDeğişti(giriş);});
        
        auto girişEtiket = new Label("Sanatçı ara");
        
        auto ağaç = new TreeView();
        auto kutu = new VBox(false, 0);
 
        auto veriModeli = new ListStore([GType.STRING, GType.STRING]);
                
        auto sanatçıSütunu = new TreeViewColumn("Sanatçı", new CellRendererText(), "text", 0);
        ağaç.appendColumn(sanatçıSütunu);
        auto şarkıSütunu = new TreeViewColumn("Şarkı ismi", new CellRendererText(), "text", 1);
        ağaç.appendColumn(şarkıSütunu);
 
        erişici = veriModeli.createIter();
        veriModeli.setValue(erişici, 0, "Ali Veli");
        veriModeli.setValue(erişici, 1, "Bir şeyler söyle");
 
        erişici = veriModeli.createIter();
        veriModeli.setValue(erişici, 0, "Ali Veli");
        veriModeli.setValue(erişici, 1, "Başka bir şeyler söyle");
 
        erişici = veriModeli.createIter();
        veriModeli.setValue(erişici, 0, "Ahmet fuat özkan");
        veriModeli.setValue(erişici, 1, "Çorba yapalım");
 
        süz = new TreeModelFilter(veriModeli, null);
        süz.setVisibleFunc(cast(GtkTreeModelFilterVisibleFunc) ağacıSüz(süz, erişici), null, null);
        
        ağaç.setModel(süz);
 
        auto anaKutu = new HBox(false, 0);
        anaKutu.packStart(girişEtiket, false, false, 5);
        anaKutu.packStart(giriş, true, true, 5);
        kutu.packStart(anaKutu, false, false, 5);
        kutu.packStart(ağaç, true, true, 5);
 
        add(kutu);
        showAll();
    }
 
    bool ağacıSüz(TreeModelFilter model, TreeIter eriş)
    {
        string sanatçıİsmi = to!string(model.getValue(eriş, 0));
 
        // writeln(sanatçıİsmi);
        
        return true;
    }
    void metinDeğişti(EditableIF giriş)
    {
        süz.refilter();
    }
 
    // void metinDeğişti(ParamSpec parametre, ObjectG nesne)
    // {
    //     süz.refilter();
    // }
}
 
void main(string[] args)
{
    Main.init(args);
    new Pencere();
    Main.run();
}
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4513 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Gördüğüm kadarıyla şöyle bir işlev:
public void setVisibleFunc(GtkTreeModelFilterVisibleFunc func, void* data, GDestroyNotify destroy)
{
    // ...
}
cast kullanmak zorunda olduğuna göre işlevinin türü doğru değil sanırım ama GtkTreeModelFilterVisibleFunc'ın tanımını bulamıyorum. (?)

Hatayı şimdi gördüm. ağacıSüz işlevini çağırıp onun sonucunu setVisibleFunc'a vermek istemiyorsun, ağacıSüz işlevinin kendisini vermek istiyorsun. Sistem ağacıSüz'ü gerektikçe kendisi 'süz' ve 'erişici' parametreleri ile sonra çağıracak. Şöyle mantıklı görünüyor:
    süz.setVisibleFunc(&ağacıSüz, null, null);
Ali
erdem (Moderatör) #3
Üye Tem 2009 tarihinden beri · 958 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
    süz.setVisibleFunc( &ağacıSüz, null, null);
Bu şekilde kullandığım zaman şu şekilde bir hata veriyor.

Error: function gtk.TreeModelFilter.TreeModelFilter.setVisibleFunc (extern (C) int function(GtkTreeModel* model, GtkTreeIter* iter, void* data) func, void* data, extern (C) void function(void* data) destroy) is not callable using argument types (bool delegate(), typeof(null), typeof(null))
make: *** [deneme3] Hata 1

Anladığım kadarıyla bu GtkTreeModelFilterVisibleFunc 'ın parametre olarak GtkTreeModel* model, GtkTreeIter* iter aldığını tahmin ediyorum.

Ama bizde TreeModel ve TreeIter sınıfı var. TreeModel yerine süzülmüş verileri C örneğinde geçerken D'de nasıl geçebileceğimizi bulamadım.
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4513 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Hata mesajına bakılırsa istenen işlev şöyle:

extern (C) int function(GtkTreeModel*, GtkTreeIter*, void* data);

Bence GtkTreeModel ve GtkTreeIter sırasıyla TreeModel ve TreeIter'in aynısıdır. alias ile isimleri değiştirilmiş olmalı ve derleyici asıl türleri bildiriyor. Orada bir sorun yok.

Asıl sorun, ağacıSüz ne bir function (çünkü bir delegate çünkü bir sınıf işlevi) ne de 'extern (C)' olarak tanımlanmış. O işlevi serbest bir işlev olarak tanımla ve sınıf nesnesini kullanabilmek için henüz yararlanmadığın data parametresini kullan. Derlemedim:
class Pencere: MainWindow
{
    // ...
}
 
// Dışarıda:
extern (C)
bool ağacıSüz(TreeModelFilter model, TreeIter eriş, void* data)
{
    Pencere pencere = cast(Pencere)data;
    assert(pencere !is null);
 
    string sanatçıİsmi = to!string(pencere.model.getValue(eriş, 0));
 
    // writeln(sanatçıİsmi);
 
    return true;
}
Ali
acehreli (Moderatör) #5
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4513 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Unutmuşum: 'data' olarak ne geleceğini de setVisibleFunc'ı çağırdığında verdiğin 'data' ile belirliyor olmalısın. O sırada 'data' olarak ne verirsen ağacıSüz de onunla çağrılır:
    // cast gerekmeyebilir; derlemedim:
    süz.setVisibleFunc( &ağacıSüz, cast(void*)this, null);
Ali
erdem (Moderatör) #6
Üye Tem 2009 tarihinden beri · 958 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Şu şekilde geçmeye denedim.
        süz.setVisibleFunc(cast(GtkTreeModelFilterVisibleFunc)  &ağacıSüz, cast(void *) this, null);
extern (C)
bool ağacıSüz(TreeModelFilter model, TreeIter eriş, void* data)
{
    Pencere pencere = cast(Pencere)data;
    assert(pencere !is null);
 
    string sanatçıİsmi = to!string(model.getValue(eriş, 0));
 
    return true;
}
Ama gene parçalama arızası hatası aldım. Gtkd forumlarında şuna benzer bir çözüm önermişler.
        süz.setVisibleFunc(cast(GtkTreeModelFilterVisibleFunc)  &ağacıSüz, null, null);
    bool ağacıSüz(GtkTreeModelFilter gtkModel, GtkTreeIter gtkErişici)
    {
        auto model1 = new TreeModelFilter(&gtkModel, false);
        auto erişici1 = new TreeIter(&gtkErişici, false);
        
        string sanatçıİsmi = to!string(model1.getValue(erişici1, 0));
        
        return true;
    }
Bu da parçalanma arızası hatası veriyor.

Ama orada bir tane TreeModel nesnesi oluşturuyor. Ama TreeModel sınıfının kurucu işlevine GtkTreeModelFilter * geçtiğimiz zaman kabul etmiyor.

    public this (GtkTreeModel* gtkTreeModel, bool ownedRef = false)
    {
        super(cast(GObject*)gtkTreeModel, ownedRef);
        this.gtkTreeModel = gtkTreeModel;
    }
erdem (Moderatör) #7
Üye Tem 2009 tarihinden beri · 958 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Çok şükür Allah'ın izniyle oldu.

Bu arada Ali Bey'in gösterdiği cast(void*) yönteminden de yararlandım. Yalnız burada bir C işlevinin bir D sınıfının üyesi olması size de ilginç gelmedi mi. C kodu olunca artık sınıf üyelerine erişemezdir herhalde değil mi.

Merak eden arkadaşlar için kodun tamamını gönderiyorum.
import gtk.Main;
import gtk.MainWindow;
import gtk.Box;
import gtk.Entry;
import gtk.EditableIF;
import gtk.TreeModelFilter;
import gtk.TreeView;
import gtk.HBox;
import gtk.VBox;
import gtk.Label;
import gtk.ListStore;
import gtk.TreeViewColumn;
import gtk.CellRendererText;
import gtk.TreeModel;
import gtk.TreeIter;
 
import std.conv;
import std.stdio;
import std.string;
 
class Pencere: MainWindow
{
    Box anaKutu;
    Entry giriş;
    TreeModelFilter süz;
    TreeIter erişici;
 
    this()
    {
        super("Ağaç örneği 3");
        setSizeRequest(500, 200);
        giriş = new Entry();
 
        giriş.addOnChanged((giriş) {metinDeğişti(giriş);});
        auto girişEtiket = new Label("Sanatçı ara");
 
        auto ağaç = new TreeView();
        auto kutu = new VBox(false, 0);
 
        auto veriModeli = new ListStore([GType.STRING, GType.STRING]);
        auto sanatçıSütunu = new TreeViewColumn("Sanatçı", new CellRendererText(), "text", 0);
        ağaç.appendColumn(sanatçıSütunu);
        auto şarkıSütunu = new TreeViewColumn("Şarkı ismi", new CellRendererText(), "text", 1);
        ağaç.appendColumn(şarkıSütunu);
 
 
        erişici = veriModeli.createIter();
        veriModeli.setValue(erişici, 0, "Ali Veli");
        veriModeli.setValue(erişici, 1, "Bir şeyler söyle");
 
        erişici = veriModeli.createIter();
        veriModeli.setValue(erişici, 0, "Ali Veli");
        veriModeli.setValue(erişici, 1, "Başka bir şeyler söyle");
 
        erişici = veriModeli.createIter();
        veriModeli.setValue(erişici, 0, "Ahmet fuat özkan");
        veriModeli.setValue(erişici, 1, "Çorba yapalım");
 
        süz = new TreeModelFilter(veriModeli, null);
        süz.setVisibleFunc(cast(GtkTreeModelFilterVisibleFunc)  &ağacıSüz, cast(void *)this, null);
 
        ağaç.setModel(süz);
 
        auto anaKutu = new HBox(false, 0);
        anaKutu.packStart(girişEtiket, false, false, 5);
        anaKutu.packStart(giriş, true, true, 5);
        kutu.packStart(anaKutu, false, false, 5);
        kutu.packStart(ağaç, true, true, 5);
 
        add(kutu);
 
        showAll();
    }
 
    static extern(C) int ağacıSüz(GtkTreeModel* gtkModeli, GtkTreeIter* gtkErişici, void* veriler)
    {
        auto model1 = new TreeModel(gtkModeli, false);
        auto erişici1 = new TreeIter(gtkErişici, false);
 
        string sanatçıİsmi = model1.getValue(erişici1, 0).dupString();
 
        Pencere pencere = cast(Pencere) veriler;
        assert(pencere !is null);
 
        if (pencere.giriş.getText() == "")
            return true;
 
        if (indexOf(sanatçıİsmi, pencere.giriş.getText()) > -1)
            return true;
        else
        {
            return false;
        }
 
    }
 
    void metinDeğişti(EditableIF giriş)
    {
        süz.refilter();
    }
}
 
 
void main(string[] args)
{
    Main.init(args);
    new Pencere();
    Main.run();
}
acehreli (Moderatör) #8
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4513 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
extern(C) işlevin yalnızca nasıl çağrıldığı ile igili bir konu. İçindeki kodlar burada da görüldüğü gibi D olabilir. Evet, sınıf üyelerine erişemezsin ama işlevin 'static' olması da zaten o etkiyi yapıyor.

Öğrenmek için denemeni öneririm, 'static extern(C)' üye yerine sınıf dışında basitçe 'extern(C)' de olabilirdi.

Parçalanma arızasının bence asıl nedeni, new Pencere() yapıyorsun ama onu hiçbir değişkende tutmuyorsun. main içindeki Main.run() sırasında yeni bellek ayrılması gerekse senin adsız Penceren uçup gider. ağacıSüz içinde şu satırda elde ettiğin sınıf referansı artık varolmayan bir nesneye eriştirmeye çalışacaktır:
    Pencere pencere = cast(Pencere) veriler;
Ali
erdem (Moderatör) #9
Üye Tem 2009 tarihinden beri · 958 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
 MVC tasarım desenini kullanarak kodu bölmek istediğimizi düşünelim. Bu durumda sizce süz işlevini hangi sınıf tanımlamalı?

class Pencere: MainWindow
{
    this()
    {
        /* ... */
        auto model =  new VeriModeli();
        auto görünüm = new GörünümModeli(model);
    }
}
 
class VeriModeli: ListStore /* model */
{
    this()
    {
        super([GType.STRING, GType.STRING]);
    }
 
    /* ... */
 
}
 
class GörünümModeli: TreeView /* görünüm */
{
    TreeViewColumn isimSütunu, söyleyenSütunu;
    TreeModelFilter süz_;
 
    this (ListStore model)
    {
        /* ... */
        süz_ = new TreeModelFilter(model, null);
 
        süz_.setVisibleFunc(cast(GtkTreeModelFilterVisibleFunc) & süz,
                            null, null);
        setModel(süz_);
    }
 
 
    static extern(C) int süz(GtkTreeModel * gtkModeli, GtkTreeIter * gtkErişici, void * veriler)
    {
        /* ... */
    }
}
 
 
void main(string[] args)
{
    Main.init(args);
    auto pencere = new Pencere();
    Main.run();
}

İlk seferde süzme işlemi aslında bir görünüm değişikliği olduğu için görünüm modelinde tanımlanmalı diye düşündüm.
acehreli (Moderatör) #10
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4513 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
MVC'yi hiç kullanmadım (belki farkında olmadan kullanmışımdır :) ) ama bildiğim kadarıyla görünüm modelinin gösterme işinden başka bilgisi yok. Örneğin, A ve B değişkenleri arasında A=3*B gibi bir ilişki olduğuyla ilgilenmemeli.

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-10-22, 01:06:14 (UTC -07:00)