eric7/WebBrowser/PageScreenDialog.py

Sat, 15 May 2021 18:45:04 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 15 May 2021 18:45:04 +0200
branch
eric7
changeset 8312
800c432b34c8
parent 8227
eric6/WebBrowser/PageScreenDialog.py@349308e84eeb
child 8318
962bce857696
permissions
-rw-r--r--

Started to rename eric6 to eric7.

1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
1 # -*- coding: utf-8 -*-
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
2
7923
91e843545d9a Updated copyright for 2021.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 7781
diff changeset
3 # Copyright (c) 2012 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
4 #
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
5
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
6 """
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
7 Module implementing a dialog to save a screenshot of a web page.
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
8 """
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
9
4780
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
10 from PyQt5.QtCore import pyqtSlot, Qt, QFile, QFileInfo, QSize
3656
441956d8fce5 Started porting eric5 to PyQt5.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3484
diff changeset
11 from PyQt5.QtGui import QImage, QPainter, QPixmap
441956d8fce5 Started porting eric5 to PyQt5.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3484
diff changeset
12 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
13
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
14 from E5Gui import E5FileDialog, E5MessageBox
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
15
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
16 from .Ui_PageScreenDialog import Ui_PageScreenDialog
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
17
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
18
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
19 class PageScreenDialog(QDialog, Ui_PageScreenDialog):
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
20 """
6047
39586a2de99d Fixed some forgotten source code documentation.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 5389
diff changeset
21 Class implementing a dialog to save a screenshot of a web page.
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
22 """
6155
ae44225e7e7c PageScreen: Removed the action to save the whole web page as a screenshot because it is not supported by QWebEngine (and probably will not in the foreseeable future).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 6048
diff changeset
23 def __init__(self, view, parent=None):
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
24 """
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
25 Constructor
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
26
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
27 @param view reference to the web view containing the page to be saved
4780
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
28 (WebBrowserView)
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
29 @param parent reference to the parent widget (QWidget)
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
30 """
8218
7c09585bd960 Applied some more code simplifications suggested by the new Simplify checker (super(Foo, self) => super()).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 8143
diff changeset
31 super().__init__(parent)
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
32 self.setupUi(self)
8143
2c730d5fd177 Changed the use of PyQt enums because the way they were used previously is deprecated since two years and replaced some deprecated Qt stuff.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 7923
diff changeset
33 self.setWindowFlags(Qt.WindowType.Window)
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
34
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
35 self.__view = view
6155
ae44225e7e7c PageScreen: Removed the action to save the whole web page as a screenshot because it is not supported by QWebEngine (and probably will not in the foreseeable future).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 6048
diff changeset
36 self.__createPixmap()
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
37 self.pageScreenLabel.setPixmap(self.__pagePixmap)
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
38
6155
ae44225e7e7c PageScreen: Removed the action to save the whole web page as a screenshot because it is not supported by QWebEngine (and probably will not in the foreseeable future).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 6048
diff changeset
39 def __createPixmap(self):
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
40 """
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
41 Private slot to create a pixmap of the associated view's page.
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
42 """
4780
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
43 res = self.__view.page().execJavaScript(
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
44 "(function() {"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
45 "var res = {"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
46 " width: 0,"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
47 " height: 0,"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
48 "};"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
49 "res.width = document.body.scrollWidth;"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
50 "res.height = document.body.scrollHeight;"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
51 "return res;"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
52 "})()"
1d203a177b16 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4631
diff changeset
53 )
4857
8dba5fb92f12 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4780
diff changeset
54 if res is not None:
6155
ae44225e7e7c PageScreen: Removed the action to save the whole web page as a screenshot because it is not supported by QWebEngine (and probably will not in the foreseeable future).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 6048
diff changeset
55 image = QImage(QSize(res["width"], self.__view.height()),
8143
2c730d5fd177 Changed the use of PyQt enums because the way they were used previously is deprecated since two years and replaced some deprecated Qt stuff.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 7923
diff changeset
56 QImage.Format.Format_ARGB32)
6155
ae44225e7e7c PageScreen: Removed the action to save the whole web page as a screenshot because it is not supported by QWebEngine (and probably will not in the foreseeable future).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 6048
diff changeset
57 painter = QPainter(image)
ae44225e7e7c PageScreen: Removed the action to save the whole web page as a screenshot because it is not supported by QWebEngine (and probably will not in the foreseeable future).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 6048
diff changeset
58 self.__view.render(painter)
ae44225e7e7c PageScreen: Removed the action to save the whole web page as a screenshot because it is not supported by QWebEngine (and probably will not in the foreseeable future).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 6048
diff changeset
59 painter.end()
4857
8dba5fb92f12 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4780
diff changeset
60
8dba5fb92f12 Continued porting the web browser.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 4780
diff changeset
61 self.__pagePixmap = QPixmap.fromImage(image)
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
62
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
63 def __savePageScreen(self):
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
64 """
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
65 Private slot to save the page screen.
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
66
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
67 @return flag indicating success (boolean)
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
68 """
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
69 fileName = E5FileDialog.getSaveFileName(
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
70 self,
3190
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
71 self.tr("Save Page Screen"),
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
72 self.tr("screen.png"),
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
73 self.tr("Portable Network Graphics File (*.png)"),
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
74 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
75 if not fileName:
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
76 return False
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
77
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
78 if QFileInfo(fileName).exists():
3020
542e97d4ecb3 Fixed a bunch of visible indentation issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 2999
diff changeset
79 res = E5MessageBox.yesNo(
542e97d4ecb3 Fixed a bunch of visible indentation issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 2999
diff changeset
80 self,
3190
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
81 self.tr("Save Page Screen"),
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
82 self.tr("<p>The file <b>{0}</b> already exists."
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
83 " Overwrite it?</p>").format(fileName),
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
84 icon=E5MessageBox.Warning)
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
85 if not res:
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
86 return False
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
87
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
88 file = QFile(fileName)
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
89 if not file.open(QFile.WriteOnly):
3020
542e97d4ecb3 Fixed a bunch of visible indentation issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 2999
diff changeset
90 E5MessageBox.warning(
542e97d4ecb3 Fixed a bunch of visible indentation issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 2999
diff changeset
91 self,
3190
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
92 self.tr("Save Page Screen"),
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
93 self.tr("Cannot write file '{0}:\n{1}.")
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
94 .format(fileName, file.errorString()))
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
95 return False
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
96
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
97 res = self.__pagePixmap.save(file)
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
98 file.close()
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
99
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
100 if not res:
3020
542e97d4ecb3 Fixed a bunch of visible indentation issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 2999
diff changeset
101 E5MessageBox.warning(
542e97d4ecb3 Fixed a bunch of visible indentation issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 2999
diff changeset
102 self,
3190
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
103 self.tr("Save Page Screen"),
a9a94491c4fd Changed the code to use QObject.tr() instead of QObject.trUtf8().
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 3160
diff changeset
104 self.tr("Cannot write file '{0}:\n{1}.")
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
105 .format(fileName, file.errorString()))
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
106 return False
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
107
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
108 return True
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
109
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
110 @pyqtSlot(QAbstractButton)
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
111 def on_buttonBox_clicked(self, button):
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
112 """
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
113 Private slot to handle clicks of the dialog buttons.
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
114
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
115 @param button button that was clicked (QAbstractButton)
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
116 """
8143
2c730d5fd177 Changed the use of PyQt enums because the way they were used previously is deprecated since two years and replaced some deprecated Qt stuff.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 7923
diff changeset
117 if button == self.buttonBox.button(
2c730d5fd177 Changed the use of PyQt enums because the way they were used previously is deprecated since two years and replaced some deprecated Qt stuff.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 7923
diff changeset
118 QDialogButtonBox.StandardButton.Cancel
2c730d5fd177 Changed the use of PyQt enums because the way they were used previously is deprecated since two years and replaced some deprecated Qt stuff.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 7923
diff changeset
119 ):
1620
8172cc5d4dda Added code to save the current page as a screen shot.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
120 self.reject()
8227
349308e84eeb Applied some more code simplifications suggested by the new Simplify checker (Y102: use single if) (batch 2).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 8218
diff changeset
121 elif (
349308e84eeb Applied some more code simplifications suggested by the new Simplify checker (Y102: use single if) (batch 2).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 8218
diff changeset
122 button == self.buttonBox.button(
349308e84eeb Applied some more code simplifications suggested by the new Simplify checker (Y102: use single if) (batch 2).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 8218
diff changeset
123 QDialogButtonBox.StandardButton.Save) and
349308e84eeb Applied some more code simplifications suggested by the new Simplify checker (Y102: use single if) (batch 2).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 8218
diff changeset
124 self.__savePageScreen()
8143
2c730d5fd177 Changed the use of PyQt enums because the way they were used previously is deprecated since two years and replaced some deprecated Qt stuff.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 7923
diff changeset
125 ):
8227
349308e84eeb Applied some more code simplifications suggested by the new Simplify checker (Y102: use single if) (batch 2).
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 8218
diff changeset
126 self.accept()

eric ide

mercurial