Skip to content

Commit b151716

Browse files
committed
MILESTONE: 1.1
1 parent 088aa76 commit b151716

File tree

2 files changed

+84
-37
lines changed

2 files changed

+84
-37
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,14 @@
88

99
## 18 APR 2020
1010
* Established CTRL+R shortcut for reloading the file
11+
12+
## 19 APR 2020
13+
* Changed from WebKit1 to WebKit2 since WebKit1 did not support printing
14+
* Added a print button to the UI
15+
* Added a keyboard shortcut to print
16+
* Implemented a print method to print the webview's content
17+
* Added an information dialog to inform the user that the data has been sent to the printer
18+
* As we have new functions available, I decided to go a minor version up to v1.1 and released the application out of beta.
19+
* Implemented the possibility to load data from Files or from parameters
20+
* Implemented error checking on the existence of a file
21+
* Edited .desktop file to include the MimeType and %F option, see https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s06.html

pymd.py

Lines changed: 73 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@
88
# Hsiaoming Yang, published at https://github.com/lepture/mistune
99
# You may have to install the dependencies from github. Please read the README file.
1010

11-
import gi, os, glob, configobj, mistune
11+
import sys, os, gi, glob, configobj, mistune
1212
gi.require_version('Gtk', '3.0')
13-
gi.require_version('WebKit', '3.0')
13+
gi.require_version('WebKit2', '4.0')
1414
gi.require_version('Keybinder', '3.0')
15-
from gi.repository import Gtk, Gdk, WebKit, Gio, GObject, Keybinder
15+
from gi.repository import Gtk, Gdk, WebKit2, Gio, GObject, Keybinder
1616
from mistune.directives import DirectiveToc
1717
from mistune.directives import Admonition
1818

1919
#Define a version number to be able to change it just in one place
2020
global VERSION_NUMBER, WEB_PAGE
21-
VERSION_NUMBER = "1.0b"
21+
VERSION_NUMBER = "1.1"
2222
WEB_PAGE="https://github.com/dsancheznet/pymd/"
2323

2424

@@ -56,11 +56,12 @@ class MainWindow(Gtk.Window):
5656
This class defines the main window of the application
5757
"""
5858

59-
def __init__(self):
59+
def __init__( self, tmpDefaultFile="" ):
6060
#Instantiate config file parser
6161
self.cConfig = configobj.ConfigObj( os.path.expanduser("~")+'/.config/pymd/default.config')
6262
Keybinder.init()
6363
Keybinder.bind("<Ctrl>R", self.onUpdateButtonClicked )
64+
Keybinder.bind("<Ctrl>P", self.onPrintButtonClicked )
6465
#TODO: Error checking
6566
#Define a path, where the css files a loaded from
6667
self.myCSSPath = os.path.expanduser("~")+'/.config/pymd/css/' #TODO: Error checking
@@ -78,7 +79,7 @@ def __init__(self):
7879
self.cHeaderBar = Gtk.HeaderBar()
7980
self.cHeaderBar.set_show_close_button(True)
8081
self.cHeaderBar.props.title = "pymd " + VERSION_NUMBER
81-
self.cHeaderBar.props.subtitle = ""
82+
self.cHeaderBar.props.subtitle = tmpDefaultFile
8283
self.set_titlebar(self.cHeaderBar)
8384

8485
#Buttons for Headerbar
@@ -97,10 +98,16 @@ def __init__(self):
9798
myUpdateButton.add( Gtk.Image.new_from_gicon( Gio.ThemedIcon( name="emblem-synchronizing-symbolic" ), Gtk.IconSize.BUTTON ) )
9899
myUpdateButton.connect( "clicked", self.onUpdateButtonClicked )
99100

101+
myPrintButton = Gtk.Button()
102+
myPrintButton.props.relief = Gtk.ReliefStyle.NONE
103+
myPrintButton.add( Gtk.Image.new_from_gicon( Gio.ThemedIcon( name="printer-printing" ), Gtk.IconSize.BUTTON ) )
104+
myPrintButton.connect( "clicked", self.onPrintButtonClicked )
105+
100106
#Pack everything
101107
self.cHeaderBar.pack_start( myConfigButton )
102108
self.cHeaderBar.pack_end( myOpenButton )
103109
self.cHeaderBar.pack_end( myUpdateButton )
110+
self.cHeaderBar.pack_start( myPrintButton )
104111
#----------Header Bar ***END***
105112

106113
#----------Scroller
@@ -110,10 +117,11 @@ def __init__(self):
110117
self.myScroller.set_policy( Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC )
111118

112119
#Create a webview
113-
self.myWebView = WebKit.WebView()
120+
self.myWebView = WebKit2.WebView()
114121
self.myWebView.get_settings().allow_universal_access_from_file_urls = True;
115-
self.myWebView.load_string( '<html><body><br><center>Empty...</center></body></html>', "text/html", "UTF-8", "file://" )
116-
self.myWebView.props.settings.props.enable_default_context_menu = False
122+
self.myWebView.connect('context-menu', self.contextMenuCallback )
123+
self.myWebView.load_html('<html><body><br><center>Empty...</center></body></html>', "file://" )
124+
#self.myWebView.props.settings.props.enable_default_context_menu = False
117125
self.myScroller.add( self.myWebView )
118126
self.add( self.myScroller )
119127
#----------Scroller ***END***
@@ -145,6 +153,11 @@ def __init__(self):
145153
self.connect( "delete-event", self.mainWindowDelete )
146154
#Connect the destroy signal to the main loop quit function
147155
self.connect("destroy", Gtk.main_quit )
156+
#Load the data (it won't do anythign if subtitle is empty)
157+
self.loadFileData( self.cHeaderBar.props.subtitle )
158+
159+
def contextMenuCallback( self, web_view, context_menu, event, hit_test_result ):
160+
return True
148161

149162
def mainWindowDelete( self, widget, data=None ):
150163
#Save default styelsheet
@@ -165,26 +178,6 @@ def onConfigButtonClicked( self, widget ):
165178
#Do your thing
166179
self.cPopover.popup()
167180

168-
def loadFileData( self, tmpFilename ):
169-
#DEBUG: print('Reloading...')
170-
#Create a mistune instance with all plugins enabled and a custom renderer
171-
tmpMarkdown = mistune.create_markdown( escape=False, renderer=ImagePathRenderer( os.path.dirname( tmpFilename )+ "/" ), plugins=[Admonition(), DirectiveToc(), 'url', 'strikethrough', 'footnotes', 'table'],)
172-
#Open the file for reading // TODO: Error checking -> Filie must be readable
173-
tmpMarkDownFile = open( tmpFilename, "r" )
174-
#Load the contents of the file as raw data
175-
tmpRawMarkdown = tmpMarkDownFile.read()
176-
#Define a string to prepend
177-
tmpPreHTML = '<html><head><link rel="stylesheet" type="text/css" href="file://' + self.myCSSPath + self.myCSSFile.get_active_text() + '"></head><body class="markdown-body">'
178-
#Define a string to append
179-
tmpPostHTML = "</body></html>"
180-
#Define a base uri // HINT: Without this, we are getting errors trying to load local files
181-
tmpBaseURI = "file://"
182-
#Load the data into the webview.
183-
self.myWebView.load_string( tmpPreHTML + tmpMarkdown( tmpRawMarkdown ) + tmpPostHTML, "text/html", "UTF-8", tmpBaseURI )
184-
#Close the file we opened for reading
185-
tmpMarkDownFile.close()
186-
#DEBUG: print(tmpPreHTML + tmpMarkdown( tmpRawMarkdown ) + tmpPostHTML)
187-
188181
def onUpdateButtonClicked( self, widget ):
189182
#Do we have a file loaded?
190183
if self.cHeaderBar.props.subtitle != "":
@@ -224,15 +217,58 @@ def onOpenButtonClicked( self, widget ):
224217
#Destroy de dialog
225218
tmpDialog.destroy()
226219

220+
def onPrintButtonClicked( self, widget ):
221+
#Do we have a file open?
222+
if self.cHeaderBar.props.subtitle != "":
223+
#YES - Launch print dialog
224+
tmpOperation = WebKit2.PrintOperation.new( self.myWebView )
225+
if tmpOperation.run_dialog() == WebKit2.PrintOperationResponse.CANCEL:
226+
print("Print Cancelled!")
227+
else:
228+
tmpDialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, "Print Job")
229+
tmpDialog.format_secondary_text( "Your print job has been sent to the printer...")
230+
tmpDialog.run()
231+
tmpDialog.destroy()
232+
233+
def loadFileData( self, tmpFilename ):
234+
#Does the file we are trying to load exist and is actually a file?
235+
if os.path.exists( tmpFilename ) and os.path.isfile( tmpFilename ):
236+
#YES - Create a mistune instance with all plugins enabled and a custom renderer
237+
tmpMarkdown = mistune.create_markdown( escape=False, renderer=ImagePathRenderer( os.path.dirname( tmpFilename )+ "/" ), plugins=[Admonition(), DirectiveToc(), 'url', 'strikethrough', 'footnotes', 'table'],)
238+
#Open the file for reading // TODO: Error checking -> Filie must be readable
239+
tmpMarkDownFile = open( tmpFilename, "r" )
240+
#Load the contents of the file as raw data
241+
tmpRawMarkdown = tmpMarkDownFile.read()
242+
#Define a string to prepend
243+
tmpPreHTML = '<html><head><link rel="stylesheet" type="text/css" href="file://' + self.myCSSPath + self.myCSSFile.get_active_text() + '"></head><body class="markdown-body">'
244+
#Define a string to append
245+
tmpPostHTML = "</body></html>"
246+
#Define a base uri // HINT: Without this, we are getting errors trying to load local files
247+
tmpBaseURI = "file://"
248+
#Load the data into the webview.
249+
self.myWebView.load_html( tmpPreHTML + tmpMarkdown( tmpRawMarkdown ) + tmpPostHTML, tmpBaseURI )
250+
#Close the file we opened for reading
251+
tmpMarkDownFile.close()
252+
#DEBUG: print(tmpPreHTML + tmpMarkdown( tmpRawMarkdown ) + tmpPostHTML)
253+
else:
254+
print("File not found...") #TODO: Load an adecuate HTML into the view.
255+
256+
if __name__ == "__main__":
227257

228-
#Create Main Window
229-
myWindow = MainWindow()
258+
#Check for parameters
259+
if len( sys.argv )>1:
260+
#DEBUG: print( "Arguments: " + str(sys.argv) )
261+
#Create Main Window with parameter
262+
myWindow = MainWindow( sys.argv[1] )
263+
else:
264+
#Create Main Window without parameter
265+
myWindow = MainWindow()
230266

231-
#Connect the destroy signal to the main loop quit function
232-
myWindow.connect("destroy", Gtk.main_quit)
267+
#Connect the destroy signal to the main loop quit function
268+
myWindow.connect("destroy", Gtk.main_quit)
233269

234-
#Show Windows on screen
235-
myWindow.show_all()
270+
#Show Windows on screen
271+
myWindow.show_all()
236272

237-
#Main Loop
238-
Gtk.main()
273+
#Main Loop
274+
Gtk.main()

0 commit comments

Comments
 (0)