2020-12-04 21:10:49 +01:00
# Copyright 2020 Romain de Laage
#
# This file is part of tkGemini.
#
# tkGemini 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
# any later version.
#
# tkGemini 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 tkGemini. If not, see <https://www.gnu.org/licenses/>.
2020-12-03 10:02:32 +01:00
import tkinter as tk
2020-12-03 18:18:29 +01:00
import tkinter . messagebox
import tkinter . simpledialog
2020-12-03 11:40:09 +01:00
import gemini
2020-12-04 17:18:09 +01:00
import renderEngine
2020-12-04 19:07:58 +01:00
import urllib . parse
2020-12-03 10:02:32 +01:00
class Application ( ) :
def __init__ ( self ) :
2020-12-04 20:50:03 +01:00
# Some global definitions
2020-12-03 10:02:32 +01:00
self . root = tk . Tk ( )
self . nav_bar = NavBar ( self )
self . content = Content ( self )
self . current_URL = " about:home "
2020-12-04 20:50:03 +01:00
# Set window title
self . root . title ( " tkGemini " )
# App main loop
self . root . mainloop ( )
2020-12-03 10:02:32 +01:00
def updateContent ( self ) :
2020-12-03 18:18:29 +01:00
# Get url asked
2020-12-04 19:07:58 +01:00
url = self . nav_bar . getURL ( )
# Is it a Gemini URL
if not ( verifyURL ( url ) ) :
tkinter . messagebox . showerror ( " URL error " , url + " is not a correct Gemini URL ! (HTTP/S is not supported, please use a web browser instead) " )
return
2020-12-03 10:52:02 +01:00
self . current_URL = self . nav_bar . getURL ( )
2020-12-03 18:18:29 +01:00
# New request
2020-12-03 11:40:09 +01:00
r = gemini . Request ( self . current_URL )
2020-12-03 18:18:29 +01:00
status = r . makeRequest ( )
# The server asked for user input
if status [ 0 ] == " 1 " :
user_input = tkinter . simpledialog . askstring ( " User input " , " The server asked for " + r . meta + " . " )
self . nav_bar . URL_var . set ( self . current_URL + " ? " + user_input )
self . updateContent ( )
# If server asked for redirection
elif status [ 0 ] == " 3 " :
# Ask to user
confirm = tkinter . messagebox . askyesno ( " Server redirection " , " This server ask for redirection to " + r . meta + " . Follow ? " )
# If he accepted
if confirm :
self . nav_bar . URL_var . set ( r . meta )
self . updateContent ( )
# The server asked for client certificate, unsupported
elif status [ 0 ] == " 6 " :
tkinter . messagebox . showerror ( " Client certificate required " , " Error " + status + " : " + r . meta )
else :
self . content . setContent ( r . content )
2020-12-03 10:02:32 +01:00
2020-12-04 19:07:58 +01:00
def linkClick ( self , url ) :
# Check if it is an absolute URL
if " :// " in url :
# Check if it is a gemini URL
if verifyURL ( url ) :
self . nav_bar . URL_var . set ( url )
self . updateContent ( )
# Else show error
else :
tkinter . messagebox . showerror ( " URL error " , url + " is not a correct Gemini URL ! (HTTP/S is not supported, please use a web browser instead) " )
# It is relative
else :
# Join current URL and relative path
base = self . current_URL
base = base . replace ( " gemini:// " , " http:// " )
url = urllib . parse . urljoin ( base , url )
url = url . replace ( " http:// " , " gemini:// " )
# We can verify because sometime there is errors (mailto:)
if verifyURL ( url ) :
self . nav_bar . URL_var . set ( url )
self . updateContent ( )
else :
tkinter . messagebox . showerror ( " URL error " , url + " is not a correct Gemini URL ! (HTTP/S is not supported, please use a web browser instead) " )
def verifyURL ( url ) :
2020-12-04 20:50:03 +01:00
# Is it an absolute path ?
2020-12-04 19:07:58 +01:00
if " :// " in url :
parsed_url = urllib . parse . urlparse ( url )
2020-12-04 20:50:03 +01:00
# Is this path supported ?
2020-12-04 19:07:58 +01:00
if parsed_url . scheme == " gemini " :
return True
else :
return False
2020-12-03 10:02:32 +01:00
class NavBar ( ) :
def __init__ ( self , parent ) :
2020-12-04 20:50:03 +01:00
# Some global definitions
2020-12-03 10:02:32 +01:00
self . parent = parent
2020-12-04 20:50:03 +01:00
# All widgets are in a frame
2020-12-03 10:02:32 +01:00
self . root = tk . Frame ( self . parent . root )
self . root . grid ( column = 0 , row = 0 )
2020-12-04 20:50:03 +01:00
# Define URL bar and variable
self . URL_var = tk . StringVar ( )
2020-12-03 10:02:32 +01:00
self . URL_bar = tk . Entry ( self . root , textvariable = self . URL_var )
self . URL_var . set ( " about:home " )
self . URL_bar . grid ( column = 0 , row = 0 )
2020-12-04 20:50:03 +01:00
# Define go button with action
2020-12-03 10:02:32 +01:00
self . go_button = tk . Button ( self . root , text = ' Go ! ' , command = self . parent . updateContent )
self . go_button . grid ( column = 1 , row = 0 )
def getURL ( self ) :
2020-12-04 20:50:03 +01:00
# Get URL from URL bar variable
2020-12-03 10:02:32 +01:00
return self . URL_var . get ( )
class Content ( ) :
def __init__ ( self , parent ) :
self . parent = parent
2020-12-04 20:50:03 +01:00
# Text container with home page
2020-12-04 19:07:58 +01:00
self . root = renderEngine . Renderer ( self . parent , " #Home page \n Welcome on tkGemini, a browser software for Gemini protocole \n =>gemini://rdelaage.ovh My gemini space " )
2020-12-04 17:18:09 +01:00
self . root . parse ( )
self . root . content . grid ( column = 0 , row = 1 )
2020-12-04 20:50:03 +01:00
# Scrollbar beside to the text container
2020-12-04 17:18:09 +01:00
self . scroll_bar = tk . Scrollbar ( command = self . root . content . yview , orient = ' vertical ' )
self . scroll_bar . grid ( column = 1 , row = 1 )
self . root . content [ ' yscrollcommand ' ] = self . scroll_bar . set
2020-12-03 10:02:32 +01:00
2020-12-04 20:50:03 +01:00
# When content is updated
2020-12-03 10:02:32 +01:00
def setContent ( self , new_content ) :
2020-12-04 17:18:09 +01:00
self . root . text = new_content
self . root . parse ( )
2020-12-03 10:02:32 +01:00
app = Application ( )