Move GUI files to separate project

This commit is contained in:
Bastian Kleineidam 2016-01-23 13:28:15 +01:00
parent e410169fd0
commit 0ef00eea56
107 changed files with 753 additions and 13226 deletions

View file

@ -10,7 +10,6 @@ addons:
apt:
packages:
- python-dev
- qt4-dev-tools
# command to install dependencies
install:
- pip install -r requirements.txt

View file

@ -12,11 +12,6 @@ include linkcheck/HtmlParser/htmllex.l
include linkcheck/HtmlParser/htmlparse.y
include linkcheck/HtmlParser/*.h
include linkcheck/HtmlParser/fixincludes.awk
include linkcheck/gui/Makefile
include linkcheck/gui/rc/Makefile
include linkcheck/gui/rc/*.png
include linkcheck/gui/rc/*.qrc
include linkcheck/gui/ui/*.ui
include po/*.po po/*.mo po/*.pot po/Makefile
include doc/*.example doc/*.txt
include doc/html/*.ico

View file

@ -18,33 +18,14 @@ DEBORIGFILE:=$(DEBUILDDIR)/$(LAPPNAME)_$(VERSION).orig.tar.$(ARCHIVE_SOURCE_EXT)
DEBPACKAGEDIR:=$(DEBUILDDIR)/$(APPNAME)-$(VERSION)
FILESCHECK_URL:=http://localhost/~calvin/
SRCDIR:=${HOME}/src
PY_FILES_DIRS:=linkcheck tests *.py linkchecker linkchecker-gui cgi-bin config doc/examples scripts
PY_FILES_DIRS:=linkcheck tests *.py linkchecker cgi-bin config doc/examples scripts
MYPY_FILES_DIRS:=linkcheck/HtmlParser linkcheck/checker \
linkcheck/cache linkcheck/configuration linkcheck/director \
linkcheck/htmlutil linkcheck/logger linkcheck/network \
linkcheck/bookmarks linkcheck/plugins linkcheck/parser \
linkcheck/gui/__init__.py \
linkcheck/gui/checker.py \
linkcheck/gui/contextmenu.py \
linkcheck/gui/debug.py \
linkcheck/gui/editor.py \
linkcheck/gui/editor_qsci.py \
linkcheck/gui/editor_qt.py \
linkcheck/gui/lineedit.py \
linkcheck/gui/help.py \
linkcheck/gui/logger.py \
linkcheck/gui/options.py \
linkcheck/gui/properties.py \
linkcheck/gui/settings.py \
linkcheck/gui/statistics.py \
linkcheck/gui/syntax.py \
linkcheck/gui/updater.py \
linkcheck/gui/urlmodel.py \
linkcheck/gui/urlsave.py \
$(filter-out %2.py,$(wildcard linkcheck/*.py)) \
cgi-bin/lc.wsgi \
linkchecker \
linkchecker-gui \
*.py
TESTS ?= tests
@ -74,10 +55,10 @@ all:
clean:
-$(PYTHON) setup.py clean --all
rm -f $(LAPPNAME)-out.* *-stamp*
$(MAKE) -C doc/html clean
$(MAKE) -C linkcheck/HtmlParser clean
rm -f linkcheck/network/_network*.so
find . -name '*.py[co]' -exec rm -f {} \;
find . -name '*.bak' -exec rm -f {} \;
find . -depth -name '__pycache__' -exec rm -rf {} \;
distclean: clean
@ -97,7 +78,6 @@ locale:
# to build in the current directory
localbuild: MANIFEST locale
$(MAKE) -C doc/html
$(MAKE) -C linkcheck/HtmlParser
$(PYTHON) setup.py build
cp -f build/lib.$(PLATFORM)-$(PYVER)*/linkcheck/HtmlParser/htmlsax*.so linkcheck/HtmlParser
@ -193,7 +173,7 @@ test: localbuild
pyflakes:
pyflakes $(PY_FILES_DIRS) 2>&1 | \
grep -v "local variable 'dummy' is assigned to but never used" | \
grep -v -E "'(PyQt4|biplist|setuptools|win32com|find_executable|parse_sitemap|parse_sitemapindex|parse_bookmark_data|parse_bookmark_file|wsgiref|pyftpdlib|linkchecker_rc)' imported but unused" | \
grep -v -E "'(biplist|setuptools|win32com|find_executable|parse_sitemap|parse_sitemapindex|parse_bookmark_data|parse_bookmark_file|wsgiref|pyftpdlib|linkchecker_rc)' imported but unused" | \
grep -v "undefined name '_'" | \
grep -v "undefined name '_n'" | cat
@ -217,17 +197,14 @@ dnsdiff:
changelog:
github-changelog $(DRYRUN) $(GITUSER) $(GITREPO) doc/changelog.txt
gui:
$(MAKE) -C linkcheck/gui
count:
@sloccount linkchecker linkchecker-gui linkcheck tests
@sloccount linkchecker linkcheck tests
# run eclipse ide
ide:
eclipse -data $(CURDIR)/..
.PHONY: test changelog gui count pyflakes ide login upload all clean distclean
.PHONY: test changelog count pyflakes ide login upload all clean distclean
.PHONY: pep8 cleandeb locale localbuild deb diff dnsdiff sign
.PHONY: filescheck update-copyright releasecheck check register announce
.PHONY: chmod dist release homepage

View file

@ -24,7 +24,7 @@ Features
- honors robots.txt exclusion protocol
- Cookie support
- HTML5 support
- a command line, GUI and web interface
- a command line and web interface
- various check plugins available, eg. HTML syntax and antivirus checks.
Installation

View file

@ -1,6 +1,6 @@
# Sample configuration file; see the linkcheckerrc(5) man page or
# execute linkchecker -h for help on these options.
# Commandline or GUI options override these settings.
# Commandline options override these settings.
##################### output configuration ##########################
[output]
@ -21,10 +21,6 @@
##################### logger configuration ##########################
# Note that the logger configuration is ignored by the linkchecker-gui
# program. Results in the GUI can be saved to a file with the command
# File -> Save results.
#
# logger output part names:
# all For all parts
# realurl The full url link

View file

@ -1,10 +1,9 @@
HTMLDIR:=web/media
MANHTMLFILES:= \
$(HTMLDIR)/man1/linkchecker.1.html \
$(HTMLDIR)/man5/linkcheckerrc.5.html \
$(HTMLDIR)/man1/linkchecker-gui.1.html
$(HTMLDIR)/man5/linkcheckerrc.5.html
MANFILES:=linkchecker.1 linkcheckerrc.5 linkchecker-gui.1
MANFILES:=linkchecker.1 linkcheckerrc.5
LOCALES:=en de
all:
@ -22,10 +21,6 @@ $(HTMLDIR)/man5/linkcheckerrc.5.html: en/linkcheckerrc.5 linkcheckerrc.5.html.di
man2html -r $< | tail -n +2 | sed 's/Time:.*//g' | sed 's@/:@/@g' > $@
patch --no-backup-if-mismatch --quiet $@ linkcheckerrc.5.html.diff
$(HTMLDIR)/man1/linkchecker-gui.1.html: en/linkchecker-gui.1 linkchecker-gui.1.html.diff
man2html -r $< | tail -n +2 | sed 's/Time:.*//g' | sed 's@/:@/@g' > $@
patch --no-backup-if-mismatch --quiet $@ linkchecker-gui.1.html.diff
# check all makefiles for formatting warnings
check:
@t=$(shell tempfile); \

857
doc/de.po

File diff suppressed because it is too large Load diff

View file

@ -1,30 +0,0 @@
.\"*******************************************************************
.\"
.\" This file was generated with po4a. Translate the source file.
.\"
.\"*******************************************************************
.TH LINKCHECKER\-GUI 1 2009\-01\-10 "LinkChecker GUI" "LinkChecker GUI Programm"
.SH NAME
linkchecker\-gui \- GUI\-Programm zum Prüfen von Verknüpfungen von Webseiten
und HTML Dokumenten
.
.SH SYNTAX
\fBlinkchecker\-gui\fP [\fIDatei\-oder\-URL\-oder\-Projekt\fP]
.
.SH BESCHREIBUNG
Eine graphische Benutzeroberfläche, um Verknüpfungen von Webseiten und HTML
Dokumenten zu prüfen.
.
.SH PROJEKTDATEIEN
Eine Projektdatei hat die Dateierweiterung .lcp. Die Datei speichert alle
aktiven Einstellungen und die zu prüfende URL. Projektdateien können mit dem
Menü oder mit Drag\-And\-Drop auf das GUI\-Fenster geladen werden.
.SH "SIEHE AUCH"
\fBlinkchecker\fP(1)
.
.SH AUTHOR
Bastian Kleineidam <bastian.kleineidam@web.de>
.
.SH COPYRIGHT
Copyright \(co 2009\-2014 Bastian Kleineidam

View file

@ -39,7 +39,7 @@ HTML\- und CSS\-Syntaxprüfung
.IP \(bu
Antivirusprüfung
.IP \(bu
ein Kommandozeilenprogramm, GUI und web interface
ein Kommandozeilenprogramm und web interface
.SH BEISPIELE
The most common use checks the given domain recursively:
\fBlinkchecker http://www.example.com/\fP
@ -81,8 +81,8 @@ Lese Liste von URLs zum Prüfen von der Standardeingabe, getrennt durch
Leerzeichen.
.TP
\fB\-t\fP\fINUMMER\fP, \fB\-\-threads=\fP\fINUMMER\fP
Generiere nicht mehr als die angegebene Anzahl von Threads. Die Standardanzahl von Threads ist 10.
Um Threads zu deaktivieren, geben Sie eine nicht positive Nummer an.
Generate no more than the given number of threads. Default number of threads
is 10. To disable threading specify a non\-positive number.
.TP
\fB\-V\fP, \fB\-\-version\fP
Gebe die Version aus und beende das Programm.
@ -94,7 +94,7 @@ Print available check plugins and exit.
.TP
\fB\-D\fP\fINAME\fP, \fB\-\-debug=\fP\fINAME\fP
Gebe Testmeldungen aus für den angegebenen Logger. Verfügbare Logger sind
\fBcmdline\fP, \fBchecking\fP,\fBcache\fP, \fBgui\fP, \fBdns\fP und \fBall\fP. Die Angabe
\fBcmdline\fP, \fBchecking\fP,\fBcache\fP, \fBdns\fP, \fBplugins\fP und \fBall\fP. Die Angabe
\fBall\fP ist ein Synonym für alle verfügbaren Logger. Diese Option kann
mehrmals angegeben werden, um mit mehr als einem Logger zu testen. Um
akkurate Ergebnisse zu erzielen, werden Threads deaktiviert.

View file

@ -47,8 +47,8 @@ bewirkt unendliche Rekursion. Standard Tiefe ist unendlich.
Kommandozeilenoption: \fB\-\-recursion\-level\fP
.TP
\fBthreads=\fP\fINUMBER\fP
Generiere nicht mehr als die angegebene Anzahl von Threads. Die Standardanzahl von Threads ist 10.
Um Threads zu deaktivieren, geben Sie eine nicht positive Nummer an.
Generate no more than the given number of threads. Default number of threads
is 10. To disable threading specify a non\-positive number.
.br
Kommandozeilenoption: \fB\-\-threads\fP
.TP
@ -82,8 +82,7 @@ Kommandozeilenoption: keine
\fBmaxrunseconds=\fP\fINUMBER\fP
Hört nach der angegebenen Anzahl von Sekunden auf, neue URLs zu prüfen. Dies
ist dasselbe als wenn der Benutzer nach der gegebenen Anzahl von Sekunden
stoppt (durch Drücken von Strg\-C oder Klicken auf den Knopf Abbrechen im
GUI).
stoppt (durch Drücken von Strg\-C).
.br
Standard ist nicht zu stoppen bis alle URLs geprüft sind.
.br
@ -111,8 +110,8 @@ Ausdruck entsprechen.
Kommandozeilenoption: \fB\-\-ignore\-url\fP
.TP
\fBignorewarnings=\fP\fINAME\fP[\fB,\fP\fINAME\fP...]
Ignoriere die kommagetrennte Liste von Warnungen. Siehe \fBWARNUNGEN\fP für die
Liste von erkannten Warnungen.
Ignore the comma\-separated list of warnings. See \fBWARNINGS\fP for the list of
supported warnings.
.br
Kommandozeilenoption: keine
.TP
@ -167,9 +166,9 @@ automatisch übermittelt.
.SS [output]
.TP
\fBdebug=\fP\fISTRING\fP[\fB,\fP\fISTRING\fP...]
Gebe Testmeldungen aus für den angegebenen Logger. Verfügbare Logger sind
\fBcmdline\fP, \fBchecking\fP,\fBcache\fP, \fBgui\fP, \fBdns\fP, \fBthread\fP und \fBall\fP. Die
Angabe \fBall\fP ist ein Synonym für alle verfügbaren Logger.
Print debugging output for the given modules. Available debug modules are
\fBcmdline\fP, \fBchecking\fP, \fBcache\fP, \fBdns\fP, \fBthread\fP, \fBplugins\fP and
\fBall\fP. Specifying \fBall\fP is an alias for specifying all available loggers.
.br
[output]
.TP
@ -277,7 +276,7 @@ Setze Warnfarbe. Standard ist \fBbold;yellow\fP.
Setze Downloadzeitfarbe. Standard ist \fBdefault\fP.
.TP
\fBcolorreset=\fP\fISTRING\fP
Setze Reset Farbe. Standard ist \fBdefault\fP.
Set reset color. Default is \fBdefault\fP.
.SS [gml]
.TP
\fBfilename=\fP\fISTRING\fP
@ -329,7 +328,7 @@ Siehe [text] Sektion weiter oben.
Setze Datenbankname zum Speichern. Standard ist \fBlinksdb\fP.
.TP
\fBseparator=\fP\fICHAR\fP
Setze SQL Kommandotrennzeichen. Standard ist ein Strichpunkt (\fB;\fP).
Set SQL command separator character. Default is a semicolon (\fB;\fP).
.SS [html]
.TP
\fBfilename=\fP\fISTRING\fP
@ -404,7 +403,7 @@ Eine Nummer zwischen 0.0 und 1.0, welche die Priorität festlegt. Die
Standardpriorität für die erste URL ist 1.0, für alle Kind\-URLs ist sie 0.5.
.TP
\fBfrequency=\fP[\fBalways\fP|\fBhourly\fP|\fBdaily\fP|\fBweekly\fP|\fBmonthly\fP|\fByearly\fP|\fBnever\fP]
Die Häufigkeit mit der Seiten sich ändern.
How frequently pages are changing.
.
.SH "AUSGABE PARTS"
\fBall\fP (für alle Teile)
@ -458,9 +457,11 @@ GeoIP or pygeoip and a local country or city lookup DB installed.
Define a regular expression which prints a warning if it matches any content
of the checked link. This applies only to valid pages, so we can get their
content.
.TP
\fBwarningregex=\fP\fIREGEX\fP
Use this to check for pages that contain some form of error message, for
example 'This page has moved' or 'Oracle Application error'.
example "This page has moved" or "Oracle Application error". \fIREGEX\fP should
be unquoted.
Man beachte, dass mehrere Werte in dem regulären Ausdruck kombiniert
werden können, zum Beispiel "(Diese Seite ist umgezogen|Oracle

View file

@ -11,23 +11,9 @@ installation is recommended.
- Install Python >= 2.7.2 from http://www.python.org/
- Qt4 SDK development tools from http://qt.nokia.com/downloads
The binary "qcollectiongenerator" is used to generate the
documentation files.
- Install PyQt >= 4.8 from
http://www.riverbankcomputing.co.uk/software/pyqt/download
- *Optional, for syntax highlighting in the GUI editor*, install
QScintilla from
http://www.riverbankcomputing.co.uk/software/qscintilla/download
- *On Windows only*, install the Windows SDK
http://msdn.microsoft.com/de-de/windows/bb980924
- *On Windows only*, install InnoSetup from
http://www.jrsoftware.org/isinfo.php
- *On Windows only*, download and install the Microsoft
Visual C++ 2008 runtime from
http://www.microsoft.com/downloads/details.aspx?FamilyID=9b2da534-3e03-4391-8a4d-074b9f2bc1bf&displaylang=en
@ -43,7 +29,7 @@ installation is recommended.
Setup for Unix/Linux
--------------------
Execute ``make localbuild`` to compile a local version and execute
``./linkchecker`` or ``./linkchecker-gui``.
``./linkchecker``.
Execute ``make test`` to run the unittest suite.
Execute ``make dist`` to build a distributable source package.
@ -51,7 +37,7 @@ Execute ``make dist`` to build a distributable source package.
Setup for Mac OS X
------------------
Execute ``make localbuild`` to compile a local version and execute
``./linkchecker`` or ``./linkchecker-gui``.
``./linkchecker``.
Execute ``make test`` to run the unittest suite.
Execute ``make app`` to build a distributable source package.

View file

@ -11,7 +11,6 @@ branches:
before_install:
- brew update
- brew install python
- brew install pyqt
- brew install gettext
- brew link --force gettext
# command to install dependencies

View file

@ -1,23 +0,0 @@
.TH LINKCHECKER-GUI 1 2009-01-10 "LinkChecker GUI" "LinkChecker GUI client"
.SH NAME
linkchecker-gui - GUI client to check links of websites and HTML documents
.
.SH SYNOPSIS
\fBlinkchecker-gui\fP [\fIfile-or-url-or-project\fP]
.
.SH DESCRIPTION
A graphical interface to check links of websites and HTML documents.
.
.SH PROJECT FILES
A project file has a .lcp extension. The file stores all active preferences
and the current checked URL. Project files can be loaded with the
menu entry or with drag-and-drop on the GUI window.
.SH "SEE ALSO"
\fBlinkchecker\fP(1)
.
.SH AUTHOR
Bastian Kleineidam <bastian.kleineidam@web.de>
.
.SH COPYRIGHT
Copyright \(co 2009-2014 Bastian Kleineidam

View file

@ -31,7 +31,7 @@ HTML and CSS syntax check
.IP \(bu
Antivirus check
.IP \(bu
a command line, GUI and web interface
a command line and web interface
.SH EXAMPLES
The most common use checks the given domain recursively:
\fBlinkchecker http://www.example.com/\fP
@ -85,7 +85,7 @@ Print available check plugins and exit.
\fB\-D\fP\fISTRING\fP, \fB\-\-debug=\fP\fISTRING\fP
Print debugging output for the given logger.
Available loggers are \fBcmdline\fP, \fBchecking\fP,
\fBcache\fP, \fBgui\fP, \fBdns\fP and \fBall\fP.
\fBcache\fP, \fBdns\fP, \fBplugins\fP and \fBall\fP.
Specifying \fBall\fP is an alias for specifying all available loggers.
The option can be given multiple times to debug with more
than one logger.

View file

@ -77,8 +77,7 @@ Command line option: none
.TP
\fBmaxrunseconds=\fP\fINUMBER\fP
Stop checking new URLs after the given number of seconds. Same as if the
user stops (by hitting Ctrl-C or clicking the abort button in the GUI)
after the given number of seconds.
user stops (by hitting Ctrl-C) after the given number of seconds.
.br
The default is not to stop until all URLs are checked.
.br
@ -161,9 +160,9 @@ values are submitted automatically.
.SS \fB[output]\fP
.TP
\fBdebug=\fP\fISTRING\fP[\fB,\fP\fISTRING\fP...]
Print debugging output for the given loggers.
Available loggers are \fBcmdline\fP, \fBchecking\fP,
\fBcache\fP, \fBgui\fP, \fBdns\fP, \fBthread\fP and \fBall\fP.
Print debugging output for the given modules.
Available debug modules are \fBcmdline\fP, \fBchecking\fP,
\fBcache\fP, \fBdns\fP, \fBthread\fP, \fBplugins\fP and \fBall\fP.
Specifying \fBall\fP is an alias for specifying all available loggers.
.br
Command line option: \fB\-\-debug\fP

View file

@ -1227,102 +1227,3 @@ msgstr ""
msgid "Copyright \\(co 2000-2009 Bastian Kleineidam"
msgstr ""
# type: TH
#~ msgid "10 March 2001"
#~ msgstr "10 mars 2001"
# type: Plain text
#, fuzzy
#~ msgid "Note that by default only errors and warnings are logged."
#~ msgstr "Notez que seules les erreurs sont journalisées par défaut."
# type: TP
#~ msgid "B<-f>I<configfile>, B<--config=>I<configfile>"
#~ msgstr "B<-f>I<configfile>, B<--config=>I<configfile>"
# type: Plain text
#~ msgid "Log warnings."
#~ msgstr "Journaliser les avertissements."
# type: SS
#~ msgid "Deprecated options"
#~ msgstr "Options obsolètes"
# type: Plain text
#~ msgid ""
#~ "Print check status every 5 seconds to stderr. This is the default now."
#~ msgstr ""
#~ "Afficher l'état des vérifications toutes les 5 secondes sur la sortie "
#~ "d'erreur. C'est le comportement par défaut."
# type: Plain text
#~ msgid ""
#~ "A B<!> before any regex negates it. So B<!^mailto:> matches everything "
#~ "but a mailto link."
#~ msgstr ""
#~ "Un B<!> avant une expression rationnelle l'inverse. Ainsi B<!^mailto:> "
#~ "correspond à tout sauf un lien mailto."
# type: TP
#~ msgid "B<-i>I<regex>, B<--intern=>I<regex>"
#~ msgstr "B<-i>I<regex>, B<--intern=>I<regex>"
# type: Plain text
#~ msgid ""
#~ "Assume URLs that match the given regular expression as internal. "
#~ "LinkChecker descends recursively only to internal URLs, not to external."
#~ msgstr ""
#~ "Supposer que les URL correspondant à l'expression rationnelle donnée sont "
#~ "internes. LinkChecker ne descend récursivement que sur les URL internes, "
#~ "et pas sur les externes."
# type: TP
#~ msgid "B<-e>I<regex>, B<--extern=>I<regex>"
#~ msgstr "B<-e>I<regex>, B<--extern=>I<regex>"
# type: Plain text
#~ msgid ""
#~ "Assume urls that match the given regular expression as external. Only "
#~ "internal HTML links are checked recursively."
#~ msgstr ""
#~ "Supposer que les URL correspondant à l'expression donnée sont externes. "
#~ "Seuls les liens HTML internes sont vérifiés récursivement."
# type: TP
#~ msgid "B<--extern-strict=>I<regex>"
#~ msgstr "B<--extern-strict=>I<regex>"
# type: Plain text
#~ msgid ""
#~ "Assume urls that match the given regular expression as strict external. "
#~ "Only internal HTML links are checked recursively."
#~ msgstr ""
#~ "Supposer que les URL correspondant à l'expression donnée sont strictement "
#~ "externes. Seuls les liens HTML internes sont vérifiés récursivement."
# type: TP
#~ msgid "B<-s>, B<--extern-strict-all>"
#~ msgstr "B<-s>, B<--extern-strict-all>"
# type: Plain text
#~ msgid ""
#~ "Check only the syntax of external links, do not try to connect to them. "
#~ "For local file urls, only local files are internal. For http and ftp "
#~ "urls, all urls at the same domain name are internal."
#~ msgstr ""
#~ "Ne vérifier que la syntaxe des liens externes, sans que l'on essaie de "
#~ "s'y connecter. Pour les URL locales, seuls les fichiers locaux sont "
#~ "internes. Pour les URL HTTP et FTP, toutes les URL avec le même nom de "
#~ "domaine sont internes."
# type: TP
#~ msgid "B<-d>, B<--denyallow>"
#~ msgstr "B<-d>, B<--denyallow>"
# type: Plain text
#~ msgid ""
#~ "Swap checking order to external/internal. Default checking order is "
#~ "internal/external."
#~ msgstr ""
#~ "Inverser l'ordre de vérification en externe/interne. L'ordre de "
#~ "vérification par défaut est interne/externe."

View file

@ -1,30 +0,0 @@
HELPFILES := lccollection.qhc
HTMLFILES := index.html
OXYGEN := ${HOME}/src/oxygen-gitsvn
ICOICONS := logo16x16.png logo32x32.png
ICNSICONS := logo16x16.png logo32x32.png logo48x48.png logo128x128.png
all: $(HELPFILES) $(HTMLFILES)
clean:
-rm -f *.qhc *.qch
%.html: %.txt html.header html.footer
(cat html.header; markdown2 $<; cat html.footer) > $@
test:
xmllint --valid --noout $(HTMLFILES)
%.qhc: %.qhcp lcdoc.qhp $(HTMLFILES)
-qcollectiongenerator $< -o $@
logo%.png: $(OXYGEN)/%/categories/applications-development-web.png
cp $< $@
favicon.ico: $(ICOICONS)
png2ico favicon.ico $(ICOICONS)
favicon.icns: $(ICNSICONS)
png2icns favicon.icns $(ICNSICONS)
.PHONY: clean test

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -1,6 +0,0 @@
<hr/>
<div class="footer">
&copy; Copyright 2012-2014, Bastian Kleineidam.
</div>
</body>
</html>

View file

@ -1,24 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Check websites for broken links</title>
<link rel="stylesheet" href="sphinxdoc.css" type="text/css" />
<link rel="stylesheet" href="pygments.css" type="text/css" />
<style type="text/css">
img { border: 0; }
</style>
</head>
<body>
<div style="background-color: white; text-align: left; padding: 10px 10px 15px 15px">
<table border="0"><tr>
<td><img
src="logo64x64.png" border="0" alt="LinkChecker"/></td>
<td><h1>LinkChecker</h1></td>
</tr></table>
</div>

View file

@ -1,204 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Check websites for broken links</title>
<link rel="stylesheet" href="sphinxdoc.css" type="text/css" />
<link rel="stylesheet" href="pygments.css" type="text/css" />
<style type="text/css">
img { border: 0; }
</style>
</head>
<body>
<div style="background-color: white; text-align: left; padding: 10px 10px 15px 15px">
<table border="0"><tr>
<td><img
src="logo64x64.png" border="0" alt="LinkChecker"/></td>
<td><h1>LinkChecker</h1></td>
</tr></table>
</div>
<h1>Documentation</h1>
<h2>Basic usage</h2>
<p>To check a URL like <a href="http://www.example.org/">http://www.example.org/</a>
it is enough to
type <code>linkchecker www.example.org</code> on the command line or
type <code>www.example.org</code> in the GUI application. This will check the
complete domain of <code>http://www.example.org</code> recursively. All links
pointing outside of the domain are also checked for validity.</p>
<p>Local files can also be checked. On Unix or OSX systems the syntax
is <code>file:///path/to/my/file.html</code>. On Windows the syntax is
<code>file://C|/path/to/my/file.html</code>. When directories are checked,
all included files will be checked.</p>
<p>On the GUI client the <code>Edit</code> menu has shortcuts for bookmark
files. For example if Google Chrome is installed, there will be
a menu entry called <code>Insert Google Chrome bookmark file</code> which
can be used to check all browser bookmarks.</p>
<h2>Options</h2>
<p>The commandline client options are documented
in the <a href="http://wummel.github.io/linkchecker/man1/linkchecker.1.html">linkchecker(1) manual page</a>.</p>
<p>In the GUI client, the following options are available:</p>
<ul>
<li><p>Recursive depth</p>
<p>Check recursively all links up to given depth.
A negative depth (eg. <code>-1</code>) will enable infinite recursion.</p></li>
<li><p>Verbose output</p>
<p>If set, log all checked URLs. Default is to log only errors and warnings.</p></li>
<li><p>Debug</p>
<p>Prints debugging output in a separate window which can be seen with
<code>Help -&gt; Show debug</code>.</p></li>
<li><p>Debug memory usage</p>
<p>Profiles memory usage and writes statistics and a dump file when checking
stops. The dump file can be examined with
<a href="https://github.com/wummel/linkchecker/blob/master/tests/analyze_memdump.py">external tools</a>.
This option should only be useful for developers.</p></li>
<li><p>Warning strings</p>
<p>Log a warning if any strings are found in the content of the checked
URL. Strings are entered one per line.</p>
<p>Use this to check for pages that contain some form of error, for example
"<code>This page has moved</code>" or "<code>Oracle Application error</code>".</p></li>
<li><p>Ignoring URLs</p>
<p>URLs matching the given regular expressions will be ignored and not checked.
Useful if certain URL types should not be checked like emails (ie.
"<code>^mailto:</code>").</p></li>
</ul>
<h2>Configuration file</h2>
<p>Each user can edit a configuration with advanced options for
checking or filtering. The
<a href="http://wummel.github.io/linkchecker/man5/linkcheckerrc.5.html">linkcheckerrc(5) manual page</a>
documents all the options.</p>
<p>In the GUI client the configuration file can be edited directly from
the dialog <code>Edit -&gt; Options</code> and the clicking on <code>Edit</code>.</p>
<h2>Performed checks</h2>
<p>All URLs have to pass a preliminary syntax test.
After the syntax check passes, the URL is queued for connection
checking. All connection check types are described below.</p>
<ul>
<li><p>HTTP links (<code>http:</code>, <code>https:</code>)</p>
<p>After connecting to the given HTTP server the given path
or query is requested. All redirections are followed, and
if user/password is given it will be used as authorization
when necessary.
Permanently moved pages (status code 301) issue a warning.
All final HTTP status codes other than 2xx are errors.</p>
<p>For HTTPS links, the SSL certificate is checked against the
given hostname. If it does not match, a warnings is printed.</p></li>
<li><p>Local files (<code>file:</code>)</p>
<p>A regular, readable file that can be opened is valid. A readable
directory is also valid. All other files, for example unreadable,
non-existing or device files are errors.</p>
<p>File contents are checked for recursion. If they are parseable
files (for example HTML files), all links in that file will be
checked.</p></li>
<li><p>Mail links (<code>mailto:</code>)</p>
<p>A mailto: link resolves to a list of email addresses.
If one email address fails the whole list will fail.
For each email address the following things are checked:</p>
<ol>
<li>Check the address syntax, both the part before and after
the @ sign.</li>
<li>Look up the MX DNS records. If no MX record is found,
print an error.</li>
<li>Check if one of the MX mail hosts accept an SMTP connection.
Check hosts with higher priority first.
If none of the hosts accept SMTP, a warning is printed.</li>
<li>Try to verify the address with the VRFY command. If there is
an answer, the verified address is printed as an info.</li>
</ol></li>
<li><p>FTP links (<code>ftp:</code>)</p>
<p>For FTP links the following is checked:</p>
<ol>
<li>Connect to the specified host.</li>
<li>Try to login with the given user and password. The default
user is <code>anonymous</code>, the default password is <code>anonymous@</code>.</li>
<li>Try to change to the given directory.</li>
<li>List the file with the NLST command.</li>
</ol></li>
<li><p>Telnet links (<code>telnet:</code>)</p>
<p>A connect and if user/password are given, login to the
given telnet server is tried.</p></li>
<li><p>NNTP links (<code>news:</code>, <code>snews:</code>, <code>nntp</code>)</p>
<p>A connect is tried to connect to the given NNTP server. If a news group or
article is specified, it will be requested from the server.</p></li>
<li><p>Unsupported links (<code>javascript:</code>, etc.)</p>
<p>An unsupported link will print a warning, but no error. No further checking
will be made.</p>
<p>The complete list of recognized, but unsupported links can be seen in the
<a href="https://github.com/wummel/linkchecker/blob/master/linkcheck/checker/unknownurl.py">unknownurl.py</a>
source file. The most prominent of them are JavaScript links.</p></li>
</ul>
<h2>Recursion</h2>
<p>Before descending recursively into a URL, it has to fulfill several
conditions. The conditions are checked in this order:</p>
<ol>
<li>The URL must be valid.</li>
<li>The URL must be parseable. This currently includes HTML files,
Bookmarks files (Opera, Chrome or Safari), directories and on
Windows systems MS Word files if Word and the Pywin32 module
is installed on your system.
If a file type cannot be determined (for example it does not have
a common HTML file extension, and the content does not look like
HTML), it is assumed to be non-parseable.</li>
<li>The URL content must be retrievable. This is usually the case
except for example mailto: or unknown URL types.</li>
<li>The maximum recursion level must not be exceeded. It is configured
with the <code>--recursion-level</code> command line option, the recursion
level GUI option, or through the configuration file.
The recursion level is unlimited by default.</li>
<li>It must not match the ignored URL list. This is controlled with
the <code>--ignore-url</code> command line option or through the
configuration file.</li>
<li>The Robots Exclusion Protocol must allow links in the URL to be
followed recursively. This is checked by evaluating the servers
robots.txt file and searching for a "nofollow" directive in the
HTML header data.</li>
</ol>
<p>Note that the local and FTP directory recursion reads all files in that
directory, not just a subset like <code>index.htm*</code>.</p>
<hr/>
<div class="footer">
&copy; Copyright 2012-2014, Bastian Kleineidam.
</div>
</body>
</html>

View file

@ -1,175 +0,0 @@
# Documentation
## Basic usage
To check a URL like [http://www.example.org/](http://www.example.org/)
it is enough to
type ``linkchecker www.example.org`` on the command line or
type ``www.example.org`` in the GUI application. This will check the
complete domain of ``http://www.example.org`` recursively. All links
pointing outside of the domain are also checked for validity.
Local files can also be checked. On Unix or OSX systems the syntax
is ``file:///path/to/my/file.html``. On Windows the syntax is
``file://C|/path/to/my/file.html``. When directories are checked,
all included files will be checked.
On the GUI client the ``Edit`` menu has shortcuts for bookmark
files. For example if Google Chrome is installed, there will be
a menu entry called ``Insert Google Chrome bookmark file`` which
can be used to check all browser bookmarks.
## Options
The commandline client options are documented
in the [linkchecker(1) manual page](http://wummel.github.io/linkchecker/man1/linkchecker.1.html).
In the GUI client, the following options are available:
- Recursive depth
Check recursively all links up to given depth.
A negative depth (eg. ``-1``) will enable infinite recursion.
- Verbose output
If set, log all checked URLs. Default is to log only errors and warnings.
- Debug
Prints debugging output in a separate window which can be seen with
``Help -> Show debug``.
- Debug memory usage
Profiles memory usage and writes statistics and a dump file when checking
stops. The dump file can be examined with
[external tools](https://github.com/wummel/linkchecker/blob/master/tests/analyze_memdump.py).
This option should only be useful for developers.
- Warning strings
Log a warning if any strings are found in the content of the checked
URL. Strings are entered one per line.
Use this to check for pages that contain some form of error, for example
"``This page has moved``" or "``Oracle Application error``".
- Ignoring URLs
URLs matching the given regular expressions will be ignored and not checked.
Useful if certain URL types should not be checked like emails (ie.
"``^mailto:``").
## Configuration file
Each user can edit a configuration with advanced options for
checking or filtering. The
[linkcheckerrc(5) manual page](http://wummel.github.io/linkchecker/man5/linkcheckerrc.5.html)
documents all the options.
In the GUI client the configuration file can be edited directly from
the dialog ``Edit -> Options`` and the clicking on ``Edit``.
## Performed checks
All URLs have to pass a preliminary syntax test.
After the syntax check passes, the URL is queued for connection
checking. All connection check types are described below.
- HTTP links (``http:``, ``https:``)
After connecting to the given HTTP server the given path
or query is requested. All redirections are followed, and
if user/password is given it will be used as authorization
when necessary.
Permanently moved pages (status code 301) issue a warning.
All final HTTP status codes other than 2xx are errors.
For HTTPS links, the SSL certificate is checked against the
given hostname. If it does not match, a warnings is printed.
- Local files (``file:``)
A regular, readable file that can be opened is valid. A readable
directory is also valid. All other files, for example unreadable,
non-existing or device files are errors.
File contents are checked for recursion. If they are parseable
files (for example HTML files), all links in that file will be
checked.
- Mail links (``mailto:``)
A mailto: link resolves to a list of email addresses.
If one email address fails the whole list will fail.
For each email address the following things are checked:
1. Check the address syntax, both the part before and after
the @ sign.
2. Look up the MX DNS records. If no MX record is found,
print an error.
3. Check if one of the MX mail hosts accept an SMTP connection.
Check hosts with higher priority first.
If none of the hosts accept SMTP, a warning is printed.
4. Try to verify the address with the VRFY command. If there is
an answer, the verified address is printed as an info.
- FTP links (``ftp:``)
For FTP links the following is checked:
1. Connect to the specified host.
2. Try to login with the given user and password. The default
user is ``anonymous``, the default password is ``anonymous@``.
3. Try to change to the given directory.
4. List the file with the NLST command.
- Telnet links (``telnet:``)
A connect and if user/password are given, login to the
given telnet server is tried.
- NNTP links (``news:``, ``snews:``, ``nntp``)
A connect is tried to connect to the given NNTP server. If a news group or
article is specified, it will be requested from the server.
- Unsupported links (``javascript:``, etc.)
An unsupported link will print a warning, but no error. No further checking
will be made.
The complete list of recognized, but unsupported links can be seen in the
[unknownurl.py](https://github.com/wummel/linkchecker/blob/master/linkcheck/checker/unknownurl.py)
source file. The most prominent of them are JavaScript links.
## Recursion
Before descending recursively into a URL, it has to fulfill several
conditions. The conditions are checked in this order:
1. The URL must be valid.
2. The URL must be parseable. This currently includes HTML files,
Bookmarks files (Opera, Chrome or Safari), directories and on
Windows systems MS Word files if Word and the Pywin32 module
is installed on your system.
If a file type cannot be determined (for example it does not have
a common HTML file extension, and the content does not look like
HTML), it is assumed to be non-parseable.
3. The URL content must be retrievable. This is usually the case
except for example mailto: or unknown URL types.
4. The maximum recursion level must not be exceeded. It is configured
with the ``--recursion-level`` command line option, the recursion
level GUI option, or through the configuration file.
The recursion level is unlimited by default.
5. It must not match the ignored URL list. This is controlled with
the ``--ignore-url`` command line option or through the
configuration file.
6. The Robots Exclusion Protocol must allow links in the URL to be
followed recursively. This is checked by evaluating the servers
robots.txt file and searching for a "nofollow" directive in the
HTML header data.
Note that the local and FTP directory recursion reads all files in that
directory, not just a subset like ``index.htm*``.

View file

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<QHelpCollectionProject version="1.0">
<assistant>
<title>LinkChecker</title>
<applicationIcon>logo16x16.png</applicationIcon>
<cacheDirectory>bfk/LinkChecker</cacheDirectory>
<startPage>qthelp://bfk.app.linkchecker/doc/index.html</startPage>
<enableDocumentationManager>false</enableDocumentationManager>
<enableAddressBar>false</enableAddressBar>
<enableFilterFunctionality>false</enableFilterFunctionality>
</assistant>
<docFiles>
<generate>
<file>
<input>lcdoc.qhp</input>
<output>lcdoc.qch</output>
</file>
</generate>
<register>
<file>lcdoc.qch</file>
</register>
</docFiles>
</QHelpCollectionProject>

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<QtHelpProject version="1.0">
<namespace>bfk.app.linkchecker</namespace>
<virtualFolder>doc</virtualFolder>
<filterSection>
<toc>
<section title="LinkChecker documentation" ref="index.html"/>
</toc>
<files>
<file>index.html</file>
</files>
</filterSection>
</QtHelpProject>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

View file

@ -1,61 +0,0 @@
.hll { background-color: #ffffcc }
.c { color: #408090; font-style: italic } /* Comment */
.err { border: 1px solid #FF0000 } /* Error */
.k { color: #007020; font-weight: bold } /* Keyword */
.o { color: #666666 } /* Operator */
.cm { color: #408090; font-style: italic } /* Comment.Multiline */
.cp { color: #007020 } /* Comment.Preproc */
.c1 { color: #408090; font-style: italic } /* Comment.Single */
.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
.gd { color: #A00000 } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #FF0000 } /* Generic.Error */
.gh { color: #000080; font-weight: bold } /* Generic.Heading */
.gi { color: #00A000 } /* Generic.Inserted */
.go { color: #303030 } /* Generic.Output */
.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.gt { color: #0040D0 } /* Generic.Traceback */
.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
.kp { color: #007020 } /* Keyword.Pseudo */
.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.kt { color: #902000 } /* Keyword.Type */
.m { color: #208050 } /* Literal.Number */
.s { color: #4070a0 } /* Literal.String */
.na { color: #4070a0 } /* Name.Attribute */
.nb { color: #007020 } /* Name.Builtin */
.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.no { color: #60add5 } /* Name.Constant */
.nd { color: #555555; font-weight: bold } /* Name.Decorator */
.ni { color: #d55537; font-weight: bold } /* Name.Entity */
.ne { color: #007020 } /* Name.Exception */
.nf { color: #06287e } /* Name.Function */
.nl { color: #002070; font-weight: bold } /* Name.Label */
.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.nt { color: #062873; font-weight: bold } /* Name.Tag */
.nv { color: #bb60d5 } /* Name.Variable */
.ow { color: #007020; font-weight: bold } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #208050 } /* Literal.Number.Float */
.mh { color: #208050 } /* Literal.Number.Hex */
.mi { color: #208050 } /* Literal.Number.Integer */
.mo { color: #208050 } /* Literal.Number.Oct */
.sb { color: #4070a0 } /* Literal.String.Backtick */
.sc { color: #4070a0 } /* Literal.String.Char */
.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.s2 { color: #4070a0 } /* Literal.String.Double */
.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
.sh { color: #4070a0 } /* Literal.String.Heredoc */
.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.sx { color: #c65d09 } /* Literal.String.Other */
.sr { color: #235388 } /* Literal.String.Regex */
.s1 { color: #4070a0 } /* Literal.String.Single */
.ss { color: #517918 } /* Literal.String.Symbol */
.bp { color: #007020 } /* Name.Builtin.Pseudo */
.vc { color: #bb60d5 } /* Name.Variable.Class */
.vg { color: #bb60d5 } /* Name.Variable.Global */
.vi { color: #bb60d5 } /* Name.Variable.Instance */
.il { color: #208050 } /* Literal.Number.Integer.Long */

View file

@ -1,303 +0,0 @@
/**
* Sphinx stylesheet -- sphinxdoc theme
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Originally created by Armin Ronacher for Werkzeug, adapted by Georg Brandl.
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
'Verdana', sans-serif;
font-size: 14px;
letter-spacing: -0.01em;
line-height: 150%;
text-align: center;
background-color: #BFD1D4;
color: black;
padding: 0;
border: 1px solid #aaa;
margin: 0px 80px 0px 80px;
min-width: 740px;
}
div.document {
background-color: white;
text-align: left;
background-image: url(contents.png);
background-repeat: repeat-x;
}
div.bodywrapper {
margin: 0 240px 0 0;
border-right: 1px solid #ccc;
}
div.body {
margin: 0;
padding: 0.5em 20px 20px 20px;
}
div.related {
font-size: 1em;
}
div.related ul {
background-image: url(navigation.png);
height: 2em;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
div.related ul li {
margin: 0;
padding: 0;
height: 2em;
float: left;
}
div.related ul li.right {
float: right;
margin-right: 5px;
}
div.related ul li a {
margin: 0;
padding: 0 5px 0 5px;
line-height: 1.75em;
color: #EE9816;
}
div.related ul li a:hover {
color: #3CA8E7;
}
div.sphinxsidebarwrapper {
padding: 0;
}
div.sphinxsidebar {
margin: 0;
padding: 0.5em 15px 15px 0;
width: 210px;
float: right;
font-size: 1em;
text-align: left;
}
div.sphinxsidebar h3, div.sphinxsidebar h4 {
margin: 1em 0 0.5em 0;
font-size: 1em;
padding: 0.1em 0 0.1em 0.5em;
color: white;
border: 1px solid #86989B;
background-color: #AFC1C4;
}
div.sphinxsidebar h3 a {
color: white;
}
div.sphinxsidebar ul {
padding-left: 1.5em;
margin-top: 7px;
padding: 0;
line-height: 130%;
}
div.sphinxsidebar ul ul {
margin-left: 20px;
}
div.footer {
background-color: #E3EFF1;
color: #86989B;
padding: 3px 8px 3px 0;
clear: both;
font-size: 0.8em;
text-align: right;
}
div.footer a {
color: #86989B;
}
/* -- body styles ----------------------------------------------------------- */
p {
margin: 0.8em 0 0.5em 0;
}
a {
color: #CA7900;
}
a:hover {
color: #2491CF;
}
h1 {
margin: 0;
padding: 0.7em 0 0.3em 0;
font-size: 1.5em;
color: #11557C;
}
h2 {
margin: 1.3em 0 0.2em 0;
font-size: 1.35em;
padding: 0;
}
h3 {
margin: 1em 0 -0.3em 0;
font-size: 1.2em;
}
div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
color: black!important;
}
h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
display: none;
margin: 0 0 0 0.3em;
padding: 0 0.2em 0 0.2em;
color: #aaa!important;
}
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
h5:hover a.anchor, h6:hover a.anchor {
display: inline;
}
h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
h5 a.anchor:hover, h6 a.anchor:hover {
color: #777;
background-color: #eee;
}
cite, code, tt {
font-family: 'Consolas', 'Deja Vu Sans Mono',
'Bitstream Vera Sans Mono', monospace;
font-size: 0.95em;
letter-spacing: 0.01em;
}
tt {
background-color: #f2f2f2;
border-bottom: 1px solid #ddd;
color: #333;
}
tt.descname, tt.descclassname, tt.xref {
border: 0;
}
hr {
border: 1px solid #abc;
margin: 2em;
}
a tt {
border: 0;
color: #CA7900;
}
a tt:hover {
color: #2491CF;
}
pre {
font-family: 'Consolas', 'Deja Vu Sans Mono',
'Bitstream Vera Sans Mono', monospace;
font-size: 0.95em;
letter-spacing: 0.015em;
line-height: 120%;
padding: 0.5em;
border: 1px solid #ccc;
background-color: #f8f8f8;
}
pre a {
color: inherit;
}
td.linenos pre {
padding: 0.5em 0;
}
div.quotebar {
background-color: #f8f8f8;
max-width: 250px;
float: right;
padding: 2px 7px;
border: 1px solid #ccc;
}
div.topic {
background-color: #f8f8f8;
}
table {
border-collapse: collapse;
margin: 0 -0.5em 0 -0.5em;
}
table td, table th {
padding: 0.2em 0.5em 0.2em 0.5em;
}
div.admonition, div.warning {
font-size: 0.9em;
margin: 1em 0 1em 0;
border: 1px solid #86989B;
background-color: #f7f7f7;
padding: 0;
}
div.admonition p, div.warning p {
margin: 0.5em 1em 0.5em 1em;
padding: 0;
}
div.admonition pre, div.warning pre {
margin: 0.4em 1em 0.4em 1em;
}
div.admonition p.admonition-title,
div.warning p.admonition-title {
margin: 0;
padding: 0.1em 0 0.1em 0.5em;
color: white;
border-bottom: 1px solid #86989B;
font-weight: bold;
background-color: #AFC1C4;
}
div.warning {
border: 1px solid #940000;
}
div.warning p.admonition-title {
background-color: #CF0000;
border-bottom-color: #940000;
}
div.admonition ul, div.admonition ol,
div.warning ul, div.warning ol {
margin: 0.1em 0.5em 0.5em 3em;
padding: 0;
}
div.versioninfo {
margin: 1em 0 0 0;
border: 1px solid #ccc;
background-color: #DDEAF0;
padding: 8px;
line-height: 1.3em;
font-size: 0.9em;
}

View file

@ -55,39 +55,28 @@ First, install the required software.
On most distributions, the distutils module is included in
an extra ``python-dev`` package.
3. Qt development tools
The binary "qcollectiongenerator" is used to generate the
documentation files.
On Debian or Ubuntu systems, install the package qt4-dev-tools.
On Redhat systems, install the package qt-devel.
3. Python requests module from https://pypi.python.org/pypi/requests
4. Python requests module from https://pypi.python.org/pypi/requests
5. *Optional, for bash-completion:*
4. *Optional, for bash-completion:*
argcomplete Python module from https://pypi.python.org/pypi/argcomplete
6. *Optional, for displaying country codes:*
5. *Optional, for displaying country codes:*
GeoIP from http://www.maxmind.com/app/python
7. *Optional, used for Virus checking:*
6. *Optional, used for Virus checking:*
ClamAv from http://www.clamav.net/
8. *Optional, for GNOME proxy setting parsing:*
7. *Optional, for GNOME proxy setting parsing:*
Python Gtk from http://www.pygtk.org/downloads.html
9. *Optional, to run the WSGI web interface:*
8. *Optional, to run the WSGI web interface:*
Apache from http://httpd.apache.org/
mod_wsgi from http://code.google.com/p/modwsgi/
Now install the application.
1. Generate Qt documentation
Run ``make -C doc/html`` to generate the Qt help file.
2. Compile Python modules
1. Compile Python modules
Run ``python setup.py sdist --manifest-only`` to create the MANIFEST
file.
@ -97,7 +86,7 @@ Now install the application.
The CC environment variable is checked before compilation, so you can
change the default C compiler with ``export CC=myccompiler``.
3.
2.
a) Installation as root
Run ``sudo python setup.py install`` to install LinkChecker.
@ -134,7 +123,6 @@ Manual setup for OSX systems
brew update
brew install python
brew install pyqt
brew install gettext
# link gettext or put the msgfmt binary in your PATH
brew link --force gettext

View file

@ -1,11 +0,0 @@
--- linkchecker-gui.1.html.orig 2011-06-14 21:22:16.160383430 +0200
+++ linkchecker-gui.1.html 2011-06-14 21:22:23.120641725 +0200
@@ -45,7 +45,7 @@
</DL>
<HR>
This document was created by
-<A HREF="/cgi-bin/man/man2html">man2html</A>,
+man2html,
using the manual pages.<BR>
</BODY>

View file

@ -1,10 +0,0 @@
[Desktop Entry]
Name=LinkChecker GUI
GenericName=URL validator
GenericName[de]=URL Validator
Version=1.0
Type=Application
Exec=linkchecker-gui
Terminal=false
Categories=Network;WebDevelopment;
Icon=logo48x48

File diff suppressed because it is too large Load diff

View file

@ -2,4 +2,3 @@
[po4a_paths] linkchecker.doc.pot $lang:$lang.po
[type: man] en/linkchecker.1 $lang:$lang/linkchecker.1
[type: man] en/linkcheckerrc.5 $lang:$lang/linkcheckerrc.5
[type: man] en/linkchecker-gui.1 $lang:$lang/linkchecker-gui.1

View file

@ -5,7 +5,6 @@ Porting status of dependent Python packages
OK Python
OK requests
OK Qt/PyQt
OK mod_wsgi from http://code.google.com/p/modwsgi/
OK argcomplete from https://pypi.python.org/pypi/argcomplete
OK dnspython (as dnspython3)

View file

@ -27,7 +27,7 @@ Features
- [Plugin support](plugins.html)
allowing custom page checks. Currently available are
HTML and CSS syntax checks, Antivirus checks, and more.
- Different interfaces: command line, GUI and web interface
- Different interfaces: command line and web interface
- ... and a lot more check options documented in the
[manual page](man1/linkchecker.1.html).
@ -35,15 +35,14 @@ Features
Screenshots
------------
[![CLI screenshot](images/shot1_thumb.jpg)](images/shot1.png) | [![GUI screenshot](images/shot2_thumb.jpg)](images/shot2.png) | [![CGI screenshot](images/shot3_thumb.jpg)](images/shot3.png)
--------------------------------------------------------------|---------------------------------------------------------------|--------------------------------------------------------------
Commandline interface | GUI client | CGI web interface
[![CLI screenshot](images/shot1_thumb.jpg)](images/shot1.png) | [![CGI screenshot](images/shot3_thumb.jpg)](images/shot3.png)
--------------------------------------------------------------|--------------------------------------------------------------
Commandline interface | CGI web interface
Basic usage
------------
To check a URL like `http://www.example.org/myhomepage/` it is enough to
enter `http://www.example.org/myhomepage/` in the GUI client or
web interface, or execute
enter `http://www.example.org/myhomepage/` in the web interface, or execute
`linkchecker http://www.example.org/myhomepage/` on the command line.
This check will validate recursively all pages starting with

View file

@ -2,11 +2,8 @@ title: "Other free link checkers"
---
All of the programs below have an
[Open Source license](http://www.opensource.org/licenses/) like LinkChecker.
Programs without an Open Source license are not mentioned here for
security and copyright reasons.
Also not mentioned are programs which have not been updated for
more than 10 years.
Programs without an Open Source license are not listed, as well as
programs which have not been updated for more than 10 years.
- [gURLChecker](http://labs.libre-entreprise.org/projects/gurlchecker/)
written in C, last updated February 22, 2011 (version 0.13.1)
@ -14,5 +11,3 @@ more than 10 years.
is an online service, but source is available, last updated 2011
- [webcheck](http://arthurdejong.org/webcheck/)
written in Python, last updated September 11, 2010 (version 1.10.4)
- [webgrep](http://cgi.linuxfocus.org/~guido/index.html#webgrep)
written in Perl, last updated April 2004 (version 2.12)

View file

@ -1,59 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML><HEAD><TITLE>Man page of LINKCHECKER-GUI</TITLE>
</HEAD><BODY>
<H1>LINKCHECKER-GUI</H1>
Section: LinkChecker GUI client (1)<BR>Updated: 2009-01-10<BR><A HREF="#index">Index</A>
<A HREF="../index.html">Return to Main Contents</A><HR>
<A NAME="lbAB">&nbsp;</A>
<H2>NAME</H2>
linkchecker-gui - GUI client to check links of websites and HTML documents
<A NAME="lbAC">&nbsp;</A>
<H2>SYNOPSIS</H2>
<B>linkchecker-gui</B> [<I>file-or-url-or-project</I>]
<A NAME="lbAD">&nbsp;</A>
<H2>DESCRIPTION</H2>
A graphical interface to check links of websites and HTML documents.
<A NAME="lbAE">&nbsp;</A>
<H2>PROJECT FILES</H2>
A project file has a .lcp extension. The file stores all active preferences
and the current checked URL. Project files can be loaded with the
menu entry or with drag-and-drop on the GUI window.
<P>
<A NAME="lbAF">&nbsp;</A>
<H2>SEE ALSO</H2>
<B><A HREF="../man1/linkchecker.1.html">linkchecker</A></B>(1)
<A NAME="lbAG">&nbsp;</A>
<H2>AUTHOR</H2>
Bastian Kleineidam &lt;<A HREF="mailto:bastian.kleineidam@web.de">bastian.kleineidam@web.de</A>&gt;
<A NAME="lbAH">&nbsp;</A>
<H2>COPYRIGHT</H2>
Copyright &#169; 2009-2014 Bastian Kleineidam
<P>
<HR>
<A NAME="index">&nbsp;</A><H2>Index</H2>
<DL>
<DT><A HREF="#lbAB">NAME</A><DD>
<DT><A HREF="#lbAC">SYNOPSIS</A><DD>
<DT><A HREF="#lbAD">DESCRIPTION</A><DD>
<DT><A HREF="#lbAE">PROJECT FILES</A><DD>
<DT><A HREF="#lbAF">SEE ALSO</A><DD>
<DT><A HREF="#lbAG">AUTHOR</A><DD>
<DT><A HREF="#lbAH">COPYRIGHT</A><DD>
</DL>
<HR>
This document was created by
man2html,
using the manual pages.<BR>
</BODY>
</HTML>

View file

@ -44,22 +44,21 @@ HTML and CSS syntax check
<DT>&bull;<DD>
Antivirus check
<DT>&bull;<DD>
a command line, GUI and web interface
a command line and web interface
</DL>
<A NAME="lbAE">&nbsp;</A>
<H2>EXAMPLES</H2>
The most common use checks the given domain recursively, plus any
URL pointing outside of the domain:
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;http://www.example.net/</B>
The most common use checks the given domain recursively:
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;<A HREF="http://www.example.com/">http://www.example.com/</A></B>
<BR>
Beware that this checks the whole site which can have thousands of URLs.
Use the <B>-r</B> option to restrict the recursion depth.
<BR>
Don't check <B>mailto:</B> URLs. All other links are checked as usual:
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;--ignore-url=^mailto:&nbsp;mysite.example.org</B>
Don't check URLs with <B>/secret</B> in its name. All other links are checked as usual:
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;--ignore-url=/secret&nbsp;mysite.example.com</B>
<BR>
Checking a local HTML file on Unix:
@ -71,15 +70,15 @@ Checking a local HTML file on Windows:
<BR>
You can skip the <B>http://</B> url part if the domain starts with <B>www.</B>:
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;www.example.com</B>
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;<A HREF="http://www.example.com">www.example.com</A></B>
<BR>
You can skip the <B>ftp://</B> url part if the domain starts with <B>ftp.</B>:
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;-r0&nbsp;ftp.example.org</B>
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;-r0&nbsp;<A HREF="ftp://ftp.example.com">ftp.example.com</A></B>
<BR>
Generate a sitemap graph and convert it with the graphviz dot utility:
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;-odot&nbsp;-v&nbsp;www.example.com&nbsp;|&nbsp;dot&nbsp;-Tps&nbsp;&gt;&nbsp;sitemap.ps</B>
<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;-odot&nbsp;-v&nbsp;<A HREF="http://www.example.com">www.example.com</A>&nbsp;|&nbsp;dot&nbsp;-Tps&nbsp;&gt;&nbsp;sitemap.ps</B>
<A NAME="lbAF">&nbsp;</A>
<H2>OPTIONS</H2>
@ -99,21 +98,17 @@ Generate no more than the given number of threads. Default number
of threads is 10. To disable threading specify a non-positive number.
<DT><B>-V</B>, <B>--version</B><DD>
Print version and exit.
<DT><B>--list-plugins</B><DD>
Print available check plugins and exit.
</DL>
<A NAME="lbAH">&nbsp;</A>
<H3>Output options</H3>
<DL COMPACT>
<DT><B>--check-css</B><DD>
Check syntax of CSS URLs with the W3C online validator.
<DT><B>--check-html</B><DD>
Check syntax of HTML URLs with the W3C online validator.
<DT><B>--complete</B><DD>
Log all URLs, including duplicates. Default is to log duplicate URLs only once.
<DT><B>-D</B><I>STRING</I>, <B>--debug=</B><I>STRING</I><DD>
Print debugging output for the given logger.
Available loggers are <B>cmdline</B>, <B>checking</B>,
<B>cache</B>, <B>gui</B>, <B>dns</B> and <B>all</B>.
<B>cache</B>, <B>dns</B> and <B>all</B>.
Specifying <B>all</B> is an alias for specifying all available loggers.
The option can be given multiple times to debug with more
than one logger.
@ -156,10 +151,6 @@ that of your locale. Valid encodings are listed at
<DT><B>-q</B>, <B>--quiet</B><DD>
Quiet operation, an alias for <B>-o none</B>.
This is only useful with <B>-F</B>.
<DT><B>--scan-virus</B><DD>
Scan content of URLs for viruses with ClamAV.
<DT><B>--trace</B><DD>
Print tracing information.
<DT><B>-v</B>, <B>--verbose</B><DD>
Log all checked URLs. Default is to log only errors and warnings.
<DT><B>-W</B><I>REGEX</I>, <B>--warning-regex=</B><I>REGEX</I><DD>
@ -177,26 +168,17 @@ for example &quot;(This page has moved|Oracle Application error)&quot;.
<BR>
See section <B>REGULAR EXPRESSIONS</B> for more info.
<DT><B>--warning-size-bytes=</B><I>NUMBER</I><DD>
Print a warning if content size info is available and exceeds the given
number of <I>bytes</I>.
</DL>
<A NAME="lbAI">&nbsp;</A>
<H3>Checking options</H3>
<DL COMPACT>
<DT><B>-a</B>, <B>--anchors</B><DD>
Check HTTP anchor references. Default is not to check anchors.
This option enables logging of the warning <B>url-anchor-not-found</B>.
<DT><B>-C</B>, <B>--cookies</B><DD>
Accept and send HTTP cookies according to RFC 2109. Only cookies
which are sent back to the originating server are accepted.
Sent and accepted cookies are provided as additional logging
information.
<DT><B>--cookiefile=</B><I>FILENAME</I><DD>
Read a file with initial cookie data. The cookie data
format is explained below.
<DT><B>--ignore-url=</B><I>REGEX</I><DD>
<DT><B>--check-extern<DD>
Check external URLs.
<DT>--ignore-url=</B><I>REGEX</I><DD>
URLs matching the given regular expression will be ignored and not checked.
<BR>
@ -221,9 +203,6 @@ See section <B>REGULAR EXPRESSIONS</B> for more info.
Read a password from console and use it for HTTP and FTP authorization.
For FTP the default password is <B>anonymous@</B>. For HTTP there is
no default password. See also <B>-u</B>.
<DT><B>-P</B><I>NUMBER</I>, <B>--pause=</B><I>NUMBER</I><DD>
Pause the given number of seconds between two subsequent connection
requests to the same host. Default is no pause between requests.
<DT><B>-r</B><I>NUMBER</I>, <B>--recursion-level=</B><I>NUMBER</I><DD>
Check recursively all links up to given depth.
A negative depth will enable infinite recursion.
@ -299,13 +278,11 @@ expression.
A cookie file contains standard HTTP header (RFC 2616) data with the
following possible names:
<DL COMPACT>
<DT><B>Scheme</B> (optional)<DD>
Sets the scheme the cookies are valid for; default scheme is <B>http</B>.
<DT><B>Host</B> (required)<DD>
Sets the domain the cookies are valid for.
<DT><B>Path</B> (optional)<DD>
Gives the path the cookies are value for; default path is <B>/</B>.
<DT><B>Set-cookie</B> (optional)<DD>
<DT><B>Set-cookie</B> (required)<DD>
Set cookie name/value. Can be given more than once.
</DL>
<P>
@ -320,7 +297,6 @@ with <B>https://example.org/</B>:
<BR>&nbsp;Set-cookie:&nbsp;ID=&quot;smee&quot;
<BR>&nbsp;Set-cookie:&nbsp;spam=&quot;egg&quot;
<P>
<BR>&nbsp;Scheme:&nbsp;https
<BR>&nbsp;Host:&nbsp;example.org
<BR>&nbsp;Set-cookie:&nbsp;baggage=&quot;elitist&quot;;&nbsp;comment=&quot;hologram&quot;
<P>
@ -331,7 +307,8 @@ To use a proxy on Unix or Windows set the $http_proxy, $https_proxy or $ftp_prox
environment variables to the proxy URL. The URL should be of the form
<B>http://</B>[<I>user</I><B>:</B><I>pass</I><B>@</B>]<I>host</I>[<B>:</B><I>port</I>].
LinkChecker also detects manual proxy settings of Internet Explorer under
Windows systems. On a Mac use the Internet Config to select a proxy.
Windows systems, and gconf or KDE on Linux systems.
On a Mac use the Internet Config to select a proxy.
You can also set a comma-separated domain list in the $no_proxy environment
variables to ignore any proxy settings for these domains.
Setting a HTTP proxy on Unix for example looks like this:
@ -360,7 +337,6 @@ After connecting to the given HTTP server the given path
or query is requested. All redirections are followed, and
if user/password is given it will be used as authorization
when necessary.
Permanently moved pages issue a warning.
All final HTTP status codes other than 2xx are errors.
HTML page contents are checked for recursion.
<DT>Local files (<B>file:</B>)<DD>
@ -412,6 +388,19 @@ For each mail address we check the following things:
<P>
</DL>
<A NAME="lbAP">&nbsp;</A>
<H2>PLUGINS</H2>
There are two plugin types: connection and content plugins.
Connection plugins are run after a successful connection to the
URL host.
Content plugins are run if the URL type has content
(mailto: URLs have no content for example) and if the check is not
forbidden (ie. by HTTP robots.txt).
See <B>linkchecker --list-plugins</B> for a list of plugins and
their documentation. All plugins are enabled via the <B><A HREF="../man5/linkcheckerrc.5.html">linkcheckerrc</A></B>(5)
configuration file.
<P>
<A NAME="lbAQ">&nbsp;</A>
<H2>RECURSION</H2>
Before descending recursively into a URL, it has to fulfill several
@ -441,7 +430,7 @@ conditions. They are checked in this order:
Note that the directory recursion reads all files in that
directory, not just a subset like <B>index.htm*</B>.
<P>
<A NAME="lbAQ">&nbsp;</A>
<A NAME="lbAR">&nbsp;</A>
<H2>NOTES</H2>
URLs on the commandline starting with <B>ftp.</B> are treated like
@ -463,7 +452,7 @@ You can supply multiple user/password pairs in a configuration file.
<P>
When checking <B>news:</B> links the given NNTP host doesn't need to be the
same as the host of the user browsing your pages.
<A NAME="lbAR">&nbsp;</A>
<A NAME="lbAS">&nbsp;</A>
<H2>ENVIRONMENT</H2>
<B>NNTP_SERVER</B> - specifies default NNTP server
@ -479,7 +468,7 @@ same as the host of the user browsing your pages.
<BR>
<B>LC_MESSAGES</B>, <B>LANG</B>, <B>LANGUAGE</B> - specify output language
<A NAME="lbAS">&nbsp;</A>
<A NAME="lbAT">&nbsp;</A>
<H2>RETURN VALUE</H2>
The return value is 2 when
@ -499,13 +488,13 @@ link warnings were found and warnings are enabled
<P>
Else the return value is zero.
<A NAME="lbAT">&nbsp;</A>
<A NAME="lbAU">&nbsp;</A>
<H2>LIMITATIONS</H2>
LinkChecker consumes memory for each queued URL to check. With thousands
of queued URLs the amount of consumed memory can become quite large. This
might slow down the program or even the whole system.
<A NAME="lbAU">&nbsp;</A>
<A NAME="lbAV">&nbsp;</A>
<H2>FILES</H2>
<B>~/.linkchecker/linkcheckerrc</B> - default configuration file
@ -522,15 +511,15 @@ might slow down the program or even the whole system.
<B><A HREF="http://docs.python.org/howto/regex.html">http://docs.python.org/howto/regex.html</A></B> - regular expression documentation
<P>
<A NAME="lbAV">&nbsp;</A>
<A NAME="lbAW">&nbsp;</A>
<H2>SEE ALSO</H2>
<B><A HREF="../man5/linkcheckerrc.5.html">linkcheckerrc</A></B>(5)
<A NAME="lbAW">&nbsp;</A>
<A NAME="lbAX">&nbsp;</A>
<H2>AUTHOR</H2>
Bastian Kleineidam &lt;<A HREF="mailto:bastian.kleineidam@web.de">bastian.kleineidam@web.de</A>&gt;
<A NAME="lbAX">&nbsp;</A>
<A NAME="lbAY">&nbsp;</A>
<H2>COPYRIGHT</H2>
Copyright &#169; 2000-2014 Bastian Kleineidam
@ -555,15 +544,16 @@ Copyright &#169; 2000-2014 Bastian Kleineidam
<DT><A HREF="#lbAM">COOKIE FILES</A><DD>
<DT><A HREF="#lbAN">PROXY SUPPORT</A><DD>
<DT><A HREF="#lbAO">PERFORMED CHECKS</A><DD>
<DT><A HREF="#lbAP">RECURSION</A><DD>
<DT><A HREF="#lbAQ">NOTES</A><DD>
<DT><A HREF="#lbAR">ENVIRONMENT</A><DD>
<DT><A HREF="#lbAS">RETURN VALUE</A><DD>
<DT><A HREF="#lbAT">LIMITATIONS</A><DD>
<DT><A HREF="#lbAU">FILES</A><DD>
<DT><A HREF="#lbAV">SEE ALSO</A><DD>
<DT><A HREF="#lbAW">AUTHOR</A><DD>
<DT><A HREF="#lbAX">COPYRIGHT</A><DD>
<DT><A HREF="#lbAP">PLUGINS</A><DD>
<DT><A HREF="#lbAQ">RECURSION</A><DD>
<DT><A HREF="#lbAR">NOTES</A><DD>
<DT><A HREF="#lbAS">ENVIRONMENT</A><DD>
<DT><A HREF="#lbAT">RETURN VALUE</A><DD>
<DT><A HREF="#lbAU">LIMITATIONS</A><DD>
<DT><A HREF="#lbAV">FILES</A><DD>
<DT><A HREF="#lbAW">SEE ALSO</A><DD>
<DT><A HREF="#lbAX">AUTHOR</A><DD>
<DT><A HREF="#lbAY">COPYRIGHT</A><DD>
</DL>
<HR>
This document was created by

View file

@ -0,0 +1,30 @@
--- linkchecker.1.html.orig 2011-06-14 21:14:55.016011206 +0200
+++ linkchecker.1.html 2011-06-14 21:17:07.108913849 +0200
@@ -38,7 +38,7 @@
The most common use checks the given domain recursively, plus any
URL pointing outside of the domain:
-<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;<A HREF="http://www.example.net/">http://www.example.net/</A></B>
+<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;http://www.example.net/</B>
<BR>
Beware that this checks the whole site which can have thousands of URLs.
@@ -59,15 +59,15 @@
<BR>
You can skip the <B>http://</B> url part if the domain starts with <B>www.</B>:
-<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;<A HREF="http://www.example.com">www.example.com</A></B>
+<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;www.example.com</B>
<BR>
You can skip the <B>ftp://</B> url part if the domain starts with <B>ftp.</B>:
-<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;-r0&nbsp;<A HREF="ftp://ftp.example.org">ftp.example.org</A></B>
+<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;-r0&nbsp;ftp.example.org</B>
<BR>
Generate a sitemap graph and convert it with the graphviz dot utility:
-<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;-odot&nbsp;-v&nbsp;<A HREF="http://www.example.com">www.example.com</A>&nbsp;|&nbsp;dot&nbsp;-Tps&nbsp;&gt;&nbsp;sitemap.ps</B>
+<BR>&nbsp;&nbsp;<B>linkchecker&nbsp;-odot&nbsp;-v&nbsp;www.example.com&nbsp;|&nbsp;dot&nbsp;-Tps&nbsp;&gt;&nbsp;sitemap.ps</B>
<A NAME="lbAF">&nbsp;</A>
<H2>OPTIONS</H2>

View file

@ -155,7 +155,7 @@ The default number of days is 14.
Command line option: none
<DT><B>maxrunseconds=</B><I>NUMBER</I><DD>
Stop checking new URLs after the given number of seconds. Same as if the
user stops (by hitting Ctrl-C or clicking the abort buttin in the GUI)
user stops (by hitting Ctrl-C)
after the given number of seconds.
<BR>
@ -273,7 +273,7 @@ Command line option: <B>--complete</B>
<DT><B>debug=</B><I>STRING</I>[<B>,</B><I>STRING</I>...]<DD>
Print debugging output for the given loggers.
Available loggers are <B>cmdline</B>, <B>checking</B>,
<B>cache</B>, <B>gui</B>, <B>dns</B>, <B>thread</B> and <B>all</B>.
<B>cache</B>, <B>dns</B>, <B>thread</B> and <B>all</B>.
Specifying <B>all</B> is an alias for specifying all available loggers.
<BR>

View file

@ -45,7 +45,6 @@ from .logconf import (
LOG_CMDLINE,
LOG_CHECK,
LOG_CACHE,
LOG_GUI,
LOG_THREAD,
LOG_PLUGIN,
)

View file

@ -61,35 +61,35 @@ def normpath (path):
return os.path.normcase(os.path.normpath(expanded))
# List optional Python modules in the form (module, name)
# List Python modules in the form (module, name, version attribute)
Modules = (
("PyQt4.Qsci", u"QScintilla"),
("argcomplete", u"Argcomplete"),
("GeoIP", u"GeoIP"), # on Unix systems
("pygeoip", u"GeoIP"), # on Windows systems
("sqlite3", u"Sqlite"),
("gconf", u"Gconf"),
("meliae", u"Meliae"),
# required modules
("requests", "Requests", "__version__"),
# optional modules
("argcomplete", u"Argcomplete", None),
("GeoIP", u"GeoIP", 'lib_version'), # on Unix systems
("pygeoip", u"GeoIP", 'lib_version'), # on Windows systems
("sqlite3", u"Pysqlite", 'version'),
("sqlite3", u"Sqlite", 'sqlite_version'),
("gconf", u"Gconf", '__version__'),
("meliae", u"Meliae", '__version__'),
)
def get_modules_info ():
"""Return list of unicode strings with detected module info."""
lines = []
# requests
import requests
lines.append(u"Requests: %s" % requests.__version__)
# PyQt
try:
from PyQt4 import QtCore
lines.append(u"Qt: %s / PyQt: %s" %
(QtCore.QT_VERSION_STR, QtCore.PYQT_VERSION_STR))
except (ImportError, AttributeError):
pass
# modules
modules = [name for (mod, name) in Modules if fileutil.has_module(mod)]
if modules:
lines.append(u"Modules: %s" % (u", ".join(modules)))
return lines
def get_modules_info():
"""Return unicode string with detected module info."""
module_infos = []
for (mod, name, version_attr) in Modules:
if not fileutil.has_module(mod):
continue
if hasattr(mod, version_attr):
attr = getattr(mod, version_attr)
version = attr() if callable(attr) else attr
module_infos.append("%s %s" % (name, version))
else:
# ignore attribute errors in case library developers
# change the version information attribute
module_infos.append(name)
return u"Modules: %s" % (u", ".join(module_infos))
def get_share_dir ():

View file

@ -149,8 +149,7 @@ def print_app_info (out=stderr):
{"version": sys.version, "platform": sys.platform}, file=out)
for key in PYTHON_ENV_VARS:
print_env_info(key, out=out)
for line in configuration.get_modules_info():
print(line, file=out)
print(configuration.get_modules_info(), file=out)
stime = strformat.strtime(time.time())
print(_("Local time:"), stime, file=out)
print(_("sys.argv:"), sys.argv, file=out)

View file

@ -1,26 +0,0 @@
# generate Python files from UI description
# edit ui/*.ui files with designer (ie. /usr/bin/designer-qt4)
UI_FILES = linkchecker_ui_main.py \
linkchecker_ui_options.py \
linkchecker_ui_debug.py \
linkchecker_ui_editor.py
RC_FILES = linkchecker_rc.py
all: $(UI_FILES) $(RC_FILES)
linkchecker_ui_%.py: ui/%.ui
pyuic4 -o $@ $<
# replace the Qt translator with the one LinkChecker uses
sed -i -r -e 's/QtGui\.QApplication\.translate\("[^"]+", "([^"]+)", None, QtGui\.QApplication\.UnicodeUTF8\)/_("\1")/g' $@
linkchecker_rc.py: rc/linkchecker.qrc
pyrcc4 -o $@ $<
clean:
rm -f *.pyc *.pyo
rebuild:
rm -f $(UI_FILES) $(RC_FILES)
$(MAKE) all

View file

@ -1,623 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2008-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
import sys
import re
import webbrowser
from PyQt4 import QtCore, QtGui
from .linkchecker_ui_main import Ui_MainWindow
from .properties import set_properties, clear_properties
from .statistics import set_statistics, clear_statistics
from .debug import LinkCheckerDebug
from .logger import SignalLogger, GuiLogHandler, StatusLogger
from .help import HelpWindow
from .options import LinkCheckerOptions
from .checker import CheckerThread
from .contextmenu import ContextMenu
from .editor import EditorWindow
from .updater import UpdateDialog
from .urlmodel import UrlItemModel
from .urlsave import urlsave
from .settings import Settings
from .recentdocs import RecentDocumentModel
from .projects import openproject, saveproject, loadproject, ProjectExt
from .. import configuration, checker, director, get_link_pat, \
strformat, mimeutil, LinkCheckerError, i18n, httputil, logconf
from ..containers import enum
from .. import url as urlutil
DocBaseUrl = "qthelp://bfk.app.linkchecker/doc/"
RegistryBase = "Bastian"
Status = enum('idle', 'checking')
MaxMessageLength = 60
def get_app_style ():
"""Return appropriate QStyle object for the current platform to
be used in QApplication.setStyle().
Currently prefers Macintosh on OS X, else Plastique.
Style names are case insensitive.
See also
http://doc.trolltech.com/latest/gallery-macintosh.html
and
http://doc.trolltech.com/latest/gallery-plastique.html
"""
if sys.platform == 'darwin':
style = "Macintosh"
else:
style = "Plastique"
return QtGui.QStyleFactory.create(style)
def get_icon (name):
"""Return QIcon with given pixmap resource name."""
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(name), QtGui.QIcon.Normal, QtGui.QIcon.Off)
return icon
def warninglines2regex(lines):
"""Convert a list of strings to a regular expression matching any of
the given strings."""
return u"|".join([re.escape(line) for line in lines])
class LinkCheckerMain (QtGui.QMainWindow, Ui_MainWindow):
"""The main window displaying checked URLs."""
log_url_signal = QtCore.pyqtSignal(object)
log_status_signal = QtCore.pyqtSignal(int, int, int, float, int)
log_stats_signal = QtCore.pyqtSignal(object)
error_signal = QtCore.pyqtSignal(str)
def __init__(self, parent=None, url=None, project=None):
"""Initialize UI."""
super(LinkCheckerMain, self).__init__(parent)
self.setupUi(self)
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowContextHelpButtonHint)
self.setWindowTitle(configuration.App)
# app settings
self.settings = Settings(RegistryBase, configuration.AppName)
# init subdialogs
self.options = LinkCheckerOptions(parent=self)
self.debug = LinkCheckerDebug(parent=self)
self.checker = CheckerThread(parent=self)
self.contextmenu = ContextMenu(parent=self)
self.editor = EditorWindow(parent=self)
# Note: do not use QT assistant here because of the .exe packaging
self.assistant = HelpWindow(self, self.get_qhcpath())
self.config_error = None
self.icon_start = get_icon(":/icons/start.png")
self.icon_stop = get_icon(":/icons/stop.png")
self.movie = QtGui.QMovie(":/icons/busy.gif")
self.movie.setCacheMode(QtGui.QMovie.CacheAll)
self.label_busy.setText(u"")
self.label_busy.setMovie(self.movie)
# init the rest
self.init_logging()
self.init_url(url)
self.init_treeview()
self.connect_widgets()
self.init_shortcuts()
self.init_config()
self.read_config()
self.init_menu()
self.init_drop()
self.init_app(project)
def init_logging(self):
"""Initialize logging."""
self.handler = GuiLogHandler(self.debug.log_msg_signal)
logconf.init_log_config(handler=self.handler)
def init_url (self, url):
"""Initialize URL input."""
documents = self.settings.read_recent_documents()
self.recent = RecentDocumentModel(parent=self, documents=documents)
self.urlinput.setModel(self.recent)
if url:
self.urlinput.setText(url)
elif documents:
self.urlinput.setText(documents[0])
def init_menu (self):
"""Add menu entries for bookmark file checking."""
self.urlinput.addMenuEntries(self.menuEdit)
self.menuLang = self.menuEdit.addMenu(_('Languages'))
self.menuLang.setTitle(_("&Language"))
# ensure only one action is checked
langActionGroup = QtGui.QActionGroup(self)
langActionGroup.triggered.connect(self.switch_language)
for i, lang in enumerate(sorted(i18n.supported_languages)):
action = self.menuLang.addAction("&%d %s" % (i, lang))
action.setCheckable(True)
action.setData(lang)
if lang == i18n.default_language:
action.setChecked(True)
langActionGroup.addAction(action)
def init_drop(self):
"""Set and activate drag-and-drop functions."""
self.__class__.dragEnterEvent = self.handleDragEvent
self.__class__.dragMoveEvent = self.handleDragEvent
self.__class__.dropEvent = self.handleDropEvent
self.setAcceptDrops(True)
def init_app (self, project):
"""Set window size and position, GUI options and reset status."""
data = self.settings.read_geometry()
if data["size"] is not None:
self.resize(data["size"])
if data["pos"] is not None:
self.move(data["pos"])
self.options.set_options(self.settings.read_options())
self.status = Status.idle
self.actionSave.setEnabled(False)
if project:
loadproject(self, project)
else:
msg = self.config_error or _("Ready.")
self.set_statusmsg(msg)
data = self.settings.read_misc()
self.saveresultas = data['saveresultas']
def get_qhcpath (self):
"""Helper function to search for the QHC help file in different
locations."""
devel_dir = os.path.join(configuration.configdata.install_data, "doc", "html")
return configuration.get_share_file('lccollection.qhc', devel_dir=devel_dir)
def connect_widgets (self):
"""Connect widget signals. Some signals use the AutoConnect feature.
Autoconnected methods have the form on_<objectname>_<signal>.
"""
def set_idle ():
"""Set application status to idle."""
self.status = Status.idle
self.set_statusmsg(_("Check finished."))
self.controlButton.clicked.disconnect(self.checker.cancel)
self.checker.finished.connect(set_idle)
self.checker.terminated.connect(set_idle)
self.log_url_signal.connect(self.model.log_url)
self.log_stats_signal.connect(self.log_stats)
self.error_signal.connect(self.internal_error)
self.options.editor.saved.connect(self.read_config)
self.log_status_signal.connect(self.log_status)
self.prop_url.linkHovered.connect(self.hover_link)
self.prop_parenturl.linkHovered.connect(self.hover_link)
def init_shortcuts (self):
"""Configure application shortcuts."""
def selectUrl():
"""Highlight URL input textbox."""
self.urlinput.setFocus()
self.urlinput.selectAll()
shortcut = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+L"), self)
shortcut.activated.connect(selectUrl)
def init_treeview (self):
"""Set treeview model and layout."""
self.model = UrlItemModel()
self.treeView.setModel(self.model)
data = self.settings.read_treeviewcols()
self.treeView.setColumnWidth(0, data["col1"])
self.treeView.setColumnWidth(1, data["col2"])
self.treeView.setColumnWidth(2, data["col3"])
selectionModel = self.treeView.selectionModel()
selectionModel.selectionChanged.connect(self.set_properties)
def get_treeviewcols (self):
"""Return URL treeview column widths."""
return dict(
col1=self.treeView.columnWidth(0),
col2=self.treeView.columnWidth(1),
col3=self.treeView.columnWidth(2),
)
def init_config (self):
"""Create a configuration object."""
self.config = configuration.Configuration()
status = StatusLogger(self.log_status_signal)
self.config.set_status_logger(status)
# dictionary holding overwritten values
self.config_backup = {}
# set standard GUI configuration values
self.config.logger_add(SignalLogger)
self.config["logger"] = self.config.logger_new(SignalLogger.LoggerName,
signal=self.log_url_signal, stats=self.log_stats_signal)
self.config["status"] = True
self.config["status_wait_seconds"] = 2
def read_config (self, filename=None):
"""Read user and system configuration file."""
try:
self.config.read()
except LinkCheckerError as msg:
self.config_error = unicode(msg)
def set_config (self):
"""Set configuration."""
data = self.options.get_options()
self.config["recursionlevel"] = data["recursionlevel"]
self.config["verbose"] = data["verbose"]
if data["debug"]:
logconf.set_debug(["all"])
# make sure at least one thread is used
self.config["threads"] = 1
else:
logconf.reset_loglevel()
if data["warninglines"]:
lines = data["warninglines"].splitlines()
pattern = warninglines2regex(lines)
args = dict(warningregex=pattern)
self.backup_config("enabledplugins", ["RegexCheck"])
self.config["RegexCheck"] = args
# set ignore patterns
ignorepats = data["ignorelines"].strip()
if ignorepats:
self.backup_config("externlinks")
lines = ignorepats.splitlines()
for line in lines:
try:
pat = get_link_pat(line, strict=1)
self.config["externlinks"].append(pat)
except re.error as err:
msg = _("Invalid regular expression %r: %s" % (pat, err))
self.set_statusmsg(msg)
# make sure the configuration is sane
self.config.sanitize()
def backup_config (self, key, value=None):
"""Backup config key if not already done and set given value."""
if key not in self.config_backup:
confvalue = self.config[key]
if isinstance(confvalue, list):
# make copy of lists to avoid unwanted inserted items
confvalue = confvalue[:]
self.config_backup[key] = confvalue
if value is not None:
self.config[key] = value
def restore_config (self):
"""Restore config from backup."""
for key in self.config_backup:
confvalue = self.config_backup[key]
if isinstance(confvalue, list):
# make copy of lists to avoid unwanted inserted items
confvalue = confvalue[:]
self.config[key] = confvalue
def get_status (self):
"""Return current application status."""
return self._status
def set_status (self, status):
"""Set application status."""
self._status = status
if status == Status.idle:
self.aggregate = None
self.controlButton.setText(_("Start"))
self.controlButton.setIcon(self.icon_start)
self.controlButton.setEnabled(True)
self.actionSave.setEnabled(True)
self.actionDebug.setEnabled(self.options.get_options()["debug"])
self.treeView.sortByColumn(0, QtCore.Qt.AscendingOrder)
self.treeView.setSortingEnabled(True)
self.treeView.scrollToTop()
self.movie.stop()
# Reset progress information.
self.label_active.setText(u"0")
self.label_queued.setText(u"0")
self.label_checked.setText(u"0")
self.label_busy.hide()
self.menubar.setEnabled(True)
self.urlinput.setEnabled(True)
self.restore_config()
elif status == Status.checking:
self.treeView.setSortingEnabled(False)
self.debug.reset()
self.set_statusmsg(_(u"Checking site..."))
# disable commands
self.menubar.setEnabled(False)
self.urlinput.setEnabled(False)
# reset widgets
self.controlButton.setText(_("Stop"))
self.controlButton.setIcon(self.icon_stop)
self.controlButton.clicked.connect(self.checker.cancel)
self.movie.start()
self.label_busy.show()
status = property(get_status, set_status)
@QtCore.pyqtSlot()
def on_actionHelp_triggered (self):
"""Show help page."""
url = QtCore.QUrl("%sindex.html" % DocBaseUrl)
self.assistant.showDocumentation(url)
@QtCore.pyqtSlot()
def on_actionOptions_triggered (self):
"""Show option dialog."""
self.options.exec_()
@QtCore.pyqtSlot()
def on_actionQuit_triggered (self):
"""Quit application."""
self.close()
def closeEvent (self, e=None):
"""Save settings and remove registered logging handler"""
self.settings.save_geometry(dict(size=self.size(), pos=self.pos()))
self.settings.save_treeviewcols(self.get_treeviewcols())
self.settings.save_options(self.options.get_options())
self.settings.save_recent_documents(self.recent.get_documents())
self.settings.save_misc(dict(saveresultas=self.saveresultas))
self.settings.sync()
logconf.remove_loghandler(self.handler)
if e is not None:
e.accept()
@QtCore.pyqtSlot()
def on_actionAbout_triggered (self):
"""Display about dialog."""
modules = u"<br>\n".join(configuration.get_modules_info())
d = {
"app": configuration.App,
"appname": configuration.AppName,
"copyright": configuration.HtmlCopyright,
"donateurl": configuration.DonateUrl,
"pyver": u"%d.%d.%d" % sys.version_info[:3],
"modules": modules,
"portable": _("yes") if configuration.Portable else _("no"),
"releasedate": configuration.ReleaseDate,
}
QtGui.QMessageBox.about(self, _(u"About %(appname)s") % d,
_(u"""<qt><center>
<h1>%(app)s</h1>
<p>Released on %(releasedate)s
<p>Python: %(pyver)s<br>
%(modules)s<br>
Portable version: %(portable)s
<p>%(copyright)s
<br>%(appname)s is licensed under the
<a href="http://www.gnu.org/licenses/gpl.html">GPL</a>
Version 2 or later.
<p>If you like %(appname)s, consider one of several ways to
<a href="%(donateurl)s">donate</a>. Thanks!
</center></qt>""") % d)
@QtCore.pyqtSlot()
def on_actionDebug_triggered (self):
"""Display debug dialog."""
self.debug.show()
@QtCore.pyqtSlot()
def on_actionOpen_project_triggered (self):
"""Open project."""
openproject(self)
@QtCore.pyqtSlot()
def on_actionSave_project_triggered (self):
"""Save project."""
saveproject(self, self.get_url())
@QtCore.pyqtSlot()
def on_actionSave_triggered (self):
"""Save URL results."""
saveresultas = urlsave(self, self.config, self.model.urls)
if saveresultas:
self.saveresultas = saveresultas
@QtCore.pyqtSlot()
def on_actionCheckUpdates_triggered (self):
"""Display update check result."""
dialog = UpdateDialog(self)
dialog.reset()
dialog.show()
def start (self):
"""Start a new check."""
if self.status == Status.idle:
self.check()
on_urlinput_returnPressed = start
def cancel (self):
"""Note that checking is canceled."""
self.controlButton.setEnabled(False)
duration = strformat.strduration_long(self.config["aborttimeout"])
self.set_statusmsg(_(u"Closing active URLs with timeout %s...") % duration)
@QtCore.pyqtSlot()
def on_controlButton_clicked (self):
"""Start or Cancel has been clicked."""
if self.status == Status.idle:
self.start()
elif self.status == Status.checking:
self.cancel()
else:
raise ValueError("Invalid application status %r" % self.status)
def get_url (self):
"""Return URL to check from the urlinput widget."""
url = strformat.stripurl(unicode(self.urlinput.text()))
url = checker.guess_url(url)
if url and u":" not in url:
# Look for local file, else assume it's an HTTP URL.
if not os.path.exists(url):
url = u"http://%s" % url
return url
def check (self):
"""Check given URL."""
self.model.clear()
clear_properties(self)
clear_statistics(self)
self.set_config()
aggregate = director.get_aggregate(self.config)
url = self.get_url()
if not url:
self.set_statusmsg(_("Error, empty URL"))
return
self.set_statusmsg(_("Checking '%s'.") % strformat.limit(url, 40))
url_data = checker.get_url_from(url, 0, aggregate, extern=(0, 0))
self.recent.add_document(url)
aggregate.urlqueue.put(url_data)
self.aggregate = aggregate
# check in background
self.checker.check(self.aggregate)
self.status = Status.checking
def set_properties (self, selected, deselected):
"""Set URL properties for selected item."""
indexes = selected.indexes()
if len(indexes):
index = indexes[0]
urlitem = self.model.getUrlItem(index)
if urlitem is not None:
set_properties(self, urlitem.url_data)
selected_rows = len(self.treeView.selectionModel().selectedRows())
if selected_rows:
self.set_statusmsg(_n("%d URL selected.", "%d URLs selected",
selected_rows) % selected_rows)
else:
self.set_statusmsg(_("Ready."))
def on_treeView_customContextMenuRequested (self, point):
"""Show item context menu."""
urlitem = self.model.getUrlItem(self.treeView.currentIndex())
if urlitem is not None:
self.contextmenu.enableFromItem(urlitem)
self.contextmenu.popup(QtGui.QCursor.pos())
@QtCore.pyqtSlot()
def on_actionViewOnline_triggered (self):
"""View item URL online."""
urlitem = self.model.getUrlItem(self.treeView.currentIndex())
if urlitem is not None:
webbrowser.open(urlitem.url_data.url)
@QtCore.pyqtSlot()
def on_actionViewParentOnline_triggered (self):
"""View item parent URL online."""
urlitem = self.model.getUrlItem(self.treeView.currentIndex())
if urlitem is not None:
webbrowser.open(urlitem.url_data.parent_url)
@QtCore.pyqtSlot()
def on_actionViewParentSource_triggered (self):
"""View item parent URL source in local text editor (read-only)."""
urlitem = self.model.getUrlItem(self.treeView.currentIndex())
if urlitem is not None:
self.view_source(urlitem.url_data.parent_url,
urlitem.url_data.line, urlitem.url_data.column)
def view_source (self, url, line, col):
"""View URL source in editor window."""
self.editor.setWindowTitle(u"View %s" % url)
self.editor.setUrl(url)
data, info = urlutil.get_content(url, proxy=self.config["proxy"])
if data is None:
msg = u"An error occurred retreiving URL `%s': %s." % (url, info)
self.editor.setText(msg)
else:
content_type = httputil.get_content_type(info)
if not content_type:
# read function for content type guessing
read = lambda: data
content_type = mimeutil.guess_mimetype(url, read=read)
self.editor.setContentType(content_type)
self.editor.setText(data, line=line, col=col)
self.editor.show()
@QtCore.pyqtSlot()
def on_actionCopyToClipboard_triggered (self):
"""Copy item URL to clipboard."""
urlitem = self.model.getUrlItem(self.treeView.currentIndex())
if urlitem:
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(urlitem.url_data.url)
event = QtCore.QEvent(QtCore.QEvent.Clipboard)
QtGui.QApplication.sendEvent(clipboard, event)
def set_statusmsg (self, msg):
"""Show given status message."""
self.statusBar.showMessage(msg)
if len(msg) > MaxMessageLength:
self.label_status.setToolTip(msg)
msg = msg[:MaxMessageLength-3]+u"..."
else:
self.label_status.setToolTip(u"")
self.label_status.setText(msg)
def hover_link (self, link):
"""Show given link in status bar."""
self.statusBar.showMessage(link)
def log_status (self, checked, in_progress, queued, duration, num_urls):
"""Update number of checked, active and queued links."""
self.label_checked.setText(u"%d" % checked)
self.label_active.setText(u"%d" % in_progress)
self.label_queued.setText(u"%d" % queued)
def log_stats (self, statistics):
"""Set statistic information for selected URL."""
set_statistics(self, statistics)
def internal_error (self, msg):
"""Display internal error message. Triggered by sys.excepthook()."""
QtGui.QMessageBox.warning(self, _(u"LinkChecker internal error"), msg)
def handleDragEvent(self, event):
"""Handle drag enter of move event."""
mime = event.mimeData()
if not mime.hasUrls():
return event.ignore()
url = mime.urls()[0]
if url.scheme() != 'file':
return event.ignore()
event.accept()
def handleDropEvent(self, event):
"""Handle drop event. Detects and loads project files, else sets the URL."""
mime = event.mimeData()
url = mime.urls()[0]
if url.path().toLower().endsWith(ProjectExt):
filename = unicode(url.toLocalFile())
loadproject(self, filename)
else:
self.urlinput.setText(url.toString())
def retranslateUi(self, Window):
"""Translate menu titles."""
super(LinkCheckerMain, self).retranslateUi(Window)
# self.menu_lang is created after calling retranslateUi
# the first time, so check for its excistance
if hasattr(self, "menu_lang"):
self.menuLang.setTitle(_("&Language"))
def switch_language(self, action):
"""Change UI language."""
lang = str(action.data().toString())
i18n.install_language(lang)
self.retranslateUi(self)
self.options.retranslateUi(self.options)
self.debug.retranslateUi(self.debug)
self.editor.retranslateUi(self.editor)

View file

@ -1,45 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2008-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtCore
from .. import director
class CheckerThread (QtCore.QThread):
"""Separate checker thread."""
def __init__ (self, parent=None):
"""Reset check variables."""
super(CheckerThread, self).__init__(parent)
self.aggregate = None
def check (self, aggregate):
"""Set check variables and start the thread."""
self.aggregate = aggregate
# setup the thread and call run()
self.start()
def cancel (self):
"""Reset check variables and set stop flag."""
if self.aggregate is not None:
aggregate = self.aggregate
self.aggregate = None
aggregate.cancel()
def run (self):
"""Start checking."""
assert self.aggregate.config["threads"] > 0
director.check_urls(self.aggregate)

View file

@ -1,65 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2009-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtGui
import os
try:
import urlparse
except ImportError:
# Python 3
from urllib import parse as urlparse
from linkcheck.checker.fileurl import get_os_filename
class ContextMenu (QtGui.QMenu):
"""Show context menu."""
def __init__ (self, parent=None):
"""Add actions to context menu."""
super(ContextMenu, self).__init__(parent)
self.addAction(parent.actionViewOnline)
self.addAction(parent.actionCopyToClipboard)
self.addAction(parent.actionViewParentOnline)
self.addAction(parent.actionViewParentSource)
def enableFromItem (self, item):
"""Enable context menu actions depending on the item content."""
parent = self.parentWidget()
# data is an instance of CompactUrlData
data = item.url_data
# enable view online actions
parent.actionViewOnline.setEnabled(bool(data.url))
parent.actionViewParentOnline.setEnabled(bool(data.parent_url))
# enable view source actions
enable_parent_url_source = self.can_view_parent_source(data)
parent.actionViewParentSource.setEnabled(enable_parent_url_source)
def can_view_parent_source (self, url_data):
"""Determine if parent URL source can be retrieved."""
if not url_data.valid:
return False
parent = url_data.parent_url
if not parent:
return False
# Directory contents are dynamically generated, so it makes
# no sense in viewing/editing them.
if parent.startswith(u"file:"):
path = urlparse.urlsplit(parent)[2]
return not os.path.isdir(get_os_filename(path))
if parent.startswith((u"ftp:", u"ftps:")):
path = urlparse.urlsplit(parent)[2]
return bool(path) and not path.endswith(u'/')
# Only HTTP left
return parent.startswith((u"http:", u"https:"))

View file

@ -1,43 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2009-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtCore, QtGui
from .linkchecker_ui_debug import Ui_DebugDialog
class LinkCheckerDebug (QtGui.QDialog, Ui_DebugDialog):
"""Show debug text."""
log_msg_signal = QtCore.pyqtSignal(str)
def __init__ (self, parent=None):
"""Setup the debug message dialog."""
super(LinkCheckerDebug, self).__init__(parent)
self.setupUi(self)
font = QtGui.QFont("Consolas", 11)
font.setFixedPitch(True)
self.textEdit.document().setDefaultFont(font)
self.log_msg_signal.connect(self.textEdit.appendPlainText)
self.reset()
def reset (self):
"""Clear all debug info."""
self.textEdit.clear()
def getText (self):
"""Get debug info as string."""
return self.textEdit.toPlainText()

View file

@ -1,185 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2010-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
try:
import urlparse
except ImportError:
# Python 3
from urllib import parse as urlparse
from PyQt4 import QtGui, QtCore
from .linkchecker_ui_editor import Ui_EditorDialog
from ..checker.fileurl import get_os_filename
try:
from .editor_qsci import ContentTypeLexers, Editor
except ImportError:
from .editor_qt import ContentTypeLexers, Editor
class EditorWindow (QtGui.QDialog, Ui_EditorDialog):
"""Editor window."""
# emitted after successful save
saved = QtCore.pyqtSignal(str)
# emitted after successful load
loaded = QtCore.pyqtSignal(str)
def __init__ (self, parent=None):
"""Initialize the editor widget."""
super(EditorWindow, self).__init__(parent)
self.setupUi(self)
# filename used for saving
self.filename = None
# the Scintilla editor widget
self.editor = Editor(parent=self.frame)
layout = QtGui.QVBoxLayout(self.frame)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.editor)
# for debugging
#self.setText(("1234567890"*8) + "\n<html><head>\n<title>x</title>\n</head>\n")
#lexer = Qsci.QsciLexerHTML()
#lexer.setFont(self.editor.font())
#self.editor.setLexer(lexer)
#self.editor.setCursorPosition(1, 1)
#self.show()
def setContentType (self, content_type):
"""Choose a lexer according to given content type."""
lexerclass = ContentTypeLexers.get(content_type.lower())
self.editor.highlight(lexerclass)
def setText (self, text, line=1, col=1):
"""Set editor text and jump to given line and column."""
self.editor.setText(text)
self.editor.setCursorPosition(line-1, col-1)
self.editor.setModified(False)
def setUrl (self, url):
"""If URL is a file:// URL, store the filename of it as base
directory for the "save as" dialog."""
self.basedir = ""
if url and url.startswith("file://"):
urlparts = urlparse.urlsplit(url)
path = get_os_filename(urlparts[2])
if os.path.exists(path):
self.basedir = path
@QtCore.pyqtSlot()
def on_actionSave_triggered (self):
"""Save changed editor contents."""
if self.editor.isModified() or not self.filename:
self.save()
def closeEvent (self, e=None):
"""Save settings and remove registered logging handler"""
if self.editor.isModified():
# ask if user wants to save
if self.wants_save():
if self.save():
e.accept()
else:
# saving error or user canceled
e.ignore()
else:
# discard changes
e.accept()
else:
# unchanged
e.accept()
def wants_save (self):
"""Ask user if he wants to save changes. Return True if user
wants to save, else False."""
dialog = QtGui.QMessageBox(parent=self)
dialog.setIcon(QtGui.QMessageBox.Question)
dialog.setWindowTitle(_("Save file?"))
dialog.setText(_("The document has been modified."))
dialog.setInformativeText(_("Do you want to save your changes?"))
dialog.setStandardButtons(QtGui.QMessageBox.Save |
QtGui.QMessageBox.Discard)
dialog.setDefaultButton(QtGui.QMessageBox.Save)
return dialog.exec_() == QtGui.QMessageBox.Save
def save (self):
"""Save editor contents to file."""
if not self.filename:
title = _("Save File As")
res = QtGui.QFileDialog.getSaveFileName(self, title, self.basedir)
if not res:
# user canceled
return
self.filename = res
self.setWindowTitle(self.filename)
else:
if not os.path.isfile(self.filename):
return
if not os.access(self.filename, os.W_OK):
return
fh = None
saved = False
try:
try:
fh = QtCore.QFile(self.filename)
if not fh.open(QtCore.QIODevice.WriteOnly):
raise IOError(fh.errorString())
stream = QtCore.QTextStream(fh)
stream.setCodec("UTF-8")
stream << self.editor.text()
self.editor.setModified(False)
saved = True
except (IOError, OSError) as e:
err = QtGui.QMessageBox(self)
err.setText(str(e))
err.exec_()
finally:
if fh is not None:
fh.close()
if saved:
self.saved.emit(self.filename)
return saved
def load (self, filename):
"""Load editor contents from file."""
if not os.path.isfile(filename):
return
if not os.access(filename, os.R_OK):
return
self.filename = filename
if not os.access(filename, os.W_OK):
title = u"%s (%s)" % (self.filename, _(u"readonly"))
else:
title = self.filename
self.setWindowTitle(title)
fh = None
loaded = False
try:
try:
fh = QtCore.QFile(self.filename)
if not fh.open(QtCore.QIODevice.ReadOnly):
raise IOError(fh.errorString())
stream = QtCore.QTextStream(fh)
stream.setCodec("UTF-8")
self.setText(stream.readAll())
loaded = True
except (IOError, OSError) as e:
err = QtGui.QMessageBox(self)
err.setText(str(e))
err.exec_()
finally:
if fh is not None:
fh.close()
if loaded:
self.loaded.emit(self.filename)

View file

@ -1,109 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2011-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Text editor implemented with QScintilla
"""
from PyQt4 import QtGui, Qsci
# Map MIME type to Scintilla lexer class
ContentTypeLexers = {
"application/x-shellscript": Qsci.QsciLexerBash,
"application/x-sh": Qsci.QsciLexerBash,
"application/x-msdos-program": Qsci.QsciLexerBatch,
#"": Qsci.QsciLexerCMake,
"text/x-c++src": Qsci.QsciLexerCPP,
"text/css": Qsci.QsciLexerCSS,
#"": Qsci.QsciLexerCSharp,
#"": Qsci.QsciLexerCustom,
"text/x-dsrc": Qsci.QsciLexerD,
"text/x-diff": Qsci.QsciLexerDiff,
#"": Qsci.QsciLexerFortran,
#"": Qsci.QsciLexerFortran77,
"text/html": Qsci.QsciLexerHTML,
#"": Qsci.QsciLexerIDL,
"text/x-java": Qsci.QsciLexerJava,
"application/javascript": Qsci.QsciLexerJavaScript,
#"": Qsci.QsciLexerLua,
"text/x-makefile": Qsci.QsciLexerMakefile,
#"": Qsci.QsciLexerPOV,
"text/x-pascal": Qsci.QsciLexerPascal,
"text/x-perl": Qsci.QsciLexerPerl,
"application/postscript": Qsci.QsciLexerPostScript,
"text/plain+ini": Qsci.QsciLexerProperties,
"text/x-python": Qsci.QsciLexerPython,
"application/x-ruby": Qsci.QsciLexerRuby,
#"": Qsci.QsciLexerSQL,
#"": Qsci.QsciLexerSpice,
"application/x-tcl": Qsci.QsciLexerTCL,
"application/x-latex": Qsci.QsciLexerTeX,
#"": Qsci.QsciLexerVHDL,
#"": Qsci.QsciLexerVerilog,
"application/xml": Qsci.QsciLexerXML,
#"": Qsci.QsciLexerYAML,
}
class Editor (Qsci.QsciScintilla):
"""Configured QsciScintilla widget."""
def __init__ (self, parent=None):
"""Set Scintilla options for font, colors, etc."""
super(Editor, self).__init__(parent)
# Use Courier font with fixed width
font = QtGui.QFont("Consolas", 11)
font.setFixedPitch(True)
# Set the default font of the editor
# and take the same font for line numbers
self.setFont(font)
self.setMarginsFont(font)
# line number margin for 4 digits (plus 2px extra space)
margin = QtGui.QFontMetrics(font).width("0"*4)+2
# Display line numbers, margin 0 is for line numbers
self.setMarginWidth(0, margin)
self.setMarginLineNumbers(0, True)
# Show whitespace to help detect whitespace errors
self.setWhitespaceVisibility(True)
# Use boxes as folding visual
self.setFolding(self.BoxedTreeFoldStyle)
# Braces matching
self.setBraceMatching(self.SloppyBraceMatch)
# Editing line color
self.setCaretLineVisible(True)
self.setCaretLineBackgroundColor(QtGui.QColor("#e5e5cb"))
# line numbers margin colors
self.setMarginsBackgroundColor(QtGui.QColor("#e5e5e5"))
self.setMarginsForegroundColor(QtGui.QColor("#333333"))
# folding margin colors (foreground,background)
self.setFoldMarginColors(QtGui.QColor("#f5f5dc"),
QtGui.QColor("#aaaaaa"))
def highlight (self, lexerclass):
"""Set syntax highlighter."""
if lexerclass:
lexer = lexerclass()
lexer.setFont(self.font())
self.setLexer(lexer)
else:
# use no styling
self.setLexer()

View file

@ -1,152 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2011-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Text editor implemented with Qt
"""
from PyQt4 import QtGui, QtCore
from . import syntax
# Map MIME type to QSyntaxHighlighter class
ContentTypeLexers = {
"text/html": syntax.HtmlHighlighter,
"application/xml": syntax.XmlHighlighter,
"text/plain+ini": syntax.IniHighlighter,
}
class LineNumberArea (QtGui.QWidget):
"""Display line numbers."""
def sizeHint (self):
"""Return calculated width for line number area."""
return QtCore.QSize(self.parentWidget().lineNumberAreaWidth(), 0)
def paintEvent (self, event):
"""Call paint method of parent widget."""
self.parentWidget().lineNumberAreaPaintEvent(event)
class Editor (QtGui.QPlainTextEdit):
"""Qt editor with line numbering."""
def __init__ (self, parent):
"""Initialize line numbering."""
super(Editor, self).__init__(parent)
font = QtGui.QFont("Consolas", 11)
font.setFixedPitch(True)
self.document().setDefaultFont(font)
self.lineNumberArea = LineNumberArea(self)
self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
self.updateRequest.connect(self.updateLineNumberArea)
self.cursorPositionChanged.connect(self.highlightCurrentLine)
self.updateLineNumberAreaWidth(0)
self.highlightCurrentLine()
def highlight (self, lexerclass):
"""Set syntax highlighter."""
if lexerclass:
self.lexer = lexerclass(self.document())
else:
self.lexer = None
def setText (self, text):
"""Set editor text."""
return self.setPlainText(text)
def text (self):
"""Return editor text."""
return self.toPlainText()
def setModified (self, flag):
"""Set modified flag of underlying document."""
return self.document().setModified(flag)
def isModified (self):
"""Return modified flag of underlying document."""
return self.document().isModified()
def setCursorPosition (self, line, column=0):
"""Move cursor to given line and column. Line counting starts
with zero."""
block = self.document().findBlockByNumber(line)
if block.isValid():
cursor = QtGui.QTextCursor(block)
if column > 0:
cursor.movePosition(QtGui.QTextCursor.Right,
QtGui.QTextCursor.MoveAnchor, column)
self.setTextCursor(cursor)
self.centerCursor()
def lineNumberAreaPaintEvent (self, event):
"""Paint line numbers."""
painter = QtGui.QPainter(self.lineNumberArea)
painter.fillRect(event.rect(), QtCore.Qt.lightGray)
block = self.firstVisibleBlock()
blockNumber = block.blockNumber()
top = self.blockBoundingGeometry(block).translated(self.contentOffset()).top()
bottom = top + self.blockBoundingRect(block).height()
while block.isValid() and top <= event.rect().bottom():
if block.isVisible() and bottom >= event.rect().top():
number = str(blockNumber + 1)
painter.setPen(QtCore.Qt.black)
painter.drawText(0, top, self.lineNumberArea.width(),
self.fontMetrics().height(),
QtCore.Qt.AlignRight, number)
block = block.next()
top = bottom
bottom = top + self.blockBoundingRect(block).height()
blockNumber += 1
def lineNumberAreaWidth (self):
"""Calculate line number area width."""
digits = max(1, len(str(self.blockCount())))
onecharwidth = self.fontMetrics().width('9')
space = 3 + onecharwidth * digits
return space
def resizeEvent (self, event):
"""Resize line number area together with editor."""
super(Editor, self).resizeEvent(event)
cr = self.contentsRect()
self.lineNumberArea.setGeometry(QtCore.QRect(cr.left(), cr.top(),
self.lineNumberAreaWidth(), cr.height()))
def updateLineNumberAreaWidth (self, newBlockCount):
"""Update the line number area width."""
self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)
def highlightCurrentLine (self):
"""Highlight the current line."""
extraSelections = []
if not self.isReadOnly():
selection = QtGui.QTextEdit.ExtraSelection()
lineColor = QtGui.QColor(QtCore.Qt.yellow).lighter(160)
selection.format.setBackground(lineColor)
selection.format.setProperty(QtGui.QTextFormat.FullWidthSelection, True)
selection.cursor = self.textCursor()
selection.cursor.clearSelection()
extraSelections.append(selection)
self.setExtraSelections(extraSelections)
def updateLineNumberArea (self, rect, dy):
"""Update the line number area."""
if dy:
self.lineNumberArea.scroll(0, dy)
else:
self.lineNumberArea.update(0, rect.y(),
self.lineNumberArea.width(), rect.height())
if rect.contains(self.viewport().rect()):
self.updateLineNumberAreaWidth(0)

View file

@ -1,77 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2009-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from .. import configuration
from PyQt4 import QtCore, QtGui, QtHelp
class HelpWindow (QtGui.QDialog):
"""A custom help display dialog."""
def __init__ (self, parent, qhcpath):
"""Initialize dialog and load qhc help project from given path."""
super(HelpWindow, self).__init__(parent)
self.engine = QtHelp.QHelpEngine(qhcpath, self)
self.engine.setupData()
self.setWindowTitle(u"%s Help" % configuration.AppName)
self.build_ui()
def build_ui (self):
"""Build UI for the help window."""
splitter = QtGui.QSplitter()
splitter.setOrientation(QtCore.Qt.Vertical)
self.browser = HelpBrowser(splitter, self.engine)
self.tree = self.engine.contentWidget()
self.tree.setExpandsOnDoubleClick(False)
self.tree.linkActivated.connect(self.browser.setSource)
splitter.addWidget(self.tree)
splitter.addWidget(self.browser)
splitter.setSizes((70, 530))
hlayout = QtGui.QHBoxLayout()
hlayout.addWidget(splitter)
self.setLayout(hlayout)
self.resize(800, 600)
def showDocumentation (self, url):
"""Show given URL in help browser."""
self.tree.expandAll()
self.browser.setSource(url)
self.show()
class HelpBrowser (QtGui.QTextBrowser):
"""A QTextBrowser that can handle qthelp:// URLs."""
def __init__ (self, parent, engine):
"""Initialize and store given HelpEngine instance."""
super(HelpBrowser, self).__init__(parent)
self.engine = engine
def setSource (self, url):
"""Open HTTP URLs in external browser, else call base class
implementation."""
if url.scheme() == "http":
import webbrowser
webbrowser.open(str(url.toString()))
else:
QtGui.QTextBrowser.setSource(self, url)
def loadResource (self, rtype, url):
"""Handle qthelp:// URLs, load content from help engine."""
if url.scheme() == "qthelp":
return QtCore.QVariant(self.engine.fileData(url))
return QtGui.QTextBrowser.loadResource(self, rtype, url)

View file

@ -1,226 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2010-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtCore, QtGui
class LineEdit (QtGui.QLineEdit):
"""A line edit widget displaying a clear button if there is some text
and a down-arrow button displaying a list of strings (eg. recent
documents)."""
def __init__ (self, parent=None):
"""Initialize buttons and size settings."""
super(LineEdit, self).__init__(parent)
self.listmodel = None
self.listview = None
self.setup_clear_button()
self.setup_list_button()
self.setup_size_metrics()
def setup_clear_button (self):
"""Initialize the clear button."""
self.clearButton = QtGui.QToolButton(self)
pixmap = QtGui.QPixmap(":/icons/clear.png")
self.clearButton.setIcon(QtGui.QIcon(pixmap))
self.clearButton.setIconSize(pixmap.size())
self.clearButton.setCursor(QtCore.Qt.ArrowCursor)
style = "QToolButton { border: none; padding: 0px; }"
self.clearButton.setStyleSheet(style)
self.clearButton.hide()
self.clearButton.clicked.connect(self.clear)
self.textChanged.connect(self.updateCloseButton)
def setup_list_button (self):
"""Initialize the dropdown list button."""
self.listButton = QtGui.QToolButton(self)
pixmap = QtGui.QPixmap(":/icons/arrow_down.png")
self.listButton.setIcon(QtGui.QIcon(pixmap))
self.listButton.setIconSize(pixmap.size())
self.listButton.setCursor(QtCore.Qt.ArrowCursor)
style = "QToolButton { border: none; padding: 0px; }"
self.listButton.setStyleSheet(style)
self.listButton.hide()
self.listButton.clicked.connect(self.toggle_list)
def setModel (self, model):
"""Set list model for list of recent documents."""
self.listmodel = model
self.listview = QtGui.QListView()
self.listview.setModel(model)
self.listview.setWindowFlags(QtCore.Qt.Popup)
self.listview.setFocusPolicy(QtCore.Qt.NoFocus)
self.listview.setFocusProxy(self)
self.listview.setMouseTracking(True)
self.listview.setUniformItemSizes(True)
self.listview.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.listview.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.listview.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
self.listview.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listview.installEventFilter(self)
self.listview.clicked.connect(self.selectRecentDocument)
self.listview.hide()
updatefunc = lambda parent, start, end: self.updateListButton
self.listmodel.rowsInserted.connect(updatefunc)
self.listmodel.rowsRemoved.connect(updatefunc)
self.updateListButton()
def eventFilter(self, obj, event):
"""Handle events from the listview popup."""
if obj != self.listview:
return False
if event.type() == QtCore.QEvent.MouseButtonPress:
self.listview.hide()
self.setFocus()
return True
if event.type() == QtCore.QEvent.KeyPress:
consumed = False
key = event.key()
if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
self.doneCompletion()
consumed = True
elif key == QtCore.Qt.Key_Escape:
self.setFocus()
self.listview.hide()
consumed = True
elif key in (QtCore.Qt.Key_Up, QtCore.Qt.Key_Down,
QtCore.Qt.Key_Home, QtCore.Qt.Key_End,
QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown):
pass
else:
self.setFocus()
self.event(event)
self.listview.hide()
return consumed
return False
def selectRecentDocument (self, index):
"""Select recent document text after click on the list view."""
self.listview.hide()
item = self.listmodel.data(index)
text = unicode(item.toString())
self.setText(text)
def setup_size_metrics (self):
"""Set widget size including the buttons."""
frameWidth = self.style().pixelMetric(QtGui.QStyle.PM_DefaultFrameWidth)
padding_right = self.clearButton.sizeHint().width() + frameWidth + 1
padding_left = self.listButton.sizeHint().width() + frameWidth + 1
style = "QLineEdit { padding-left: %dpx; padding-right: %dpx } " % (
padding_left, padding_right)
self.setStyleSheet(style)
# minimum width
minSize = self.minimumSizeHint()
buttonWidth = padding_left + padding_right
minWidth = max(minSize.width(), buttonWidth)
# minimum height
buttonHeight = max(self.clearButton.sizeHint().height(),
self.listButton.sizeHint().height())
minHeight = max(minSize.height(), buttonHeight + frameWidth*2)
# set minimum size
self.setMinimumSize(minWidth, minHeight)
def resizeEvent (self, event):
"""Move the buttons due to resize event."""
frameWidth = self.style().pixelMetric(QtGui.QStyle.PM_DefaultFrameWidth)
bottom = self.rect().y() + self.rect().height()
# clear button
sizeHint = self.clearButton.sizeHint()
x = self.rect().right() - frameWidth - sizeHint.width()
y = (bottom - sizeHint.height()) / 2
self.clearButton.move(x,y)
# list button
sizeHint = self.listButton.sizeHint()
# add one to x and y since the button icon is a little off
x = self.rect().left() + frameWidth + 1
y = (bottom - sizeHint.height()) / 2 + 1
self.listButton.move(x,y)
def updateListButton (self):
"""Show or hide button for list of documents."""
self.listButton.setVisible(bool(self.listmodel.rowCount()))
def updateCloseButton (self, text):
"""Only display the clear button if there is some text."""
self.clearButton.setVisible(bool(text))
def toggle_list (self):
"""Show or hide list of documents."""
if self.listview.isHidden():
self.listview.adjustSize()
point = self.mapToGlobal(QtCore.QPoint(0, self.height()))
self.listview.move(point)
self.listview.setFocus()
self.listview.show()
else:
self.listview.hide()
def addMenuEntries (self, menu):
"""Add browser bookmark actions to menu."""
name = _("Insert %(browser)s bookmark file")
if find_firefox():
action = menu.addAction(name % {"browser": u"Firefox"})
action.triggered.connect(lambda: self.setText(find_firefox()))
if find_chrome():
action = menu.addAction(name % {"browser": u"Google Chrome"})
action.triggered.connect(lambda: self.setText(find_chrome()))
if find_chromium():
action = menu.addAction(name % {"browser": u"Chromium"})
action.triggered.connect(lambda: self.setText(find_chromium()))
if find_opera():
action = menu.addAction(name % {"browser": u"Opera"})
action.triggered.connect(lambda: self.setText(find_opera()))
if find_safari():
action = menu.addAction(name % {"browser": u"Safari"})
action.triggered.connect(lambda: self.setText(find_safari()))
def contextMenuEvent (self, event):
"""Handle context menu event."""
menu = self.createStandardContextMenu()
self.addMenuEntries(menu)
menu.exec_(event.globalPos())
def find_firefox ():
"""Return Firefox bookmark filename or empty string if not found."""
from ..bookmarks.firefox import find_bookmark_file
return find_bookmark_file()
def find_chrome ():
"""Return Google Chrome bookmark filename or empty string if not found."""
from ..bookmarks.chrome import find_bookmark_file
return find_bookmark_file()
def find_chromium ():
"""Return Chromium bookmark filename or empty string if not found."""
from ..bookmarks.chromium import find_bookmark_file
return find_bookmark_file()
def find_opera ():
"""Return Opera bookmark filename or empty string if not found."""
from ..bookmarks.opera import find_bookmark_file
return find_bookmark_file()
def find_safari ():
"""Return Safari bookmark filename or empty string if not found."""
from ..bookmarks.safari import find_bookmark_file
return find_bookmark_file()

View file

@ -1,882 +0,0 @@
# -*- coding: utf-8 -*-
# Resource object code
#
# Created: Wed May 11 00:26:36 2011
# by: The Resource Compiler for PyQt (Qt v4.7.2)
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore
qt_resource_data = "\
\x00\x00\x01\xbc\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x0c\x00\x00\x00\x0c\x08\x06\x00\x00\x00\x56\x75\x5c\xe7\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\
\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\x61\x00\x00\x0d\x3a\x01\
\x65\x6b\xe6\xb1\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdb\x05\x0a\
\x16\x19\x20\xab\xb5\x7f\x4a\x00\x00\x00\x19\x74\x45\x58\x74\x43\
\x6f\x6d\x6d\x65\x6e\x74\x00\x43\x72\x65\x61\x74\x65\x64\x20\x77\
\x69\x74\x68\x20\x47\x49\x4d\x50\x57\x81\x0e\x17\x00\x00\x01\x17\
\x49\x44\x41\x54\x28\xcf\xad\x91\x3d\x4e\x02\x61\x14\x45\xcf\xc7\
\x4c\xe5\x00\x56\xac\x00\x88\x83\x7b\x90\x15\xe0\x0e\xa4\x22\xa0\
\xb4\x6a\x2b\x09\x84\x0e\x4c\x24\x91\x1e\x1b\xcc\xb0\x01\x0a\x4a\
\x76\x41\x31\xb0\x00\xf9\x99\x38\x34\x30\xe4\x5a\x49\x20\xd2\x90\
\x78\xcb\xf7\xee\x79\xc5\x3b\x66\x36\xf5\x39\x27\x31\xce\xcc\x1e\
\xf0\x3c\x4f\x9e\xe7\x49\x92\x0e\x0b\x92\xf4\xd9\xef\xcb\x1b\x0c\
\x04\x60\x03\x84\x61\xa8\x56\xab\x05\xc0\x66\xbb\xa1\x78\x57\xdc\
\x03\xbd\xde\x07\xdd\xee\x3b\x00\xb7\x85\x82\x62\x00\x89\x44\x82\
\x52\xa9\x04\x40\xe7\xad\xc3\x68\x34\x12\xc0\x70\x38\xd4\x6f\xb9\
\x5c\xa9\xe0\x38\x0e\xcc\xa6\x3e\xb3\xa9\xcf\x72\xb1\xd0\x7d\xa5\
\xac\x6c\x26\xad\xeb\x9c\xab\x66\xb3\xa1\x9c\x7b\xa5\x6c\x26\xad\
\x6a\xf5\x41\xcb\xc5\x42\xb3\xa9\x8f\x39\xfc\x52\x32\x79\xa9\x5a\
\xed\x85\xc9\x64\xb2\x9f\xb9\xae\x4b\xbd\xde\x20\x08\x56\x06\x38\
\x06\x8c\x31\xba\x70\xe2\xbc\xb6\xdb\xcc\xe7\x5f\xa4\x52\x29\x1e\
\x9f\x9e\x59\x87\xdf\x48\xfa\x0b\x00\x58\x96\x25\xcb\xb6\x19\x8f\
\xc7\xe4\x6f\xf2\x44\xd1\x96\xdd\x6e\x67\xf6\x47\x4f\x89\xb3\x6d\
\x5b\x8e\x13\x27\x5c\x87\xec\xa2\xc8\x1c\xed\x4e\xc9\x89\xa2\xc8\
\x04\xc1\xea\x7f\x4c\xff\x00\xb4\xa0\x86\x57\x3b\x81\xd3\x82\x00\
\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x03\x23\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x02\xa0\x49\x44\
\x41\x54\x78\xda\x75\x93\xdf\x4b\x14\x51\x14\xc7\xbf\x77\xe6\xce\
\xce\xfe\xd2\x4d\x13\x95\x7e\x2c\x61\x44\x04\x66\x8a\x3f\x88\x0a\
\x1f\x84\x42\xea\xb1\x87\x20\x24\x88\xac\xe8\x17\x59\x61\x84\x58\
\x19\x2b\xf4\x90\x69\x50\x20\xf6\xe0\x4b\xf4\x50\x7f\x40\x12\xd9\
\x4b\x61\x82\xa1\x0f\x45\x68\x92\x8a\x4b\x3d\xb4\x9b\xb3\xcd\xba\
\xce\xec\xce\xcc\xce\xed\xde\x5d\x56\x54\xf2\x03\x87\x7b\x39\xe7\
\x7c\xbf\x67\x0e\x33\x43\x18\x63\xd8\x00\xe1\xa1\x88\x18\x9d\x5a\
\x28\x97\x24\x42\x5a\x6a\x77\xc5\x01\xd8\x3c\x2c\x1e\x2e\xd6\xb0\
\xd1\x40\xbe\xf6\x74\xa4\x71\x3e\x66\x3c\x2e\xdd\x52\x5c\xbd\xb3\
\xb2\xb8\x28\xe0\x55\x48\x3c\x61\x1a\x5a\xd2\x98\xad\x2a\xf7\x77\
\xf4\xb4\x1d\x1e\x03\xe0\xfc\xcf\x40\x3a\x70\x6e\xb0\x4b\xf6\x15\
\x75\xb7\x1f\xaf\x57\xab\x2a\x43\x50\x15\x19\xa2\x6c\x39\x2e\x62\
\xba\x81\xb7\x93\x8b\x8e\xa6\x27\x06\x46\x22\x27\xbb\x84\xc9\x3a\
\x83\xb2\x13\xbd\xb7\xb6\x56\x6e\xef\xbb\x73\xba\x19\x5a\xca\x86\
\xbe\x62\xc3\xaf\xca\x10\x18\x99\x2c\x8a\x7c\x0a\xb6\x95\xaa\x78\
\xf9\x71\x16\x73\xf3\xd1\xfb\xdf\x87\xcf\x47\x00\xb0\x9c\x01\x69\
\xbc\xbe\x97\x96\x56\x4c\xdd\x6e\x6b\xf5\x9b\x16\xcb\x4d\x0d\xfa\
\x28\xee\x9e\xda\x0f\x41\xe4\xd5\x57\xa4\x4c\x07\x84\x00\x21\xbf\
\x82\x87\xaf\x3f\x98\x34\xa3\xd5\xa7\xde\xdc\x9b\x96\x20\xa0\x4a\
\x6f\x73\xdd\x3e\x7f\x5c\xb7\xf8\x64\x0b\x49\xc3\x82\x91\x76\x20\
\x4b\x44\x84\xb8\xf3\x5c\xbe\xf6\x73\xc9\xc0\x91\xea\x2a\xdf\x4a\
\x1a\x91\x9c\x14\x02\x82\x06\x22\xab\xf8\xcb\xb3\x05\x96\xcd\x0c\
\xae\x0e\x8e\x43\x3c\xa1\xc6\xd7\x59\x8b\x57\x51\x00\x89\xd6\xe7\
\x0c\x48\xcd\xe5\x12\x04\xfd\x61\x22\x11\x2e\xb2\x50\x60\xa4\xe7\
\x18\x0a\xb4\x3e\x18\x05\x61\x58\x7d\x83\xaa\x42\x00\xb0\x30\xa9\
\xb9\x52\x42\x91\xf5\x12\x30\x17\xc9\x94\x0d\xaa\x38\xc8\x21\x7b\
\x70\xa8\xfb\x1d\x3e\xf5\x1e\x85\x20\x95\xa5\x70\xdd\x2c\xf4\xe5\
\x0c\xf4\x64\x12\xb1\x84\x09\x64\x6d\xc0\x26\x12\x65\xdf\xfa\x35\
\x72\xf0\x66\x7c\x62\x66\xb1\x82\x28\x1e\x28\xde\x20\x68\x20\x00\
\x4a\x15\x24\x12\x09\x08\xc6\xa2\x26\xb8\x03\x17\x58\x80\xc5\x4f\
\x47\x88\x33\x71\x36\xfd\x6c\x89\x42\xe0\xb2\x1f\x70\xd2\x15\x8c\
\x8b\x2d\xc9\xc3\x7b\x54\xc0\x91\xb0\x0a\x55\x01\x22\xe5\x83\xb9\
\x40\x5a\x07\xec\xf4\x1c\x38\xf9\x2e\x89\x74\x22\x15\x73\x40\xe4\
\x7c\xb3\xa2\x42\xeb\x6f\x42\x01\xed\x51\x1d\xa0\xfa\x73\x79\x80\
\xf0\x44\x54\xec\xda\xb9\xee\x43\x22\x4d\x1d\x43\xf0\x85\x2e\x60\
\x47\x2d\x10\x2c\x03\xdf\x25\x2f\xa2\xfc\x74\xd2\xf9\x9d\xf5\xdf\
\xc0\xfc\x38\x60\xea\xcf\xd9\xc4\xc0\xc5\xf5\x06\x1c\x34\x76\x0c\
\x43\xa6\x67\x20\xd5\x4a\xd8\x13\x02\xec\xdd\xf9\xa9\x9e\x05\x60\
\xe6\x0f\x24\x67\xd2\x75\x1d\xfb\x05\x3e\x3f\x39\xcb\x38\xab\x06\
\x6b\x21\x0d\x37\x5a\x54\x1f\x1d\x02\x95\xc3\x56\xc6\xf1\x88\xaa\
\x12\xf0\xd8\x94\xe1\x97\x65\x5a\xed\xce\x58\xdf\xfb\x4d\xff\xc6\
\x8d\x48\x35\x97\xc2\xa2\xca\xbe\x0c\x46\xb1\x09\xff\x00\x97\x08\
\x2c\x5e\x2a\x10\x42\x0c\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
\x00\x00\x01\xf3\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x04\x00\x00\x00\xb5\xfa\x37\xea\
\x00\x00\x00\x02\x73\x42\x49\x54\x08\x08\x55\xec\x46\x04\x00\x00\
\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\x01\x3a\
\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\
\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\
\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\x72\x49\x44\x41\x54\
\x28\xcf\x45\x91\x4f\x2b\x04\x71\x1c\xc6\xbf\xf3\x32\xe4\x6c\xde\
\x80\xa2\x44\x39\xbb\xec\x1f\xb3\x23\x6d\x9b\x25\x8b\x10\xfd\x76\
\x36\xec\xa2\x31\x89\x13\x0e\x2e\xca\xfb\x98\x4d\x7b\xf0\x12\xb4\
\x85\x83\x36\x17\x97\xb1\xa2\xe9\x47\xfd\x0e\x63\xb6\x8f\x83\xb5\
\x9e\xe7\xf6\xf4\xf4\x1c\x9e\x8f\x20\xbf\x3e\xb1\x8f\x83\x20\xf4\
\x23\x3f\x0a\xc2\xe3\xe0\xc4\xfe\xcb\x05\x41\x7c\xeb\x50\xd5\x4d\
\x95\x1a\x3e\x3e\x35\xaa\xd4\xcd\xa1\xf2\xad\x7e\xa1\x61\xd5\x9b\
\xdb\xec\xd2\xa2\xcd\x13\x1d\x1e\x68\xb1\xc3\x36\xf5\x66\xc3\x42\
\x04\xf1\xd4\x06\x17\xdc\xf3\x4a\xcc\x27\x5f\x68\xde\x78\xe6\x9c\
\x0d\x3c\x85\x88\xb2\x37\x8d\xc7\x23\x1f\x18\xbe\xe9\xd1\x23\x25\
\x41\xf3\x42\x8d\x4d\xa3\x6c\x59\x0f\x16\xb9\xe5\x1d\xc3\x15\x67\
\x1c\xa0\xd8\x42\x91\xa2\x69\xb3\xc8\xfa\x91\x54\xc2\x15\xee\xd0\
\xa4\x5c\xd2\xa0\x82\x4b\x8e\x59\x20\xa1\xcb\x1a\x95\x50\xca\x91\
\x47\x9b\x98\x94\x3d\x96\xc9\x31\xc5\x38\xd3\x40\x4a\xcc\x3e\xe5\
\x48\x4a\x51\x95\x47\x34\x3d\xb2\x8c\x32\x84\x30\xc4\x28\xd0\x43\
\x73\x40\x29\x92\x62\x58\xee\x2f\xb8\x4c\x30\xc2\x30\x23\x4c\xf4\
\x17\x96\x29\x86\x52\x0c\x1c\x6e\xe8\x92\xb0\xc4\x0c\x93\x8c\x31\
\xc9\x0c\x90\xd0\xc1\xa1\x78\x24\xf3\x76\xc1\xac\xf2\x8c\x26\xe5\
\x5f\x29\x1a\x8f\x82\x99\xb7\x05\x71\x55\x96\x53\x5e\xd0\x24\xa4\
\x83\x1f\xae\xc9\xe2\x2a\x44\x90\x39\xcb\x6d\x66\x58\xa3\x4d\x97\
\x18\x4d\x4c\x87\x2a\x19\xdc\xe6\x9c\xd5\x87\xe5\x5a\x8e\xca\x9b\
\x0c\x25\x76\xd8\x63\x81\x0c\x79\xe3\x28\xd7\x1a\xd0\x44\x90\x82\
\xed\x04\xf9\x30\x17\xe5\xa2\x7c\xe8\x04\x85\x01\xee\x1f\x8d\x42\
\x66\xb3\xf5\x8b\xfe\x99\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
\x00\x00\x05\xb0\
\x47\
\x49\x46\x38\x39\x61\x10\x00\x10\x00\xf6\x00\x00\xff\xff\xff\x00\
\x00\x00\xfa\xfa\xfa\x92\x92\x92\x88\x88\x88\xee\xee\xee\xc8\xc8\
\xc8\xd8\xd8\xd8\x9e\x9e\x9e\x00\x00\x00\x8e\x8e\x8e\xc6\xc6\xc6\
\x32\x32\x32\x52\x52\x52\xec\xec\xec\xa6\xa6\xa6\x94\x94\x94\xf2\
\xf2\xf2\x82\x82\x82\x1c\x1c\x1c\xb2\xb2\xb2\xa4\xa4\xa4\x9a\x9a\
\x9a\xf4\xf4\xf4\xf8\xf8\xf8\xa8\xa8\xa8\xce\xce\xce\x44\x44\x44\
\x0c\x0c\x0c\x60\x60\x60\xde\xde\xde\xe8\xe8\xe8\xbc\xbc\xbc\x2a\
\x2a\x2a\x36\x36\x36\x46\x46\x46\xd4\xd4\xd4\xc4\xc4\xc4\x3c\x3c\
\x3c\x4e\x4e\x4e\x3e\x3e\x3e\x48\x48\x48\xd0\xd0\xd0\xca\xca\xca\
\x5a\x5a\x5a\xb4\xb4\xb4\xea\xea\xea\x70\x70\x70\xac\xac\xac\xb8\
\xb8\xb8\xba\xba\xba\x5e\x5e\x5e\x5c\x5c\x5c\x62\x62\x62\x86\x86\
\x86\xe0\xe0\xe0\x7e\x7e\x7e\xfc\xfc\xfc\xa2\xa2\xa2\x18\x18\x18\
\x2c\x2c\x2c\x56\x56\x56\x04\x04\x04\x50\x50\x50\xcc\xcc\xcc\x38\
\x38\x38\x58\x58\x58\x1a\x1a\x1a\xf0\xf0\xf0\xd6\xd6\xd6\x9c\x9c\
\x9c\xe2\xe2\xe2\xe6\xe6\xe6\x40\x40\x40\xaa\xaa\xaa\x24\x24\x24\
\x20\x20\x20\xae\xae\xae\x72\x72\x72\x4a\x4a\x4a\x34\x34\x34\x6a\
\x6a\x6a\xd2\xd2\xd2\xc0\xc0\xc0\x26\x26\x26\x7c\x7c\x7c\x42\x42\
\x42\x54\x54\x54\x0a\x0a\x0a\x08\x08\x08\xb0\xb0\xb0\xe4\xe4\xe4\
\x4c\x4c\x4c\xf6\xf6\xf6\xb6\xb6\xb6\x66\x66\x66\x68\x68\x68\xdc\
\xdc\xdc\xa0\xa0\xa0\x12\x12\x12\x22\x22\x22\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x21\xff\x0b\x4e\
\x45\x54\x53\x43\x41\x50\x45\x32\x2e\x30\x03\x01\x00\x00\x00\x21\
\xfe\x1a\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x61\
\x6a\x61\x78\x6c\x6f\x61\x64\x2e\x69\x6e\x66\x6f\x00\x21\xf9\x04\
\x09\x08\x00\x00\x00\x2c\x00\x00\x00\x00\x10\x00\x10\x00\x00\x07\
\x68\x80\x00\x82\x83\x20\x22\x26\x25\x83\x89\x00\x0b\x12\x1a\x00\
\x21\x09\x09\x28\x8a\x82\x06\x0c\x09\x1b\x1e\x97\x09\x29\x82\x11\
\x89\x04\x91\x1c\x16\x0b\x23\x27\x2a\x00\x18\x19\x9f\x82\x07\x0d\
\x13\x1d\x1f\x94\x18\x8a\x0e\x14\x05\x94\x8a\x02\x08\x0f\xb9\x94\
\x03\x91\x15\xbe\x00\x24\x88\xa1\x09\x16\xc3\xc5\x00\x05\x0a\x10\
\x17\xc3\xd1\xd2\xa9\xbe\xb4\x89\x11\x19\xd6\x89\xaa\xac\x83\xdd\
\x24\x24\xde\xd1\x25\x88\xd3\xd1\x81\x00\x21\xf9\x04\x09\x08\x00\
\x00\x00\x2c\x00\x00\x00\x00\x10\x00\x10\x00\x00\x07\x6b\x80\x00\
\x82\x83\x07\x34\x35\x37\x83\x89\x8a\x33\x09\x09\x2f\x39\x3a\x3d\
\x19\x39\x83\x2b\x2f\x1a\x17\x2f\x8d\x38\x10\x3b\x09\x3b\x30\x83\
\x2c\x09\x0d\x32\x2e\x12\x36\x05\x21\x8d\x09\x35\x83\x2d\x29\x31\
\x05\x89\x15\x3c\x3e\x3c\x32\x83\x2e\x30\xb3\x8a\x30\x3f\x20\x8a\
\xc2\xc3\x00\x25\x24\xc4\x82\x24\x25\x82\xc6\xc8\x00\xca\xce\xd1\
\xd2\x83\x18\xc4\xd5\x89\x11\x19\xd7\x89\x18\x19\x11\x8a\xdf\xc9\
\xc7\x82\xe1\xc4\x25\xcb\xd3\xc8\x81\x00\x21\xf9\x04\x09\x08\x00\
\x00\x00\x2c\x00\x00\x00\x00\x10\x00\x10\x00\x00\x07\x68\x80\x00\
\x82\x83\x02\x08\x0f\x83\x88\x89\x00\x03\x09\x09\x15\x00\x25\x12\
\x2a\x89\x11\x82\x04\x8d\x16\x40\x41\x09\x26\x45\x83\x11\x19\x18\
\x00\x05\x0a\x10\x17\x38\x3e\x8d\x46\x88\xa2\x89\x1e\x42\x43\x34\
\x47\x8a\x8a\x0e\x14\x44\xb4\xb4\x20\x22\x26\x25\x90\x24\xb9\x00\
\x21\x8d\x28\xbf\xc1\x0c\x8d\x29\xc1\x83\x0b\x23\x27\x93\xcb\xb9\
\xad\x8a\xd3\x82\xa0\xd5\x82\x18\x19\x95\x88\xdc\x00\x24\xc0\xd6\
\xcb\x25\xbe\xd1\xd1\x81\x00\x21\xf9\x04\x09\x08\x00\x00\x00\x2c\
\x00\x00\x00\x00\x10\x00\x10\x00\x00\x07\x67\x80\x00\x82\x83\x84\
\x85\x86\x82\x25\x25\x87\x83\x11\x83\x24\x24\x00\x44\x0b\x4e\x52\
\x84\x11\x19\x18\x85\x0f\x49\x09\x51\x85\x99\x85\x48\x4a\x4f\x53\
\x8b\x85\x1f\x30\x05\xa6\x85\x07\x34\x35\x37\x00\x25\x90\x8b\x33\
\x09\x09\x2f\xb1\xb3\x87\x2f\xb6\x38\xab\x82\x2e\x12\x36\xaa\xab\
\x46\x50\x0f\x9f\x86\x10\x4b\x09\x4c\x30\x8c\x98\x85\x21\xb6\x09\
\x35\x96\x8e\x90\x15\x4c\x09\x54\x32\x8b\x89\x82\x4d\x51\xde\xbf\
\x86\x81\x00\x21\xf9\x04\x09\x08\x00\x00\x00\x2c\x00\x00\x00\x00\
\x10\x00\x10\x00\x00\x07\x68\x80\x00\x82\x83\x84\x85\x86\x82\x25\
\x25\x87\x83\x11\x83\x24\x24\x8c\x85\x11\x19\x18\x86\x18\x19\x8d\
\x84\x95\x87\x9b\x8b\x9e\x9f\x82\x02\x08\x0f\x88\x90\x8b\x03\x09\
\x09\x15\x00\x25\xa6\x87\x04\xa9\x16\xa0\x00\x05\x0a\x10\x17\xa0\
\x0b\x4e\x45\x85\x9d\x83\x2b\x56\x58\x56\xbc\x82\x93\x95\x20\x22\
\x26\x25\x55\x3e\xa9\x46\x84\x99\x21\xa9\x28\x47\x57\x59\x42\x5b\
\x87\x0c\xa9\x29\x00\x47\x5a\x1f\x8b\x0b\x23\x27\x2a\x86\x81\x00\
\x21\xf9\x04\x09\x08\x00\x00\x00\x2c\x00\x00\x00\x00\x10\x00\x10\
\x00\x00\x07\x67\x80\x00\x82\x83\x84\x85\x86\x82\x25\x25\x87\x83\
\x11\x83\x24\x24\x8c\x85\x11\x19\x18\x86\x18\x19\x8d\x84\x95\x87\
\x9b\x8b\x9e\x9f\x87\x25\x90\x9e\x24\x8a\x00\xa2\x9f\xa5\xa0\x8b\
\x16\x50\x0f\x86\x5d\x20\x5d\x83\x46\x13\x09\x21\x19\x84\x44\x53\
\x2c\x1a\x83\x5c\x09\xc1\x29\x07\x34\x35\x37\x0f\x49\x09\x60\x83\
\x19\x43\x09\x3c\x32\x33\xc1\x2f\x1f\x5e\x5f\x0b\x84\x4d\x51\x32\
\x00\x2f\xc1\x38\xab\x2e\x12\x36\x05\x86\x81\x00\x21\xf9\x04\x09\
\x08\x00\x00\x00\x2c\x00\x00\x00\x00\x10\x00\x10\x00\x00\x07\x67\
\x80\x00\x82\x83\x84\x85\x86\x82\x25\x25\x87\x83\x11\x83\x24\x24\
\x8c\x85\x11\x19\x18\x86\x18\x19\x8d\x84\x95\x87\x9b\x8b\x9e\x20\
\x22\x26\x8a\x9e\x82\x21\x09\x09\x28\x9e\x24\x8a\x0c\xa7\x29\xaa\
\x8a\x0b\x23\x27\x2a\xa4\x84\x2b\x4e\x52\xb6\x00\x06\x41\x1c\x4f\
\x61\x96\x84\x36\xa7\x1c\x16\x02\x08\x0f\x82\x97\x99\x00\x61\x5c\
\x59\x33\x0e\x03\xa7\x15\x82\xcd\x82\x5b\x5a\x48\x00\x04\xa7\x16\
\xbb\x05\x0a\x10\x17\x86\x81\x00\x21\xf9\x04\x09\x08\x00\x00\x00\
\x2c\x00\x00\x00\x00\x10\x00\x10\x00\x00\x07\x68\x80\x00\x82\x83\
\x84\x85\x82\x02\x62\x3d\x4a\x82\x25\x25\x86\x82\x46\x63\x09\x4c\
\x19\x00\x24\x24\x83\x11\x84\x5c\x09\x9d\x4f\x85\x18\x19\x9a\x82\
\x19\x64\x3e\x22\x32\x86\x18\x85\x30\x3f\x31\x8f\x84\x07\x34\x35\
\x37\xb0\x84\x33\x9d\x2f\xb6\x24\x8e\x2f\x9d\x38\xbb\x8e\x2e\x12\
\x36\x05\xb6\x85\x11\x32\x02\xc7\x83\x25\x42\x2b\x5d\xaa\x85\x2c\
\x09\x0d\xaf\x84\xa1\xa3\x82\x53\x5f\x53\x44\x96\x98\x82\xda\x8f\
\x8d\xcc\xe6\x81\x00\x3b\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x03\x4a\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x03\x76\x00\x00\
\x03\x76\x01\x7d\xd5\x82\xcc\x00\x00\x00\x07\x74\x49\x4d\x45\x07\
\xd7\x0c\x1b\x16\x0a\x05\x13\x29\x78\x6f\x00\x00\x02\xd7\x49\x44\
\x41\x54\x78\xda\x8d\x92\xcf\x6b\x54\x57\x14\xc7\x3f\xf7\xbe\x37\
\x6f\x5e\x66\x32\x93\xa9\x24\x1d\x27\x89\x10\x75\x5c\x34\xb5\x3f\
\xd4\xaa\x7f\x81\x0b\x15\x17\xa1\xe8\x2a\xd0\x45\x6d\x17\x81\x2e\
\xda\x95\xbb\x4a\x76\x5d\x15\x04\x41\x8b\x36\x5d\x74\x91\x62\xe9\
\x1f\x10\x88\x6e\x5c\x88\xa0\xa8\xd8\x92\x90\x74\x88\x21\x93\xa8\
\x33\x31\x33\xe3\xcb\xcc\xbc\x5f\xf7\x79\x78\x74\x21\xd2\x85\x07\
\x0e\xe7\xbe\xfb\xee\xf7\x73\xbf\xe7\x70\x55\x6b\x7e\xfe\x68\xef\
\xee\xdd\x9b\xad\x85\x85\x7d\x00\xc9\x5b\x09\x60\x80\x77\xf7\x9d\
\xbd\x7b\xed\xca\xf4\xb4\xf7\x6a\x65\xe5\x8c\xaa\x5f\xba\x74\x2f\
\x3c\x70\xe0\x64\x57\x29\xde\x37\x12\xa5\xd0\xad\x16\x2f\xaf\x5f\
\xbb\xa3\x16\xb4\xde\xd8\x33\x3b\x3b\x66\x95\x4a\x24\x5a\xe3\x45\
\x11\x05\xa9\xff\x17\xaf\x8d\x21\x6f\xdb\x68\xa9\x96\xd4\xa7\x33\
\x33\x75\x1d\xc8\x47\xd0\xe9\x10\x78\x1e\xfe\xc1\x83\x94\x4f\x9d\
\xa2\x1d\x86\xf8\xed\x36\x6f\xa7\xec\xa5\xff\xc2\x6a\x95\x60\x77\
\x97\xb0\xdb\xc5\x17\xad\x0e\x21\x15\x27\x49\xc2\xe4\x89\x13\x94\
\x2b\x15\xc6\xcf\x9e\xa5\xa7\x35\x81\x08\x25\xd3\xf5\xe8\xe9\xd3\
\x8c\x94\xcb\x7c\x74\xfc\x38\x72\x36\x05\x44\x90\x02\x52\x07\xde\
\xb3\x67\xac\xcc\xcd\x61\xa4\x85\xa2\xb4\x33\x3e\x35\x45\x9c\x1b\
\x20\xca\xb9\x54\xce\x9d\x63\xb0\x58\x24\x0e\xc3\xf4\x8c\xb7\xb6\
\x46\x24\x80\x10\xb0\xa3\x8c\x9d\x3a\x40\x84\xcf\xef\xdf\x27\xdc\
\xf5\xd8\xff\xf5\x45\xdc\x7c\x9e\xd1\xf3\x17\xe4\x36\x83\x93\xcb\
\x61\x44\x5c\x9b\xbb\x49\xf3\xe9\xdf\x80\x22\x5b\x1a\x4a\x01\xd6\
\x54\x36\xf3\x43\xe0\x64\x8b\xb1\x00\x94\x89\x31\xcd\x3a\xf1\x46\
\x8d\xfc\x67\xc7\x30\x5a\x83\xb6\xd0\x62\x79\xe7\x8f\x5f\xe9\x3c\
\x79\x48\xaf\xd9\xa4\xbd\xbe\xc1\xfa\xe2\x22\x7e\xbf\xff\xda\x8e\
\x2c\x8b\xf6\xe3\xc7\x98\x24\xa6\x58\x74\x28\xed\x71\xe9\xf5\xb7\
\x51\x67\xbe\x64\xb0\xf4\x01\x91\x80\x77\x5e\x6d\xb3\xb9\xf0\x17\
\xc9\xf2\x3f\x78\x5d\xf0\xfa\x9a\xd8\x76\x09\x01\x1d\xdb\x16\x89\
\x02\xe9\x84\xac\x0e\x50\xfb\xc6\x99\xb8\x7c\x85\xd2\xf0\x08\x16\
\x06\x2b\x31\x64\x07\x0b\x7c\xf8\xe3\x55\x32\x93\x87\x91\x91\xe0\
\x66\x15\xb6\xad\x49\x01\xc6\x56\x0a\xad\x70\x6c\x70\x0f\x7f\xca\
\xc7\x57\xe7\x19\x19\x1b\xc7\xd1\x90\xbb\x3e\xc3\xd0\xdc\x77\xb2\
\x56\x0c\x09\x70\xe2\xa7\xdf\xc8\x7e\x72\x04\xc7\x01\x2b\xa3\xfe\
\x73\x90\xd1\x28\x0d\x45\x79\x03\x5f\xdc\xf8\x93\x91\x51\x11\x5b\
\xc2\xbc\xf2\x0d\xee\xf2\x6d\x0a\xff\xde\x61\xf8\xf7\xef\x29\xe6\
\x73\x0c\x8f\x8e\xf1\xf9\xb5\x5b\x14\xaa\x87\xb0\x05\x10\xa5\x0e\
\x84\x0e\xe0\x37\x1a\x38\xad\x06\x16\x32\xb0\xd9\xaf\xf0\x1f\x2e\
\x92\x00\x26\x81\xf8\xd1\x6d\xcc\xcf\xdf\x32\xe0\x64\xc8\xb4\x9a\
\x84\xdb\x0d\x94\x05\x06\x50\x37\x8e\x56\x9f\xf7\x6a\xf5\x72\x4e\
\xc7\x72\xc3\x10\x95\xc9\x2a\x6a\xed\x01\x85\x1c\x69\xbf\x96\x06\
\x3f\x00\xaf\x07\xf1\xc4\x31\x5e\x2e\xd5\xd8\x69\xb4\xe9\x3b\x05\
\x96\x6a\xdb\x75\xdb\x2d\xef\x5f\x37\x41\x54\x56\xdd\x0e\x3d\x13\
\xf3\x62\x75\x99\x01\x77\x10\x1f\x70\x22\x40\x41\x6c\x20\xd0\xd0\
\x5b\x59\xa6\x1b\x42\x24\x43\xf5\xfa\x03\xe2\xc2\x5a\xb5\xb7\x96\
\x56\xa7\x3b\x9b\x5b\xbf\x84\xbe\x5f\x4d\x78\xbf\x50\x5a\x23\xb9\
\x2a\xaf\xf6\xe2\x1b\x6a\x91\x52\x21\x98\x91\x3a\x79\x00\x00\x00\
\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x04\x3d\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x37\x5c\x00\x00\
\x37\x5c\x01\xcb\xc7\xa4\xb9\x00\x00\x03\xaf\x49\x44\x41\x54\x38\
\xcb\x05\xc1\x5b\x68\x1c\x55\x00\x06\xe0\xff\x9c\x33\x97\x9d\xd9\
\x5b\x92\xcd\x65\xd3\x24\xdd\x6e\xd2\xb4\x69\x62\x52\xa4\xd6\x34\
\xa2\x85\x16\x8b\x97\x97\x12\xa1\x16\x6c\x51\xfb\xa2\x14\xaa\x0f\
\x8a\x10\x2d\xf8\x52\x6b\x0b\x62\x14\x7c\x28\x4a\xa9\x50\x44\xa9\
\xa4\xe0\x8b\xb7\xb4\x18\x30\x92\x12\x42\xad\xb5\x95\x90\xd0\x68\
\x2f\xc9\xee\x26\xd9\xcb\xcc\xec\xcc\xec\xec\xcc\xec\x39\x7e\x1f\
\x99\xfc\x62\x06\xaa\x2a\xa1\x52\xae\x92\x03\x07\x87\xc8\x53\x7b\
\xb7\xf2\xb3\x67\x7e\xde\x56\x28\xd7\xf6\xd7\x82\xc6\x8e\x5c\xde\
\xc2\xed\x3b\xb9\xe5\xc0\xad\xff\x16\x2a\xea\x6a\xac\x49\x23\xa1\
\x1f\x82\x4a\x54\x40\x00\xd2\xd2\x72\x11\x94\x80\x3c\x58\x2c\x88\
\x6a\xc5\xef\x98\x99\x59\x3e\x1b\x69\x4b\x1c\xcd\x6c\x69\x89\x3e\
\xda\xb0\x45\x2e\xef\x40\xed\x6c\x26\xcc\xad\x5b\x81\xeb\x5f\xae\
\x6e\x98\x1f\x1a\x6b\xc5\x4a\xef\xe3\xbd\x44\x8d\x48\x82\xed\x1a\
\x3c\x4c\xec\x92\x23\xea\x10\xbd\x03\xbb\x7b\xa6\xb5\xee\xd4\x21\
\xaf\xbd\x45\x5a\x63\xb2\xc8\x87\x54\x74\x76\x26\x85\x1c\x8b\x40\
\x8b\x45\x14\x89\xd1\x51\xca\xe8\x61\x16\x51\x7f\x32\x2a\x6e\x85\
\x32\x4a\x08\x90\x05\xb0\x55\x3b\xfd\xd1\x07\xb3\xed\x03\x5d\x7b\
\xc2\x54\x34\x68\x6a\x92\x25\x08\x46\xfe\x7e\x68\x8a\xb5\x75\x07\
\x8a\x17\x90\xdc\x83\xa2\x08\x4c\x37\xac\x97\x6c\xd9\x33\x9c\x9b\
\x3a\x0f\x9f\x09\x3c\x5e\x63\x27\xdf\xb9\x84\x6d\xdb\x87\xde\xcd\
\x0c\xf5\xbc\x6a\xc3\x09\xe6\xaf\x7c\x2e\xaf\xcd\xfd\x8a\x1e\x6e\
\x92\x37\x5f\x1c\x25\x1d\x1a\x27\x4b\x79\x13\xd5\x3a\x81\x61\xd5\
\x98\xef\x87\x41\xe8\x85\xdd\x1c\xb0\x0d\x2f\xfc\x83\x5e\x98\x7c\
\x49\x76\x05\x39\x4e\x34\x05\x1b\x2e\x67\x85\x64\x3f\x6e\x45\x07\
\xc8\x95\x5b\xf7\xa1\x4a\x0c\xfb\xba\x22\x78\xb6\xb5\x84\xed\x69\
\x95\xc4\x12\x3a\x88\x2c\xb1\x78\x8b\x8e\x74\x47\xe2\xf5\x8d\xbc\
\xa9\xb3\x78\xe7\xe9\x21\xb9\x29\x36\xc1\xa3\xaa\x54\x95\x75\x44\
\xfb\x46\x48\xac\x6f\x04\x2f\x8f\x0d\x81\xaf\xdf\xc3\xf1\xb7\x26\
\x70\xfb\xcf\x05\x8c\x3f\x91\x86\x13\x2a\x58\x5a\xad\xe3\xe9\x91\
\x4e\xe2\x39\x7e\xb2\x62\x79\x3f\xb0\xfe\xe1\xf1\x11\xaa\x2b\x27\
\x2c\x50\x11\x4f\x28\x78\x64\x08\xf2\x64\xab\x8c\xe7\x52\x65\xbc\
\x71\xee\x22\xea\x7d\x87\x50\xd7\xba\xb0\x70\xed\x2a\x0c\x97\x80\
\xc6\x32\x30\x4a\x16\xca\x25\x87\x25\x74\x79\x4a\x8a\x46\x15\xcf\
\xf2\x42\xd0\x9a\x07\xd7\x51\x30\x1a\xbd\x86\x53\x3b\xbb\xf1\xf1\
\xe5\xff\x80\xfe\xe7\xb1\xb5\xf7\x31\xd4\x4c\x0b\x1b\x0d\x1d\x7a\
\x22\x85\xa4\x60\x28\xe6\xeb\x50\x01\x14\xcb\xae\x47\x63\x5a\x64\
\x85\xf0\xb0\x58\xb5\x08\xd1\xcc\x79\x9c\xdb\x7b\x01\x85\x1b\x27\
\x70\x63\x35\x44\x4b\x5b\x2f\xaa\x85\x02\x02\xdb\x81\xde\x9c\x05\
\x65\x51\xe8\x32\x90\xd4\x15\xe2\x38\xfe\xa6\x69\x7a\x2b\xf4\xe6\
\x66\x3c\xcf\xa8\xf2\xbb\xe2\x17\xf1\xde\x9e\x2f\xb9\xd4\xd8\xc4\
\x67\xd3\x7d\xe0\xb1\x11\xf8\xa6\x01\xdf\x09\x60\x1b\x35\x48\x81\
\x27\xba\x9a\x15\x90\x86\x68\x94\x4a\x36\xbc\x7a\x38\xab\xb5\xc6\
\xf3\xd4\xbc\xd3\x84\xbb\xff\x46\x3f\x39\x35\x76\x15\x63\x3b\x73\
\xe4\x9b\x69\xce\x57\xc4\x31\x34\x69\xba\x08\xac\x1a\xe4\x46\x03\
\xd9\x94\x26\x32\x29\x9d\x14\x72\x26\x7f\xb8\x5a\x21\x01\x87\x90\
\x64\xf6\xa9\x2e\x53\x48\xf7\xbf\x7e\x01\xf9\xa2\xe8\x1b\xde\xd5\
\x8e\xbf\xee\xda\xf8\x6a\xfe\x20\x51\xfb\x86\x79\x77\x94\x13\x9b\
\x52\x11\x51\x18\x1c\xd3\xc1\xe2\xaa\xd9\x88\xe8\x2a\xb8\xaa\x30\
\x1a\xf0\xf7\xa5\xa4\x3e\x87\x06\xa7\x74\xbd\xc4\x07\xb3\xd9\x8e\
\x49\xb7\xe6\xe1\xe2\x8f\xca\x9a\x9f\x7e\xa5\x1c\x4d\x37\x53\x57\
\x4f\x20\xd9\xdd\x4e\x0c\xa6\x92\x3c\x22\x48\x64\xb7\x30\xb5\x25\
\xe1\x53\x4a\xdf\xce\xee\x1f\x3a\xaf\x69\x0a\xc9\xf4\xa7\x39\xdb\
\xb7\x3b\x7e\xb4\xbd\x99\x1c\x99\x59\xa8\xd8\x67\x2e\x85\xaf\x85\
\x35\xe9\x3b\xdb\x32\x32\x65\xbb\xde\x52\xa8\x38\x0a\xe7\x75\x2e\
\x37\x2c\xd3\xdf\x5c\x99\xb5\xef\xcd\x9d\x54\xd2\xfd\xdf\x57\x56\
\x0a\x34\x77\xfd\x5b\x61\x98\x04\x04\x48\xd2\x23\x07\xcc\x09\xcb\
\x01\xff\x65\x1e\xe7\xe3\x3a\x3a\xec\x1a\xd2\x04\x74\x87\x1c\x49\
\x75\x06\x0d\x34\x44\x50\x5c\x05\xc4\x22\x08\x2b\xb4\x0d\x8e\xbb\
\x9b\xff\x4c\x85\x00\x70\x6c\x4a\xe0\x7f\x70\x2b\xc1\xc5\x00\xe2\
\xed\x86\x00\x00\x00\x22\x7a\x54\x58\x74\x53\x6f\x66\x74\x77\x61\
\x72\x65\x00\x00\x78\xda\x2b\x2f\x2f\xd7\xcb\xcc\xcb\x2e\x4e\x4e\
\x2c\x48\xd5\xcb\x2f\x4a\x07\x00\x36\xd8\x06\x58\x10\x53\xca\x5c\
\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x01\xf5\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x04\x00\x00\x00\xb5\xfa\x37\xea\
\x00\x00\x00\x02\x73\x42\x49\x54\x08\x08\x55\xec\x46\x04\x00\x00\
\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\x01\x3a\
\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\
\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\
\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\x74\x49\x44\x41\x54\
\x18\x19\x05\xc1\x41\x4b\x53\x01\x1c\x00\xf0\xff\x3b\xf5\x11\xea\
\xda\xa1\x7d\x84\x2e\x5d\x3c\x46\x17\x75\x6d\xb3\x18\x96\x42\x9a\
\xa8\x20\x6f\x13\x6b\x96\xcc\x87\xe8\xcd\xba\x74\xea\x63\x04\x6f\
\x84\x41\x5f\xa0\xa8\x41\x79\x08\xf1\xe2\x65\x19\xc5\x7a\x06\xef\
\x30\xde\xf8\xf5\xfb\x85\x10\x42\x1c\xd6\x0e\xb2\x2c\xef\x8f\xfa\
\xa3\x2c\x3f\xc8\x0e\x6b\x42\x08\x11\x42\xf4\x93\xbd\xb4\x57\x76\
\x6c\xeb\xeb\xdb\xd6\xd1\x2b\xf7\xd2\x7e\x22\x44\x88\xdd\xa4\x37\
\xd8\xf2\xcc\x89\xa1\x1f\xce\x7c\x77\x62\xc7\x96\xde\x60\x37\x11\
\x21\xba\xe9\x86\x57\xbe\xf9\x69\xec\xca\x3f\x85\x5f\xce\x1d\xdb\
\xd0\x4d\x45\xa4\xb5\xcd\xb2\xeb\xd4\x1f\xa5\x77\xae\x4c\x55\x26\
\x0a\x17\xb6\x6d\x96\x69\x2d\xd6\xb3\x65\x1f\xfd\x56\x9a\x3a\x76\
\xe4\x2b\xa8\x14\x86\x96\xad\xef\xc7\x4a\xbe\xea\x8b\x42\x85\x3d\
\xab\x1e\x78\xed\x0a\x13\x97\xd6\xac\xe4\xb1\x34\xea\x1a\x1a\xab\
\xb0\x6a\xde\x8c\x19\x8f\x7c\x56\x19\x7b\x61\x69\x14\x8b\xa3\x8e\
\x53\x85\x29\x6e\xbb\xee\x9a\x5b\xee\xfb\x64\xaa\xf0\xd2\xe2\x28\
\xda\xf9\x92\xa1\xb1\x0a\x77\xdc\x74\x43\xc7\x5f\x54\xc6\x9e\x68\
\xe7\xd1\xce\x1a\xde\xbb\x34\xc1\x3d\x77\x7d\x00\x4c\x9c\x69\x68\
\xef\xc7\xc3\x5a\xb3\x7c\xea\x5c\xa1\xf2\x46\x01\xa8\x14\xba\x9a\
\xe5\xc3\x5a\x88\x56\x3a\xe7\xc8\x85\xc2\x44\x65\xaa\x32\x51\x78\
\x6b\x4e\x2b\x15\x21\x16\x92\xd6\x60\xd6\x9a\xa1\x4b\x63\x85\xb1\
\x33\x1d\xb3\x5a\x83\x85\x44\x84\x10\xad\xa4\x91\xd6\xcb\x59\x8b\
\x76\x3c\xf7\xd8\xac\x7a\xd9\x48\x5b\x89\x10\x21\x84\x10\xcd\x5a\
\x23\xab\xe7\xf3\xa3\xf9\x51\x3d\x6f\x64\xcd\x9a\x10\x42\xfc\x07\
\x7b\x2d\x6e\x9f\x2f\x2d\x37\x8c\x00\x00\x00\x00\x49\x45\x4e\x44\
\xae\x42\x60\x82\
\x00\x00\x01\xe5\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\
\x00\x00\x09\x70\x48\x59\x73\x00\x00\x06\xec\x00\x00\x06\xec\x01\
\x1e\x75\x38\x35\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x03\x14\
\x12\x23\x3b\xba\x62\x67\xa1\x00\x00\x01\x65\x49\x44\x41\x54\x78\
\xda\x95\x90\xcf\x4a\xc3\x40\x10\xc6\x67\x37\xa6\xa5\x81\x5e\x8a\
\xa7\x3c\x86\x78\xf1\x01\xd4\x1e\xac\x6f\xe0\xc5\x73\xbd\xd8\x53\
\x2d\xf8\x08\xbe\x4b\xcf\x3e\x80\xa0\x10\x3c\xfb\x00\x56\xda\x54\
\x4a\x82\x25\x7f\x77\x3a\xb3\x6c\xe8\x9a\x90\xa2\x1f\x7c\x7c\xbb\
\xec\xcc\x6f\x77\x56\x00\xc0\x80\x7c\x46\x16\x70\x58\x48\x7e\x21\
\x7f\x43\x4d\x57\xf8\x37\x31\x60\x04\x35\x1d\x55\x37\xaf\xc2\x10\
\xa4\x94\x20\x85\x00\x41\x29\x38\xd9\xa6\xb0\xdf\xef\x73\x88\x26\
\xc0\xc8\x71\x1c\x0d\x88\xa3\x08\x82\x20\x00\x2d\x0b\xd0\xed\x76\
\x39\x4e\xc8\xa9\x35\xd2\x2b\x2f\x46\x48\xda\x6c\x36\x18\xc5\x31\
\xce\xe7\x73\xfc\xc7\x48\xc3\xc6\x0b\xf8\x56\x56\xb8\x5e\x83\xc3\
\x23\x19\x0b\xb2\x3d\x92\xe7\x79\x1c\xb2\x02\xe8\x22\x0d\x31\x00\
\xdd\x4c\x7b\x9d\x55\x33\x67\xdb\x1f\x48\xab\xd0\xec\xf7\x10\xeb\
\x53\xa1\x15\x60\x15\xd9\x40\xa7\x06\xa6\x6c\x00\xea\x07\x36\x60\
\x0f\x3e\x0c\x68\x42\x44\xad\xb9\x28\x0a\x08\xc3\x10\x3a\x1d\x17\
\x7a\x3d\x0f\x14\x08\xa4\xb2\x82\x01\x8a\x0e\xd1\x75\x5d\x51\xdd\
\xac\xb3\x76\x2b\x37\xfb\xbe\x0f\xac\xed\xf6\x07\x1e\x67\xb3\x67\
\x5a\x06\xbc\x3f\x26\xdf\x90\x6f\x8d\x9f\x90\x94\x24\x09\x66\x59\
\x86\x0c\x2f\xcb\x12\x17\x5f\x0b\x54\x4a\x61\x1c\xc7\x38\xbe\x1b\
\xbf\x51\xdd\x29\xb4\x68\xc8\x80\x34\x4d\x31\xcf\x73\x06\xe8\xc6\
\xe5\x6a\xa9\x9b\x27\x93\xfb\x77\xaa\xb9\x26\xcb\x36\xc0\x05\x35\
\x2a\xb4\x94\x15\x25\x7e\x2e\x57\x38\x7d\x98\xf2\x93\x2f\x7f\x7d\
\x3e\x34\x35\x20\x9f\x9b\x22\x5b\x68\x66\xfe\x20\x2b\x30\xda\x01\
\x68\x0b\xe8\x88\x71\x7b\x2b\x7d\x00\x00\x00\x00\x49\x45\x4e\x44\
\xae\x42\x60\x82\
\x00\x00\x03\x47\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x02\xc4\x49\x44\
\x41\x54\x78\xda\x9d\x93\x5b\x48\x53\x71\x1c\xc7\x3f\xe7\x6c\xe9\
\xa6\x36\x8f\xb5\x91\xa7\x48\x6c\x0b\x32\x8c\x08\xa4\xfb\x58\x2d\
\xbb\x88\xd5\x53\x62\x17\x8b\xae\xf3\xb5\xb2\x46\x17\x24\x28\xba\
\x47\x05\x41\x85\xbd\x44\x74\x2f\x0d\x2a\x95\x82\xc0\x82\x6e\x08\
\x25\xdd\x2f\x76\xa3\x8b\xb5\x6a\x73\xd3\xed\x2c\xdd\x39\xae\x79\
\x40\x5d\xf4\x12\x7d\xe1\xfb\x76\xbe\x1f\xbe\xbf\xef\x9f\x23\xc4\
\xe3\x71\xfe\x45\xd5\x6b\xe4\x41\x79\xcf\xf3\x1b\xd4\x48\xf4\x4d\
\x3f\x59\x2e\xcf\xaf\xae\xfe\x06\xa0\x03\xe6\xce\x99\xd3\xfa\xeb\
\x57\x87\xb4\x7a\xad\x97\x64\x09\x22\x80\x88\x40\x8c\x91\x6c\xe1\
\x63\xad\x84\xe5\xf2\x0b\x9e\x29\x0a\x17\x26\x4e\x0c\x5e\xa9\xab\
\xcb\x32\x02\x28\x11\x45\xca\x96\xb3\x71\x4d\x75\x13\x4f\x06\x74\
\x5b\x88\x13\x7d\xb4\x98\x1f\x3e\x91\x65\xf5\xaf\xf1\x48\x22\xb6\
\x9f\x61\xc4\xd6\xa0\x04\xa0\x03\xba\xba\xba\x30\xa5\x9a\x30\xa5\
\x18\x38\x79\xe3\x31\xc9\xca\xf4\x1d\x64\x8c\xf5\x15\x0b\x2b\x15\
\x04\xd5\x4f\x91\x37\x85\x9a\x9b\x23\x09\xbe\x35\xd2\x0b\xd0\x12\
\x00\x55\x55\x11\x45\x58\x5c\x38\x0a\x01\xf4\x26\xaf\x1a\xab\xc8\
\xb5\x3c\xa5\xb8\xa2\x03\xff\xcf\xef\x9c\xdd\x9a\x46\x28\x65\x1a\
\xb7\xdf\xb4\x24\x32\x1a\x00\x62\x4f\x03\x4d\xd3\x68\x8f\x76\x12\
\xed\x54\x51\x12\x7e\xff\xbc\x96\xbc\xd4\xe3\x94\x6d\xed\xe4\xdd\
\xc7\x00\x47\xd6\x9b\x21\x2d\x8f\xc6\x2f\x13\x30\x99\xcd\x00\xf4\
\x9d\xa0\x69\x7a\x83\x70\x02\x70\xfe\xda\x3d\x52\x63\xef\xf1\x4c\
\x7e\x4d\xf9\x2e\x81\x47\x2f\x43\x6c\x28\x53\xc9\xb0\x48\xec\xbe\
\x32\x8c\xd9\x33\x25\xa4\xcc\x4c\xda\xdb\xda\xfe\x6e\xd0\x16\x8e\
\xe2\x1a\x6d\xc5\x33\xc5\xcf\xe1\x73\x9f\xb8\xdb\x14\x62\xc9\xf4\
\x08\xee\x82\x74\x2e\x36\xcd\x20\x7f\xc4\x70\x0a\xc6\xbb\xba\xbf\
\xd7\x9d\x34\xa2\x86\xa6\xaa\x6c\x5b\xb7\x82\x03\xde\xa1\x9c\xbe\
\xfe\x95\xaa\xd3\x2f\x28\xc8\xfd\x4c\x59\xa1\x91\xe5\x7b\x44\x82\
\x91\x06\x1c\x0e\x07\x6f\x9f\x3c\xa0\x27\xd3\x37\xa2\x96\x20\x6a\
\x9d\x6c\x5c\xaa\x71\xeb\xc6\x25\xf6\x9e\xca\x22\x77\xa0\x8f\x1d\
\xe5\x06\x56\xed\x4b\xe3\xab\x3f\x8e\x7d\x58\x36\x46\x83\x41\x3f\
\xb5\x27\xf3\xc7\x06\x2b\xa7\x7f\xa0\xf5\x9b\x9f\xed\x67\x24\x06\
\x59\xda\x38\xe6\x85\xfd\x97\xed\x08\x19\x56\x36\x6e\x9a\x87\xcb\
\xe5\xa2\x74\x5e\x89\x7e\xaa\xc3\x6e\xd7\x33\xbd\x1b\x38\x0b\x72\
\x49\x4f\x37\x50\x71\xd4\x42\x7f\xb3\xca\xe1\xd5\xed\xec\x3a\xd5\
\x45\xc3\x03\x8d\x9c\x9c\x1c\x64\x59\xa6\xb9\xb9\x19\x79\xf0\x60\
\x44\xa3\x41\x7f\xf6\x98\xaa\xf6\x01\x0a\xdd\x93\x90\xc7\x6c\x27\
\xd3\x62\x62\x9f\xe7\x3b\x57\xef\x08\x9c\xa8\x8f\x61\xb3\xd9\x70\
\x3a\x9d\x84\x42\x21\xdd\xf1\xee\xf1\x12\xd5\xad\x56\x2b\xb1\x58\
\x0c\x1d\xb0\xad\x62\xbe\x71\xc8\x10\x1b\x4a\xa0\x91\x35\x0b\x24\
\xee\xbf\xb4\x72\xa8\x26\x8d\x01\x52\x16\xc5\xc5\xc5\x84\xc3\xe1\
\x5e\x40\x24\x12\xd1\x83\x51\x45\xd1\x47\x07\x30\xf6\x33\x65\x6c\
\xae\xdc\x59\xc5\xac\xb1\x16\xf5\x6c\xbd\xcf\xe8\x2e\x2a\x65\xf9\
\x4a\x03\x00\x81\x40\x80\x64\x7d\x69\x69\x01\xe2\x3c\x6c\x6a\x42\
\x34\x88\x41\x00\x2a\x56\x15\x2d\xf2\x94\x8c\x73\x74\xff\x95\xff\
\xe3\xdf\xfd\x96\x70\x9f\x9f\x28\xbe\x9f\x00\x00\x00\x00\x49\x45\
\x4e\x44\xae\x42\x60\x82\
\x00\x00\x02\x84\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00\x28\x2d\x0f\x53\
\x00\x00\x00\x03\x73\x42\x49\x54\x08\x08\x08\xdb\xe1\x4f\xe0\x00\
\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\x01\
\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\
\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\
\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\x35\x50\x4c\x54\
\x45\xff\xff\xff\x00\x00\x00\x3a\x42\x3a\x00\x00\x00\x2c\x32\x2c\
\x00\x00\x00\x20\x20\x20\x00\x00\x00\x15\x15\x12\x00\x00\x00\x05\
\x05\x05\x3d\x3e\x3c\x00\x00\x00\x3d\x3e\x3b\x63\x63\x63\x00\x00\
\x00\x01\x01\x01\x30\x31\x2f\x02\x02\x02\x24\x25\x24\x02\x02\x02\
\x18\x18\x17\x04\x04\x04\x0d\x0d\x0d\x01\x01\x01\x02\x02\x02\x04\
\x04\x04\x05\x05\x05\x06\x06\x06\x07\x07\x07\x08\x08\x08\x0c\x0c\
\x0c\x0d\x0d\x0d\x10\x10\x10\x14\x14\x13\x14\x14\x14\x19\x19\x19\
\x20\x20\x20\x21\x22\x21\x22\x22\x22\x27\x27\x26\x2f\x30\x2e\x31\
\x31\x31\x32\x33\x31\x37\x37\x37\x3a\x3a\x3a\x3d\x3e\x3b\x3f\x3f\
\x3f\x41\x41\x41\x41\x42\x3f\x44\x45\x43\x45\x45\x45\x47\x47\x47\
\x4a\x4a\x4a\x4a\x4b\x48\x4b\x4b\x4b\x4d\x4e\x4b\x4e\x4e\x4e\x4e\
\x4f\x4d\x50\x50\x50\x53\x53\x53\x54\x54\x54\x56\x56\x55\x56\x57\
\x54\x58\x59\x56\x59\x59\x59\x5b\x5b\x5b\x64\x64\x63\x64\x66\x62\
\x66\x68\x64\x68\x68\x68\x6a\x6a\x6a\x6a\x6b\x67\x71\x71\x71\x75\
\x75\x75\x79\x79\x79\x7a\x7a\x7a\x84\x84\x84\x86\x86\x86\x8a\x8a\
\x8a\x90\x90\x90\x9f\x9f\x9f\xac\xac\xac\xae\xae\xae\xb2\xb2\xb1\
\xb7\xb8\xb7\xc1\xc1\xc1\xc4\xc5\xc4\xc6\xc6\xc6\xcf\xd0\xcf\xd4\
\xd4\xd4\xde\xde\xde\xe1\xe1\xe1\xe7\xe7\xe7\xe9\xe9\xe9\xea\xea\
\xea\xed\xed\xed\xf0\xf0\xf0\xf3\xf3\xf3\xf4\xf4\xf4\xfa\xfa\xfa\
\xfb\xfb\xfb\xfc\xfc\xfc\x75\x4a\xf7\xaa\x00\x00\x00\x18\x74\x52\
\x4e\x53\x00\x1f\x1f\x2e\x2e\x3f\x3f\x54\x54\x65\x65\xb8\xca\xca\
\xd4\xe5\xe5\xe5\xf0\xf0\xf8\xf8\xfd\xfd\x0a\xa9\xac\x9a\x00\x00\
\x00\x9d\x49\x44\x41\x54\x18\x19\x9d\xc1\x03\x16\x02\x01\x00\x05\
\xc0\x9f\x6d\xdb\xb6\x6d\xdb\x76\x5b\x7b\xff\x23\x84\x3d\x40\xef\
\x35\x03\xfc\x89\x2e\x0a\x53\x04\xf8\x62\xca\xea\xe3\x41\xbf\x37\
\xec\xb4\x7d\xf8\x60\x2b\x8a\x33\x62\x52\x1f\x11\xf3\xa2\x1b\x6f\
\x5c\x55\xaa\xb6\x7f\xdc\x17\x04\x79\xc9\xd9\x01\xf0\x35\xd1\x4c\
\xb2\x74\x78\x3c\xc9\x5b\x21\x62\x04\x20\xf1\x47\x42\xc1\xe0\x94\
\x24\x9f\x53\x8f\x53\x0b\x80\xa7\xb6\x58\x6d\x89\xc3\xf5\x74\x3d\
\xe6\x74\x3a\xbc\x71\x94\x06\xfd\xf6\xbc\x29\xaf\xcf\x3b\x97\x1e\
\x1f\x2c\xb9\x23\xbe\xcc\xc7\x2a\xab\x46\xc0\x80\x2f\x86\xd4\x9b\
\xae\x36\xbb\xad\x6a\xd6\x04\x0a\x4d\x68\xa6\x88\xf1\xdb\x0b\x5c\
\x72\x1c\x18\xbd\x2b\x0f\x2f\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
\x42\x60\x82\
\x00\x00\x02\xd2\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x02\x4f\x49\x44\
\x41\x54\x78\xda\xa5\x93\xcb\x4f\x13\x51\x14\x87\xbf\x3b\x33\x1d\
\x5a\x5b\x0c\x19\xc0\x42\xa0\xe5\x61\x13\x17\x24\xa8\x71\x65\x8c\
\x1b\x8d\x89\x3b\x57\xee\x64\xa7\x0b\x1f\x7b\x48\x7c\x9b\xe0\x42\
\x4d\x8c\x8f\x3f\x42\x57\x2e\x5d\x68\x74\x61\x0a\xa8\x41\x40\x5d\
\xb0\xd0\x50\x1e\xa2\xb5\x0d\x8f\x4e\xa1\x32\x33\x9d\xeb\x1d\x26\
\x4e\x0a\x5b\x4f\x72\x72\xef\xe6\xfb\xf2\x3b\x77\xce\x08\x29\x25\
\xff\x53\x06\xbb\x6a\x4e\x88\xc1\x55\x78\x66\xe6\x72\xc9\xa6\x5c\
\x2e\x16\x4b\xa7\x75\xb7\x58\xac\x3b\xb3\xb3\xf6\x9e\x42\xe1\x6c\
\x9f\x94\x9f\x77\x08\x76\xc3\xa5\x6c\x36\xdf\x79\x77\x34\xd5\x64\
\x59\x08\xa1\x81\xa6\x21\x3d\x17\xa7\x62\x77\x2e\x0f\x0f\xe7\x11\
\xe2\x58\xa3\x24\x18\x21\x82\x17\xbb\xbb\xf2\x3d\x37\x6e\xa6\xcc\
\x8d\x2a\xb2\x5e\x07\xcf\xc3\x57\xa7\xef\xba\xd4\x7d\x1f\x69\xb5\
\xb2\x74\xff\x5e\x35\xf3\x63\x39\x92\x68\xff\xe0\xb9\x8e\xf4\x58\
\xcf\xed\x5b\x29\xbd\x5c\x42\x28\x48\x57\x2d\x2a\x15\x74\xd5\x86\
\x82\x0d\x29\x91\xdf\xbf\x91\x1d\x19\x4e\x15\x3a\x3a\xc6\x02\x86\
\x48\x60\x18\xcf\x7b\xaf\x5f\x4d\x6a\xf3\x0b\xe8\xbe\x4f\xdb\xb9\
\x21\x5a\x87\x86\xd4\x3d\x10\x79\xb4\x9f\xbf\x40\xe7\xc5\x4b\x98\
\x02\xdc\xc9\x49\x7a\xaf\x8d\x24\x03\x26\x7a\x83\x9a\xe7\x25\xaa\
\x1f\x26\x68\x69\x69\x43\x98\x26\x38\x0e\x46\x26\x83\x75\xf9\x0a\
\xc1\x88\x31\x75\x77\x0b\x73\xe8\xab\xab\x18\x2a\xd1\xc6\xfb\x89\
\x6d\x26\x4a\xe0\x80\x60\xb3\x8a\x56\x59\x47\x2f\xfe\x62\x65\xf4\
\x0e\xee\xc2\x3c\x46\x77\x46\xc1\x59\xdc\xc5\x05\xd6\x9f\x3c\x26\
\xae\x44\xcd\x03\x03\x18\xba\xd8\x66\xa2\x04\x1e\x88\x95\xfc\x5b\
\x9a\x8c\x66\xea\xc9\x24\x7a\x36\x1b\x3e\x22\x61\x49\xd7\x65\x63\
\xfa\x13\xde\xf4\x14\x75\xdb\x66\x2d\x11\x32\x8d\x09\x90\x9b\x36\
\xfc\x5c\xc6\x5d\x5f\xa3\xfd\xc1\x43\xcc\xbe\x7e\xfe\x7c\xfd\xb2\
\xdd\x66\xff\x7e\xd2\x8f\x9e\xe2\x27\xe2\x88\x00\xd2\x43\x26\x4a\
\x20\x61\xab\xa6\xb3\xa3\xb6\x14\xb8\x78\xfa\x24\xbe\xef\xd3\xf3\
\xf2\x35\x9a\x69\x22\x01\x01\x54\xf4\x90\x89\xf6\x60\x4a\x88\x83\
\xef\x62\x8c\x0f\x36\x93\xe8\xb2\x41\xdb\xd7\x1e\xda\x83\x4f\x0a\
\xb8\x96\x05\x7a\x0c\x7e\x17\x59\x4a\xc1\x8c\x4d\xed\xb8\xcb\xd1\
\xc3\x52\xce\x44\x8b\x14\x48\xde\x98\x8c\x1f\xd9\x4b\x22\x53\x21\
\x8c\x2a\xc2\x53\x02\xbe\x84\xa5\x16\xc1\xc7\x35\x59\x3b\xe1\x84\
\x70\xe3\x26\x46\x92\x57\x4a\x72\xc0\x57\x49\x52\x49\x62\xf1\x38\
\xba\x61\x50\xf7\x3c\xca\x08\x26\x57\xca\xb5\x53\x0d\xf0\x6e\x41\
\x24\x19\x87\x17\xea\x27\x4a\xc4\x2d\x4b\x0b\x66\xf7\x1d\x07\xaf\
\x54\xaa\x1d\x2a\x97\xcf\x44\x70\xa3\xe0\x7f\xea\x2f\xb2\x2a\x1f\
\x46\x55\x40\xa7\x1e\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\
\x82\
\x00\x00\x03\x60\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x37\x5c\x00\x00\
\x37\x5c\x01\xcb\xc7\xa4\xb9\x00\x00\x02\xd2\x49\x44\x41\x54\x78\
\xda\x95\x8e\x4d\x68\x9c\x45\x18\xc7\xff\xcf\xcc\xbc\xef\xec\xbb\
\xbb\x6f\xb2\xd9\xb4\x5b\x63\x3e\x68\x44\x5b\xac\x60\xab\xb4\xc5\
\x16\x3f\xa8\xe2\x41\x05\xaf\x16\xf1\xe3\xa0\x50\xf0\xd0\x5e\xea\
\xcd\x83\x17\x4f\x1e\x14\x0a\x82\x57\xd1\x8b\xe2\x51\x2f\xf5\x20\
\x88\x88\xa0\xd2\x58\x9b\x8a\xa9\x36\x9a\xa4\xc9\xa6\x26\xdb\xcd\
\xbb\xbb\xef\xee\xbe\x33\xcf\xe3\xec\xc5\xe6\x24\xf5\xf7\xe7\xcf\
\xcc\x30\xcc\x6f\x1e\x7a\xe2\xed\xeb\x38\x34\x13\xe9\x6a\xd9\xa0\
\xd7\x6a\xd3\x2c\x7a\xfe\x85\xd3\x47\xe4\xfc\x1b\x1f\xce\x4f\xcf\
\x34\x0e\x5f\x5f\x69\x15\x57\xae\xae\xfe\x38\xd1\xd8\xbf\x51\x29\
\x0d\xd4\xd2\xcf\x8b\x6c\x93\x32\x00\x82\x2b\x0a\x10\x02\xaf\x9f\
\xf9\x08\x14\xf2\xfb\x6f\xeb\x70\xec\xd2\xa7\x9f\x3d\xf6\x6e\x3a\
\x51\x79\xf9\xd2\x2f\xeb\xe5\x5e\x5e\x40\x11\x5a\x59\x77\xf8\xde\
\x17\x9f\xbc\xf2\xce\x85\x6f\x0b\x2c\x5e\x5e\x21\xd6\x31\x56\xb7\
\xbc\x1f\x4d\xa0\xef\x9b\x32\x67\x6c\xa4\xa6\x07\x03\x97\x25\xcb\
\x0b\xcf\x1d\x3d\x3a\xf7\x68\x65\x72\x8c\x3f\xfb\x72\x11\x36\xd6\
\xd4\x5c\xdb\xe6\xf1\x34\xd1\x1b\xcb\xcd\x0b\xc7\x9f\x7c\xe8\x6c\
\xe1\x98\xde\x7f\xf3\x84\xd4\xc7\x5f\x83\xb6\x87\xcf\xd6\x4f\x1c\
\x88\x3f\x7d\xf0\x9e\xe4\x99\x41\x73\xfd\xa9\xd4\xf8\xb9\x63\x27\
\xef\xe5\x5b\x03\x56\x9b\xb9\x57\x0b\xd7\x6e\xd2\xca\xcd\x0e\xda\
\x9d\x42\x14\xf0\x30\xaa\xf5\x7a\x32\x7f\xe0\x91\xcf\xbf\xdb\x3e\
\xd2\x38\x79\xea\x27\xa3\x15\x81\x45\x3c\x33\xe3\xf2\x0f\x4b\xae\
\x3e\x51\xd2\x03\x26\x6d\xcb\xb1\x24\xd5\x18\x79\xc9\x0a\x8d\x57\
\x15\x84\x65\xfa\xee\xbd\x26\xb5\xfe\xdc\x03\x33\x4a\xfd\xb9\xae\
\x36\x2f\x2d\x17\x1f\x9b\x5a\x19\xba\x3f\x64\xd3\xea\x14\xd8\xe9\
\x0c\xf5\x52\x33\x53\x07\x7f\x6d\xe2\x96\x13\xfa\xa3\x5b\x20\xbd\
\xab\x46\x7d\x21\x89\x85\x29\x2e\xc5\xe8\x65\x5d\x37\x74\x4e\x8d\
\x3e\x4d\x62\x68\x55\x29\x95\x7c\x5e\xb0\xb4\x07\x82\x28\x29\x21\
\xeb\xe4\xf8\xfa\xea\x26\x56\xc2\x39\xdd\x57\x83\xab\x55\x10\x4f\
\x56\x08\x5a\xf0\xfd\x37\x57\x48\xb4\xd1\xad\x1e\xa3\x37\x64\x5d\
\xb6\xd6\xeb\xf9\x53\x2f\xbd\x05\xf1\x8f\x6f\x65\x83\xd8\x69\x83\
\xc8\x5a\xb2\x13\x63\x98\x4c\x2b\x38\xb8\x27\x05\x39\x42\x04\x85\
\x88\xc3\x1a\x59\x54\xa6\xf6\xa1\xd5\xf7\xd4\xcd\x0b\x08\x67\x9a\
\x5e\xfd\xe0\x5a\xf7\xfe\xd9\xf1\x78\xe8\xd8\x04\xb9\x28\x02\xb9\
\xc2\x43\x00\xe8\x70\x88\x34\xc1\x79\x09\xe5\x20\x8f\xc0\x9e\x25\
\x94\x8c\x56\xb2\xb6\xd5\xe9\x9b\x9e\xb3\xab\x37\x32\x3b\xc7\xcc\
\x06\x01\x11\x81\x30\x01\x44\x28\x59\x0d\xcf\x82\x22\x08\x21\x1a\
\xd4\x55\x20\xd2\x18\xa1\x94\xe2\x8d\x9d\x7c\xcd\xd4\xaa\x51\x3e\
\x55\x37\xc6\x7b\x06\x11\x61\x84\x8c\x22\x08\x65\x00\x0a\x8a\xcc\
\xbf\x77\x80\x84\x40\x54\x30\xe5\xfd\x38\x37\x63\xe5\xa8\xdd\xa8\
\x69\xed\x99\x04\xbb\xa0\x10\xdc\x7e\x03\x09\xd9\xcd\x48\xf8\x77\
\xdb\xb4\x4d\x60\x3b\xb1\x20\x02\x79\xc1\x7f\x41\xbb\x77\xe2\x19\
\xc6\x68\xd3\x32\x73\x8d\xa4\x43\xda\x40\x04\x04\x40\xe1\x0e\x10\
\xc0\x13\x01\xb3\x7b\xd5\x8e\x71\x7f\x7d\x75\x71\x71\x21\x9b\x75\
\xce\x0d\x29\x70\x47\x82\x40\x98\xdc\xee\xa9\xa5\x17\x71\xe8\xb1\
\x17\x11\x88\x42\xed\xff\x6c\x74\xfc\xf9\x73\xf8\x07\x10\x7f\x4e\
\xbe\xda\xd6\x75\xe4\x00\x00\x00\x22\x7a\x54\x58\x74\x53\x6f\x66\
\x74\x77\x61\x72\x65\x00\x00\x78\xda\x2b\x2f\x2f\xd7\xcb\xcc\xcb\
\x2e\x4e\x4e\x2c\x48\xd5\xcb\x2f\x4a\x07\x00\x36\xd8\x06\x58\x10\
\x53\xca\x5c\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x02\xac\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x02\x29\x49\x44\
\x41\x54\x78\xda\x8d\x91\xbf\x4f\x13\x61\x1c\x87\x9f\xf7\xee\xfd\
\xd1\x16\x28\xad\x80\x0a\x8b\x89\xc1\x84\x41\x42\xc2\xe0\x64\xa2\
\xa6\xea\xe0\x22\x8b\x83\xc1\xc4\x18\xff\x01\x17\x9d\x8c\x8b\x31\
\x2e\x0c\x26\x0e\x2c\x98\xe8\x3f\x60\x5c\x4c\x1c\x30\xda\xd9\x01\
\x13\x14\xc2\x20\x1a\xa0\x44\x0c\xa5\xa5\x42\xef\xa0\x77\xf7\x7a\
\xb4\x56\x21\x5c\xa2\xcf\xf2\xe6\xfd\xde\x27\xcf\x7d\xbe\x77\xc2\
\x5a\x8b\xe8\x1b\x9e\x1a\xd0\x1b\xb7\x3d\xcf\xa3\x92\x3e\x05\xa7\
\xc7\xf9\x27\x7e\xed\xae\x2d\xde\x9f\x90\x34\x89\x06\xcf\x17\x2e\
\x72\xef\xc1\x63\xfe\x87\x17\xc5\x15\x9e\x4f\x2f\x8e\x01\xbf\x05\
\xeb\x73\xd5\xcf\xf3\xdd\x5c\xbb\x72\x81\xb0\x6f\x94\xcc\xc8\x0d\
\x1a\x61\xc4\x6e\x60\x69\xa3\xa5\x13\xdf\x23\x00\xc2\xa0\x81\x6a\
\xd4\xfb\x01\x24\x2d\x3e\xe6\x7a\xfb\xaf\x2e\x97\x77\xc8\x9a\x3c\
\xe9\xee\x3e\x2e\x0f\xe5\x18\x3d\x99\x25\x08\x2d\xd9\x8c\x4b\x67\
\x4a\x32\x35\xbd\xc2\x5c\xa9\x0e\xc0\xcf\xf2\xea\x32\x80\xc3\x3e\
\xa2\x20\xc0\x75\x1c\x72\x1d\x9a\x87\xd7\x07\x59\x58\xf5\x78\xfa\
\xa6\xc4\xa3\x97\x4b\x7c\xfd\xe1\xf3\xe4\xd6\x10\x19\xa3\x30\x4a\
\xa2\x94\xe2\xb0\x20\x0a\x71\x5d\x97\xb1\x33\xc7\xc8\x68\x27\x0e\
\xba\x18\xad\xd0\x71\xf8\xd5\x87\x0a\xc7\x73\x9a\x4b\x23\x3d\xcd\
\xbb\x54\x1a\x00\xc9\x3e\xac\xb5\xc8\xb8\xc1\xeb\x99\x2a\xbd\x5d\
\x9a\xd9\x25\x3f\x3e\x0d\x35\x2f\xa4\x30\x9c\x07\x01\x4b\xeb\x41\
\xab\x81\x4c\x10\x80\x8d\x1b\x38\x04\x91\xcb\xb3\xf7\x65\x00\x8c\
\x74\xe8\xe9\x92\xdc\x3c\x77\x34\x5e\x67\x8d\xb5\x5a\x44\x4a\xef\
\x35\x50\x87\x05\x0e\x20\xa5\x4b\x26\xa5\xd9\xcf\xf8\xd9\x3c\xd3\
\x9f\xb6\x78\x37\xef\x35\x9f\x09\x21\x50\xda\x24\x08\x9c\xbd\xbd\
\x35\x9d\xe9\x14\x6d\x3a\x8d\xc3\xc0\x11\xc3\xe4\xdb\x2a\xd9\x78\
\x1e\x01\x02\xd0\x09\x82\x66\xad\x5c\x3e\x4f\x47\xda\xd0\xe6\x44\
\xaf\x64\xb6\x14\xc6\x6f\x4e\x01\x96\xc8\x5a\x40\xa0\x75\xc2\x37\
\x50\xae\x24\x1d\x07\x33\xc6\xfc\x9d\x49\x87\x95\x8a\x25\xa5\x35\
\xae\xd8\x13\x08\x2c\x16\xa5\x92\x1a\x48\x89\x63\x2d\x69\xa3\x69\
\xd3\x88\xc0\x0a\x68\x97\x12\xc2\x36\x07\x2a\xa9\x81\x2b\x5d\x7c\
\xbf\x8e\x8c\x4f\x80\x0e\x03\x77\x0a\x82\x8d\x6d\x98\x2c\xda\x96\
\xe0\x4f\x36\xe1\x2f\x20\x1c\xfc\x1d\x9f\x9d\xdd\x46\x2b\x04\x94\
\x2a\x2a\x5e\x21\x8a\x67\xe1\xc1\xa8\x70\x0f\x08\xbe\x6d\xd5\xaa\
\x78\xdb\x9b\x94\x37\x36\x59\xf8\xb2\x48\x9b\x99\x79\x0e\xb1\x1b\
\x06\xd4\x3d\xef\x3b\xc0\x2f\xbb\xd9\xb9\x56\x43\x7d\x15\xe6\x00\
\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x03\xc9\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x03\x46\x49\x44\
\x41\x54\x38\x8d\x65\x93\xcd\x6f\x14\x65\x00\xc6\x7f\xef\xbc\x3b\
\x3b\x3b\xfb\xc5\x2e\xb6\x9b\x52\x1a\x96\xd2\x8a\x21\x6d\x15\xaa\
\x50\xa3\x05\x8c\x36\x0a\x18\x48\x8c\x9a\x18\x0f\x8d\x1a\x0f\x06\
\x13\x0f\x22\xff\x00\x1c\x4c\x4c\x53\xc3\xc1\x8f\x83\x21\x42\x68\
\x24\x22\x1c\xa8\x58\x35\x46\x43\x53\xb5\x40\xd3\x4a\x0c\x69\x89\
\xb6\x29\x6c\x69\xd3\xee\x47\x3f\x76\x67\x66\x77\x76\x66\x5f\x4f\
\x36\x88\xcf\xf9\xc9\xef\xf2\x3c\x3f\xa1\x94\xe2\x81\xe8\xfd\xa7\
\xae\x1a\x93\xb7\x17\x9f\x72\x9c\x6a\x97\x6d\xbb\xde\xf8\xc4\xdc\
\x4f\x96\xed\xde\xcc\xce\x9d\x74\x1f\x2c\x8b\xfb\x00\x72\xea\xf6\
\x52\xec\xcc\xc0\x8d\xbe\x68\x24\xd8\xeb\xd5\x94\x9e\xc9\x5a\x8c\
\xdc\xc8\xe0\xd8\x2e\x9e\xed\x96\xdd\x92\x73\x02\xc5\x47\xd9\xb9\
\x93\xfe\xff\x00\x4f\x3c\xdd\xdf\x74\xe4\xc5\xf6\x61\x11\x90\xcd\
\x8e\x61\xb0\xaa\x69\xcc\xe6\xcb\x48\xdf\xa7\x58\xb0\x58\x59\x5a\
\xa3\x94\x2d\x52\x5e\x2e\x5d\x2b\x17\xac\x97\xb2\x99\x13\x0b\x00\
\x81\x7f\x49\xcf\xec\x6d\xbd\x8c\xa1\x37\x97\x13\x31\xc2\x5b\xeb\
\x71\x35\x49\x2a\x6f\xe3\xaf\xd9\x6c\x4f\x87\x99\x9a\x09\x51\x4c\
\x44\x28\xaf\x94\xba\xec\x5c\xf1\x4b\xe0\x05\x00\x0d\xe0\xb9\x83\
\x9f\xbd\x1f\x8e\x9b\xbb\x2a\x51\x13\xbd\x21\xc9\x72\x2c\xca\xa2\
\x34\xb0\x0d\x83\x57\x9a\x0a\xbc\xdd\xbd\x91\x37\xf7\x47\x29\xeb\
\x92\xb2\x26\xf1\x0d\xfd\xf9\xc7\x7b\x3e\x3d\xba\x0e\x50\x4a\xbd\
\xa5\x4c\x83\xbc\x2f\x98\x29\x56\xb9\x97\xb3\xf1\x1c\x97\x87\x8a\
\x19\xda\x5a\xb6\xe0\x54\x3c\x3e\x3c\x7d\x19\x19\x0a\x12\x08\x07\
\x09\x45\x43\x6c\x4e\x27\x8f\x02\x52\x7e\xf2\x85\x1f\x74\xd1\xfa\
\xdc\xa8\x29\xcb\x86\x41\x09\x0d\x21\x04\xca\xab\xd1\x9a\x9f\xa0\
\x65\x73\x8a\x64\x62\x03\xb6\x2f\xd8\x12\x5a\x65\xa6\x60\xd0\xb9\
\xbd\x8e\x7c\xde\x4a\xae\x2e\x5b\xfd\x32\x1c\xdf\xd7\x11\xab\x8f\
\xbd\x6b\xc9\x00\x89\xfa\x18\x15\x25\x40\x00\x5e\x95\x03\x8d\x3e\
\xe7\xcf\x0f\x50\x75\x3d\x52\x11\xf8\xfe\xea\x38\x76\x30\x4d\x3e\
\x67\xe1\x58\x15\xf9\xfb\xe8\xec\xc5\x00\xb0\xe8\x2b\x85\xf4\x6b\
\xd4\x5c\x8f\xaa\x5f\x26\x20\x7c\x8e\x34\xdc\x63\xfa\xaf\x39\x82\
\x41\x93\xdf\xae\x8f\x73\x6b\x36\x47\xac\xe3\x75\xf4\x95\x0a\xe5\
\x8a\x47\x50\x13\x58\x4e\x75\x41\x28\xa5\x78\xe4\xc9\x8f\xe7\x65\
\x6a\xc3\xa6\x64\xd3\x46\xea\x53\x11\x0e\x6f\x5b\xe4\xe7\x1f\xbe\
\xc3\x4c\x34\x30\x56\x6a\x24\x5c\xb7\x0d\x21\x4c\x22\x02\x7c\xc7\
\x45\x54\x5c\xe6\xee\xe4\x17\xa6\x7e\x7c\xa7\x51\x03\x90\x1a\x23\
\xca\xa9\xa2\x1c\x8b\x43\x4d\x77\xb9\xf4\xf5\x57\xa4\x1a\xb7\x72\
\xb3\xb6\x93\x58\x43\x07\x42\x85\x50\xae\x47\x22\x24\x89\x85\x24\
\xf3\x8b\x45\x6a\xbe\x1a\x5e\x5f\xa1\xb0\x54\x3c\xd6\xb8\xc9\x28\
\xbd\xd6\x59\x60\xe0\xdc\x19\x76\x76\xee\xe1\x97\xf9\x26\xa4\x4c\
\x10\xf4\x7d\x52\x66\x80\x96\xfa\x30\xb9\x6c\x89\xbf\x67\x72\x08\
\x4d\x5b\xf3\x2b\xd5\xe3\xeb\x47\xfa\xbc\xef\xd1\xd8\xe4\xe4\x64\
\xe4\xec\xd9\x6f\x38\x70\xf0\x30\xc3\xd3\x09\xda\x5b\x5a\x59\xb3\
\xaa\xe8\x52\xb0\xba\x62\x31\x93\xb7\x30\x0c\x1d\x2d\x1a\xc6\x5b\
\x2e\x1d\x9b\x1e\x79\x2f\x03\x20\xdb\xda\xda\x76\x58\x96\xf5\xeb\
\x95\x2b\xdf\x9a\xfb\xf6\xee\xf7\x87\x33\x75\x56\xfc\xe1\xc7\x0c\
\x57\x68\x24\x92\x26\x79\xdb\x67\xb5\x26\xd0\x93\x71\x64\x48\xcf\
\xfb\x6b\xf6\x1b\x7f\x5e\xec\x3d\xb7\x2e\x50\x3a\x9d\x3e\x1e\x8f\
\xc7\x2f\xec\xde\xbd\xe7\xd9\xc1\xc1\xc1\x97\xa7\x67\x9b\x3f\x28\
\xd9\x6e\xcd\xae\xa1\x2d\x59\x6e\xac\xe2\xab\x4a\xc2\xd4\x6e\xe9\
\xae\x7b\x49\xdd\x5d\x7a\xf5\xfa\x85\xde\xb1\xff\xd8\xd8\xdd\xdd\
\xdd\xde\xd3\xd3\x73\x7a\x74\x74\xf4\xd4\xd0\xd0\xd0\x80\x10\x22\
\x05\xec\x00\x76\x01\x5d\x40\x1c\xf8\x03\x98\x00\xc6\x80\x3b\xea\
\x3e\x85\xff\x01\xeb\xf9\x7f\xc7\xb1\xde\x54\x6d\x00\x00\x00\x00\
\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x03\xb6\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x37\x5c\x00\x00\x37\x5c\
\x01\xcb\xc7\xa4\xb9\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\
\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x03\x28\x49\x44\x41\x54\x78\
\xda\x75\x92\x5b\x48\x93\x61\x18\xc7\xff\xdf\x3e\xf2\xd8\xb9\x70\
\x98\x41\x75\x63\x45\x46\x84\xdd\x74\x22\x0c\xea\x22\xa2\xc3\x45\
\x17\x19\xd9\x41\xd3\x9d\x9c\x3b\x1f\xdc\xd1\x22\x2d\x6d\x6b\xe5\
\x37\x91\x8a\x72\xd3\xcd\x39\x4f\xe5\x74\x82\xe6\x66\x90\xb9\x42\
\x8b\x0a\x5a\xd8\x61\xe4\x5d\x4a\x12\x23\x3a\xd8\xe1\xed\x5d\x48\
\x10\xb1\x1f\xfc\xee\xde\xff\xf3\x3e\xfc\x79\x90\x0c\x8f\xb7\x05\
\x07\x0f\x1d\x80\xcb\xd5\x04\xce\x59\xcf\xd8\x2f\xdb\x20\x91\x88\
\x37\xf8\xdb\xfd\x8d\x43\x43\x83\xb7\x3c\xde\xe6\x1d\x4f\x9f\x3d\
\x41\x52\x9c\x0d\x1c\x14\x4a\x19\xca\x04\x67\x98\xcd\xf9\x9b\xb0\
\x73\xd7\x76\x7e\x28\x34\x34\x19\x8f\xc7\x49\x9b\xdf\xf7\xc9\x5a\
\x65\x36\xbc\x8d\xbd\x41\x52\xba\xbb\xbb\x50\x2e\x95\xd0\x21\x72\
\xb6\xb8\xe4\x14\x84\x22\x41\xf1\xf8\xe3\x31\x32\x35\xf5\xfe\xb3\
\xc5\x62\x5e\x5b\x77\xa9\x16\xd7\xae\x5f\x63\xfe\x0b\xce\xcc\x7c\
\x40\x38\x1c\x46\xe4\x61\x04\xaf\xdf\x4c\xc0\xd7\xe6\xe5\x95\x9c\
\x39\x89\x7a\xee\x4a\x5f\x4f\xe0\x0e\x99\x9e\x9e\x22\xde\x56\x4f\
\x51\x30\x18\x44\x8b\xc7\x9d\xfb\x4f\x78\xf8\x5e\x08\x09\x94\x6a\
\x15\x0d\xd4\xa3\xa3\xb3\x9d\x9d\x98\x78\x89\x47\x8f\x22\x9b\x9a\
\x5b\xdc\xdf\x04\x62\xf1\x8f\x50\x38\xf4\xab\xb3\xab\x63\xe6\xf6\
\x9d\xee\x57\x2e\x77\x53\xeb\xdf\x70\x6d\x5d\x0d\x2d\xeb\x0a\x2d\
\xcf\x0d\x9b\xfd\x42\xa2\x38\x36\xfa\x32\x8a\xb1\xb1\x31\xfe\x68\
\x64\x74\xa4\xcd\xef\x27\x47\x8e\x16\xfe\xe4\x1a\x1a\x7e\x86\xc2\
\x43\xc4\x6e\xb7\xbd\x16\x89\x45\xab\x90\x40\xae\xac\x80\x4a\xa3\
\x80\x46\xa7\x82\x5c\x21\xc5\xd9\x73\x55\x6c\xa0\x2f\x80\xf0\x70\
\x68\xab\x5c\x21\x8f\xe5\x6f\xc9\x27\x03\x83\x03\xd3\xd5\x35\xd5\
\xbe\x8b\xb5\x17\x6b\x9c\x4e\xae\x2c\x8b\x9f\x95\x95\x96\x96\x0a\
\x58\xaa\x4c\xd0\x1b\xb4\x30\x9a\xf4\x74\x75\x39\x23\x10\x96\xf1\
\x8e\x17\x15\xd1\x2d\xea\x04\x87\x0e\x1f\xfc\x92\xbd\x22\x9b\x88\
\x25\xe2\x17\x8f\x9f\x8c\xe7\xce\xce\x7e\xc5\x83\xd1\x11\xa6\xbf\
\x3f\x88\xc1\xbb\x83\xb0\x5a\xad\x0c\x08\x21\x18\x89\xdc\x87\x5a\
\xab\xe4\xd9\x1c\x56\x28\x54\xe5\x69\x6a\x8d\xf2\xc6\x9e\xbd\x7b\
\x48\xce\xca\x1c\x42\x07\x8e\xc7\xe3\x1f\xb3\x13\xef\xcc\x56\x2b\
\xeb\x6e\x76\x53\x5d\x6c\xde\xc6\x3c\x66\xdb\xb6\xad\xc0\xf1\xa2\
\x63\xa8\x34\x6a\x59\xa1\xb8\x14\xa7\x4b\x4e\xac\x91\x2b\x65\x0f\
\x0b\x8f\x15\x92\x82\xdd\x05\xf4\x67\xd1\xe8\x8b\xe8\xf3\x65\x84\
\x7c\x47\x57\x77\x27\x2f\xd8\xdf\x47\x8b\x1e\xc6\xbb\xc9\x49\x70\
\x9c\x03\x7f\x30\x59\x0c\x3c\xa5\x5a\x06\x71\xb9\x70\x9f\x4e\xaf\
\x99\x36\x18\x0d\x44\x28\x12\x12\xa5\x5a\x71\xaf\xa7\xb7\x6b\x51\
\x6c\x32\x8a\x26\xd7\x4d\xde\x8d\x9b\xd7\x41\x5b\x47\x5b\xbb\x0f\
\x81\x9e\x0e\xfc\xa5\xa0\x60\x37\xa3\x50\xc9\x2e\xd0\x43\x21\x15\
\xb2\x8a\x59\xa3\xc9\x48\x2a\x8d\xba\xbb\xe7\xce\x9b\xe7\x57\xd7\
\xe9\x60\x77\x5c\x62\xec\x0e\x1b\x38\xe7\x55\x7a\x38\x8d\x88\xc5\
\xa2\xf8\x07\x5d\xa5\xda\x68\x30\xe9\x34\x15\x32\x69\xa8\xb8\xa4\
\x98\x68\xf5\xea\x9e\x52\xc1\xc9\x74\xad\xd4\x0b\x81\xa8\x94\x07\
\x4a\x66\x66\x26\x92\x62\xb6\x18\x3c\xad\x3e\xcf\x3c\xbd\x41\xc3\
\xe9\xf4\xea\xde\x8f\x5f\x26\x98\x8e\x40\x23\xea\x9d\x0e\x34\xb7\
\x34\x25\x4a\xfe\x63\x32\xe8\x06\x9a\xfd\xd4\x5e\x89\x54\x74\x7e\
\xf5\x9a\x55\xf3\xd3\xd3\xd3\x17\xa7\xa4\xa6\x2c\x07\xb0\x94\xba\
\x84\xba\x88\xba\x80\x9a\x41\x4d\xa3\xa6\x50\x59\x2a\x83\x04\xeb\
\xd7\xaf\x43\xee\xda\xdc\x05\xa9\x94\x8c\x8c\x0c\x3e\xcb\xb2\x39\
\x00\xb2\xe7\xe4\x53\x97\xcf\x0d\x5a\x48\xcd\x9c\x1b\x32\x8f\xca\
\x03\xe5\x37\x40\x64\x67\x7f\x6c\xb6\xdc\xf4\x00\x00\x00\x22\x7a\
\x54\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\x00\x00\x78\xda\x2b\
\x2f\x2f\xd7\xcb\xcc\xcb\x2e\x4e\x4e\x2c\x48\xd5\xcb\x2f\x4a\x07\
\x00\x36\xd8\x06\x58\x10\x53\xca\x5c\x00\x00\x00\x00\x49\x45\x4e\
\x44\xae\x42\x60\x82\
"
qt_resource_name = "\
\x00\x05\
\x00\x6f\xa6\x53\
\x00\x69\
\x00\x63\x00\x6f\x00\x6e\x00\x73\
\x00\x0e\
\x06\x0c\xe6\x07\
\x00\x61\
\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x09\
\x06\xc7\x98\x67\
\x00\x61\
\x00\x62\x00\x6f\x00\x75\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x0b\x63\x58\x07\
\x00\x73\
\x00\x74\x00\x6f\x00\x70\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x0c\xac\x40\xd6\
\x00\x62\
\x00\x75\x00\x73\x00\x79\x00\x2e\x00\x67\x00\x69\x00\x66\
\x00\x08\
\x0f\x07\x5a\xc7\
\x00\x65\
\x00\x78\x00\x69\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x07\
\x08\x73\x57\x87\
\x00\x61\
\x00\x70\x00\x70\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x09\
\x08\x97\xa2\x07\
\x00\x73\
\x00\x74\x00\x61\x00\x72\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x06\x7c\x5a\x07\
\x00\x63\
\x00\x6f\x00\x70\x00\x79\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x08\xc8\x58\x67\
\x00\x73\
\x00\x61\x00\x76\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x09\
\x0b\x85\x83\x07\
\x00\x63\
\x00\x6c\x00\x65\x00\x61\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0a\
\x09\xb2\x67\xc7\
\x00\x63\
\x00\x61\x00\x6e\x00\x63\x00\x65\x00\x6c\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0a\
\x00\x4a\x9d\x27\
\x00\x6f\
\x00\x6e\x00\x6c\x00\x69\x00\x6e\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x0c\x33\x5a\x87\
\x00\x68\
\x00\x65\x00\x6c\x00\x70\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0b\
\x06\xba\xa1\x47\
\x00\x6f\
\x00\x70\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x73\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0f\
\x0e\x5e\x99\xe7\
\x00\x70\
\x00\x72\x00\x65\x00\x66\x00\x65\x00\x72\x00\x65\x00\x6e\x00\x63\x00\x65\x00\x73\x00\x2e\x00\x70\x00\x6e\x00\x67\
"
qt_resource_struct = "\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0f\x00\x00\x00\x02\
\x00\x00\x01\x16\x00\x00\x00\x00\x00\x01\x00\x00\x20\xac\
\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x01\x00\x00\x16\x1a\
\x00\x00\x01\x46\x00\x00\x00\x00\x00\x01\x00\x00\x26\xc0\
\x00\x00\x00\x32\x00\x00\x00\x00\x00\x01\x00\x00\x01\xc0\
\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x0f\xe0\
\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x14\x21\
\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x18\x03\
\x00\x00\x00\xfc\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xd6\
\x00\x00\x00\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x04\xe7\
\x00\x00\x00\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x4e\
\x00\x00\x01\x30\x00\x00\x00\x00\x00\x01\x00\x00\x24\x10\
\x00\x00\x00\x60\x00\x00\x00\x00\x00\x01\x00\x00\x06\xde\
\x00\x00\x01\x62\x00\x00\x00\x00\x00\x01\x00\x00\x2a\x8d\
\x00\x00\x00\x76\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x92\
"
def qInitResources():
QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()

View file

@ -1,43 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/debug.ui'
#
# Created: Fri Feb 28 21:24:59 2014
# by: PyQt4 UI code generator 4.9.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_DebugDialog(object):
def setupUi(self, DebugDialog):
DebugDialog.setObjectName(_fromUtf8("DebugDialog"))
DebugDialog.setWindowModality(QtCore.Qt.ApplicationModal)
DebugDialog.resize(564, 547)
self.verticalLayout = QtGui.QVBoxLayout(DebugDialog)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.frame = QtGui.QFrame(DebugDialog)
self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame.setFrameShadow(QtGui.QFrame.Raised)
self.frame.setObjectName(_fromUtf8("frame"))
self.verticalLayout_2 = QtGui.QVBoxLayout(self.frame)
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.textEdit = QtGui.QPlainTextEdit(self.frame)
self.textEdit.setUndoRedoEnabled(False)
self.textEdit.setReadOnly(True)
self.textEdit.setPlainText(_fromUtf8(""))
self.textEdit.setObjectName(_fromUtf8("textEdit"))
self.verticalLayout_2.addWidget(self.textEdit)
self.verticalLayout.addWidget(self.frame)
self.retranslateUi(DebugDialog)
QtCore.QMetaObject.connectSlotsByName(DebugDialog)
def retranslateUi(self, DebugDialog):
DebugDialog.setWindowTitle(_("LinkChecker debug log"))

View file

@ -1,60 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/editor.ui'
#
# Created: Mon Dec 12 19:00:37 2011
# by: PyQt4 UI code generator 4.8.6
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_EditorDialog(object):
def setupUi(self, EditorDialog):
EditorDialog.setObjectName(_fromUtf8("EditorDialog"))
EditorDialog.setWindowModality(QtCore.Qt.ApplicationModal)
EditorDialog.resize(640, 600)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(EditorDialog.sizePolicy().hasHeightForWidth())
EditorDialog.setSizePolicy(sizePolicy)
EditorDialog.setWindowTitle(_("LinkChecker source view"))
self.verticalLayout = QtGui.QVBoxLayout(EditorDialog)
self.verticalLayout.setMargin(0)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.menubar = QtGui.QMenuBar(EditorDialog)
self.menubar.setObjectName(_fromUtf8("menubar"))
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setTitle(_("&File"))
self.menuFile.setObjectName(_fromUtf8("menuFile"))
self.verticalLayout.addWidget(self.menubar)
self.frame = QtGui.QFrame(EditorDialog)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
self.frame.setSizePolicy(sizePolicy)
self.frame.setFrameShape(QtGui.QFrame.NoFrame)
self.frame.setFrameShadow(QtGui.QFrame.Plain)
self.frame.setLineWidth(0)
self.frame.setObjectName(_fromUtf8("frame"))
self.verticalLayout.addWidget(self.frame)
self.actionSave = QtGui.QAction(EditorDialog)
self.actionSave.setText(_("&Save"))
self.actionSave.setShortcut(_("Ctrl+S"))
self.actionSave.setObjectName(_fromUtf8("actionSave"))
self.menuFile.addAction(self.actionSave)
self.menubar.addAction(self.menuFile.menuAction())
self.retranslateUi(EditorDialog)
QtCore.QMetaObject.connectSlotsByName(EditorDialog)
def retranslateUi(self, EditorDialog):
pass

View file

@ -1,844 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/main.ui'
#
# Created: Fri Feb 28 21:24:58 2014
# by: PyQt4 UI code generator 4.9.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(713, 627)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/app.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
MainWindow.setStatusTip(_fromUtf8(""))
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout.setMargin(4)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.horizontalLayout_3 = QtGui.QHBoxLayout()
self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
self.label = QtGui.QLabel(self.centralwidget)
self.label.setObjectName(_fromUtf8("label"))
self.horizontalLayout_3.addWidget(self.label)
spacerItem = QtGui.QSpacerItem(4, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem)
self.urlinput = LineEdit(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(1)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.urlinput.sizePolicy().hasHeightForWidth())
self.urlinput.setSizePolicy(sizePolicy)
self.urlinput.setMaxLength(2048)
self.urlinput.setObjectName(_fromUtf8("urlinput"))
self.horizontalLayout_3.addWidget(self.urlinput)
spacerItem1 = QtGui.QSpacerItem(10, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem1)
self.controlButton = QtGui.QPushButton(self.centralwidget)
self.controlButton.setStatusTip(_fromUtf8(""))
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/start.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.controlButton.setIcon(icon1)
self.controlButton.setDefault(True)
self.controlButton.setObjectName(_fromUtf8("controlButton"))
self.horizontalLayout_3.addWidget(self.controlButton)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.horizontalLayout_4 = QtGui.QHBoxLayout()
self.horizontalLayout_4.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint)
self.horizontalLayout_4.setContentsMargins(0, 0, -1, -1)
self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4"))
self.label_29 = QtGui.QLabel(self.centralwidget)
self.label_29.setObjectName(_fromUtf8("label_29"))
self.horizontalLayout_4.addWidget(self.label_29)
self.label_32 = QtGui.QLabel(self.centralwidget)
self.label_32.setObjectName(_fromUtf8("label_32"))
self.horizontalLayout_4.addWidget(self.label_32)
self.label_active = QtGui.QLabel(self.centralwidget)
self.label_active.setMinimumSize(QtCore.QSize(40, 0))
self.label_active.setObjectName(_fromUtf8("label_active"))
self.horizontalLayout_4.addWidget(self.label_active)
self.label_30 = QtGui.QLabel(self.centralwidget)
self.label_30.setObjectName(_fromUtf8("label_30"))
self.horizontalLayout_4.addWidget(self.label_30)
self.label_queued = QtGui.QLabel(self.centralwidget)
self.label_queued.setMinimumSize(QtCore.QSize(40, 0))
self.label_queued.setObjectName(_fromUtf8("label_queued"))
self.horizontalLayout_4.addWidget(self.label_queued)
self.label_28 = QtGui.QLabel(self.centralwidget)
self.label_28.setObjectName(_fromUtf8("label_28"))
self.horizontalLayout_4.addWidget(self.label_28)
self.label_checked = QtGui.QLabel(self.centralwidget)
self.label_checked.setMinimumSize(QtCore.QSize(50, 0))
self.label_checked.setObjectName(_fromUtf8("label_checked"))
self.horizontalLayout_4.addWidget(self.label_checked)
self.label_15 = QtGui.QLabel(self.centralwidget)
self.label_15.setObjectName(_fromUtf8("label_15"))
self.horizontalLayout_4.addWidget(self.label_15)
self.label_busy = QtGui.QLabel(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(16)
sizePolicy.setVerticalStretch(16)
sizePolicy.setHeightForWidth(self.label_busy.sizePolicy().hasHeightForWidth())
self.label_busy.setSizePolicy(sizePolicy)
self.label_busy.setMinimumSize(QtCore.QSize(16, 16))
self.label_busy.setObjectName(_fromUtf8("label_busy"))
self.horizontalLayout_4.addWidget(self.label_busy)
self.label_status = QtGui.QLabel(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_status.sizePolicy().hasHeightForWidth())
self.label_status.setSizePolicy(sizePolicy)
self.label_status.setText(_fromUtf8(""))
self.label_status.setObjectName(_fromUtf8("label_status"))
self.horizontalLayout_4.addWidget(self.label_status)
self.verticalLayout.addLayout(self.horizontalLayout_4)
self.treeView = QtGui.QTreeView(self.centralwidget)
self.treeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.treeView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.treeView.setAlternatingRowColors(True)
self.treeView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.treeView.setRootIsDecorated(False)
self.treeView.setUniformRowHeights(True)
self.treeView.setItemsExpandable(False)
self.treeView.setSortingEnabled(False)
self.treeView.setAllColumnsShowFocus(True)
self.treeView.setExpandsOnDoubleClick(False)
self.treeView.setObjectName(_fromUtf8("treeView"))
self.verticalLayout.addWidget(self.treeView)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.url_properties = QtGui.QGroupBox(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.url_properties.sizePolicy().hasHeightForWidth())
self.url_properties.setSizePolicy(sizePolicy)
self.url_properties.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.url_properties.setObjectName(_fromUtf8("url_properties"))
self.horizontalLayout_2 = QtGui.QHBoxLayout(self.url_properties)
self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
self.frame = QtGui.QFrame(self.url_properties)
self.frame.setFrameShape(QtGui.QFrame.NoFrame)
self.frame.setFrameShadow(QtGui.QFrame.Plain)
self.frame.setLineWidth(0)
self.frame.setObjectName(_fromUtf8("frame"))
self.formLayout = QtGui.QFormLayout(self.frame)
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label_2 = QtGui.QLabel(self.frame)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
self.prop_url = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_url.sizePolicy().hasHeightForWidth())
self.prop_url.setSizePolicy(sizePolicy)
self.prop_url.setMinimumSize(QtCore.QSize(300, 0))
self.prop_url.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_url.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_url.setText(_fromUtf8(""))
self.prop_url.setTextFormat(QtCore.Qt.RichText)
self.prop_url.setOpenExternalLinks(True)
self.prop_url.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_url.setObjectName(_fromUtf8("prop_url"))
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.prop_url)
self.label_3 = QtGui.QLabel(self.frame)
self.label_3.setObjectName(_fromUtf8("label_3"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_3)
self.prop_name = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_name.sizePolicy().hasHeightForWidth())
self.prop_name.setSizePolicy(sizePolicy)
self.prop_name.setMinimumSize(QtCore.QSize(300, 0))
self.prop_name.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_name.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_name.setText(_fromUtf8(""))
self.prop_name.setTextFormat(QtCore.Qt.PlainText)
self.prop_name.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_name.setObjectName(_fromUtf8("prop_name"))
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.prop_name)
self.label_4 = QtGui.QLabel(self.frame)
self.label_4.setObjectName(_fromUtf8("label_4"))
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_4)
self.prop_parenturl = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_parenturl.sizePolicy().hasHeightForWidth())
self.prop_parenturl.setSizePolicy(sizePolicy)
self.prop_parenturl.setMinimumSize(QtCore.QSize(300, 0))
self.prop_parenturl.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_parenturl.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_parenturl.setText(_fromUtf8(""))
self.prop_parenturl.setTextFormat(QtCore.Qt.RichText)
self.prop_parenturl.setOpenExternalLinks(True)
self.prop_parenturl.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_parenturl.setObjectName(_fromUtf8("prop_parenturl"))
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.prop_parenturl)
self.label_5 = QtGui.QLabel(self.frame)
self.label_5.setObjectName(_fromUtf8("label_5"))
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_5)
self.prop_base = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_base.sizePolicy().hasHeightForWidth())
self.prop_base.setSizePolicy(sizePolicy)
self.prop_base.setMinimumSize(QtCore.QSize(300, 0))
self.prop_base.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_base.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_base.setText(_fromUtf8(""))
self.prop_base.setTextFormat(QtCore.Qt.RichText)
self.prop_base.setOpenExternalLinks(False)
self.prop_base.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_base.setObjectName(_fromUtf8("prop_base"))
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.prop_base)
self.label_7 = QtGui.QLabel(self.frame)
self.label_7.setObjectName(_fromUtf8("label_7"))
self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_7)
self.prop_checktime = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_checktime.sizePolicy().hasHeightForWidth())
self.prop_checktime.setSizePolicy(sizePolicy)
self.prop_checktime.setMinimumSize(QtCore.QSize(300, 0))
self.prop_checktime.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_checktime.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_checktime.setText(_fromUtf8(""))
self.prop_checktime.setTextFormat(QtCore.Qt.PlainText)
self.prop_checktime.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_checktime.setObjectName(_fromUtf8("prop_checktime"))
self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.prop_checktime)
self.label_8 = QtGui.QLabel(self.frame)
self.label_8.setObjectName(_fromUtf8("label_8"))
self.formLayout.setWidget(5, QtGui.QFormLayout.LabelRole, self.label_8)
self.prop_dltime = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_dltime.sizePolicy().hasHeightForWidth())
self.prop_dltime.setSizePolicy(sizePolicy)
self.prop_dltime.setMinimumSize(QtCore.QSize(300, 0))
self.prop_dltime.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_dltime.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_dltime.setText(_fromUtf8(""))
self.prop_dltime.setTextFormat(QtCore.Qt.PlainText)
self.prop_dltime.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_dltime.setObjectName(_fromUtf8("prop_dltime"))
self.formLayout.setWidget(5, QtGui.QFormLayout.FieldRole, self.prop_dltime)
self.label_9 = QtGui.QLabel(self.frame)
self.label_9.setObjectName(_fromUtf8("label_9"))
self.formLayout.setWidget(6, QtGui.QFormLayout.LabelRole, self.label_9)
self.prop_size = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_size.sizePolicy().hasHeightForWidth())
self.prop_size.setSizePolicy(sizePolicy)
self.prop_size.setMinimumSize(QtCore.QSize(300, 0))
self.prop_size.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_size.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_size.setText(_fromUtf8(""))
self.prop_size.setTextFormat(QtCore.Qt.PlainText)
self.prop_size.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_size.setObjectName(_fromUtf8("prop_size"))
self.formLayout.setWidget(6, QtGui.QFormLayout.FieldRole, self.prop_size)
self.label_10 = QtGui.QLabel(self.frame)
self.label_10.setObjectName(_fromUtf8("label_10"))
self.formLayout.setWidget(8, QtGui.QFormLayout.LabelRole, self.label_10)
self.prop_info = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_info.sizePolicy().hasHeightForWidth())
self.prop_info.setSizePolicy(sizePolicy)
self.prop_info.setMinimumSize(QtCore.QSize(300, 0))
self.prop_info.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_info.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_info.setText(_fromUtf8(""))
self.prop_info.setTextFormat(QtCore.Qt.PlainText)
self.prop_info.setWordWrap(True)
self.prop_info.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_info.setObjectName(_fromUtf8("prop_info"))
self.formLayout.setWidget(8, QtGui.QFormLayout.FieldRole, self.prop_info)
self.label_11 = QtGui.QLabel(self.frame)
self.label_11.setObjectName(_fromUtf8("label_11"))
self.formLayout.setWidget(9, QtGui.QFormLayout.LabelRole, self.label_11)
self.prop_warning = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_warning.sizePolicy().hasHeightForWidth())
self.prop_warning.setSizePolicy(sizePolicy)
self.prop_warning.setMinimumSize(QtCore.QSize(300, 0))
self.prop_warning.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_warning.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_warning.setText(_fromUtf8(""))
self.prop_warning.setTextFormat(QtCore.Qt.PlainText)
self.prop_warning.setScaledContents(True)
self.prop_warning.setWordWrap(True)
self.prop_warning.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_warning.setObjectName(_fromUtf8("prop_warning"))
self.formLayout.setWidget(9, QtGui.QFormLayout.FieldRole, self.prop_warning)
self.label_12 = QtGui.QLabel(self.frame)
self.label_12.setObjectName(_fromUtf8("label_12"))
self.formLayout.setWidget(10, QtGui.QFormLayout.LabelRole, self.label_12)
self.prop_result = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_result.sizePolicy().hasHeightForWidth())
self.prop_result.setSizePolicy(sizePolicy)
self.prop_result.setMinimumSize(QtCore.QSize(300, 0))
self.prop_result.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_result.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_result.setText(_fromUtf8(""))
self.prop_result.setTextFormat(QtCore.Qt.PlainText)
self.prop_result.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_result.setObjectName(_fromUtf8("prop_result"))
self.formLayout.setWidget(10, QtGui.QFormLayout.FieldRole, self.prop_result)
self.label_16 = QtGui.QLabel(self.frame)
self.label_16.setObjectName(_fromUtf8("label_16"))
self.formLayout.setWidget(7, QtGui.QFormLayout.LabelRole, self.label_16)
self.prop_modified = QtGui.QLabel(self.frame)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prop_modified.sizePolicy().hasHeightForWidth())
self.prop_modified.setSizePolicy(sizePolicy)
self.prop_modified.setMinimumSize(QtCore.QSize(300, 0))
self.prop_modified.setFrameShape(QtGui.QFrame.StyledPanel)
self.prop_modified.setFrameShadow(QtGui.QFrame.Sunken)
self.prop_modified.setText(_fromUtf8(""))
self.prop_modified.setTextFormat(QtCore.Qt.PlainText)
self.prop_modified.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.prop_modified.setObjectName(_fromUtf8("prop_modified"))
self.formLayout.setWidget(7, QtGui.QFormLayout.FieldRole, self.prop_modified)
self.horizontalLayout_2.addWidget(self.frame)
self.horizontalLayout.addWidget(self.url_properties)
self.statistics = QtGui.QFrame(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.statistics.sizePolicy().hasHeightForWidth())
self.statistics.setSizePolicy(sizePolicy)
self.statistics.setLineWidth(0)
self.statistics.setObjectName(_fromUtf8("statistics"))
self.verticalLayout_2 = QtGui.QVBoxLayout(self.statistics)
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.groupBox = QtGui.QGroupBox(self.statistics)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth())
self.groupBox.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.groupBox.setFont(font)
self.groupBox.setObjectName(_fromUtf8("groupBox"))
self.gridLayout = QtGui.QGridLayout(self.groupBox)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.label_24 = QtGui.QLabel(self.groupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_24.sizePolicy().hasHeightForWidth())
self.label_24.setSizePolicy(sizePolicy)
self.label_24.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_24.setObjectName(_fromUtf8("label_24"))
self.gridLayout.addWidget(self.label_24, 0, 0, 1, 1)
self.stats_valid_urls = QtGui.QLabel(self.groupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_valid_urls.sizePolicy().hasHeightForWidth())
self.stats_valid_urls.setSizePolicy(sizePolicy)
self.stats_valid_urls.setMinimumSize(QtCore.QSize(30, 0))
self.stats_valid_urls.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_valid_urls.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_valid_urls.setText(_fromUtf8(""))
self.stats_valid_urls.setTextFormat(QtCore.Qt.RichText)
self.stats_valid_urls.setOpenExternalLinks(True)
self.stats_valid_urls.setObjectName(_fromUtf8("stats_valid_urls"))
self.gridLayout.addWidget(self.stats_valid_urls, 0, 1, 1, 1)
self.label_26 = QtGui.QLabel(self.groupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_26.sizePolicy().hasHeightForWidth())
self.label_26.setSizePolicy(sizePolicy)
self.label_26.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_26.setObjectName(_fromUtf8("label_26"))
self.gridLayout.addWidget(self.label_26, 0, 2, 1, 1)
self.stats_warnings = QtGui.QLabel(self.groupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_warnings.sizePolicy().hasHeightForWidth())
self.stats_warnings.setSizePolicy(sizePolicy)
self.stats_warnings.setMinimumSize(QtCore.QSize(30, 0))
self.stats_warnings.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_warnings.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_warnings.setText(_fromUtf8(""))
self.stats_warnings.setTextFormat(QtCore.Qt.RichText)
self.stats_warnings.setOpenExternalLinks(True)
self.stats_warnings.setObjectName(_fromUtf8("stats_warnings"))
self.gridLayout.addWidget(self.stats_warnings, 0, 3, 1, 1)
self.label_25 = QtGui.QLabel(self.groupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_25.sizePolicy().hasHeightForWidth())
self.label_25.setSizePolicy(sizePolicy)
self.label_25.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_25.setObjectName(_fromUtf8("label_25"))
self.gridLayout.addWidget(self.label_25, 1, 0, 1, 1)
self.stats_invalid_urls = QtGui.QLabel(self.groupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_invalid_urls.sizePolicy().hasHeightForWidth())
self.stats_invalid_urls.setSizePolicy(sizePolicy)
self.stats_invalid_urls.setMinimumSize(QtCore.QSize(30, 0))
self.stats_invalid_urls.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_invalid_urls.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_invalid_urls.setText(_fromUtf8(""))
self.stats_invalid_urls.setTextFormat(QtCore.Qt.RichText)
self.stats_invalid_urls.setOpenExternalLinks(True)
self.stats_invalid_urls.setObjectName(_fromUtf8("stats_invalid_urls"))
self.gridLayout.addWidget(self.stats_invalid_urls, 1, 1, 1, 1)
self.verticalLayout_2.addWidget(self.groupBox)
self.groupBox_3 = QtGui.QGroupBox(self.statistics)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth())
self.groupBox_3.setSizePolicy(sizePolicy)
self.groupBox_3.setObjectName(_fromUtf8("groupBox_3"))
self.gridLayout_2 = QtGui.QGridLayout(self.groupBox_3)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.label_6 = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_6.sizePolicy().hasHeightForWidth())
self.label_6.setSizePolicy(sizePolicy)
self.label_6.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_6.setObjectName(_fromUtf8("label_6"))
self.gridLayout_2.addWidget(self.label_6, 0, 0, 1, 1)
self.stats_content_image = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_content_image.sizePolicy().hasHeightForWidth())
self.stats_content_image.setSizePolicy(sizePolicy)
self.stats_content_image.setMinimumSize(QtCore.QSize(40, 0))
self.stats_content_image.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_content_image.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_content_image.setText(_fromUtf8(""))
self.stats_content_image.setTextFormat(QtCore.Qt.RichText)
self.stats_content_image.setOpenExternalLinks(True)
self.stats_content_image.setObjectName(_fromUtf8("stats_content_image"))
self.gridLayout_2.addWidget(self.stats_content_image, 0, 1, 1, 1)
self.label_13 = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_13.sizePolicy().hasHeightForWidth())
self.label_13.setSizePolicy(sizePolicy)
self.label_13.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_13.setObjectName(_fromUtf8("label_13"))
self.gridLayout_2.addWidget(self.label_13, 0, 2, 1, 1)
self.stats_content_text = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_content_text.sizePolicy().hasHeightForWidth())
self.stats_content_text.setSizePolicy(sizePolicy)
self.stats_content_text.setMinimumSize(QtCore.QSize(40, 0))
self.stats_content_text.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_content_text.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_content_text.setText(_fromUtf8(""))
self.stats_content_text.setTextFormat(QtCore.Qt.RichText)
self.stats_content_text.setOpenExternalLinks(True)
self.stats_content_text.setObjectName(_fromUtf8("stats_content_text"))
self.gridLayout_2.addWidget(self.stats_content_text, 0, 3, 1, 1)
self.label_27 = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_27.sizePolicy().hasHeightForWidth())
self.label_27.setSizePolicy(sizePolicy)
self.label_27.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_27.setObjectName(_fromUtf8("label_27"))
self.gridLayout_2.addWidget(self.label_27, 0, 4, 1, 1)
self.stats_content_application = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_content_application.sizePolicy().hasHeightForWidth())
self.stats_content_application.setSizePolicy(sizePolicy)
self.stats_content_application.setMinimumSize(QtCore.QSize(40, 0))
self.stats_content_application.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_content_application.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_content_application.setText(_fromUtf8(""))
self.stats_content_application.setTextFormat(QtCore.Qt.RichText)
self.stats_content_application.setOpenExternalLinks(True)
self.stats_content_application.setObjectName(_fromUtf8("stats_content_application"))
self.gridLayout_2.addWidget(self.stats_content_application, 0, 5, 1, 1)
self.label_17 = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_17.sizePolicy().hasHeightForWidth())
self.label_17.setSizePolicy(sizePolicy)
self.label_17.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_17.setObjectName(_fromUtf8("label_17"))
self.gridLayout_2.addWidget(self.label_17, 1, 0, 1, 1)
self.stats_content_audio = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_content_audio.sizePolicy().hasHeightForWidth())
self.stats_content_audio.setSizePolicy(sizePolicy)
self.stats_content_audio.setMinimumSize(QtCore.QSize(40, 0))
self.stats_content_audio.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_content_audio.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_content_audio.setText(_fromUtf8(""))
self.stats_content_audio.setTextFormat(QtCore.Qt.RichText)
self.stats_content_audio.setOpenExternalLinks(True)
self.stats_content_audio.setObjectName(_fromUtf8("stats_content_audio"))
self.gridLayout_2.addWidget(self.stats_content_audio, 1, 1, 1, 1)
self.label_21 = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_21.sizePolicy().hasHeightForWidth())
self.label_21.setSizePolicy(sizePolicy)
self.label_21.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_21.setObjectName(_fromUtf8("label_21"))
self.gridLayout_2.addWidget(self.label_21, 1, 2, 1, 1)
self.stats_content_video = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_content_video.sizePolicy().hasHeightForWidth())
self.stats_content_video.setSizePolicy(sizePolicy)
self.stats_content_video.setMinimumSize(QtCore.QSize(40, 0))
self.stats_content_video.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_content_video.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_content_video.setText(_fromUtf8(""))
self.stats_content_video.setTextFormat(QtCore.Qt.RichText)
self.stats_content_video.setOpenExternalLinks(True)
self.stats_content_video.setObjectName(_fromUtf8("stats_content_video"))
self.gridLayout_2.addWidget(self.stats_content_video, 1, 3, 1, 1)
self.stats_content_other = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_content_other.sizePolicy().hasHeightForWidth())
self.stats_content_other.setSizePolicy(sizePolicy)
self.stats_content_other.setMinimumSize(QtCore.QSize(40, 0))
self.stats_content_other.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_content_other.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_content_other.setText(_fromUtf8(""))
self.stats_content_other.setTextFormat(QtCore.Qt.RichText)
self.stats_content_other.setOpenExternalLinks(True)
self.stats_content_other.setObjectName(_fromUtf8("stats_content_other"))
self.gridLayout_2.addWidget(self.stats_content_other, 2, 5, 1, 1)
self.label_23 = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_23.sizePolicy().hasHeightForWidth())
self.label_23.setSizePolicy(sizePolicy)
self.label_23.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_23.setObjectName(_fromUtf8("label_23"))
self.gridLayout_2.addWidget(self.label_23, 2, 4, 1, 1)
self.stats_content_mail = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_content_mail.sizePolicy().hasHeightForWidth())
self.stats_content_mail.setSizePolicy(sizePolicy)
self.stats_content_mail.setMinimumSize(QtCore.QSize(40, 0))
self.stats_content_mail.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_content_mail.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_content_mail.setText(_fromUtf8(""))
self.stats_content_mail.setTextFormat(QtCore.Qt.RichText)
self.stats_content_mail.setOpenExternalLinks(True)
self.stats_content_mail.setObjectName(_fromUtf8("stats_content_mail"))
self.gridLayout_2.addWidget(self.stats_content_mail, 1, 5, 1, 1)
self.label_22 = QtGui.QLabel(self.groupBox_3)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_22.sizePolicy().hasHeightForWidth())
self.label_22.setSizePolicy(sizePolicy)
self.label_22.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_22.setObjectName(_fromUtf8("label_22"))
self.gridLayout_2.addWidget(self.label_22, 1, 4, 1, 1)
self.verticalLayout_2.addWidget(self.groupBox_3)
self.groupBox_2 = QtGui.QGroupBox(self.statistics)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth())
self.groupBox_2.setSizePolicy(sizePolicy)
self.groupBox_2.setObjectName(_fromUtf8("groupBox_2"))
self.gridLayout_3 = QtGui.QGridLayout(self.groupBox_2)
self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
self.label_18 = QtGui.QLabel(self.groupBox_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_18.sizePolicy().hasHeightForWidth())
self.label_18.setSizePolicy(sizePolicy)
self.label_18.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_18.setObjectName(_fromUtf8("label_18"))
self.gridLayout_3.addWidget(self.label_18, 0, 0, 1, 1)
self.stats_url_minlen = QtGui.QLabel(self.groupBox_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_url_minlen.sizePolicy().hasHeightForWidth())
self.stats_url_minlen.setSizePolicy(sizePolicy)
self.stats_url_minlen.setMinimumSize(QtCore.QSize(30, 0))
self.stats_url_minlen.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_url_minlen.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_url_minlen.setText(_fromUtf8(""))
self.stats_url_minlen.setTextFormat(QtCore.Qt.RichText)
self.stats_url_minlen.setOpenExternalLinks(True)
self.stats_url_minlen.setObjectName(_fromUtf8("stats_url_minlen"))
self.gridLayout_3.addWidget(self.stats_url_minlen, 0, 1, 1, 1)
self.label_20 = QtGui.QLabel(self.groupBox_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_20.sizePolicy().hasHeightForWidth())
self.label_20.setSizePolicy(sizePolicy)
self.label_20.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_20.setObjectName(_fromUtf8("label_20"))
self.gridLayout_3.addWidget(self.label_20, 0, 2, 1, 1)
self.stats_url_avglen = QtGui.QLabel(self.groupBox_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_url_avglen.sizePolicy().hasHeightForWidth())
self.stats_url_avglen.setSizePolicy(sizePolicy)
self.stats_url_avglen.setMinimumSize(QtCore.QSize(30, 0))
self.stats_url_avglen.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_url_avglen.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_url_avglen.setText(_fromUtf8(""))
self.stats_url_avglen.setTextFormat(QtCore.Qt.RichText)
self.stats_url_avglen.setOpenExternalLinks(True)
self.stats_url_avglen.setObjectName(_fromUtf8("stats_url_avglen"))
self.gridLayout_3.addWidget(self.stats_url_avglen, 0, 3, 1, 1)
self.label_19 = QtGui.QLabel(self.groupBox_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_19.sizePolicy().hasHeightForWidth())
self.label_19.setSizePolicy(sizePolicy)
self.label_19.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_19.setObjectName(_fromUtf8("label_19"))
self.gridLayout_3.addWidget(self.label_19, 1, 0, 1, 1)
self.stats_url_maxlen = QtGui.QLabel(self.groupBox_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stats_url_maxlen.sizePolicy().hasHeightForWidth())
self.stats_url_maxlen.setSizePolicy(sizePolicy)
self.stats_url_maxlen.setMinimumSize(QtCore.QSize(30, 0))
self.stats_url_maxlen.setFrameShape(QtGui.QFrame.StyledPanel)
self.stats_url_maxlen.setFrameShadow(QtGui.QFrame.Sunken)
self.stats_url_maxlen.setText(_fromUtf8(""))
self.stats_url_maxlen.setTextFormat(QtCore.Qt.RichText)
self.stats_url_maxlen.setOpenExternalLinks(True)
self.stats_url_maxlen.setObjectName(_fromUtf8("stats_url_maxlen"))
self.gridLayout_3.addWidget(self.stats_url_maxlen, 1, 1, 1, 1)
self.verticalLayout_2.addWidget(self.groupBox_2)
self.horizontalLayout.addWidget(self.statistics)
self.verticalLayout.addLayout(self.horizontalLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 713, 20))
self.menubar.setObjectName(_fromUtf8("menubar"))
self.menuEdit = QtGui.QMenu(self.menubar)
self.menuEdit.setObjectName(_fromUtf8("menuEdit"))
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setObjectName(_fromUtf8("menuFile"))
self.menuHelp = QtGui.QMenu(self.menubar)
self.menuHelp.setObjectName(_fromUtf8("menuHelp"))
MainWindow.setMenuBar(self.menubar)
self.statusBar = QtGui.QStatusBar(MainWindow)
self.statusBar.setObjectName(_fromUtf8("statusBar"))
MainWindow.setStatusBar(self.statusBar)
self.actionAbout = QtGui.QAction(MainWindow)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/about.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionAbout.setIcon(icon2)
self.actionAbout.setObjectName(_fromUtf8("actionAbout"))
self.actionHelp = QtGui.QAction(MainWindow)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/help.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionHelp.setIcon(icon3)
self.actionHelp.setObjectName(_fromUtf8("actionHelp"))
self.actionViewOnline = QtGui.QAction(MainWindow)
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/online.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionViewOnline.setIcon(icon4)
self.actionViewOnline.setObjectName(_fromUtf8("actionViewOnline"))
self.actionOptions = QtGui.QAction(MainWindow)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/preferences.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionOptions.setIcon(icon5)
self.actionOptions.setObjectName(_fromUtf8("actionOptions"))
self.actionCopyToClipboard = QtGui.QAction(MainWindow)
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/copy.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionCopyToClipboard.setIcon(icon6)
self.actionCopyToClipboard.setObjectName(_fromUtf8("actionCopyToClipboard"))
self.actionViewParentOnline = QtGui.QAction(MainWindow)
self.actionViewParentOnline.setIcon(icon4)
self.actionViewParentOnline.setObjectName(_fromUtf8("actionViewParentOnline"))
self.actionViewParentSource = QtGui.QAction(MainWindow)
self.actionViewParentSource.setIcon(icon4)
self.actionViewParentSource.setObjectName(_fromUtf8("actionViewParentSource"))
self.actionDebug = QtGui.QAction(MainWindow)
self.actionDebug.setObjectName(_fromUtf8("actionDebug"))
self.actionViewProperties = QtGui.QAction(MainWindow)
self.actionViewProperties.setObjectName(_fromUtf8("actionViewProperties"))
self.actionSave = QtGui.QAction(MainWindow)
icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/save.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionSave.setIcon(icon7)
self.actionSave.setObjectName(_fromUtf8("actionSave"))
self.actionQuit = QtGui.QAction(MainWindow)
icon8 = QtGui.QIcon()
icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/exit.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionQuit.setIcon(icon8)
self.actionQuit.setObjectName(_fromUtf8("actionQuit"))
self.actionCheckUpdates = QtGui.QAction(MainWindow)
self.actionCheckUpdates.setObjectName(_fromUtf8("actionCheckUpdates"))
self.actionDonate = QtGui.QAction(MainWindow)
self.actionDonate.setObjectName(_fromUtf8("actionDonate"))
self.actionOpen_project = QtGui.QAction(MainWindow)
self.actionOpen_project.setObjectName(_fromUtf8("actionOpen_project"))
self.actionSave_project = QtGui.QAction(MainWindow)
self.actionSave_project.setObjectName(_fromUtf8("actionSave_project"))
self.menuEdit.addAction(self.actionOptions)
self.menuFile.addAction(self.actionOpen_project)
self.menuFile.addAction(self.actionSave_project)
self.menuFile.addAction(self.actionSave)
self.menuFile.addAction(self.actionQuit)
self.menuHelp.addAction(self.actionAbout)
self.menuHelp.addAction(self.actionHelp)
self.menuHelp.addAction(self.actionDebug)
self.menuHelp.addAction(self.actionCheckUpdates)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuEdit.menuAction())
self.menubar.addAction(self.menuHelp.menuAction())
self.label.setBuddy(self.urlinput)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_("LinkChecker"))
self.label.setText(_("URL:"))
self.controlButton.setToolTip(_("Start checking the given URL."))
self.controlButton.setText(QtGui.QApplication.translate("MainWindow", "Start", "Start checking URL", QtGui.QApplication.UnicodeUTF8))
self.label_29.setText(_("URLs: "))
self.label_32.setText(_("active"))
self.label_active.setText(_("0"))
self.label_30.setText(_("queued"))
self.label_queued.setText(_("0"))
self.label_28.setText(_("checked"))
self.label_checked.setText(_("0"))
self.label_15.setText(_("Info:"))
self.label_busy.setText(_("-"))
self.url_properties.setTitle(_("URL properties"))
self.label_2.setText(_("URL"))
self.label_3.setText(_("Name"))
self.label_4.setText(_("Parent URL"))
self.label_5.setText(_("Base"))
self.label_7.setText(_("Check time"))
self.label_8.setText(_("D/L time"))
self.label_9.setText(_("Size"))
self.label_10.setText(_("Info"))
self.label_11.setText(_("Warning"))
self.label_12.setText(_("Result"))
self.label_16.setText(_("Modified"))
self.groupBox.setTitle(_("Check results"))
self.label_24.setText(_("Valid URLs"))
self.label_26.setText(_("Warnings"))
self.label_25.setText(_("Invalid URLs"))
self.groupBox_3.setTitle(_("Content type statistics"))
self.label_6.setText(_("Image"))
self.label_13.setText(_("Text"))
self.label_27.setText(_("Application"))
self.label_17.setText(_("Audio"))
self.label_21.setText(_("Video"))
self.label_23.setText(_("Other"))
self.label_22.setText(_("Mail"))
self.groupBox_2.setTitle(_("URL statistics"))
self.label_18.setText(_("Min. length"))
self.label_20.setText(_("Avg. length"))
self.label_19.setText(_("Max. length"))
self.menuEdit.setTitle(_("&Edit"))
self.menuFile.setTitle(_("&File"))
self.menuHelp.setTitle(_("&Help"))
self.actionAbout.setText(_("A&bout"))
self.actionAbout.setIconText(_("About"))
self.actionHelp.setText(_("&Help"))
self.actionHelp.setIconText(_("Help"))
self.actionViewOnline.setText(_("View online"))
self.actionViewOnline.setToolTip(_("View URL online"))
self.actionOptions.setText(_("&Options"))
self.actionOptions.setIconText(_("Options"))
self.actionCopyToClipboard.setText(_("Copy to clipboard"))
self.actionCopyToClipboard.setToolTip(_("Copy URL to clipboard"))
self.actionCopyToClipboard.setShortcut(_("Ctrl+C"))
self.actionViewParentOnline.setText(_("View parent online"))
self.actionViewParentOnline.setToolTip(_("View parent URL online"))
self.actionViewParentSource.setText(_("View parent source"))
self.actionViewParentSource.setToolTip(_("View parent URL source"))
self.actionDebug.setText(_("Show debug"))
self.actionViewProperties.setText(_("View properties"))
self.actionViewProperties.setToolTip(_("View URL properties"))
self.actionSave.setText(_("Save &results..."))
self.actionQuit.setText(_("&Quit"))
self.actionQuit.setShortcut(_("Ctrl+Q"))
self.actionCheckUpdates.setText(_("Check for updates"))
self.actionDonate.setText(_("Donate"))
self.actionOpen_project.setText(_("&Open project..."))
self.actionOpen_project.setIconText(_("Open project"))
self.actionOpen_project.setShortcut(_("Ctrl+O"))
self.actionSave_project.setText(_("&Save project..."))
self.actionSave_project.setShortcut(_("Ctrl+S"))
from lineedit import LineEdit
import linkchecker_rc

View file

@ -1,147 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/options.ui'
#
# Created: Fri Feb 28 21:24:59 2014
# by: PyQt4 UI code generator 4.9.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Options(object):
def setupUi(self, Options):
Options.setObjectName(_fromUtf8("Options"))
Options.resize(455, 550)
Options.setMinimumSize(QtCore.QSize(400, 550))
self.verticalLayout_3 = QtGui.QVBoxLayout(Options)
self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
self.groupBox_2 = QtGui.QGroupBox(Options)
self.groupBox_2.setObjectName(_fromUtf8("groupBox_2"))
self.verticalLayout = QtGui.QVBoxLayout(self.groupBox_2)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.widget = QtGui.QWidget(self.groupBox_2)
self.widget.setObjectName(_fromUtf8("widget"))
self.formLayout = QtGui.QFormLayout(self.widget)
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
self.formLayout.setMargin(0)
self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label = QtGui.QLabel(self.widget)
self.label.setObjectName(_fromUtf8("label"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label)
self.recursionlevel = QtGui.QSpinBox(self.widget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.recursionlevel.sizePolicy().hasHeightForWidth())
self.recursionlevel.setSizePolicy(sizePolicy)
self.recursionlevel.setMinimumSize(QtCore.QSize(0, 25))
self.recursionlevel.setMinimum(-1)
self.recursionlevel.setMaximum(100)
self.recursionlevel.setProperty("value", -1)
self.recursionlevel.setObjectName(_fromUtf8("recursionlevel"))
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.recursionlevel)
self.label_2 = QtGui.QLabel(self.widget)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_2)
self.verbose = QtGui.QCheckBox(self.widget)
self.verbose.setEnabled(True)
self.verbose.setText(_fromUtf8(""))
self.verbose.setObjectName(_fromUtf8("verbose"))
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.verbose)
self.label_4 = QtGui.QLabel(self.widget)
self.label_4.setObjectName(_fromUtf8("label_4"))
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_4)
self.debug = QtGui.QCheckBox(self.widget)
self.debug.setText(_fromUtf8(""))
self.debug.setObjectName(_fromUtf8("debug"))
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.debug)
self.verticalLayout.addWidget(self.widget)
spacerItem = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.label_5 = QtGui.QLabel(self.groupBox_2)
self.label_5.setObjectName(_fromUtf8("label_5"))
self.verticalLayout.addWidget(self.label_5)
self.warninglines = QtGui.QPlainTextEdit(self.groupBox_2)
self.warninglines.setMaximumSize(QtCore.QSize(16777215, 150))
self.warninglines.setObjectName(_fromUtf8("warninglines"))
self.verticalLayout.addWidget(self.warninglines)
self.label_6 = QtGui.QLabel(self.groupBox_2)
self.label_6.setObjectName(_fromUtf8("label_6"))
self.verticalLayout.addWidget(self.label_6)
self.ignorelines = QtGui.QPlainTextEdit(self.groupBox_2)
self.ignorelines.setMaximumSize(QtCore.QSize(16777215, 150))
self.ignorelines.setObjectName(_fromUtf8("ignorelines"))
self.verticalLayout.addWidget(self.ignorelines)
self.verticalLayout_3.addWidget(self.groupBox_2)
self.groupBox = QtGui.QGroupBox(Options)
self.groupBox.setObjectName(_fromUtf8("groupBox"))
self.verticalLayout_2 = QtGui.QVBoxLayout(self.groupBox)
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.label_3 = QtGui.QLabel(self.groupBox)
self.label_3.setWordWrap(True)
self.label_3.setObjectName(_fromUtf8("label_3"))
self.verticalLayout_2.addWidget(self.label_3)
spacerItem1 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem1)
self.user_config_filename = QtGui.QLabel(self.groupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.user_config_filename.sizePolicy().hasHeightForWidth())
self.user_config_filename.setSizePolicy(sizePolicy)
self.user_config_filename.setFrameShape(QtGui.QFrame.NoFrame)
self.user_config_filename.setLineWidth(0)
self.user_config_filename.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
self.user_config_filename.setWordWrap(True)
self.user_config_filename.setMargin(0)
self.user_config_filename.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
self.user_config_filename.setObjectName(_fromUtf8("user_config_filename"))
self.verticalLayout_2.addWidget(self.user_config_filename)
self.user_config_button = QtGui.QPushButton(self.groupBox)
self.user_config_button.setEnabled(False)
self.user_config_button.setToolTip(_fromUtf8(""))
self.user_config_button.setObjectName(_fromUtf8("user_config_button"))
self.verticalLayout_2.addWidget(self.user_config_button)
self.verticalLayout_3.addWidget(self.groupBox)
spacerItem2 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout_3.addItem(spacerItem2)
self.widget_2 = QtGui.QWidget(Options)
self.widget_2.setObjectName(_fromUtf8("widget_2"))
self.horizontalLayout = QtGui.QHBoxLayout(self.widget_2)
self.horizontalLayout.setMargin(0)
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.closeButton = QtGui.QPushButton(self.widget_2)
self.closeButton.setObjectName(_fromUtf8("closeButton"))
self.horizontalLayout.addWidget(self.closeButton)
spacerItem3 = QtGui.QSpacerItem(317, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem3)
self.verticalLayout_3.addWidget(self.widget_2)
self.retranslateUi(Options)
QtCore.QMetaObject.connectSlotsByName(Options)
def retranslateUi(self, Options):
Options.setWindowTitle(_("Options"))
self.groupBox_2.setTitle(_("Checking options"))
self.label.setToolTip(_("Check recursively all links up to given depth. A negative depth will enable infinite recursion."))
self.label.setText(_("Recursive depth"))
self.recursionlevel.setToolTip(_("Check recursively all links up to given depth. A negative depth will enable infinite recursion."))
self.label_2.setToolTip(_("Log all checked URLs once. Default is to log only errors and warnings."))
self.label_2.setText(_("Verbose output"))
self.verbose.setToolTip(_("Log all checked URLs once. Default is to log only errors and warnings."))
self.label_4.setText(_("Debug"))
self.label_5.setText(_("Warn when one of these strings are found (one per line):"))
self.label_6.setText(_("Ignore URLs matching one of these patterns (one per line):"))
self.groupBox.setTitle(_("Configuration file"))
self.label_3.setText(_("The configuration file holds advanced options and can be edited with an integrated text editor."))
self.user_config_filename.setToolTip(_("Overrides system wide configuration file settings."))
self.user_config_filename.setText(_("/home/user/.linkchecker/linkcheckerrc"))
self.user_config_button.setText(_("Edit"))
self.closeButton.setText(_("Close"))

View file

@ -1,73 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2009-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from logging import Handler
from ..logger import _Logger
class GuiLogHandler (Handler, object):
"""Delegate log messages to the UI."""
def __init__ (self, signal):
"""Save widget."""
super(GuiLogHandler, self).__init__()
self.signal = signal
def emit (self, record):
"""Emit a record. It gets logged in the debug widget."""
self.signal.emit(self.format(record))
class SignalLogger (_Logger):
"""Use Qt signals for logged URLs and statistics."""
LoggerName = "gui"
def __init__ (self, **args):
"""Store signals for URL and statistic data."""
super(SignalLogger, self).__init__(**args)
self.log_url_signal = args["signal"]
self.log_stats_signal = args["stats"]
def start_fileoutput (self):
"""Override fileoutput handling of base class."""
pass
def close_fileoutput (self):
"""Override fileoutput handling of base class."""
pass
def log_url (self, url_data):
"""Emit URL data which gets logged in the main window."""
self.log_url_signal.emit(url_data)
def end_output (self, **kwargs):
"""Emit statistic data which gets logged in the main window."""
self.stats.downloaded_bytes = kwargs.get("downloaded_bytes")
self.log_stats_signal.emit(self.stats)
class StatusLogger (object):
"""GUI status logger, signaling to progress labels."""
def __init__ (self, signal):
"""Store given signal object."""
self.signal = signal
def log_status (self, checked, in_progress, queued, duration, num_urls):
"""Emit signal with given status information."""
self.signal.emit(checked, in_progress, queued, duration, num_urls)

View file

@ -1,110 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2009-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
from PyQt4 import QtGui
from .linkchecker_ui_options import Ui_Options
from .editor import EditorWindow
from ..fileutil import is_writable
from .. import configuration
class LinkCheckerOptions (QtGui.QDialog, Ui_Options):
"""Hold options for current URL to check."""
def __init__ (self, parent=None):
"""Reset all options and initialize the editor window."""
super(LinkCheckerOptions, self).__init__(parent)
self.setupUi(self)
self.editor = EditorWindow(self)
self.closeButton.clicked.connect(self.close)
self.user_config_button.clicked.connect(self.edit_user_config)
self.reset()
def reset (self):
"""Reset GUI and config options."""
self.user_config = configuration.get_user_config()
self.reset_gui_options()
self.reset_config_options()
def reset_gui_options (self):
"""Reset GUI options to default values."""
self.recursionlevel.setValue(-1)
self.verbose.setChecked(False)
self.debug.setChecked(False)
self.warninglines.setPlainText(u"")
self.ignorelines.setPlainText(u"")
def reset_config_options (self):
"""Reset configuration file edit buttons."""
self.user_config_writable = is_writable(self.user_config)
set_edit_button(self.user_config, self.user_config_button,
self.user_config_filename, self.user_config_writable)
def edit_user_config (self):
"""Show editor for user specific configuration file."""
return start_editor(self.user_config, self.user_config_writable,
self.editor)
def get_options (self):
"""Return option data as dictionary."""
return dict(
debug=self.debug.isChecked(),
verbose=self.verbose.isChecked(),
recursionlevel=self.recursionlevel.value(),
warninglines=unicode(self.warninglines.toPlainText()),
ignorelines=unicode(self.ignorelines.toPlainText()),
)
def set_options (self, data):
"""Set GUI options from given data."""
if data.get("debug") is not None:
self.debug.setChecked(data["debug"])
if data.get("verbose") is not None:
self.verbose.setChecked(data["verbose"])
if data.get("recursionlevel") is not None:
self.recursionlevel.setValue(data["recursionlevel"])
if data.get("warninglines") is not None:
self.warninglines.setPlainText(data["warninglines"])
if data.get("ignorelines") is not None:
self.ignorelines.setPlainText(data["ignorelines"])
def start_editor (filename, writable, editor):
"""Start editor for given filename."""
if not os.path.isfile(filename):
# file vanished
return
editor.load(filename)
# all config files are in INI format
editor.setContentType("text/plain+ini")
editor.editor.setReadOnly(not writable)
editor.show()
def set_edit_button (filename, button, label, writable):
"""Update edit button depending on writable flag of file."""
label.setText(filename)
if os.path.isfile(filename):
button.setEnabled(True)
if writable:
button.setText(_(u"Edit"))
else:
button.setText(_(u"Read"))
else:
button.setEnabled(False)
button.setText(_(u"File not found"))

View file

@ -1,205 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2012-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import re
import os
import shutil
from PyQt4 import QtGui
from ..configuration import get_user_config, confparse
from ..url import url_split
from ..fileutil import is_readable, is_writable
ProjectExt = ".lcp"
ProjectFilter = _("LinkChecker project (*%(ext)s)") % dict(ext=ProjectExt)
class ProjectParser (confparse.LCConfigParser):
def __init__ (self, config, gui_options, urlinput):
super(ProjectParser, self).__init__(config)
# has set_options(data) function
self.gui_options = gui_options
# has setText(url) function
self.urlinput = urlinput
def read (self, files):
super(ProjectParser, self).read(files)
self.read_project_config()
self.read_gui_config()
def read_project_config(self):
section = "project"
if not self.has_section(section):
return
option = "url"
if self.has_option(section, option):
url = self.get(section, option)
self.urlinput.setText(url)
else:
self.urlinput.setText(u"")
def read_gui_config(self):
section = "gui"
if not self.has_section(section):
return
data = {}
option = "debug"
if self.has_option(section, option):
data[option] = self.getboolean(section, option)
option = "verbose"
if self.has_option(section, option):
data[option] = self.getboolean(section, option)
option = "recursionlevel"
if self.has_option(section, option):
data[option] = self.getint(section, option)
option = "warninglines"
if self.has_option(section, option):
data[option] = self.get(section, option)
option = "ignorelines"
if self.has_option(section, option):
data[option] = self.get(section, option)
self.gui_options.set_options(data)
def write (self, fp):
"""Write project configuration to given file object."""
self.write_project_config()
self.write_gui_config()
super(ProjectParser, self).write(fp)
def write_project_config(self):
"""Write project section configuration."""
section = "project"
self.add_section(section)
self.set(section, "url", self.urlinput.text())
def write_gui_config(self):
"""Write gui section configuration."""
section = "gui"
self.add_section(section)
for key, value in self.gui_options.get_options().items():
self.set(section, key, value)
def url_to_filename(url, extension):
value = unicode(url)
# filter host and document
parts = url_split(url)
value = parts[1]+parts[3]
# normalize
import unicodedata
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
# replace non-alpha characters and convert to lowercase
value = re.sub('[^\w-]+', '_', value).strip().lower()
# add extension
return value + extension
def saveproject(parent, url):
"""Save a project file."""
try:
msg = saveproject_msg(parent, url)
except Exception as errmsg:
msg = str(errmsg)
parent.set_statusmsg(msg)
def saveproject_msg(parent, url):
"""Save a project file and return status message."""
title = _("Save LinkChecker project")
func = QtGui.QFileDialog.getSaveFileName
suggestedname = url_to_filename(url, ProjectExt)
res = func(parent, title, suggestedname, ProjectFilter)
if not res:
# user canceled
return _("Canceled saving a project file.")
filename = unicode(res)
d = dict(filename=filename)
if not is_writable(filename):
return _("Could not write project file %(filename)s.") % d
user_config = get_user_config()
if is_readable(user_config):
# Copy user config to filename since this is the current
# configuration.
# This way it is not necessary to write the parent.config
# dictionary back to a file.
shutil.copy(user_config, filename)
filter_comments = True
else:
# use default config (ie. do not write anything)
filter_comments = False
write_header(filename, filter_comments)
parser = ProjectParser(parent.config, parent.options, parent.urlinput)
with open(filename, 'a') as fp:
parser.write(fp)
return _("Project file %(filename)s saved successfully.") % d
def write_header(filename, filter_comments):
"""Write header and filter comment lines if file already exists."""
lines = [
'# This is a generated LinkChecker project file. Do not edit'+os.linesep,
]
if filter_comments:
with open(filename, 'r') as fp:
for line in fp:
if not line.lstrip().startswith((';', '#')):
lines.append(line)
with open(filename, 'w') as fp:
for line in lines:
fp.write(line)
def openproject (parent):
"""Select and load a project file."""
try:
msg = openproject_msg(parent)
except Exception as errmsg:
msg = str(errmsg)
parent.set_statusmsg(msg)
def openproject_msg(parent):
"""Select and load a project file. Returns message to display
which indicates if file has been loaded successful."""
title = _("Open LinkChecker project")
func = QtGui.QFileDialog.getOpenFileName
directory = ""
filename = func(parent, title, directory, ProjectFilter)
if not filename:
# user canceled
return _("Canceled opening a project file.")
if not is_readable(filename):
return _("Could not read project file %(filename)s.") % dict(filename=filename)
return loadproject(filename, parent.config, parent.options, parent.urlinput)
def loadproject(parent, filename):
"""Load a project file."""
try:
msg = loadproject_msg(parent, filename)
except Exception as errmsg:
args = dict(filename=filename, err=errmsg)
msg = _("Could not load project %(filename)s: %(err)s") % args
parent.set_statusmsg(msg)
def loadproject_msg(parent, filename):
"""Load a project file. Returns message to display which indicates if
file has been loaded successful."""
parser = ProjectParser(parent.config, parent.options, parent.urlinput)
parser.read([filename])
d = dict(filename=filename)
return _("Project file %(filename)s loaded successfully.") % d

View file

@ -1,80 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2010-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
from .. import strformat
def set_properties (widget, data):
"""Write URL data values into widget text fields."""
if data.base_url and data.url:
widget.prop_url.setText(u'<a href="%(url)s">%(base_url)s</a>' % \
dict(url=data.url, base_url=data.base_url))
else:
widget.prop_url.setText(u"")
widget.prop_name.setText(data.name)
if data.parent_url:
widget.prop_parenturl.setText(u'<a href="%(url)s">%(url)s</a>' % \
dict(url=data.parent_url))
else:
widget.prop_parenturl.setText(u"")
widget.prop_base.setText(data.base_ref)
widget.prop_checktime.setText(_("%.3f seconds") % data.checktime)
if data.dltime >= 0:
widget.prop_dltime.setText(_("%.3f seconds") % data.dltime)
else:
widget.prop_dltime.setText(u"")
if data.size >= 0:
widget.prop_size.setText(strformat.strsize(data.size))
else:
widget.prop_size.setText(u"")
if data.modified:
widget.prop_modified.setText(data.modified.isoformat(" "))
else:
widget.prop_modified.setText(u"")
widget.prop_info.setText(wrap(data.info, 65))
warning_msgs = [x[1] for x in data.warnings]
widget.prop_warning.setText(wrap(warning_msgs, 65))
if data.valid:
result = u"Valid"
else:
result = u"Error"
if data.result:
result += u": %s" % data.result
widget.prop_result.setText(result)
def clear_properties (widget):
"""Reset URL data values in widget text fields."""
widget.prop_url.setText(u"")
widget.prop_name.setText(u"")
widget.prop_parenturl.setText(u"")
widget.prop_base.setText(u"")
widget.prop_checktime.setText(u"")
widget.prop_dltime.setText(u"")
widget.prop_size.setText(u"")
widget.prop_info.setText(u"")
widget.prop_warning.setText(u"")
widget.prop_result.setText(u"")
def wrap (lines, width):
"""Format lines with given line-width."""
sep = os.linesep+os.linesep
text = sep.join(lines)
kwargs = dict(break_long_words=False, break_on_hyphens=False)
return strformat.wrap(text, width, **kwargs)

View file

@ -1,62 +0,0 @@
# refresh media files
# base directory of oxygen icon set checkout
OXYGEN = $(HOME)/src/oxygen-gitsvn/16x16
ICONS = \
cancel.png \
online.png \
options.png \
preferences.png \
save.png \
start.png \
stop.png \
about.png \
help.png \
exit.png \
copy.png \
clear.png
all: $(ICONS)
app.png: $(OXYGEN)/categories/applications-development-web.png
cp $< $@
save.png: $(OXYGEN)/actions/document-save-as.png
cp $< $@
start.png: $(OXYGEN)/actions/media-playback-start.png
cp $< $@
stop.png: $(OXYGEN)/actions/media-playback-stop.png
cp $< $@
cancel.png: $(OXYGEN)/actions/process-stop.png
cp $< $@
about.png: $(OXYGEN)/actions/help-about.png
cp $< $@
help.png: $(OXYGEN)/actions/help-contents.png
cp $< $@
exit.png: $(OXYGEN)/actions/application-exit.png
cp $< $@
copy.png: $(OXYGEN)/actions/edit-copy.png
cp $< $@
online.png: $(OXYGEN)/actions/document-open-remote.png
cp $< $@
options.png: $(OXYGEN)/categories/preferences-system-network.png
cp $< $@
preferences.png: $(OXYGEN)/categories/preferences-other.png
cp $< $@
clear.png: $(OXYGEN)/actions/edit-clear-locationbar-rtl.png
cp $< $@
clean:
rm -f $(ICONS)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 684 B

View file

@ -1,19 +0,0 @@
<RCC>
<qresource prefix="icons">
<file>clear.png</file>
<file>arrow_down.png</file>
<file>busy.gif</file>
<file>save.png</file>
<file>copy.png</file>
<file>about.png</file>
<file>help.png</file>
<file>exit.png</file>
<file>online.png</file>
<file>cancel.png</file>
<file>app.png</file>
<file>options.png</file>
<file>preferences.png</file>
<file>start.png</file>
<file>stop.png</file>
</qresource>
</RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 950 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 B

View file

@ -1,89 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2011-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtCore
EmptyQVariant = QtCore.QVariant()
class RecentDocumentModel(QtCore.QAbstractListModel):
"""Model class for list of recent documents."""
def __init__ (self, parent=None, documents=[], maxentries=10):
"""Set document list."""
super(RecentDocumentModel, self).__init__(parent)
self.maxentries = maxentries
self.documents = documents[:maxentries]
def rowCount (self, parent=QtCore.QModelIndex()):
"""Return number of documents."""
return len(self.documents)
def index (self, row, column=0, parent=QtCore.QModelIndex()):
"""Return index of document in given row."""
return self.createIndex(row, column)
def data (self, index, role=QtCore.Qt.DisplayRole):
"""Return data at given index for given role."""
V = QtCore.QVariant
if not index.isValid() or \
not (0 <= index.row() < len(self.documents)) or \
index.column() != 0:
return EmptyQVariant
if role == QtCore.Qt.DisplayRole:
return V(self.documents[index.row()])
return EmptyQVariant
def headerData (self, section, orientation, role):
"""Return header column data for given parameters."""
return EmptyQVariant
def flags (self, index):
"""Return flags that given valid item index is enabled and
selected."""
if not index.isValid():
return 0
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
def clear (self):
"""Empty the document list."""
self.beginResetModel()
self.documents = []
self.endResetModel()
def add_document (self, document):
"""Add document to model."""
if not document:
return False
assert isinstance(document, unicode)
while document in self.documents:
row = self.documents.index(document)
self.beginRemoveRows(QtCore.QModelIndex(), row, row)
del self.documents[row]
self.endRemoveRows()
while len(self.documents) >= self.maxentries:
row = len(self.documents) - 1
self.beginRemoveRows(QtCore.QModelIndex(), row, row)
del self.documents[row]
self.endRemoveRows()
self.beginInsertRows(QtCore.QModelIndex(), 0, 0)
self.documents.insert(0, document)
self.endInsertRows()
return True
def get_documents (self):
"""Return copy of document list."""
return self.documents[:]

View file

@ -1,159 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2010-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""Read and store QSettings for this application."""
from PyQt4 import QtCore
def save_point (qpoint):
"""Ensure positive X and Y values of point."""
qpoint.setX(max(0, qpoint.x()))
qpoint.setY(max(0, qpoint.y()))
return qpoint
def save_size (qsize):
"""Ensure minimum width and height values of the given size."""
qsize.setWidth(max(400, qsize.width()))
qsize.setHeight(max(400, qsize.height()))
return qsize
class Settings (object):
"""Save and read GUI settings."""
def __init__ (self, base, appname):
"""Initialize a QSettings object."""
self.settings = QtCore.QSettings(base, appname)
def read_geometry (self):
"""Return stored size and position of main window."""
data = dict(size=None, pos=None)
self.settings.beginGroup('mainwindow')
if self.settings.contains('size'):
data["size"] = save_size(self.settings.value('size').toSize())
if self.settings.contains('pos'):
data["pos"] = save_point(self.settings.value('pos').toPoint())
self.settings.endGroup()
return data
def save_geometry (self, data):
"""Save size and position of main window."""
size = save_size(data["size"])
pos = save_point(data["pos"])
self.settings.beginGroup('mainwindow')
self.settings.setValue("size", QtCore.QVariant(size))
self.settings.setValue("pos", QtCore.QVariant(pos))
self.settings.endGroup()
def read_treeviewcols (self):
"""Return widths of URL treeview columns."""
data = dict(col1=200, col2=200, col3=150)
self.settings.beginGroup('treeview')
for key in ("col1", "col2", "col3"):
if self.settings.contains(key):
value, ok = self.settings.value(key).toInt()
if ok:
if value < 50:
value = 50
elif value > 500:
value = 500
data[key] = value
self.settings.endGroup()
return data
def save_treeviewcols (self, data):
"""Save widths of URL treeview columns."""
self.settings.beginGroup('treeview')
for key in ("col1", "col2", "col3"):
self.settings.setValue(key, QtCore.QVariant(data[key]))
self.settings.endGroup()
def read_options (self):
"""Return stored GUI options."""
data = dict(debug=None, verbose=None,
recursionlevel=None, warninglines=None, ignorelines=None)
self.settings.beginGroup('output')
for key in ("debug", "verbose"):
if self.settings.contains(key):
data[key] = self.settings.value(key).toBool()
self.settings.endGroup()
self.settings.beginGroup('checking')
if self.settings.contains('recursionlevel'):
value, ok = self.settings.value('recursionlevel').toInt()
if ok:
if value < -1:
value = -1
elif value > 100:
# 100 is the maximum GUI option value
value = 100
else:
value = -1
data['recursionlevel'] = value
if self.settings.contains('warninglines'):
value = self.settings.value('warninglines').toString()
data['warninglines'] = unicode(value)
if self.settings.contains('ignorelines'):
value = self.settings.value('ignorelines').toString()
data['ignorelines'] = unicode(value)
self.settings.endGroup()
return data
def save_options (self, data):
"""Save GUI options."""
self.settings.beginGroup('output')
for key in ("debug", "verbose"):
self.settings.setValue(key, QtCore.QVariant(data[key]))
self.settings.endGroup()
self.settings.beginGroup('checking')
for key in ("recursionlevel", "warninglines", "ignorelines"):
self.settings.setValue(key, QtCore.QVariant(data[key]))
self.settings.endGroup()
def read_recent_documents (self):
"""Return list of recent documents."""
self.settings.beginGroup('recent')
data = self.settings.value('documents').toStringList()
self.settings.endGroup()
return [unicode(doc) for doc in data]
def save_recent_documents (self, data):
"""Save list of recent documents."""
self.settings.beginGroup('recent')
self.settings.setValue('documents', QtCore.QVariant(data))
self.settings.endGroup()
def read_misc(self):
"""Get misc options."""
data = dict(saveresultas=None)
self.settings.beginGroup('misc')
key = 'saveresultas'
value = self.settings.value(key).toString()
data[key] = unicode(value)
self.settings.endGroup()
return data
def save_misc(self, data):
"""Save misc options."""
self.settings.beginGroup('misc')
key = 'saveresultas'
self.settings.setValue(key, QtCore.QVariant(data[key]))
self.settings.endGroup()
def sync (self):
"""Synchronize QSettings object to disk."""
self.settings.sync()

View file

@ -1,47 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2010-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from ..logger import ContentTypes
def set_statistics (widget, statistics):
"""Set statistic information in given widget."""
widget.stats_url_minlen.setText(u"%d" % statistics.min_url_length)
widget.stats_url_maxlen.setText(u"%d" % statistics.max_url_length)
widget.stats_url_avglen.setText(u"%d" % statistics.avg_url_length)
widget.stats_valid_urls.setText(u"%d" % (statistics.number - statistics.errors))
if statistics.errors > 0:
color = '#aa0000'
else:
color = '#00aa00'
style = "QLabel {font-weight:bold; color:%s;}" % color
widget.stats_invalid_urls.setStyleSheet(style)
widget.stats_invalid_urls.setText(u"%d" % statistics.errors)
widget.stats_warnings.setText(u"%d" % statistics.warnings)
for key, value in statistics.link_types.items():
getattr(widget, "stats_content_%s"%key).setText(u"%d" % value)
def clear_statistics (widget):
"""Reset statistic information in given widget."""
widget.stats_url_minlen.setText(u"")
widget.stats_url_maxlen.setText(u"")
widget.stats_url_avglen.setText(u"")
widget.stats_valid_urls.setText(u"")
widget.stats_invalid_urls.setText(u"")
widget.stats_warnings.setText(u"")
for key in ContentTypes:
getattr(widget, "stats_content_%s"%key).setText(u"")

View file

@ -1,98 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2011-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtCore, QtGui
def format (color, style=''):
"""Return a QTextCharFormat with the given attributes."""
format = QtGui.QTextCharFormat()
format.setForeground(getattr(QtCore.Qt, color))
if 'bold' in style:
format.setFontWeight(QtGui.QFont.Bold)
if 'italic' in style:
format.setFontItalic(True)
return format
class Highlighter (QtGui.QSyntaxHighlighter):
"""Base class for all highlighters."""
def __init__ (self, document):
"""Initialize rules and styles."""
super(Highlighter, self).__init__(document)
self.rules = []
self.styles = {}
def highlightBlock(self, text):
"""Highlight a text block."""
for expression, format in self.rules:
# get first match
index = expression.indexIn(text)
while index >= 0:
length = expression.matchedLength()
self.setFormat(index, length, format)
# jump to next match
index = expression.indexIn(text, index + length)
self.setCurrentBlockState(0)
def addRule (self, pattern, style):
"""Add a rule pattern with given style."""
self.rules.append((QtCore.QRegExp(pattern), self.styles[style]))
class XmlHighlighter (Highlighter):
"""XML syntax highlighter."""
def __init__(self, document):
"""Set XML syntax rules."""
super(XmlHighlighter, self).__init__(document)
self.styles.update({
'keyword': format('darkBlue'),
'attribute': format('darkGreen'),
'comment': format('darkYellow'),
'string': format('darkMagenta'),
})
# keywords
for reg in ('/>', '>', '<!?[a-zA-Z0-9_]+'):
self.addRule(reg, 'keyword')
# attributes
self.addRule(r"\b[A-Za-z0-9_]+(?=\s*\=)", 'attribute')
# double-quoted string, possibly containing escape sequences
self.addRule(r'"[^"\\]*(\\.[^"\\]*)*"', 'string')
# single-quoted string, possibly containing escape sequences
self.addRule(r"'[^'\\]*(\\.[^'\\]*)*'", 'string')
# comments
self.addRule(r"<!--[^>]*-->", 'comment')
# Treat HTML as XML
HtmlHighlighter = XmlHighlighter
class IniHighlighter (Highlighter):
"""INI syntax highlighter."""
def __init__(self, document):
"""Set INI syntax rules."""
super(IniHighlighter, self).__init__(document)
self.styles.update({
'section': format('darkBlue'),
'property': format('darkGreen'),
'comment': format('darkYellow'),
})
self.addRule(r'\b\[[a-zA-Z0-9_]+\]\b', 'section')
self.addRule(r'\b[a-zA-Z0-9_]+\](?=\s*\=)', 'property')
self.addRule(r'#[^\n]*', 'comment')

View file

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DebugDialog</class>
<widget class="QDialog" name="DebugDialog">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>564</width>
<height>547</height>
</rect>
</property>
<property name="windowTitle">
<string>LinkChecker debug log</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPlainTextEdit" name="textEdit">
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="plainText">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -1,71 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditorDialog</class>
<widget class="QDialog" name="EditorDialog">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>600</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>LinkChecker source view</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QMenuBar" name="menubar">
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionSave"/>
</widget>
<addaction name="menuFile"/>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
</layout>
<action name="actionSave">
<property name="text">
<string>&amp;Save</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

File diff suppressed because it is too large Load diff

View file

@ -1,285 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Options</class>
<widget class="QDialog" name="Options">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>455</width>
<height>550</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>550</height>
</size>
</property>
<property name="windowTitle">
<string>Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Checking options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="toolTip">
<string>Check recursively all links up to given depth. A negative depth will enable infinite recursion.</string>
</property>
<property name="text">
<string>Recursive depth</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="recursionlevel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>Check recursively all links up to given depth. A negative depth will enable infinite recursion.</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="toolTip">
<string>Log all checked URLs once. Default is to log only errors and warnings.</string>
</property>
<property name="text">
<string>Verbose output</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="verbose">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Log all checked URLs once. Default is to log only errors and warnings.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Debug</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="debug">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Warn when one of these strings are found (one per line):</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="warninglines">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>150</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Ignore URLs matching one of these patterns (one per line):</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="ignorelines">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>150</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Configuration file</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>The configuration file holds advanced options and can be edited with an integrated text editor.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="user_config_filename">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Overrides system wide configuration file settings.</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="text">
<string>/home/user/.linkchecker/linkcheckerrc</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="user_config_button">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>317</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -1,82 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2011-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtCore, QtGui
from .. import updater, configuration
class UpdateThread (QtCore.QThread):
"""Thread to check for updated versions."""
def reset (self):
"""Reset version information."""
self.result = self.value = None
def run (self):
"""Check for updated version."""
self.result, self.value = updater.check_update()
class UpdateDialog (QtGui.QMessageBox):
"""Dialog displaying results of an update check."""
def __init__ (self, parent=None):
"""Initialize dialog and start background update thread."""
super(UpdateDialog, self).__init__(parent)
title = _('%(app)s update information') % dict(app=configuration.App)
self.setWindowTitle(title)
self.thread = UpdateThread()
self.thread.finished.connect(self.update)
def reset (self):
"""Reset dialog and restart update check."""
self.thread.reset()
self.thread.start()
self.setIcon(QtGui.QMessageBox.Information)
self.setText(_('Checking for updates...'))
def update (self):
"""Display update thread result (which must be available)."""
result, value = self.thread.result, self.thread.value
if result:
if value is None:
# no update available: display info
text = _('Congratulations: the latest version '
'%(app)s is installed.')
attrs = dict(app=configuration.App)
else:
version, url = value
if url is None:
# current version is newer than online version
text = _('Detected local or development version %(currentversion)s. '
'Available version of %(app)s is %(version)s.')
else:
# display update link
text = _('A new version %(version)s of %(app)s is '
'available for <a href="%(url)s">download</a>.')
attrs = dict(version=version, app=configuration.AppName,
url=url, currentversion=configuration.Version)
else:
# value is an error message or None if UpdateThread has been
# terminated
if value is None:
value = _('update thread has been terminated')
self.setIcon(QtGui.QMessageBox.Warning)
text = _('An error occured while checking for an '
'update of %(app)s: %(error)s.')
attrs = dict(error=value, app=configuration.AppName)
self.setText(text % attrs)

View file

@ -1,196 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2010-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import operator
from PyQt4 import QtCore, QtGui
from .. import strformat
Headers = [_(u"Parent"), _(u"URL"), _(u"Name"), _(u"Result")]
EmptyQVariant = QtCore.QVariant()
class UrlItem (object):
"""URL item storing info to be displayed."""
def __init__ (self, url_data):
"""Save given URL data and initialize display and tooltip texts."""
# url_data is of type CompactUrlData
self.url_data = url_data
# format display and tooltips
self.init_display()
self.init_tooltips()
def __getitem__ (self, key):
"""Define easy index access (used for sorting):
0: Parent URL
1: URL
2: URL name
3: Result
"""
if not isinstance(key, int):
raise TypeError("invalid index %r" % key)
if key == 0:
return (self.url_data.parent_url, self.url_data.line,
self.url_data.column)
elif key == 1:
return self.url_data.url
elif key == 2:
return self.url_data.name
elif key == 3:
return (self.url_data.valid, self.url_data.result)
raise IndexError("invalid index %d" % key)
def init_display (self):
"""Store formatted display texts from URL data."""
# result
if self.url_data.valid:
if self.url_data.warnings:
self.result_color = QtCore.Qt.darkYellow
text = u"\n".join(x[1] for x in self.url_data.warnings)
result = u"Warning: %s" % strformat.limit(text, length=25)
else:
self.result_color = QtCore.Qt.darkGreen
result = u"Valid"
if self.url_data.result:
result += u": %s" % self.url_data.result
else:
self.result_color = QtCore.Qt.darkRed
result = u"Error"
if self.url_data.result:
result += u": %s" % self.url_data.result
# Parent URL
if self.url_data.parent_url:
parent = u"%s%s%s" % (self.url_data.parent_url,
(_(", line %d") % self.url_data.line),
(_(", col %d") % self.url_data.column))
else:
parent = u""
# display values
self.display = [
# Parent URL
parent,
# URL
unicode(self.url_data.url),
# Name
self.url_data.name,
# Result
result,
]
def init_tooltips (self):
"""Store formatted tooltip texts from URL data."""
# Display warnings in result tooltip
if self.url_data.warnings:
text = u"\n".join(x[1] for x in self.url_data.warnings)
result = strformat.wrap(text, 60)
else:
result = u""
self.tooltips = [
# Parent URL
u"",
# URL
unicode(self.url_data.url),
# Name
self.url_data.name,
# Result
result,
]
class UrlItemModel(QtCore.QAbstractItemModel):
"""Model class for list of URL items."""
def __init__ (self, parent=None):
"""Set empty URL item list."""
super(UrlItemModel, self).__init__(parent)
# list of UrlItem objects
self.urls = []
def rowCount (self, parent=QtCore.QModelIndex()):
"""Return number of URL items."""
return len(self.urls)
def columnCount (self, parent=QtCore.QModelIndex()):
"""Return number of header columns."""
return len(Headers)
def parent (self, child=QtCore.QModelIndex()):
"""Return empty QModelIndex since the URL list is not hierarchical."""
return QtCore.QModelIndex()
def index (self, row, column, parent=QtCore.QModelIndex()):
"""Return index of URL item in given row and column."""
return self.createIndex(row, column)
def data (self, index, role=QtCore.Qt.DisplayRole):
"""Return URL item data at given index for given role."""
V = QtCore.QVariant
if not index.isValid() or \
not (0 <= index.row() < len(self.urls)):
return EmptyQVariant
urlitem = self.urls[index.row()]
column = index.column()
if role == QtCore.Qt.DisplayRole:
return V(urlitem.display[column])
elif role == QtCore.Qt.ToolTipRole:
return V(urlitem.tooltips[column])
elif role == QtCore.Qt.TextColorRole and column == 3:
return QtGui.QColor(urlitem.result_color)
else:
return EmptyQVariant
def headerData (self, section, orientation, role):
"""Return header column data for given parameters."""
if orientation == QtCore.Qt.Horizontal and \
role == QtCore.Qt.DisplayRole:
return Headers[section]
return EmptyQVariant
def flags (self, index):
"""Return flags that given valid item index is enabled and
selected."""
if not index.isValid():
return 0
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
def clear (self):
"""Empty the URL item list."""
self.beginResetModel()
self.urls = []
self.endResetModel()
def log_url (self, url_data):
"""Add URL data to tree model."""
row = self.rowCount()
self.beginInsertRows(QtCore.QModelIndex(), row, row)
self.urls.append(UrlItem(url_data))
self.endInsertRows()
return True
def getUrlItem (self, index):
"""Get URL item object at given index."""
if not index.isValid() or \
not (0 <= index.row() < len(self.urls)):
return None
return self.urls[index.row()]
def sort (self, column, order=QtCore.Qt.AscendingOrder):
"""Sort URL items by given column and order."""
self.layoutAboutToBeChanged.emit()
reverse = (order == QtCore.Qt.DescendingOrder)
self.urls.sort(key=operator.itemgetter(column), reverse=reverse)
self.layoutChanged.emit()

View file

@ -1,87 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2010-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from PyQt4 import QtGui, QtCore
FilterHtml = _("HTML output (*.html)")
FilterText = _("Text output (*.txt)")
FilterXml = _("XML output (*.xml)")
FilterCsv = _("CSV output (*.csv)")
LoggerFilters = (
FilterHtml,
FilterText,
FilterXml,
FilterCsv,
)
Logtype2Filter = {
'html': FilterHtml,
'text': FilterText,
'xml': FilterXml,
'csv': FilterCsv,
}
Filter2Logtype = {v: k for k, v in Logtype2Filter.items()}
Logtype2FileExt = {
"html": ".html",
"text": ".txt",
"xml": ".xml",
"csv": ".csv",
}
def urlsave (parent, config, urls):
"""Save URL results in file."""
filename, logtype = get_save_filename(parent)
if not filename:
# user canceled
return
filename = unicode(filename)
kwargs = dict(fileoutput=1, filename=filename, encoding="utf_8_sig")
logger = config.logger_new(logtype, **kwargs)
logger.start_output()
for urlitem in urls:
do_print = True
logger.log_filter_url(urlitem.url_data, do_print)
# inject the saved statistics before printing them
logger.stats = config['logger'].stats
logger.end_output()
return logtype
def get_save_filename (parent):
"""Open file save dialog for given parent window and base directory.
Return dialog result."""
title = _("Save check results")
func = QtGui.QFileDialog.getSaveFileName
logtype = parent.saveresultas if parent.saveresultas else 'html'
filters = ";;".join(sortwithfirst(LoggerFilters, Logtype2Filter[logtype]))
filename = "linkchecker-out" + Logtype2FileExt[logtype]
selectedFilter = QtCore.QString()
res = func(parent, title, filename, filters, selectedFilter)
logtype = Filter2Logtype.get(unicode(selectedFilter))
return res, logtype
def sortwithfirst(sequence, firstelement):
"""Move firstelement in a sequence to the first position."""
res = []
for elem in sequence:
if elem == firstelement:
res.insert(0, elem)
else:
res.append(elem)
return res

View file

@ -1,43 +0,0 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2011-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""Provide custom validators."""
from PyQt4 import QtGui
import re
def check_regex (value):
"""Check if given string value can be compiled with re.compile()."""
try:
re.compile(value)
except re.error:
return False
else:
return True
class PyRegexValidator (QtGui.QValidator):
"""Validate input that it is a valid Python regular expression."""
def validate (self, input, pos):
if check_regex(unicode(input)):
return (QtGui.QValidator.Acceptable, pos)
return (QtGui.QValidator.Intermediate, pos)
def fixup (self, input):
while not check_regex(unicode(input)):
input.chop(1)

View file

@ -26,14 +26,12 @@ LOG_ROOT = "linkcheck"
LOG_CMDLINE = "linkcheck.cmdline"
LOG_CHECK = "linkcheck.check"
LOG_CACHE = "linkcheck.cache"
LOG_GUI = "linkcheck.gui"
LOG_THREAD = "linkcheck.thread"
LOG_PLUGIN = "linkcheck.plugin"
lognames = {
"cmdline": LOG_CMDLINE,
"checking": LOG_CHECK,
"cache": LOG_CACHE,
"gui": LOG_GUI,
"thread": LOG_THREAD,
"plugin": LOG_PLUGIN,
"all": LOG_ROOT,

View file

@ -1,78 +0,0 @@
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2008-2014 Bastian Kleineidam
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Check HTML pages for broken links. This is the GUI client.
"""
import sys
import signal
from linkcheck import configuration, drop_privileges, i18n
from linkcheck.loader import is_frozen
if is_frozen():
# Let Python find the C++ runtime DLLs for PyQt.
import os
from linkcheck import get_install_data
sys.path.append(os.path.join(get_install_data(), 'Microsoft.VC90.CRT'))
from PyQt4.QtGui import QApplication
from linkcheck.fileutil import is_readable
from linkcheck.gui import LinkCheckerMain, get_app_style
from linkcheck.gui.projects import ProjectExt
def excepthook (window, etype, evalue, tb):
"""Catch unhandled exceptions."""
from cStringIO import StringIO
from linkcheck.director.console import internal_error
out = i18n.get_encoded_writer(out=StringIO(), encoding="utf-8")
internal_error(out=out, etype=etype, evalue=evalue, tb=tb)
# signal main window to be thread-safe
window.error_signal.emit(out.getvalue())
def main (argv=None):
"""Initialize the Qt application, handle commandline arguments
and show the main window."""
if argv is None:
argv = sys.argv
app = QApplication(argv)
app.setApplicationName(configuration.AppName)
app.setApplicationVersion(configuration.Version)
app.setOrganizationName(configuration.Author)
QApplication.setStyle(get_app_style())
QApplication.setPalette(QApplication.style().standardPalette())
args = app.arguments()
mainkwargs = {}
if len(args) > 1:
fileorurl = unicode(args[1])
if is_readable(fileorurl) and fileorurl.lower().endswith(ProjectExt):
mainkwargs["project"] = fileorurl
else:
mainkwargs["url"] = fileorurl
signal.signal(signal.SIGINT, signal.SIG_DFL)
# use local variable here to avoid garbage collection of the main
# window before app.exec_() finishes
window = LinkCheckerMain(**mainkwargs)
window.show()
window.raise_() # this will raise the window on Mac OS X
drop_privileges()
sys.excepthook = \
lambda etype, evalue, tb: excepthook(window, etype, evalue, tb)
sys.exit(app.exec_())
if __name__ == "__main__":
main()

View file

@ -1,2 +0,0 @@
[Paths]
qt_plugpath=Plugins

View file

@ -2,7 +2,7 @@ XGETTEXT := xgettext
MSGFMT := msgfmt
MSGMERGE := msgmerge
POSOURCES = $(shell find ../linkcheck -name \*.py) \
../linkchecker ../linkchecker-gui /usr/lib/python2.7/argparse.py
../linkchecker /usr/lib/python2.7/argparse.py
LDIR = ../share/locale
PACKAGE = linkchecker
TEMPLATE = $(PACKAGE).pot

1465
po/de.po

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more