試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

端末の256色パレットをGTK+のGUI上で表示できるツールを作成

(2010/3/24)本記事のツールを改善したものを「端末の256色パレットをGUI上で確認できるツールを更新(ボタンを改善・クリップボードに色の情報を記憶)」に貼り付けた。
以下、以前の内容となる。

以前、端末の256色拡張についてを扱ったときに全ての色/コード番号を順番にまとめた表を「端末の256色拡張の色(パレット)について」で作成したのだが、PyGTKでGTK+GUIウィンドウ上に色選択用ボタンを並べてその初期色としてそれぞれの色を付けたパレット確認用ツールを作成した。

カラーキューブ色・赤成分が0x00の部分

グレイスケール色(グレイスケール用の色に加えてカラーキューブ色にある無彩色も追加)
これはGladeでUI定義ファイル(.glade形式)を作成してgtk-builder-convertでGtkBuilderファイル(.ui形式)に変換*1し、それを(ファイルサイズが巨大でここに貼り付けられないので)bzip2圧縮+Base64変換したものをスクリプトに埋め込んで、Pythonの「base64」モジュールのbase64.b64decode()でデコード後「bz2」モジュールのbz2.BZ2Decompressorオブジェクトを用いて伸長してPyGTKのGtkBuilderサポート機能へ渡して読み込んでいる。
このGtkBuilderファイルとbzip2圧縮の両方により、Pythonのコードとしてはかなりシンプルにまとまった。
実行にはバージョン2.12以上のPyGTKが必要。
[任意]ファイル名: termcolorpalette256-0.9.1.py ライセンス: GPL-3

#! /usr/bin/python
# -*- encoding: utf-8 -*-

# TermColorPalette256 (C) 2009 kakurasan
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.


import base64
import bz2
import sys
try:
  import pygtk
  pygtk.require('2.0')
except:
  pass
try:
  import gtk
except:
  print >> sys.stderr, 'Error: PyGTK is not installed'
  sys.exit(1)
if gtk.pygtk_version < (2,12,0):
  errmsg = 'PyGTK >= 2.12.0 required'
  if gtk.pygtk_version < (2,4,0):
    print >> sys.stderr, errmsg
  else:
    errdlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK, message_format=errmsg)
    errdlg.set_title('This program cannot be run')
    errdlg.run()
  sys.exit(1)


class UIDefAndHandlers(gtk.Builder):
  """
  GtkBuilderのUI定義とハンドラ群
  """
  # アイコンの場所(システム上のものを使用・無くてもOK)
  __iconpath = '/usr/share/pixmaps/gnome-color-xterm.png'
  # .uiファイルの内容が4500行以上/222Kもあるのでbzip2圧縮+base64
  __xml_bz2_b64 = '''
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
'''
  def __init__(self):
    gtk.Builder.__init__(self)
    d = bz2.BZ2Decompressor()
    self.__xml = d.decompress(base64.b64decode(self.__xml_bz2_b64))
  def init_widgets(self):
    self.add_from_string(self.__xml)
    self.__window = self.get_object('window1')
    self.__window.show_all()
    self.__window.connect('delete_event', gtk.main_quit)
    self.__aboutdlg = self.get_object('aboutdialog1')
    self.__aboutdlg.set_authors(['kakurasan <kakurasan AT gmail DOT com>',])
    self.__aboutdlg.connect('delete_event', self.__aboutdlg.hide_on_delete)
    self.__aboutdlg.connect('response', self.__on_aboutdlg_hide)
    self.__item_quit = self.get_object('imagemenuitem1')
    self.__item_quit.connect('activate', gtk.main_quit)
    self.__item_about = self.get_object('imagemenuitem2')
    self.__item_about.connect('activate', self.__on_item_about_activate)
    try:
      self.__icon = gtk.gdk.pixbuf_new_from_file(self.__iconpath)
      self.__window.set_icon(self.__icon)
      self.__aboutdlg.set_icon(self.__icon)
      self.__aboutdlg.set_logo(self.__icon)
    except:
      pass
  def __on_item_about_activate(self, widget):
    self.__aboutdlg.show_all()
  def __on_aboutdlg_hide(self, widget, resid):
    widget.hide()

class TermColorPalette256:
  """
  256色端末向けのパレット
  """
  def main(self):
    """
    アプリケーションのメイン処理
    """
    builder = UIDefAndHandlers()
    builder.init_widgets()
    gtk.main()


if __name__ == '__main__':
  app = TermColorPalette256()
  app.main()

(2009/10/15)綴りミスを修正・バージョンを0.9.1とした

*1:直接.uiファイルを生成するとバージョンの高いGTK+を要求するので、個人的には.gladeファイルに保存してから変換するのが好み