月別アーカイブ: 2010年7月

SeeMe for Windows 5.0.0

SeeMe for Windows 5.0.0 公開。
実は大半が二日前に終わっていたのですが、たった一箇所で二日掛かった。
Deleted プロパティ変更を SeeMe 本体でどうやって検知するかで。

INotifyPropertyChanged によって ListView にはバインディングされているんだけど…

<Window.Resources>
<DataTemplate x:Key="tpl_show">
    <CheckBox IsChecked="{Binding Path=delete}" IsTabStop="False" Click="CheckBox_Click" />
</DataTemplate>

と C# で作っていた時には DataTemplate で CheckBox.Click イベントのハンドラを指定していた。
こうしておけばこの DataTemplate を利用した CheckBox 全てに同一ハンドラがコネクトされる。
クリックで property が変更されましたというのを本体で知りたいだけなのでコレで十分。

IronPython では partial class にする方法が解らない(方法あるの?)というのと
SeeMe for Linux の GTK+ と限界までソックリにしたいということで ListView をパーツ化した。
結果イベントハンドラのコネクトはコードで行う以外に手が無い。

ListView サブクラスを作って partial にして XAML の x:Name 属性を…
散々試してみたんだがどうしても上手くいかない、やはり無理か?

えっと、ハンドラを含めたリソースをコードで書いて…
方法が解らない、つかそんなことできるのかいな?

res = self.custome_listview.FindResource("tpl_show")
print res
checkbox = res.LoadContent()
print checkbox
checkbox.Click += self.on_modification

例外にならないけど反映されない、困った。
海外を探しまくったけどやはり IronPython の細かい情報は少ない…

まてよ、INotifyPropertyChanged を利用しているんだ。
それならコイツを引っ張り出して CheckBox の変更を感知すればいいかも。
無理に Click イベントに拘る必要は無かったのではないか?

と気が付くまで二日も無駄にしたというわけです…

while 1:
    i += 1
    s = "Search Engine %i" % i
    if not ini.section_exists(s):
        break
    en = Engine()
    en.name   = ini.read_str(s, "Name", "")
    en.key    = ini.read_str(s, "Key", "")
    en.url    = ini.read_str(s, "URL", "")
    en.delete = not ini.read_bool(s, "Deleted", False)
    #...
    en.PropertyChanged += self.on_modification
    self.custome_liststore.Add(en)

という感じで PropertyChanged にハンドラをコードで追加メソッドにできる。
しかもコレなら全部のプロパティ変更を監視できるので自前検知処理を減らすことができる。
でもコレだけでは ObservableCollection への追加や削除は検知できないので

self.custome_liststore = ObservableCollection[Engine]()
#...
self.custome_liststore.CollectionChanged += self.on_modification

と CollectionChanged イベントにもハンドラを指定。
コレでやっと予定していたとおりの動作になった。
WPF が複雑すぎるのではなかった、自分が方法に気が付かなかっただけだ。
細かいことは SeeMe スクリプトの Python コードを見てください。

ということで予定を大幅に遅れて Windows 版公開。
メソッド名やアトリビュート名は Linux 版とだいたい合わせたので今後更新は早くなる。
と思う、つか Aspire 1410 ミニノートだけで作るのは結構辛い…

SeeMe V5 002

SeeMe for Windows v4 で一番気にしている部分。
エディット部の XAML が超テキトーであること…

Grid のレイアウトがよく解らなかったので StackPanelのみでレイアウト。
自分で見ても解り辛い、何故か下方から積み上げる最悪のコーディング。
今の私ならパネルを噛ませる技なんかを使うけど当事は手探りだったし。

IronPython でゼロから作り変えするんだ、そろそろなんとかしなければ。
ということで Grid を利用して Linux 版の GTK+ と同じになるようにする。
ちなみに Linux 版のエディット部は GtkTable を継承して

class IniEditor(gtk.Table):
    """
        カスタムタブのエディタ部
    """
    def __init__(self):
        gtk.Table.__init__(self, 6, 7)
        label = []
        for i in range(len(editor_labels)):
            l = gtk.Label(editor_labels[i])
            label.append(l)
        self.edit_name = gtk.Entry()
        self.attach(self.edit_name, 1, 2, 0, 1)
        self.edit_key = gtk.Entry()
        self.attach(self.edit_key, 3, 5, 0, 1, 0)
        self.edit_url = gtk.Entry()
        self.attach(self.edit_url, 1, 6, 1, 2)
        self.edit_query = gtk.Entry()
        self.attach(self.edit_query, 1, 6, 2, 3)
        self.edit_uniqueid = gtk.Entry()
        self.attach(self.edit_uniqueid, 1, 5, 3, 4)
        self.check_post = gtk.CheckButton(editor_checks[0])
        self.attach(self.check_post, 5, 6, 3, 4, gtk.FILL)
        self.edit_icon = gtk.Entry()
        self.attach(self.edit_icon, 1, 5, 4, 5)
        self.check_separator = gtk.CheckButton(editor_checks[1])
        self.attach(self.check_separator, 5, 6, 4, 5, gtk.FILL)
        self.edit_encode = gtk.Entry()
        self.attach(self.edit_encode, 1, 4, 5, 6)
        self.edit_type = gtk.Entry()
        self.attach(self.edit_type, 5, 6, 5, 6, 0)
        # Label
        self.attach(label[0], 0, 1, 0, 1, gtk.FILL)
        self.attach(label[1], 2, 3, 0, 1, 0, xpadding=10)
        self.attach(label[2], 0, 1, 1, 2, 0)
        self.attach(label[3], 0, 1, 2, 3, 0)
        self.attach(label[4], 0, 1, 3, 4, 0)
        self.attach(label[5], 0, 1, 4, 5, 0)
        self.attach(label[6], 0, 1, 5, 6, 0)
        self.attach(label[7], 4, 5, 5, 6, 0)
        self.etc_label = gtk.Label("<span color=\"darkgreen\">Verfbtext =  Position =  NameID =  UseTLD =  </span>")
        self.etc_label.set_use_markup(True)
        #self.etc_label.set_justify(gtk.JUSTIFY_LEFT)
        self.etc_label.set_alignment(0.1, 1.0)
        self.attach(self.etc_label, 0, 6, 6, 7)
        # Button
        self.button = gtk.Button("リストに反映")
        self.attach(self.button, 5, 6, 0, 1, 0)

こうはやりたくないなぁ…
やはりメニュー等と同様に XAML で綺麗に仕上げたい。

とりあえず基本的にコントロールサイズに Column を合わせるには Auto を指定。
サイズ変更した時に表示名エディット部は連動して広がるように。
マージンが必要な所は Margin プロパティを指定。

editor_str = """<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>

    <Label Grid.Row='0' Grid.Column='0'>表示名</Label>
    <TextBox Grid.Row='0' Grid.Column='1' Grid.ColumnSpan='1' Name="edit_name" />
    <Label Grid.Row='0' Grid.Column='2'>キー</Label>
    <TextBox Grid.Row='0' Grid.Column='3' Grid.ColumnSpan='2' Name="edit_key" />
    <Button Grid.Row='0' Grid.Column='6' Grid.ColumnSpan='1' Margin="20,0,20,0" Name="button">リストに反映</Button>

    <Label Grid.Row='1' Grid.Column='0'>URL</Label>
    <TextBox Grid.Row='1' Grid.Column='1' Grid.ColumnSpan='5' Name="edit_url" />

    <Label Grid.Row='2' Grid.Column='0'>クエリ</Label>
    <TextBox Grid.Row='2' Grid.Column='1' Grid.ColumnSpan='5' Name="edit_query" />

    <Label Grid.Row='3' Grid.Column='0'>UNIQUEID</Label>
    <TextBox Grid.Row='3' Grid.Column='1' Grid.ColumnSpan='4' Name="edit_uniqueid" />
    <CheckBox Grid.Row='3' Grid.Column='5' Grid.ColumnSpan='2' Name="check_post">POSTで送信</CheckBox>

    <Label Grid.Row='4' Grid.Column='0'>ICON</Label>
    <TextBox Grid.Row='4' Grid.Column='1' Grid.ColumnSpan='4' Name="edit_icon" />
    <CheckBox Grid.Row='4' Grid.Column='5' Grid.ColumnSpan='2' Name="check_separator">下にセパレータ</CheckBox>

    <Label Grid.Row='5' Grid.Column='0'>エンコード</Label>
    <TextBox Grid.Row='5' Grid.Column='1' Grid.ColumnSpan='3' Name="edit_encode" />
    <Label Grid.Row='5' Grid.Column='4'>サーチタイプ</Label>
    <TextBox Grid.Row='5' Grid.Column='5' Grid.ColumnSpan='2' Name="edit_type" />

    <Label Grid.Row='6' Grid.Column='0' Grid.ColumnSpan='6' Name="label_etc" Foreground="DarkGreen">Verbtext Position NameID UseTLD</Label>
</Grid>"""

なんとか同じようになった、しかし

GTK+ と違って WPF は縮めるとこうなってしまう…
MinWidth とか数値プロパティでではなくコントロールサイズを最小サイズにしたい。
知らないだけで方法があるのだろうか?

んで、コントロール名を元にアトリビュートを作成。
ということで下記のようなコードを書いてみたのだが。

self.editor = XamlReader.Parse(editor_str)
self.editor.edit_name = self.editor.FindName("edit_name")
self.editor.edit_name.Text = "abcde"
DockPanel.SetDock(self.editor, Dock.Bottom)

なんでだよ、Python なのにアトリビュートにできないじゃん。
しかたがないからダミーのクラスを作ってみる。

class Editor():
    pass

class SeeMe(Window):
    def __init__(self, sset):
        # ...
        self.editor = Editor()
        edit = XamlReader.Parse(editor_str)
        self.editor.edit_name = edit.FindName("edit_name")
        self.editor.edit_name.Text = "abcde"
        DockPanel.SetDock(edit, Dock.Bottom)

これなら上手くいく。
XAML から作成すると Python オブジェクトとして扱ってくれないようだ。
IronPython は Python クローンだと思って使うと色々落とし穴がありますね。

seeme5_002.zip

どうでもいいけど readme.txt と ChangeLog.txt を BOM 付き UTF-8 に。
Python コードは BOM 無し UTF-8 に、色々と事情があってコレに統一。
それと改行を CRLF にしとかないと notepad.exe で改行してくれない。
Windows って面倒くさいなぁ…

見た目はなんとかなったので後は編集コードの作成だ。
連休だけど月曜は仕事だ、明日には仕上がるだろうか…

追記 @ 2010.07.19
進んでいないけど盗難が怖いのでバックアップ、畜生、夏のやろう!

seeme5_003.zip

追記 @ 2010.07.20
エディタ部への設定書き出しを実装、思っていたより手間が掛かる。
そういえば Linux 版は競合キーチェックを入れ忘れしていた…
ついでに Has endseparator をマイナスにしていない、10.60 では無意味な部分だが。

seeme5_004.zip

追記 @ 2010.07.21
__init__.pyw というファイル追加、コレを ipyw(64).exe に関連付けかドロップ。
としておけば Python ワカンネな人でも理解しやすいかも?と思ったので…
ini 保存は色々あって UTF-8 に BOM を付けるようにした。
デフォルト uuid 指定タブもなんとか完成、もう変更できるようにしておいた。
Item の編集と削除は実装したけど新規追加や並べ替え処理はまだ実装していない。
Linux 版とアトリビュート名やメソッド名合わせを考えなければもっと早く作れるけど…
次の日の仕事に影響が出ない範囲で作っているのもあって我ながら遅い…

seeme5_005.zip

Microsoft.Win32.OpenFileDialog for .NET 4.0

今日 IronPython を少し試していて気が付いたのだが

# -*- coding: UTF-8 -*-

import clr

clr.AddReferenceByPartialName("PresentationFramework")

import Microsoft

def dlg_open():
    dlg = Microsoft.Win32.OpenFileDialog()
    dlg.ShowDialog()

dlg_open()

あれ?Windows 7 標準のダイアログになった。
この関数だと XP 時代の古いダイアログになってしまうはずなのに。
x64 の Windows 7 だからなのか IronPython が .NET 4.0 版だからなのか?

IronPython – Release: 2.6.1

試しに .NET 2.0 版の IronPython zip 版も落として実験。
同じコードを動かしてみる。

やはり 2.0 版だと Windows 7 でも古いまんまだ。
なるほど、.NET 4.0 は同じ関数でも地味に改良してくれているんだね。
WPF を使うのが少し楽になった、地味に調べてみると面白いかもしれない。

SeeMe V5 001

SeeMe for Windows の Opera 10.60 対応版は IronPython で作ります。
一年前に途中まで作ってみたけど色々あってボツにした下記をベースで。

SeeMe is to IronPython

Linux しか使わなくなった作者が Windows のアプリを作るのは苦痛でしかない。
というより作者自身が使わないアプリを作ってもメンテナンスに疑問が残る。
こんな需要が少ないアプリを他の人がやってくれるとも思えない。
それより今の C# という言語が自分の趣味に合わない、Ruby が嫌いな理由と同じ。
ついでに VisualStudio を使いたくない、コンパイルもメンドクサイ。

一週間悩んだ結果、好き勝手にやることにした。
使いたい人は IronPython を導入してくれ、というトンデモネェ暴挙をマジでやる。

もちろんスクリプトのままで配る。
Windows しか使えない人の大半は EXE でないと拒否反応をするのは知っている。
それがキッカケで IronPython に興味を持ってくれる人が増えれば嬉しい。

戯言終わり、ということで。

xml:lang

現行の IronPyton では XAML に xml:lang=”ja-JP” を追記せずとも文字化けしない。
結局アレは IronPython のバグだったのだろうか?

WPF ListView DataBinding for IronPython

この pyevent.py をコピーさせなければいけないのもなんとかしたい。
ということでよく考えてみたらコレでいいのでは?と。

from System import *
from System.ComponentModel import *

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

zip 版でも exe パス直下に Tutorial ディレクトリがあるのでイケるはず。
なんにせよ INotifyPropertyChanged は使わなければいけないわけで。
ただ zip 版を考えると os.path.join() は使えない…
追記 System.IO.Path.Combine() ってのがあった。

.NET Framework required BOM

この件もあった…
inifile8.py は他に os.path.exists を System.IO.File.Exists に書き換えて…
sys は組み込まれているけど他は Python 標準モジュールを使わないように…

SeeMe for Linux と共用できるコードがほとんど無いんだなコレが。

あとは x64 を見分けて Opera デフォルトインストール場所振り分けとか。
それから何があったかなぁ?もう少し更新が遅れるのはご了承。
とりあえず現在までのバックアップ。

seeme5_001.zip

少し楽しくなってきた、こんなことをやりながら作り上げていくのが楽しいんだよね。
「プログラミングを楽しむ」と「アプリを作って楽しむ」とでは実は少し違うのよ。

Mandriva 2010.1?

Mandriva Linux 2010.1 Finally Released – The Spring version of Mandriva Linux 2010 – Softpedia

http://fundawang.lcuc.org.cn/mandriva/official/iso/2010.1/

見つけたけど上記だと転送が 20KB/s くらい、日本の FTP サーバーに来るのを待つか。
ATI Radeon video driver 6.13 って X.Org 7.5 に対応しているのだろうか?
作りによっては Ubuntu から Mandriva One GNOME に戻るけど、どうなんだろう。
実際ココまでリリースが遅れると今後がかなり不安…