★210円ちょっとで書見台自作(非PC)

普段使っている書見台はページを抑えている部分の間隔が広く、文庫や新書に不向きでした。
少し小さめの書見台を別途購入しようとあちこちWebを探していました。
安ければ800円くらいからあるようですが、ちょっとお金が勿体無い。

そんな今日この頃、封筒を買いに100円ショップに買いに行ったと際にブックエンドを見て自作することを思いつきました。
主な材料はブックエンドとホビークランプ。

ホビークランプをクッションのある強力両面テープでブックエンドに固定。
ブックエンドの水平に伸びている部分をちょっと曲げて角度を調整しました。
これだけだと中央の隙間に本が逃げてしまうのでちょっとストッパーをつけました。
結構グッドデザインと思ってます。

材料 出来上がり
中公新書を開いて乗せたところ 普段使っている書見台との比較

☆BloGTK補完計画

先日の☆Ubuntu で使えるブログエディタ BloGTKの投稿で「できないこと」に挙げた"画像のアップロード"と"ラベルの設定"を何とかしない限りどうしてもWeb Browserでの作業が発生してしまいます。
BloggerのWeb Browserで行うラベルの設定は比較的操作しやすく、こちらはそれほど面倒ではないのですが、画像のアップロードは改善したいと感じます。

そこで、BloggerのAPIを見て画像アップの方法を探してみました。探しかたが足りないのかもしれませんが見つかりません。
Bloggerでアップした画像はPicasa ウェブ アルバムに保存されていることを思い出して、 Picasa Web Albums Data APIの方を調べてみました。
コマンドラインで画像をアップして、そのURLを取得するのは比較的簡単でしたので、以下に手順を示します。

●必要なもの

  • python-gdataパッケージ(BloGTK2.0を入れていればもう導入済みのはずです)
  • Googleアカウント(とりあえず一つはPicasaのアルバムがある状態を前提とします。)

●前準備

Pythonのスクリプトを2つ準備します。(テスト用の画像も必要です。)
get_albumid.py は画像をアップするアルバムのIDを見るため、
post_new_phots.py は画像の投稿に使用します。
2つとも実行権限をつけてPATHの通ったところにおきます。(たとえば ~/bin )

get_albumid.py
#!/usr/bin/python
import sys
import gdata.photos.service

args = sys.argv
args.pop(0)
email = args.pop(0)
password = args.pop(0)
username='default'

gd_client = gdata.photos.service.PhotosService()
gd_client.email = email
gd_client.password = password
gd_client.source = 'exampleCo-exampleApp-1'
gd_client.ProgrammaticLogin()

albums = gd_client.GetUserFeed(user=username)
for album in albums.entry:
  print 'id:[%s] title:[%s] number of photos: %s' % (album.gphoto_id.text, album.title.text, album.numphotos.text)
post_new_phots.py
#!/usr/bin/python
import sys
import gdata.photos.service
import gdata.media
#
args = sys.argv
args.pop(0)
email = args.pop(0)
password = args.pop(0)
album_id = args.pop(0)
username='default'
#
gd_client = gdata.photos.service.PhotosService()
gd_client.email = email
gd_client.password = password
gd_client.source = 'exampleCo-exampleApp-1'
gd_client.ProgrammaticLogin()
#
album_url = '/data/feed/api/user/%s/albumid/%s' % (username, album_id)
# print 'album_url:', album_url
for arg in args:
  #photo = gd_client.InsertPhoto(album_url, 'New Photo', arg, content_type='image/png')
  photo_name = arg.split('/')[-1]
  ext = arg.split('.')[-1]
  content_type = 'image/' + ext
  photo = gd_client.InsertPhotoSimple(album_url, photo_name, photo_name, arg, content_type=content_type)
  print '-' * 80
  print arg, photo.gphoto_id.text, photo.content.src
  for thumb in photo.media.thumbnail:
    print "\t%s %s %s" % (thumb.width, thumb.height, thumb.url)
  for thumb in photo.media.thumbnail:
    print '<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="%s"><img style="cursor:pointer; cursor:hand;width: %spx; height: %spx;" src="%s" border="0" alt="" id="BLOGGER_PHOTO_ID_%s" /></a>' % (photo.content.src, thumb.width, thumb.height, thumb.url, photo.gphoto_id.text)

●アルバムIDの取得

get_albumid.pyにGmailのメールアドレスとパスワードを指定して起動します。
下記のような要領です。
出力から画像をアップロード先のアルバムを選びます。

$ get_albumid.py hoge@gmail.com hogepassword
id:[9999999999999999991] title:[Blogger の画像] number of photos: 4
id:[9999999999999999992] title:[Windows Live Writer] number of photos: 4
id:[9999999999999999993] title:[ミドルスペックを低負荷で] number of photos: 44

●画像のアップロード

画像を実際にアップロードします。
post_new_phots.pyにGmailのメールアドレスとパスワード、アルバムID、ローカルに存在する画像ファイルのパス(複数可)を指定して起動します。
出力はやや冗長です。アップロード1ファイルごとに7行出力されると思います。自動で作成されるサムネイルの個数で変動するかもしれません。
ファイルへリダイレクトしておいて、[サムネイルを表示画像としたアップロード後のURLへのリンク]をCopy/Pasteして使うことを想定しています。
割と段純なので、少し知識があればお好みにカスタマイズするのは簡単だと思います。
1行目:[ローカルファイルのパス] [画像のID] [アップロード後のURL]
2行目~4行目[タブ][サムネイルの幅] [サムネイルの高さ] [サムネイルのURL]
5行目~7行目[サムネイルを表示画像としたアップロード後のURLへのリンク]
試してみたのはjpgとpngだけです。

実行例
$ ./post_new_phots.py hoge@gmail.com hogepassword 9999999999999999993 ../scrot_01.png  ../scrot_02.jpeg
--------------------------------------------------------------------------------
../scrot_01.png 5441426425664051714 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/
 72 60 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/s72/scrot_01.png
 144 119 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/s144/scrot_01.png
 288 238 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/s288/scrot_01.png
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/"><img style="cursor:pointer; cursor:hand;width: 72px; height: 60px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/s72/scrot_01.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5441426425664051714" /></a>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/"><img style="cursor:pointer; cursor:hand;width: 144px; height: 119px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/s144/scrot_01.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5441426425664051714" /></a>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/"><img style="cursor:pointer; cursor:hand;width: 288px; height: 238px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMqutk7GAju_WbosDBisglRrV2gZmVxyTeTdUoJSFJ856xZpowWQHPXzQ3Ko_blVBTUNesGV-gQfrMZgi56P3FCSNOU-aL6TxhUvpuPG0VrVBgNPfS9IvIjZjh_joue57sPpSvgxlbKooN/s288/scrot_01.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5441426425664051714" /></a>
--------------------------------------------------------------------------------
../scrot_02.jpeg 5441426435389373794 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/
 72 60 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/s72/scrot_02.jpeg
 144 119 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/s144/scrot_02.jpeg
 288 238 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/s288/scrot_02.jpeg
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/"><img style="cursor:pointer; cursor:hand;width: 72px; height: 60px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/s72/scrot_02.jpeg" border="0" alt="" id="BLOGGER_PHOTO_ID_5441426435389373794" /></a>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/"><img style="cursor:pointer; cursor:hand;width: 144px; height: 119px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/s144/scrot_02.jpeg" border="0" alt="" id="BLOGGER_PHOTO_ID_5441426435389373794" /></a>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/"><img style="cursor:pointer; cursor:hand;width: 288px; height: 238px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXsjjP_Jeb0QZqVzPSXA23nreT5yxxu83yE5jqr_Rm0LpBbZzZxy4nOuFC7Lv5eqqQ-hNabQMI7s4XvFhub-WW8OnrDDXCppxksNlfG-zdSfFKh20QD5WT0yKeSVYS2KJUZUuFtwC2NZO/s288/scrot_02.jpeg" border="0" alt="" id="BLOGGER_PHOTO_ID_5441426435389373794" /></a>
実行例の出力を貼り付けてみたもの

●その他

Blogger以外のユーザでも、上記の画像アップロードは有効な手段だとおもいます。(どうしてもGoogleのアカウントを作りたくないという人もいるかもしれませんが。)
GTKの知識やPyGTKの知識があればBloGTK本体に組み込みたいのですが、あいにくありませんし、自分的にはこれで十分かなと思ってます。
英語が達者なら Jay Reding - jay@jayreding.com に相談してみる手もありますが....自信がないので....
そもそも下記の内容もサンプルを少し変えただけであまりわかってませんし....
ログアウトとか探してみたのですが、見つかりません。終了時にやってくれていると良いのですが....

☆Ubuntuで使えるブログエディタ BloGTK

ちょっと前にUbuntuで使えるブログエディタ(KDEベース除く)を探していた際に行き着いたblogtkを紹介します。
環境はUbuntu 910 Karmic Koala、対象ブログサイトはBloggerです。
これがあればWeb Browserがいらないという訳にはいきませんが、ユーザが増えて開発が進むことを期待しています。

●特徴

機能は最小限といったところでしょうか。

■できること
  • ブログへの新規投稿(当然ですね)
  • ブログからの投稿の取得と再投稿(当然ですね)
  • ツールバーやメニューによるタグ挿入ベースの入力補助
  • 投稿時刻の変更
■できないこと
  • 画像のアップロード
  • ラベルの設定
  • WYSWYG編集
  • 表の編集
■バグ?
  • LANG=ja_JP.UTF-8で投稿のエディタが立ち上がらない
  • ステータスバーに表示されるメッセージ
    An Error occurred: enchant error for language: ja_JP.UTF-8
    
    端末から起動した場合に出てくるメッセージ
    Exception in thread Thread-1:
    Traceback (most recent call last):
      File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner
        self.run()
      File "/usr/lib/python2.6/threading.py", line 477, in run
        self.__target(*self.__args, **self.__kwargs)
      File "/usr/bin/../share/blogtk2/lib/blogtk2/main.py", line 560, in sendPostToEditor
        newEditor.destroy(None)
    UnboundLocalError: local variable 'newEditor' referenced before assignment
    
    Traceback (most recent call last):
      File "/usr/bin/../share/blogtk2/lib/blogtk2/main.py", line 357, in update_progress_bar
        gobject.source_remove(self.timeout_handler_id)
    AttributeError: BloGTK instance has no attribute 'timeout_handler_id'
    
  • 多分上記の影響と思われますが、投稿を取得して再投稿すると投稿時刻が9時間進む
(ロケールとタイムゾーンは別もので、9時間進むのとロケールは関係ないです。)
(これで初めて知ったのですが、投稿を公開しても投稿日時が未来の日時になっていると"予定"扱いになるんですね。)

●導入

Karmicのリポジトリにあるバージョン(1.1-2ubuntu3)はBloggerに接続できませんでした。
仕方がないのでPPAから取得します。

sudo add-apt-repository ppa:jayreding/ppa  
sudo apt-get update
sudo apt-get install blogtk

●起動

コマンドは "blogtk2" です。ja_JP.UTF-8 のままだとメインと設定画面は立ち上がるのですが、編集画面が立ち上がりません
そこで /usr/share/applications/blogtk.desktop を開いて Exec= の行を編集します。

編集前
Exec=blogtk2
編集後
Exec=env LANG=C blogtk2

メニュー/ネットワーク/BloGTK 2.0 をクリックして起動します。

●設定

初回起動時はメイン画面と同時に設定画面が立ち上がります。
[Acount Name]と[Blog Address]を入力して[Autodetect Settings]ボタンを押すと
[Username]、[Password]以外は自動設定してくれるようです。
[Preferences]タブはフォントの設定しかありません。

起動直後 [Autodetect Settings]ボタン押下後 [Preferences]タブ

●投稿

設定が正しいか確認するため、とりあえず[Refresh]ボタンを押して既存の投稿が取得できるか調べます。
(スクリーンショットはLANG=ja_JP.UTF-8の状態で撮ったので[更新]になっています。)
取得できれば設定は問題ないと思います。
右下の"Welcome to BloGTK 2" と表示されている部分は投稿を選択するとプレビューが出ます。

あとは投稿を選択して[Edit Post]ボタンを押すか、[New Post]ボタンを押して"BloGTK Editor"を立ち上げます。
投稿時刻の設定ダイアログは[Edit]メニューの[Date and Time..]で起動できます。
ツールバー下段右端はリンク挿入用のボタンです。
Webへ反映する際は[Publish]を押下すればOKです。このとき右下の[Save As Draft?]にチェックを入れておけば下書きとして保存されます。

設定終了後 [Refresh]ボタン押下後
BloGTK Editorの[Main]タブ 投稿時刻設定用のダイアログ リンク挿入用のダイアログ
BloGTK Editorの[Extended]タブ
何も表示されません?
BloGTK Editorの[Preview]タブ
レイアウトはイマイチです

☆懐かしのインテルブランドオーディオプレイヤー

インテルブランドマウスと同じときに出てきたものです。まだ鳴ります。
ネタがないので画像をアップしてみました。
買った当初からノイズが気になっていたのですが、そこそこ持ち歩いたので傷だらけです。
専用ソフトがないとオーディオファイルを転送できないという、今では考えられないシロモノです。

☆bookmark.htm(bookmarks.html)をWebkit用に変換

IEのお気に入りを[ファイル]メニューからエクスポートするとbookmark.htmができます。
このファイル、"<!DOCTYPE NETSCAPE-Bookmark-file-1>"と宣言されてますが、なんだか良くわからない規格です。
"<html>"も"<head>"も"<body>"もない、"<p>"や"<DT>"は閉じていませんし、
タグは大文字だったり小文字だったりします。

それでも文字コードさえ指定しなおせばWebkitベースのブラウザでも一応表示できます。べったり左寄せになりますが。
(短い間ですがMidoriをメインで使っていました。起動時間が改善された気がするので最近はFirefox3.6メインです。)
Operaも同じような状態です。

そこで下記のようなperlのスクリプトを使って変換をしてやります。(conv_bm.pl)
CSSを使ってレイアウトを整えるのが主目的です。<DL>や<DT>は使ったほうが良いのかもしれませんが、よく理解していないので取り除きました。
<A> タグは小文字にすべきかもしれませんが、やってません。
Firefoxから出力したBookmarkも扱えるように文字コード変換はnkfに任せてしまいます。
nkfが入っていない場合は sudo apt-get install nkf で導入します。
(Firefox 3.6はWindows版もbookmarks.htmlをUTF-8でエクスポートするようです。)

WindowsのIEから出力したbookmark.htmの場合は
nkf -w8 bookmark.htm | ./conv_bm.pl > bookmarks-normal.html

Firefoxから出力したbookmark.htmの場合は
./conv_bm.pl bookmarks.html | bookmarks-normal.html

のようにして使用します。

conv_bm.pl
#!/usr/bin/perl

while(<>){
    last if m#<TITLE>.*</TITLE>#i;
}

print <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
div {
    margin-top:0.5em;
    margin-bottom:1.0em;
    margin-left:2.0em;
}
h3 {
    margin:0.0em;
    margin-top:1.0em;
}
</style>
<title>Bookmarks</title>
</head>
<body>
EOF

while(<>){
    s#<DL><p>#<div>#ig;
    s#</DL><p>#</div>#ig;
    s#<DT>##g;
    s#</A>#</A><br />#ig;
    print;
}

print <<EOF;
</body>
</html>
EOF