はじめに

開発にかぎらず、働いていると環境に関して色々と制限を受ける。所定の手続きを取れば必要なツールをインストールできるが、例外なのがWebブラウザ。いずれのOSもデフォルトとなるWebブラウザを最初から積んでおり、それ以外のブラウザを新たにインストールするとなると(事務的に)かなりめんどくさい。

Webブラウザをインストールすることはできないが、ブラウザを作ることは禁止されていない。というわけで、自分が使いやすいブラウザを作ることにした。(今年の年越しハッカソン)

前提と環境

  • OSを選ばず動かせる
  • ブラウザ以外の用途としても使えるツールを使う
  • 各Webページの情報が参照できれば良い(きれいなレンダリングとかいらない)

以上より、自分が普段使っているPythonと、過去かじったことのあるQt(今回はPyQt5)を使うことにした。

PyQt5の勉強

Qtは使ったことがあるものの、PyQt5となるとまた別。というわけで、tutorialで勉強する。ひたすら写経。
並行して、PyQt5 Reference Guideで使えるアイテムをチェック。

PyQt5で作った簡易ブラウザ:Persephone

できた画面はこんな具合。
window_of_persephone.png

  • back / forward / reload / move ボタンは実装
  • webページは表示可。YouTubeを見れる。
  • url入力部は貧弱ではあるものの、一応ある。

コードはGitHubにアップしてるが、こんな感じ。簡単にかける。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit, 
                             QTextEdit, QGridLayout, QApplication, QPushButton,  QDesktopWidget)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView

__program__ = 'PERSEPHONE'


class PersephoneWindow(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        initurl = 'https://www.google.co.jp'

        # setting browser
        self.browser = QWebEngineView()
        self.browser.load(QUrl(initurl))        
        self.browser.resize(1000,600)
        self.browser.move(200,200)
        self.browser.setWindowTitle(__program__)

        # setting button
        self.back_button = QPushButton('back')
        self.back_button.clicked.connect(self.browser.back)        
        self.forward_button = QPushButton('forward')
        self.forward_button.clicked.connect(self.browser.forward)
        self.reload_button = QPushButton('reload')
        self.reload_button.clicked.connect(self.browser.reload)
        self.url_edit = QLineEdit()
        self.move_button = QPushButton('move')
        self.move_button.clicked.connect(self.loadPage)

        # signal catch from moving web pages.
        self.browser.urlChanged.connect(self.updateCurrentUrl)

        # setting layout
        grid = QGridLayout()
        grid.setSpacing(10)
        grid.addWidget(self.back_button, 1, 0)
        grid.addWidget(self.forward_button, 1, 1)
        grid.addWidget(self.reload_button, 1, 2)
        grid.addWidget(self.url_edit, 1, 3, 1, 10)
        grid.addWidget(self.move_button, 1, 14)
        grid.addWidget(self.browser,2, 0, 5, 15)
        self.setLayout(grid) 
        self.resize(1200, 800)
        self.center()
        self.setWindowTitle(__program__)
        self.show()


    def center(self):
        ''' centering widget
        '''
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def loadPage(self):
        ''' move web page which is set at url_edit
        '''
        move_url = QUrl(self.url_edit.text())
        self.browser.load(move_url)
        self.updateCurrentUrl

    def updateCurrentUrl(self):
        ''' rewriting url_edit when you move different web page.
        '''
        # current_url = self.browser.url().toString()
        self.url_edit.clear()
        self.url_edit.insert(self.browser.url().toString())

if __name__ == '__main__':
    # mainPyQt5()
    app = QApplication(sys.argv)

    # setWindowIcon is a method for QApplication, not for QWidget
    path = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'icon_persephone.png')
    app.setWindowIcon(QIcon(path))

    ex = PersephoneWindow()
    sys.exit(app.exec_())

ちょっと面倒だったのは、下から4行目のos.path.join(os.path.dirname(sys.modules[__name__].__file__), 'icon_persephone.png')。ここだけ上述のチュートリアルと異なり、このように書くことでアイコンの画像を設定することができる(ここを参考にした)。
ちなみに名前の由来は、自分の星座である乙女座のモデルとなった(らしい)少女ペルセポネ。

感想と今後実装したいもの

  • やはりQtはクロスプラットフォーム向けのフレームワークとして優秀。使いやすい。
  • タッチパネルのスワイプに対応した画面遷移機能はまだない。ほしい。
  • url入力部分が貧弱。httpの省略表示や入力補完ができていない。
  • タブ機能がほしい。
  • ブックマークはいらないが、それに相当するページをホームとして、そこに移動するためのボタンがほしい。
  • proxy対応は必要かも。