SeeMe」タグアーカイブ

SeeMe for Windows v4.0.1

あわわ、v4.0.0 はプロファイル編集ができないじゃんコレ。
ここは弄くっていないので前からか、まぁ普通はデフォルト位置で十分だし。

とはいえ放置もアレなので修正しようかどうか、そういえば

ぱぇぽぃ2 ? Blog Archive ? GetFullPath

のようにファイルドロップでフルパス指定にしようとして忘れていた!
なんたってそうすれば System.Windows.Form への参照を排除できる。
WPF なのに OpenFileDialog のためだけに WindowsForm を参照していたし。
よく見たら System.Xml.Linq まで…こんなの SeeMe で使っていないよ。

ということで AboutDlg のように上記 IronPython コードを C# 化…
しようと思ったけど面倒なのでハンドラの追記だけで済ませた。

ちなみに

ぱぇぽぃ2 ? Blog Archive ? WPF Hyperlink class for IronPython

の C# 化はこうやった。

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Text;
using System.Windows.Media;
using System.Collections.Generic;

namespace SeeMe4
{
    class About : Window
    {
        public About(Window owner)
        {
            this.Owner = owner;
            this.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            this.Title = "About SeeMe for Windows";
            this.SizeToContent = SizeToContent.WidthAndHeight;
            this.ResizeMode = ResizeMode.NoResize;
            this.Icon = owner.Icon;
            // StackPanel
            var panel = new StackPanel();
            // Dialog Icon and Image
            var img = new Image();
            img.Source = owner.Icon;
            img.Width = 32;
            img.Height = 32;
            panel.Children.Add(img);
            // Create TextBlock List
            var v = new List<TextBlock>();
            for (int i = 0; i < 5; i++)
            {
                var b = new TextBlock();
                panel.Children.Add(b);
                v.Add(b);
            }
            v[0].Inlines.Add( new Bold(new Run("SeeMe for Windows 4.0.0\n")));
            v[1].Text = "Windows Version ( " + Environment.OSVersion.Version + " )";
            v[2].Text = "CLR Version ( " + Environment.Version.ToString() + " )\n";
            v[3].Text = "Copyright(c)2003-2009 by sasakima-nao";
            var url = new Hyperlink(new Run("http://palepoli.skr.jp/"));
            url.Click +=new RoutedEventHandler(url_Click);
            v[4].Inlines.Add(url);
            // Align Right button
            var btn = new Button();
            btn.Content = "Close";
            btn.Click += new RoutedEventHandler(btn_Click);
            DockPanel.SetDock(btn, Dock.Right);
            var dp = new DockPanel();
            dp.LastChildFill = false;
            dp.Children.Add(btn);
            panel.Children.Add(dp);
            // Append
            this.Content = panel;
        }

        void btn_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        void url_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://palepoli.skr.jp/");
        }
    }
}

スクリーンショットを撮って気がついたが About のバージョンが 4.0.0 のままだ…
まあいいや、次の更新で直しておこう。

about_win

型指定がメンドクサイので var を使ったが何もかも IronPython より面倒。
中括弧とセミコロンと new と var が増えリストを System.Collections.Generic です。
特にハンドラ指定の RoutedEventHandler みたいなのってマジ書かなくてもよくないか?
こんなの Visual Studio エディタの助けが無かったら私は書けなかったかもだよ。

やっぱりこれからは IronPython だよ、EmEditor だけでデバッグもできるし。

WPF Hyperlink class for IronPython

SeeMe for Windows v4 beta2 のソースにコッソリ書いているが、
Hyperlink クラスをコードで作る方法が解らなかった。

Hyperlink クラス (System.Windows.Documents)

なんだよ、MSDN に普通に書いてあるや、どこを探していたのやら。
つまり Bold とかと同じように使えばいいということねん。

ぱぇぽぃ2 ? Blog Archive ? 初心者同然

よし、これで Linux 版の GtkAboutDialog と同じレイアウトにしてみる。
Windows 自体というか WPF だけでも専用ダイアログを用意してほしいんだが。

class AboutDlg(Window):
    """
        SeeMe About class
    """
    def __init__(self, owner, path):
        """
            Hyperlink, Run
            from System.Windows.Documents import *
        """
        self.Owner = owner
        self.path = path
        self.WindowStartupLocation = WindowStartupLocation.CenterOwner
        self.Title = "About SeeMe for Windows"
        self.SizeToContent = SizeToContent.WidthAndHeight
        self.ResizeMode = ResizeMode.NoResize
        self.Icon = BitmapFrame.Create(Uri(self.path + "\\img\\seeme.ico"))
        # StackPanel
        panel = StackPanel()
        # Dialog Icon and Image
        img = Image()
        img.Source = BitmapImage(Uri(self.path + "\\img\\seeme.ico"))
        img.Width = 32
        img.Height = 32
        panel.Children.Add(img)
        # Create TextBlock List
        v = []
        for i in range(5):
            b = TextBlock()
            panel.Children.Add(b)
            v.append(b)
        v[0].Inlines.Add(Bold(Run("SeeMe for Windows 5.0.0\n")))
        v[1].Text = "Windows Version ( %s )" % Environment.OSVersion.Version
        v[2].Text = sys.version + "\n"
        v[3].Text = "Copyright(c)2003-2009 by sasakima-nao"
        url = Hyperlink(Run("http://palepoli.skr.jp/"))
        url.Click += self.on_url
        v[4].Inlines.Add(url)
        # Align Right button
        btn = Button()
        btn.Content = "Close"
        btn.Click += self.on_exit
        DockPanel.SetDock(btn, Dock.Right)
        dp = DockPanel()
        dp.LastChildFill = False
        dp.Children.Add(btn)
        panel.Children.Add(dp)
        # Append
        self.Content = panel

    def on_url(self, sender, e):
        Diagnostics.Process.Start("http://palepoli.skr.jp/")

    def on_exit(self, sender, e):
        self.Close()

コレを Show() でオーナーウインドウから呼び出す

def on_about(self, sender, e):
    about = AboutDlg(self, self.path)
    about.Show()

about_dialog

ちょっとデザインが違うけど Windows ではこういう感じのほうが好まれそう。
WPF 使っているのに .NET 2.0 がどうのと出るのが少しだけ気に入らない。
つーかまだアルファにも達していないので自身のバージョン表記が滅茶苦茶だ。

とりあえず Hyperlink クラスの使い方はこれでオケのようだ。
たったコレだけのコードで About 完成、XAML ってマジで無駄だと思った。

今日はココしかやっていないのでバックアップはヤメとこう。

.NET Framework required BOM

デフォルトの search.ini や lng 読み込みで文字化けする理由が判明。
BOM が付いていない UTF-8 文書は UTF-16 文字列に変換読み込みしてくれないということ…

何を今更 BOM での判別といい UNICODE と cp932 の混在といい…
もうイヤだこの変態 OS は、全てが UTF-8 である最近の Linux を見習ってくれ!

Python 組み込みの open() では読み込んだ後に変換しかできないわけだから、方法ある?
System.IO.StreamReader と System.Text.Encoding.UTF8 を普通に使うのが一番だよな。
StreamReader オブジェクトは for ループに…やっぱり無理か。

import os

# 略

class Inifile(InifileBase):
    def __init__(self, filename):
        InifileBase.__init__(self, filename)
        self.header = ""
        self.ini = []
        if os.path.exists(filename):
            f = open(filename)
            x = f.read()
            f.close()
            lines = x.split("\n")
            section = ""
            for line in lines:
                if line == "":
                    continue
                if len(line) > 2 and line[0] =="[" and line[-1] == "]":
                    section = line[1:-1]
                elif section == "":
                    pass # 何もしない
                elif "=" in line:
                    pos = line.index("=")
                    self._add(section, line[:pos], line[pos+1:])

from System.IO import *
from System.Text import *

# 略

class Inifile(InifileBase):
    def __init__(self, filename):
        # ベースクラスでアトリビュートを利用する場合は IronPython でも必要
        InifileBase.__init__(self, filename)
        self.header = ""
        self.ini = []
        #if os.path.exists(filename):
        if File.Exists(self.filename):
            f = StreamReader(self.filename, Encoding.UTF8)
            try:
                section = ""
                while 1:
                    line = f.ReadLine()
                    if line == None:
                        break
                    if line == "":
                        continue
                    if len(line) > 2 and line[0] =="[" and line[-1] == "]":
                        section = line[1:-1]
                    elif section == "":
                        pass # 何もしない
                    elif "=" in line:
                        pos = line.index("=")
                        self._add(section, line[:pos], line[pos+1:])
            finally:
                f.Close()

utf8read

大体同じに仕上げたけど Linux 版とコード共有はもうあきらめるしかない。
組み込みの open とは違い StreamReader は Close 必須なので忘れないでね。
しかし私は無限ループを作って null で抜けるコードばかりだ、一番単純に書けるのよね。
if not line: だと空文字も拾ってしまうのは Python という言語の常識かな。

ついでに継承ベースクラスの __init__() が不要の IronPython も必要な場合があると解った。
ここではベースクラスで self.filename を定義しているだけなんだが、そういう場合に。
だから無意味に呼び出しても結果が同じなのか、ふむふむ。

これならコンストラクタ化されているというのに自由に __init__() を定義できる。
C++ の継承で頭を抱えた経験がある人にしか解らないだろうけど嬉しい仕様だ。

seeme_a405.zip

次はメニューの文字化けか、一部だけ化けるというのが理解に苦しむ。

こんなノロノロ作っている間に Opera 10 が RC になっているわ。
SeeMe for Windows v4 はもうしばらく C# つまり exe 形式のままね。
そのほうがいいという人のほうが多いと知っているけどシラネ!

GtkNoteBook and TabControl

SeeMe for Linux では GtkNoteBook の各ページは Python の List でアクセス。

note = gtk.Notebook()
page = []
for i in range(4):
    tab = gtk.Label(tab_label[i])
    page.append(gtk.VBox())
    self.note.append_page(page[i], tab)
page[0].pack_start(self.sw1)
page[1].pack_start(self.sw2)

という方法を見つけたけど IronPython でも同じようにできるのかな?
.NET Framework では TabControl と TabItem なんていうものを使う。
まあこんなのは実際にやってみるのが早い。

note = TabControl()
self.page = []
for i in range(3):
    page = TabItem()
    page.Header = tab_label[i]
    note.AddChild(page)
    self.page.append(page)
self.page[0].Content = self.custome_listview
self.page[1].Content = self.default_listview

tab1

おぉ同じように使えるじゃないの!
XAML で作っているとこんな添え字でのアクセスは考え付きもしないだろう。
リストの添え字アクセスにメリットを感じるかどうかで人それぞれだと思うけど。

だけど…

tab2

又しても文字化けだよ。
lng ファイルは for Linux で使っている InifileReader クラスで読んでいるののだが…
もしかして一度全部読み込まないと UTF-8 を UTF-16 に自動変換できないのかな?
メニューの文字化けも解決していないしまいった、以下今日のバックアップ。

seeme_a404.zip

GetFullPath

ぱぇぽぃ2 ? Blog Archive ? Opera WMV

の最後でカレントディレクトリからでは端末で絶対パス名を取れない場合があると書いた。
待てよ? os.path が無い IronPython ではどうやるのだろう?

Path メンバ (System.IO)

System.IO.Path で普通に GetFullPath メソッドがあった。
そういえば IronPython では __file__ は使えるのだろうか?
ということで試してみる。

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

import sys
import System

print sys.argv[0]
print __file__
print System.IO.Path.GetFullPath(__file__)

abspath

あぁやはりカレントディレクトリではこうなるのか。
見落とししやすい所なので注意したほうがいいね、cmd.exe から起動しない!と言わない。

それと。

ShowDialog() メソッドで開いた Window で Value を参照しようとすると例外になる。
調べると ShowDialog() の戻り値自体が Boolean になっている、C# と違うじゃん。
何故?よく解らないけどコンパイルしないとこういう結果になるのかな。

それと。

バックアップを試せば解るけど Welcome クラスは Application インスタンスを作成していない。
それなのに Window が普通に動くんだが、メッセージループはどうなっているの?
試しに Show() メソッドで表示してみたら即終了、なるほどそういうことなのか。
Window は ShowDialog() メソッドを使うなら Application インスタンスから動かす必要は無いのね。
何のことか解らない人は Windows アプリは何故動くのかを勉強しておこう、→の本で。

ついでに Welcome のインスタンスを作ったらその中で sys.exit() できなかった。
その前に Close() しなきゃいけないのか、ふむふむ。

それと。

GtkEntry は Nautilus からファイルをドロップするとファイルのフルパスが流し込まれる。
Linux 版と動作を合わせたいので「ようこそ」のフルパス入力部で同じようにしたい。
つか「ファイルの参照ダイアログ」は使いたくないだけだが、多分使う人はいないと思うし。
「minipoli を使え」にしてもイイけどそれはやはりあんまりかと。

[WPF]ドラッグアンドドロップ

検索したら簡単に方法が見つかった、IronPython 言語への書き換えも普通どおり。
あぁ Windows の開発は楽チンだなぁ…日本語でアッサリ見つかるんだもの。
PyGtk になると日本語では実用的コードなんかまったく見つからないからね。

今日は結構勉強になった。
Ubuntu 上の VirtualBox で動かしている Windows 7 RC でやったほうが開発が楽しいなんて…
困ったら即 Ubuntu に戻れるからだろうけどさ、ということで今日のバックアップ。

welcomedlg

seeme_a403.zip

とりあえず「ようこそ」だけ移植完了、先はまだ長い。