投稿者「sasakima-nao」のアーカイブ

WPF ListView DataBinding for IronPython

ぱぇぽぃ2 ? Blog Archive ? Python getter, setter
の続き、上手くいったので覚書に。
ObservableCollection を作って ListView で DataBinding させる。

Silverlight Dynamic Languages SDK – Discussions

ほう、こうすればいいんだ。
コレを IronPython 2.6 から使える property setter でやってみる。

{ironpythondir}/Tutorial/pyevent.py
をソースコードと同じ場所にコピー

追記と小変更

pyevent.py の import はこうすればコピー不要

import sys
tutorial_path = IO.Path.GetDirectoryName(sys.executable) + "\\Tutorial"
sys.path.insert(0, tutorial_path)
from pyevent import *

データトリガーなんかをコードで行う方法が解らないので XAML で。
以下ソースコード

#-*- coding:utf-8 -*-

import clr

clr.AddReferenceByPartialName("PresentationCore")
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("WindowsBase")

from System import *
from System.Windows import *
from System.Windows.Controls import *
from System.Collections.ObjectModel import *
from System.ComponentModel import *
from System.Windows.Markup import XamlReader

# Search pyevent.py
import sys
tutorial_path = IO.Path.GetDirectoryName(sys.executable) + "\\Tutorial"
sys.path.insert(0, tutorial_path)
from pyevent import *

listview_str = """<ListView
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ListView.Resources>
        <Style x:Key="sensitive" TargetType="TextBlock">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=show}" Value="False">
                    <Setter Property="Foreground" Value="Silver" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
        <DataTemplate x:Key="tpl_show">
            <CheckBox IsChecked="{Binding Path=show}" />
        </DataTemplate>
        <DataTemplate x:Key="tpl_name">
            <TextBlock Text="{Binding Path=name}" TextTrimming="CharacterEllipsis"
                Style="{StaticResource sensitive}" />
        </DataTemplate>
    </ListView.Resources>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Show" CellTemplate="{StaticResource tpl_show}" />
            <GridViewColumn Header="Name" CellTemplate="{DynamicResource tpl_name}" />
        </GridView>
    </ListView.View>
</ListView>"""

class NotifyPropertyChangedBase(INotifyPropertyChanged):
    """
        http://sdlsdk.codeplex.com/Thread/View.aspx?ThreadId=30322
    """
    PropertyChanged = None
    def __init__(self):
        (self.PropertyChanged, self._propertyChangedCaller) = make_event()

    def add_PropertyChanged(self, value):
        self.PropertyChanged += value

    def remove_PropertyChanged(self, value):
        self.PropertyChanged -= value
    
    def OnPropertyChanged(self, propertyName):
        self._propertyChangedCaller(self, PropertyChangedEventArgs(propertyName))


class MyData(NotifyPropertyChangedBase):
    """
        use setter getter.
        IronPython 2.6 or later.
    """
    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value
        self.OnPropertyChanged("name")

    @property
    def show(self):
        return self._show

    @show.setter
    def show(self, value):
        self._show = value
        self.OnPropertyChanged("show")

class DataBindingTest(Window):
    """
        ListView DataBinding Test class
    """
    def __init__(self):
        self.data = ObservableCollection[MyData]()
        self.Resources["data"] = self.data
        self.listview = XamlReader.Parse(listview_str)
        self.listview.ItemsSource = self.data
        # Temporary Data
        datadict = {"IronPython": True,
                    "C#": False,
                    "F#": True,
                    "Python": True,
                    "Ruby": False,
                    "Perl": False,
                    "C/C++": True }
        for key in datadict.keys():
            en = MyData()
            en.name = key
            en.show = datadict[key]
            self.data.Add(en)
        self.Content = self.listview
        self.Title = "DataBindingTest"
        self.Width = 300
        self.Height = 300
        # Data Check
        self.Closed += self.on_closed

    def on_closed(self, sender, e):
        """
            Checking self.data
        """
        s = ""
        for data in self.data:
            s += "%s: %s\r\n" % (data.name, data.show)
        MessageBox.Show(s)

if __name__ == "__main__":
    a = Application()
    a.Run(DataBindingTest())

data_binding_test

見事にデータ内容と表示が一致するようになりました。
CheckBox On Off で TextBlock の色が即座に変更されます。
Ruby だけ Off に変更してみた例

ruby_off

終了時に ObservableCollection の内容を確認。

off_result

CheckBox の値がそのままデータとなっていることが解ります。
IronPython でもコレが可能なんですね、2.6 正式版が待ちどおしい。

Enjoy!

Get MIME Type and Description

ファイル情報取得で MIME Type を取得したい、その2。

GnomeVFS – Wikipedia
[mew-dist 24325] Re: Content-typeの取り扱いについて

なんだ、gnomevfs ってのを使えばいいのか。

gnome-vfs python – Google Search
Python gnomevfs Reference Manual

簡単に見つかった、メリケンの google が便利すぐる。

Finding the MIME type of a file – Community Ubuntu Documentation

方法まであっさり、しかし他国でこの手を探すと Python コードがすぐ見つかる。
日本ってこんなことでもガラパゴス状態なんだよなぁと。
しかしファイルの種類は日本語での取得ができるのかな?試してみよう。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import gtk
import gnomevfs

class MimeWin2(gtk.Window):
    """
        Showing MIME Type and Description of Dropped file
    """
    def __init__(self):
        gtk.Window.__init__(self)
        dnd_list = [("text/uri-list", 0, 0)]
        self.drag_dest_set( gtk.DEST_DEFAULT_MOTION |
                            gtk.DEST_DEFAULT_HIGHLIGHT |
                            gtk.DEST_DEFAULT_DROP,
                            dnd_list, gtk.gdk.ACTION_MOVE )
        self.connect("drag_data_received", self.on_drop)
        self.label = gtk.Label("Drop")
        self.add(self.label)
        self.connect("delete-event", gtk.main_quit)
        self.resize(320, 150)
        self.show_all()

    def on_drop(self, widget, context, x, y, selection_data, info, time):
        drops = selection_data.data.split("\n")
        for drop in drops:
            if not drop == "":
                name = drop[:-1]
                mime = gnomevfs.get_mime_type(name)
                desc = gnomevfs.mime_get_description(mime)
                self.label.set_text("MIME Type = %s\nDescription = %s" % (mime, desc))

if __name__ == "__main__":
    w = MimeWin2()
    gtk.main()

mime_win2

うん、これなら拡張子無しでもなんでも完璧に Nautilus と同じだ。

dir(gnomevfs)

で見ると更にオイシソウなメソッドが見つかりますね。
ファイル情報取得はこれだけでイケそうです。
ただ GNOME 限定になるのはしかたがない。

Enjoy!

Get MIME Type

ファイル情報取得で MIME Type を取得したい。
mimetypes モジュールでは拡張子判別しかできないみたいですけど。
Nautilus は拡張子が優先だけど無くても取得できているじゃないか。
ということで地味に方法を探してみる。

ファイルの MIME タイプの検出 (GNOME 2.2 システム管理 (Linux 版)) – Sun Microsystems

/etc/gnome-vfs-mime-magic
/etc/mime.types

のファイルが元ということになっているみたいなんだが Ubuntu では

ubuntuで対応しているMIME Typeを調べるには:Linux つれづれ日記:So-net blog

/usr/share/mime 以下なのか。
xdg-mime は MIME Types のインストール関連に使うものだがどっちに登録するのかな?

つーか Nautilus が取得できているんだから絶対にシェルから取得できるはずだ。
色々調べていたらこんなのを見つけた。

Nautilus File Manager Scripts: File Information Querying Scripts

file コマンドだけでこんなことができるのか。

$ file --help

で調べると –mime-type オプションがあるらしい、それならこうしてみよう。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import gtk
import urllib
import os.path
import commands

class MimeWin(gtk.Window):
    """
        Showing MIME Type of Dropped file
    """
    def __init__(self):
        gtk.Window.__init__(self)
        dnd_list = [("text/uri-list", 0, 0)]
        self.drag_dest_set( gtk.DEST_DEFAULT_MOTION |
                            gtk.DEST_DEFAULT_HIGHLIGHT |
                            gtk.DEST_DEFAULT_DROP,
                            dnd_list, gtk.gdk.ACTION_MOVE )
        self.connect("drag_data_received", self.on_drop)
        self.label = gtk.Label("Drop")
        self.add(self.label)
        self.connect("delete-event", gtk.main_quit)
        self.resize(320, 150)
        self.show_all()

    def on_drop(self, widget, context, x, y, selection_data, info, time):
        drops = selection_data.data.split("\n")
        for drop in drops:
            name = urllib.unquote(drop)[7:-1]
            if os.path.isfile(name):
                # Get MIME Type
                mime = commands.getoutput("file --mime-type %s" % name)
                self.label.set_text(mime)

if __name__ == "__main__":
    w = MimeWin()
    gtk.main()

ext_non

おお、しっかり取得してくれているじゃないか。
しかし Python Script では

ext_py

text/x-java …
text/x-python のはずなのに、ダメだこりゃ。

mime = mimetypes.guess_type(name)[0]
if mime:
    self.label.set_text(mime)
else:
    self.label.set_text("Non Extension")

ならキチンと text/x-python になる、しかし拡張子が無いなら None になる。
んーどっちも使えない、もうちょっと調べます。

Enjoy!

create_small_image Nautilus-Script

次の覚書は GtkUIManager を利用してツールバーに独自画像を。
とやりたかったけどストック以外を指定する方法が無いみたい。
一旦個別に抜きだしして割り当てるならできそうだけどどうしよう。

ところで

gtk.gdk.Pixbuf

GDK-PixBuf には save というメソッドがあるんだね。
これは…上手く使えそう。

たとえば blog に使う大きな画像へのリンク用の小さな画像作りなんかに。
これを Nautilus スクリプトにしてしまえばそのためだけに Gimp を利用する手間が省ける。
ということで試しに書いてみる。
生成する画像の名前は WordPress が付ける名前に合わせサイズを付加する例。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

"""
    create_small_image Nautilus-Script
    written in Python.
"""

import gtk
import os

path_array = os.environ["NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"].split("\n")
for picfile in path_array:
    try:
        pixbuf = gtk.gdk.pixbuf_new_from_file(picfile)
    except:
        continue
    # Under 300*300 image
    d_width = 300
    d_height = 300
    # GdkPixbuf size
    p_width = pixbuf.get_width()
    p_height = pixbuf.get_height()
    # Calculated to fit the smaller
    width = 0
    height = 0
    if (d_width * p_height) > (d_height * p_width):
        width = p_width * d_height / p_height
        height = d_height
    else:
        width = d_width
        height = p_height * d_width / p_width
    # Create Resizeing GtkPixbuf
    small_image = pixbuf.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR)
    # Create small_image Name
    pos = picfile.rindex(".")
    image_name = "%s-%dx%d.png" % (picfile[:pos], width, height)
    small_image.save(image_name, "png")

で、Nautilus script に登録する。
Nautilus で画像を選択状態にして右クリックメニューからスクリプトを選択。

sclipt_menu

で、画像があるディレクトリに縮小された画像が生成されているはず。
てかおいおい、こんな簡単にスモール画像が作れちゃったよ。
今まで書いたスクリプトを組み合わせただけなので製作時間 15 分。

さてコレを覚書ページに…どこに入れればいいのだ?
よく解らないから blog に書いてみた。

追記

また script を sclipt と書いていた…ので書き換えておます。

Enjoy!

Who wants to program

Pythonの’,’.join()がキモいと思ってた時代が僕にもありました – by edvakf in hatena

そういえば join なんて一度も使ったことがないや。
というか join なんて実用アプリを作るのに必要な場面があるのだろうか?
リストにしたデータを全部くっつけるという場面が思い浮かばなくて困った。

オタクをピクっとさせる10の発言 | WIRED VISION

第10位の PHP を否定って意味すら解らない。
PHP は HTML 中に書け拡張子を php にして実効パーミッションを与えるだけで動かせんだよ。
だからココまで広まったし私も利用している、私はそんなにヲタクでは無かったようだ。

Ubuntu日本語フォーラム / PythonのIDEを教えてください

Python がやりたいの? IDE が使いたいの?みたいな。
IronPython Studio に至っては検索すると皆「インストールしました」で終わっている。
俺 Ubuntu では Gedit、Windows では EmEditor Professional ですけど。
ココで Emacs といかないからやっぱりヲタクにはなれない。

以前から思っていたけど趣味でプログラミングをする人は大きく分けて二種類いる。

とにかく何かアプリケーションが作りたいからプログラミングをやっている人。
それとプログラミングがやりたいからプログラミングをやっている人。

IDE がどうとかって完全にプログラミングがやりたい人でしょ。
アプリケーションが作りたい人は適材適所で言語を選んでいるだけなわけで。
文法がどうとかマジどうでもいい、所詮他人が作った言語なので従うのみ。
言語は作品を作る道具としてしか見ていないわけで。

んでアプリケーション作りで覚える必要が無いことには興味も持たない。
ラムダ式とかって普通に関数を書けばいいだけだし利用する気にもならん。

「こんなことができないかな?」
とはいつも思うが
「こんな書き方ができないかな?」
なんて思ったことなんか私は色々な言語で十年やっているけど一度も無いんですけど。

私は Python が気に入ったのではなく PyGtk が気に入ったわけだから。
Gtk+ や WPF を利用する道具として Python, IronPython を選んでいるだけ。
きっと日本の Python マニアから見ると変な人なんだろう。
ま、元々が Windows のオンラインソフト作者だもので。