Programming」カテゴリーアーカイブ

GtkGestureClick

前回 GtkPan って何だよ GtkGesturePan だろ。
まあいいか、自戒を込めてそのままのタイトルにしておこう。

ところで、ウソを書いてごめんなチャイ。
ダブルクリック検出は n_press パラメータで判別できました。
あの時は何をやっても 1 だったんだけど、実験コードを間違えていただけっぽい。

#!/usr/bin/env python3
 
import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Win(Gtk.ApplicationWindow):
    '''
        Double Click is Destroy
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # Mouse Button Press
        ges = Gtk.GestureClick()
        #ges.set_button(0) # zero is All Mouse Button
        ges.connect('released', self.on_gesture_click_released)
        self.add_controller(ges)
        # resize
        self.set_default_size(400, 300)
        # activate
        self.present()

    def on_gesture_click_released(self, ges, n_press, x, y):
        print(n_press)
        if n_press == 2:
            self.close()
        else:
            print(x)
            print(y)

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        pass

app = App()
app.run(sys.argv)

button プロパティでどのボタンを使うか選択、デフォルトは 1 なのか。
ゼロをセットでどのボタンにも反応する、なるほど。

いやそれはいいんだ。

HANDLES_COMMAND_LINE 指定で activate が発行されないまんまじゃないか!
GtkApplication は GTK3 と何も変わっていないってどうよ。
いやまあ、コイツは GLib::GApplication のサブクラスだし。
GLib 側がどうにかしてくれないとこのまんまってことだろう。

連休でイケると思ったけど全然進まなかった、今月中には。。。。。

GtkPan

困った。
Gtk ? 4.0: Migrating from GTK 3.x to GTK 4

GTK4 Python のページを作っているんだが。
GtkWdget の draw シグナルが廃止されていたのを忘れていた。

つまり枠無しウインドウで背景透過させる手段が無くなった。
これじゃ萌え萌えなデスクトップマスコットが作れないじゃん。
いや作る気は全然無いんだけど。

それと button-press-event 等が GtkGesture を使いなさいに変わった。
GtkGestureClick を試してみたけどダブルクリックの検出ができないみたい。
パンやスワイプが AppKit なんかより簡単に実装できるようになっているけど。

#!/usr/bin/env python3
 
import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Win(Gtk.ApplicationWindow):
    '''
        GtkPan Sample Code
        TouchPanel and Mouse
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # var
        self.mem_pan = -1
        # pan
        pan = Gtk.GesturePan(orientation=Gtk.Orientation.VERTICAL)
        pan.connect('pan', self.on_pan)
        self.add_controller(pan)
        # resize
        self.set_default_size(400, 300)

    def on_pan(self, ges, direction, offset):
        '''
            Pan Up on Quit
        '''
        if direction != self.mem_pan:
            self.mem_pan = direction
            if direction == Gtk.PanDirection.UP:
                self.close()

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        self.props.active_window.present()

app = App()
app.run(sys.argv)

てか GTK4 はマジでタッチパネル前提ってことですね。
過去のを残すと WindowsForm みたいに誰も WPF を使わない、みたいになるし。
AppKit もネットで見つけたコードは非推奨ばかり、みたいになるし。
GTK4 は正常進化に見えて実は過去をバッサリって感じです。

ついでに、GTK+ のドキュメントはプロパティのデフォルト値を書いていない。
GtkPan::orientation のデフォルトは HORIZONTAL だった。
自分で確かめるしか今は手段が無い、面倒なんですけど。

GTK3 のをそのまま書き換えしようと思っていたけど無理だ。
どういう感じでまとめよう?あぁまた更新が滞る。。。。。

developer.gnome.org

GNOME Development

ちょっとー!
実は地味に GTK4 Python のページ作りを進めていたんだけーが。
なんか突然変わってしもーた、先週まで今までどおりだったのに。

https://developer.gnome.org/gdk4/stable/

が 404 なんですけど、API Documents はドコにいったの???
developer.gnome.org でいくら探しても見つからない。
今までのを消さなくてもいいだろうと思うんだけど。

もしかして gtk.org のほうにあるかも。

The GTK Project – A free and open-source cross-platform widget toolkit

上部の Docs を選択、API References | GTK をクリック。

Gtk ? 4.0

見つかった、ああよかった進められる。
ただ今までと違い Valadoc みたいで変な感じ。
いや今までのが決して解りやすかったとは言えないんだけど。

developer.gnome.org は方針を変えて持株会社みたいになったのか?
てか今までのがないと devhelp を使ってローカルで参照できない。
Web ドキュメントのみって結構辛いんですけど。

pinch

今日の大口町。

chougenbou

チョウゲンボウ、ハヤブサ(スズキ)じゃないようで残念。
今日の収穫は以上、いやアオサギやダイサギは沢山いたんだけど。

って本当に野鳥ブログにするんかい。
いいかげんにプログラミングを再開しよう。
とりあえず macOS 用 RAW 画像選別アプリのほうを。

まずピンチを実装したい、トラックパッドで拡大縮小ね。
標準アプリはあたりまえにできるけど実装しなきゃできない。

cocoa – -[NSResponder swipeWithEvent:] not called – Stack Overflow

最初にまんまコレやって失敗した。
だってメソッド名がまぎらわしいんだもんもん。

Cocoaの日々: 1月 2011

こっちでいい、なんだ日本語で見つかるジャン。
NSResponder の magnifyWithEvent メソッドね。

ただ setFrameSize するのはどうなんだ。。。。。
拡大や縮小を指定し再描写にする。

#!/usr/bin/env python3

from AppKit import *
# Kill of control+C
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)

PATH = 'P1012925.RW2' # LUMIX(Panasonic) RAW image
RECT = NSMakeRect(0, 0, 600, 400)
wins = []

class RawView(NSView):
    def initWithFrame_(self, rect):
        objc.super(RawView, self).initWithFrame_(RECT)
        self.image = NSImage.alloc().initWithContentsOfFile_(PATH)
        self.draw_size  = 1
        #self.setWantsRestingTouches_(True) # ?
        return self

    def acceptsFirstResponder(self):
        return True

    def magnifyWithEvent_(self, event):
        print(event.magnification())
        if event.magnification() != 0:
            self.draw_size = event.magnification() + 1
            self.display()

    def swipeWithEvent_(self, event):
        print('swipe')

    def keyDown_(self, event):
        print('key down test')

    def mouseDown_(self, event):
        print('mouse down test')

    def drawRect_(self, rect):
        NSColor.blackColor().set()
        NSRectFill(rect)
        aw = rect.size.width * self.draw_size
        ah = rect.size.height * self.draw_size
        w = self.image.size().width
        h = self.image.size().height
        if aw * h > ah * w:
            width = w * ah / h
            height = ah
            x = (aw - width) / 2
            y = 0
        else:
            width = aw
            height = h * aw / w
            x = 0
            y = (ah - height) / 2
        r1 = NSMakeRect(x, y, width, height)
        self.image.drawInRect_(r1)

class MyWindow(NSWindow):
    def init(self):
        objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
            RECT,
            NSTitledWindowMask | NSClosableWindowMask |
            NSResizableWindowMask | NSMiniaturizableWindowMask,
            NSBackingStoreBuffered, False)
        # NSView
        self.rawview = RawView.alloc().initWithFrame_(RECT)
        self.contentView().addSubview_(self.rawview)
        # self
        self.setTitle_('RAW image Viewer')
        return self

class AppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, notification):
        window = MyWindow.new()
        window.makeKeyAndOrderFront_(window)
        # save
        wins.append(window)
        # Activate
        NSApp.activateIgnoringOtherApps_(True)

class AppMenu(NSMenu):
    def init(self):
        objc.super(AppMenu, self).init()
        item_app  = NSMenuItem.new().autorelease()
        self.addItem_(item_app)
        menu_app = NSMenu.new().autorelease()
        item_app.setSubmenu_(menu_app)
        # quit menu
        item_quit = NSMenuItem.new().autorelease()
        item_quit.initWithTitle_action_keyEquivalent_('Quit App', 'terminate:', 'q')
        menu_app.addItem_(item_quit)
        return self

pool = NSAutoreleasePool.new()

NSApplication.sharedApplication()
NSApp.setMainMenu_(AppMenu.new().autorelease())
NSApp.setDelegate_(AppDelegate.new().autorelease())
NSApp.run()

できたけど。
拡縮の原点は左下、ジェスチャ終了でゼロを投げてくる。
数値はアクション毎にリセット、うーん計算が難しい。
てかレスポンスが酷い、Preview.app 等と全然違う。

コレ違うだろって感じ、もう少し調べなきゃ。

Eye of Mac

筆者は Fedora と Mac を併用しています。
写真関連は現在全部 Mac でやっている。
そして思う、Eye of GNOME(eog) を Mac で使いたい。

大量画像の Exif 情報をサクッと確認したくなる場合が多い。
eog は左右矢印キーでディレクトリ内を巡回できるのがいい。
Finder のギャラリー表示はなんかもどかしくて。

Photo management | Paepoi Blog

Mac にインスト、、、、、いや Gedit でやって劇遅だったじゃん。
だから Atom を Gedit 風にカスタムして使っているのだし。
コレも似たようなビューアを探す?いやどうせなら自分で作ろうかなって。
カスタムするくらいなら最初から自分好みに作ったほうがいいので。

まて、その前に RAW 画像を NSImage は表示できるのか?
ということで試してみた。

#!/usr/bin/env python3

from AppKit import *

PATH = 'P1012925.RW2' # LUMIX(Panasonic) RAW image
RECT = NSMakeRect(0, 0, 600, 400)
wins = []

class RawView(NSView):
    def initWithFrame_(self, rect):
        objc.super(RawView, self).initWithFrame_(RECT)
        self.image = NSImage.alloc().initWithContentsOfFile_(PATH)
        return self

    def drawRect_(self, rect):
        NSColor.blackColor().set()
        NSRectFill(rect)
        aw = rect.size.width
        ah = rect.size.height
        w = self.image.size().width
        h = self.image.size().height
        if w - h > 0:
            if aw * h > ah * w:
                width = w * ah / h
                height = ah
                x = (aw - width) / 2
                y = 0
            else:
                width = aw
                height = h * aw / w
                x = 0
                y = (ah - height) / 2
            r1 = NSMakeRect(x, y, width, height)
            self.image.drawInRect_(r1)

class MyWindow(NSWindow):
    def init(self):
        objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
            RECT,
            NSTitledWindowMask | NSClosableWindowMask |
            NSResizableWindowMask | NSMiniaturizableWindowMask,
            NSBackingStoreBuffered, False)
        # NSView
        view = RawView.alloc().initWithFrame_(RECT)
        self.contentView().addSubview_(view)
        # self
        self.setTitle_('RAW image Viewer')
        return self

class AppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, notification):
        window = MyWindow.new()
        window.makeKeyAndOrderFront_(window)
        # save
        wins.append(window)
        # Activate
        NSApp.activateIgnoringOtherApps_(True)

class AppMenu(NSMenu):
    def init(self):
        objc.super(AppMenu, self).init()
        item_app  = NSMenuItem.new().autorelease()
        self.addItem_(item_app)
        menu_app = NSMenu.new().autorelease()
        item_app.setSubmenu_(menu_app)
        # quit menu
        item_quit = NSMenuItem.new().autorelease()
        item_quit.initWithTitle_action_keyEquivalent_('Quit App', 'terminate:', 'q')
        menu_app.addItem_(item_quit)
        return self

pool = NSAutoreleasePool.new()

NSApplication.sharedApplication()
NSApp.setMainMenu_(AppMenu.new().autorelease())
NSApp.setDelegate_(AppDelegate.new().autorelease())
NSApp.run()

rw2_view

普通に表示できるじゃん。
macOS が対応している RAW は全部表示できると思う。
RAW 対応は「システムレポート」で見ることができる。

mac_raw

EXIF は以下の方法で RAW でも取得できるようだ。

PyObjC Exif | Paepoi Blog

これは思ったより簡単に作れそうだぞ。
GTK4 もやらなきゃだけど今はこっちをやりたいかな。