<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BulTux &#187; Код</title>
	<atom:link href="http://www.bultux.org/category/code/feed" rel="self" type="application/rss+xml" />
	<link>http://www.bultux.org</link>
	<description>Български блог посветен на свободния софтуер и новото от Linux света</description>
	<lastBuildDate>Sat, 03 Dec 2011 08:18:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Да разведрим деня с pynotify</title>
		<link>http://www.bultux.org/code/da-razvedrim-denq-s-pynotify</link>
		<comments>http://www.bultux.org/code/da-razvedrim-denq-s-pynotify#comments</comments>
		<pubDate>Tue, 18 May 2010 09:51:30 +0000</pubDate>
		<dc:creator>Владимир Колев</dc:creator>
				<category><![CDATA[Код]]></category>
		<category><![CDATA[pynotify]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[жени]]></category>
		<category><![CDATA[майтап]]></category>

		<guid isPermaLink="false">http://www.bultux.org/?p=479</guid>
		<description><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/codes.png" width="22" height="22" alt="" title="Код" /><br/>Така в предния урок ви показах как да си направите браузър, самият урок беше трудно да бъде предаден в по-разбираем вид. Ако сте го разбрали &#8211; добре, ако не съжалявам. За онези, които не са го разбрали или е все още сложно за тях реших да добавя днешния малко хумористичен урок на тема pynotify. Като [...]]]></description>
			<content:encoded><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/codes.png" width="22" height="22" alt="" title="Код" /><br/><div id="attachment_483" class="wp-caption alignright" style="width: 305px"><a href="http://www.bultux.org/wp-content/uploads/2010/05/screenshot_056.png" class="highslide-image" onclick="return hs.expand(this);"><img class="size-full wp-image-483" style="margin-left: 5px; margin-right: 5px;" title="Notification" src="http://www.bultux.org/wp-content/uploads/2010/05/screenshot_056.png" alt="" width="295" height="111" /></a><p class="wp-caption-text">Кратки афоризми в уведомителни балончета</p></div>
<p style="text-align: justify;">Така в предния урок ви показах как да си направите браузър, самият урок беше трудно да бъде предаден в по-разбираем вид. Ако сте го разбрали &#8211; добре, ако не съжалявам. За онези, които не са го разбрали или е все още сложно за тях реших да добавя днешния малко хумористичен урок на тема <a href="http://www.galago-project.org/news/index.php" target="_blank">pynotify</a>. Като крайния резултат ще бъде информативно балонче, което ще се стартира през определен период от време (или при стартирането на компютъра) и ще изважда афоризъм за жените от <a href="http://www.sqlite.org/" target="_blank">sqlite</a> база данни. От сега искам да кажа, че самият скрипт като цяло е изключително лесен, но за начинаещите в Python може да им бъде полезен, представяйки им някои полезни и доста лесни функции за работа с бази данни и хващане на грешки.</p>
<p style="text-align: justify;">Преди да започнем с урока искам да се извиня на всички жени, които попаднат на статията &#8211; афоризмите не са измислени от мен, но просто бяха най-удобния текст, с който можех да си поиграя за настоящия скрипт.<br />
<span id="more-479"></span></p>
<h2>Какво ще ни бъде необходимо</h2>
<p style="text-align: justify;">Както и в предните уроци ще посъветвам да избегнете използването на IDE (Integrated Development Environment) &#8211; причината: Ако не напишете нещо грешно, няма как да го научите. Средите за разработка ви помагат едва след като сте усвоили самият език и ви трябва нещо по-мощно за работа, но ако сте твърдо решени да ползвате такава среда &#8211; не е проблем. Предварително трява да се уверите, че имате инсталирани следните библиотеки за Python:</p>
<ul>
<li>python-pysqlite2</li>
<li>python-notify</li>
<li>sqlite3</li>
</ul>
<p style="text-align: justify;">За да бъде примера по-близък до реалността няма да добавям в урока .db файла с базата данни, а само препратка към списъка с афоризмите. Първата ни стъпка ще бъде този списък да го превърнем в база данни и след това ще я използваме в нашият скрипт.</p>
<p style="text-align: justify;">Списъкът можете да намерите на следния адрес: <a href="http://is.gd/c839M" target="_blank">http://is.gd/c839M</a> (използвайте опцията &#8220;Виж&#8221; и копирайте текста в нов файл, тъй като функцията за изтегляне все още не работи)</p>
<h2>От текстов файл към база данни</h2>
<p style="text-align: justify;">Приемайки, че вече сте инсталирали всичко необходимо и имате файл <strong><em>thewomen</em></strong>, в който се съдържат афоризмите, идва моментът с прехвърлянето на тези записи в една база данни. Принципно бихме могли за този пример да използваме и самия файл, но това би било прекалено лесно, пък и какво по-хубаво от това да разберете малко за sqlite. Нека преди да напишем скрипта, който ще прехвърли всичко от текстовия файл в .db файла да структурираме стъпка по стъпка това, което трябва да се случи:</p>
<ol>
<li>Тъй като това е проста информация и не се нуждаем от кой знае каква функционалност базата ни данни ще съдържа две колони: <em>id</em> и <em>womenfact</em></li>
<li><em>id</em> реално ще отговаря на реда в текстовия файл, <em>womenfact</em> на текста</li>
<li>За да прехвърлим информацията е необходимо да прочетем файла ред по ред и всеки ред да бъде записан под следващото ID в базата данни</li>
<li>id-то ще използваме по-късно, за да изкарваме произволен ред.</li>
</ol>
<p style="text-align: justify;">Нека пристъпим към самият скрипт. Аз ще го запиша първо целия и след това ще обясня ред по ред какво се случва:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="co1">#!/usr/bin/env python</span>
&nbsp;
<span class="kw1">import</span> <span class="kw3">codecs</span>
<span class="kw1">from</span> pysqlite2 <span class="kw1">import</span> dbapi2 <span class="kw1">as</span> sqlite
&nbsp;
<span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:
    <span class="kw2">file</span> <span class="sy0">=</span> <span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">'newtexts'</span><span class="sy0">,</span> <span class="st0">'r'</span><span class="br0">&#41;</span>
    <span class="kw1">try</span>:
        conn <span class="sy0">=</span> sqlite.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'thewomen.db'</span><span class="br0">&#41;</span>
        c <span class="sy0">=</span> conn.<span class="me1">cursor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="kw1">except</span>:
        <span class="kw1">print</span> <span class="st0">&quot;*** Problem creating the db file&quot;</span>
    <span class="kw1">try</span>:
        c.<span class="me1">execute</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;&quot;CREATE TABLE women (id INTEGER PRIMARY KEY, womenfact TEXT)&quot;&quot;&quot;</span><span class="br0">&#41;</span>
        conn.<span class="me1">commit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="kw1">except</span>:
        <span class="kw1">print</span> <span class="st0">&quot;*** Problem creatint the table&quot;</span>
    <span class="kw1">for</span> line <span class="kw1">in</span> <span class="kw2">file</span>:
        <span class="kw1">try</span>:
            c.<span class="me1">execute</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;&quot;INSERT INTO women(womenfact) VALUES('%s')&quot;&quot;&quot;</span> % <span class="br0">&#40;</span>line.<span class="me1">decode</span><span class="br0">&#40;</span><span class="st0">'utf-8'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
            conn.<span class="me1">commit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="kw1">except</span>:
            <span class="st0">&quot;*** Can't write to the database&quot;</span>
    <span class="kw2">file</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    c.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="kw1">if</span> __name__ <span class="sy0">==</span> <span class="st0">'__main__'</span>:
    main<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">Нека обясним сега какво сме направили.</p>
<p style="text-align: justify;">В първите два реда вмъкваме необходимите библиотеки, които ще използва скрипта. След което дефинираме нашият главен метод <em>main()</em>. Започваме нашият метод с отварянето на файла <em>thewomen</em> в режим на четене (за това служи параметъра &#8216;<strong>r</strong>&#8216;). След което опитваме да се свържем към базата данни <strong>thewomen.db</strong>. С <em>except</em> прихващаме възможни грешки, които евентуално биха възникнали при създаването на .db файла. После поставяме курсор &#8220;<strong>c</strong>&#8220;, и в следващият опит създаваме нашата таблица с две колони <em>id</em> и <em>womenfact</em>. Първата колона трябва да бъде <em>Integer</em> (т.е. число) и ще бъде наш главен ключ &#8211; това е достатъчно за sqlite да разбере, че тази стойност ще трябва сама да увеличава стойността си (за разлика от <a href="http://www.mysql.com/" target="_blank">MySQL</a>, където това трябва да опоменем изрично). Колоната <em>womenfact</em> ще съдържа текст (запознатите с MySQL може да потърсят VARCHAR, но в sqlite няма такъв тип данни[http://www.sqlite.org/datatype3.html]). Чрез <em>conn.commit()</em> казваме на sqlite да приложи нанесените от нас промени, т.е. да бъдат записани във файла. Това, което остава за нас е за всеки ред да извъшиме нов запис в базата данни, като важното в случая е да запомните, че ние ще ще декодираме информацията в utf-8, за да нямаме проблеми по-късно с родния ни език. При всеки запис ще потвърждаваме промените с conn.commit(). След като приключи цикъла, т.е. обходили сме всичките 130 реда от нашия файл, затваряме файла, който сме чели и затваряме връзката към базата данни.</p>
<p style="text-align: justify;">Изпълнението на самият скрипт отнема около 5 секунди след което можете да прегледате съдържанието на базата данни с <a href="http://sqliteman.com/" target="_blank">sqliteman</a>.</p>
<h2>Да се научим и да четем</h2>
<p style="text-align: justify;">В нашият случай първо се научихме да пишем, а след това да четем, но това е основният път към научаването в нашият случай. Ако незнаехме как да пишем &#8211; нямаше да има какво да четем нали така? Нека погледнем какво ще трябва да се случая в нашият четец:</p>
<ol>
<li>Трябва да осъществим връзка с базата данни</li>
<li>Трябва да си генерираме произволно число между 0 и 130 (все пак не искаме всеки път да виждаме едно и също)</li>
<li>Ще поискаме ред от базата данни с номер произволното число, което сме генерирали</li>
<li>Резултата ще го разкодираме в utf-8 и ще го покажем чрез Notify балон.</li>
</ol>
<p style="text-align: justify;">Ето го и готовият скрипт:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="co1">#!/usr/bin/env python</span>
<span class="kw1">from</span> pysqlite2 <span class="kw1">import</span> dbapi2 <span class="kw1">as</span> sqlite
<span class="kw1">import</span> <span class="kw3">codecs</span>
<span class="kw1">import</span> <span class="kw3">random</span>
<span class="co1"># това го забравих, но ще ни е необходимо ако не искаме</span>
<span class="co1"># всеки път да пишем директния път до базата данни</span>
<span class="kw1">import</span> <span class="kw3">os</span>
<span class="kw1">try</span>:
    <span class="kw1">import</span> pynotify
<span class="kw1">except</span>:
    <span class="st0">&quot;*** You don't have pynotify installed!&quot;</span>
&nbsp;
<span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:
&nbsp;
    <span class="kw1">try</span>:
        <span class="co1"># Използваме os.environ['HOME'] за да вземем пътя до личната директория</span>
        <span class="co1"># на потребителя, все пак скрипта ни ще бъде стартиран като обикновен потребител</span>
        <span class="co1"># ако го стартираме като root, то ще трябва да запишем базата данни в</span>
        <span class="co1"># директорията на root: /root/.config/</span>
        conn <span class="sy0">=</span> sqlite.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'%s/.config/thewomen.db'</span> % <span class="kw3">os</span>.<span class="me1">environ</span><span class="br0">&#91;</span><span class="st0">'HOME'</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
    <span class="kw1">except</span>:
        <span class="kw1">print</span> <span class="st0">&quot;*** Error connecting to the db file&quot;</span>
    c <span class="sy0">=</span> conn.<span class="me1">cursor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    number <span class="sy0">=</span> <span class="kw3">random</span>.<span class="me1">randint</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="nu0">130</span><span class="br0">&#41;</span>
    <span class="kw1">try</span>:
        c.<span class="me1">execute</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;&quot;SELECT womenfact FROM women WHERE id = %i&quot;&quot;&quot;</span> % number<span class="br0">&#41;</span>
    <span class="kw1">except</span>:
        <span class="kw1">print</span> <span class="st0">&quot;*** Problem selecting a row from the db file&quot;</span>
    row <span class="sy0">=</span> c.<span class="me1">fetchone</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    pynotify.<span class="me1">init</span><span class="br0">&#40;</span><span class="st0">&quot;womenfacts&quot;</span><span class="br0">&#41;</span>
    n <span class="sy0">=</span> pynotify.<span class="me1">Notification</span><span class="br0">&#40;</span><span class="st0">&quot;Womenfact:&quot;</span><span class="sy0">,</span> <span class="st0">&quot;%s&quot;</span> % row<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">encode</span><span class="br0">&#40;</span><span class="st0">'utf-8'</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="st0">&quot;dialog-information&quot;</span><span class="br0">&#41;</span>
    n.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    c.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="kw1">if</span> __name__ <span class="sy0">==</span> <span class="st0">'__main__'</span>:
    main<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">И така първите два реда с import са ви познати и от първия скрипт. С реда <code>import random</code> добавяме библиотеката за генериране на произволни числа. За библиотеката pynotify използваме опит, защото в случай, че потребителя няма инсталиран pynotify той трябва да знае за това, за да може да го инсталира. Ако предоставяте приложението си като .deb пакет примерно тази част можете и да я пропуснете, тъй като най-вероятно ще сте добавили python-pynotify в зависимостите на пакета. В <code>main()</code> метода свързването с базата данни е абсолютно същото, както и при създаването на базата данни &#8211; в случая нищо ново под слънцето. Променливата number използваме, за да запишем в нея произволно число използвайки метода <code>randint (произволен integer)</code>, който приема като параметри диапазона, в който трябва да бъде числото, тъй като ние имаме 130 записа в нашата база данни, то диапазона ще бъде между 1 и 130. След което извикваме нашият курсор, като му казваме да избере <strong>womenfact</strong> от таблицата <em>women</em>, където <strong>id</strong> е равно на генерираното от нас число. Забележете, че при SQLITE сравненията не се правят с двойно равенство, както в Python. Нещо, което изпуснах да отбележа също е и, че при execute използваме тройни кавички &#8211; причината е, че в подобни заявки, може да ни се наложи да използваме двойни и единички кавички и е добра практика да използвате тройни, за всеки случай. Задаваме променлива row (ред), към която присвояваме първият резултат от нашата заявка. Имайте предвид, че резултата е масив &#8211; конкретно в нашият случай е с една единствена стойност, но все пак остава масив и ще трябва по-късно да го третираме като такъв. С реда <code>pynotify.init("womenfacts")</code> инициализираме pynotify, като му казваме, че ние сме ново приложение, което иска да използва услугата за уведомявания. Ако изпуснете този ред, най-вероятно няма да видите никакво балонче ;). Променливата n става нашето уведомление &#8220;Notification&#8221;, което приема три параметръра:</p>
<ol>
<li>Заглавие &#8211; &#8220;Womenfact:&#8221;</li>
<li>Текст, който е първият елемент от масива, кодиран в utf-8</li>
<li>Име на изображение, което да бъде използвано &#8211; dialog-information</li>
</ol>
<p>Казваме на нашето уведомление да бъде показано с метода <code>show()</code> и прекъсваме връзката с базата данни.</p>
<h2>Да направим използването на системата забавно</h2>
<p style="text-align: justify;">След като вече имаме нашият скрипт, който от своята база данни извежда произволен афоризъм може да се каже, че сме почти готови. Това което остава е да свъжеме скрипта ни със системата, така че да се показва автоматично. За целта имам три възможности:</p>
<ol>
<li>Да прикачим скрипта към глобална клавишна комбинация (виж <a href="http://www.bultux.org/scripts/python-aktualna-pesen-w-clipboard" target="_blank">Python: Актуалната песен в Clipboard</a>)</li>
<li>Да добавим скрипта към автоматично стартиращите се приложения (можете да го направите от Startup Applications)</li>
<li>Последния и по-забавен разбира се е да накараме нашият скрипт да се стартира през определен период от време. За тази цел обаче ще трябва да използваме <strong>cron</strong> (услуга в UNIX/Linux света за автоматизиране на процеси)</li>
</ol>
<p>Тъй като първите два варианта по обясними причини не са толкова интересни, в този урок ще обясня само последния. Преди да добавим нашият скрипт към списъка на cron е редно да направим няколко корекции.</p>
<ul>
<li>-Ще прекръстим скрипта си на нещо по-кратко и ще махнем разширението му &#8211; нека бъде <code>womenfacts</code> и ще го направим изпълнум</li>
</ul>


<div class="wp-geshi-highlight"><div class="bash"><pre class="de1"><span class="kw2">mv</span> името_на_вашия_скрипт.py womenfacts <span class="sy0">&amp;&amp;</span> <span class="kw2">chmod</span> +x womenfacts</pre></div></div>


<ul>
<li>Ще преместим нашата база данни на място, от което няма да я забършем по погрешка (<code>~/.config</code>)</li>
</ul>


<div class="wp-geshi-highlight"><div class="bash"><pre class="de1"><span class="kw2">mv</span> thewomen.db ~<span class="sy0">/</span>.config<span class="sy0">/</span></pre></div></div>


<ul>
<li>Трябва да нанесем промяната в нашият скрипт, за да нямаме проблеми с връзката към базата данни</li>
</ul>
<p>Променяме:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">conn <span class="sy0">=</span> sqlite.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'women.db'</span><span class="br0">&#41;</span></pre></div></div>


<p>на:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">conn <span class="sy0">=</span> sqlite.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'%s/.config/women.db'</span> % <span class="kw3">os</span>.<span class="me1">environ</span><span class="br0">&#91;</span><span class="st0">'HOME'</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="co1"># Използваме os.environ['HOME'], за да вземем пътя до домашната директория на потребителя!</span></pre></div></div>


<p>Наложително е да използваме абсолютния път до директорията &#8211; в случая <code>~/</code> няма да ни бъде от голяма полза.</p>
<ul>
<li>Копираме скрипта ни в <code>/usr/local/bin</code> (за да бъде глобално изпълним):</li>
</ul>


<div class="wp-geshi-highlight"><div class="bash"><pre class="de1"><span class="kw2">sudo</span> <span class="kw2">cp</span> <span class="re5">-fp</span> womenfacts <span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>bin<span class="sy0">/</span> <span class="co0"># използваме и параметъра -p, за да запазим правата върху файла</span></pre></div></div>


<p style="text-align: justify;">Тествайте, за да се уверите, че при изпълнението на womenfacts от терминала виждате балончето.</p>
<p style="text-align: justify;">Сега идва реда на cron. Ако до сега не сте използвали cron. Първото нещо, което трябва да направите е да стартирате <strong>crontab</strong> с параметъра <strong>-e</strong>, в което ще бъдете попитани кой редактор искате да използвате (none, pino, vi, joe и т.н.). Имайте предвид, че ако искате cron да бъде запазен за всяка сесия, а не само за настоящата ще трябва да стартирате corntab като root (с администраторски права). По подрабиране, най-вероятно cron ще бъде празен. За нашия скрипт ние ще трябва да въведем следното:</p>


<div class="wp-geshi-highlight"><div class="bash"><pre class="de1"><span class="sy0">*/</span><span class="nu0">5</span> <span class="sy0">*</span> <span class="sy0">*</span> <span class="sy0">*</span> <span class="sy0">*</span> <span class="re2">DISPLAY</span>=:<span class="nu0">0</span> <span class="re2">PYTHONPATH</span>=::<span class="sy0">/</span>usr<span class="sy0">/</span>lib<span class="sy0">/</span>python2.6<span class="sy0">/</span>dist-packages<span class="sy0">/</span>gtk-<span class="nu0">2.0</span><span class="sy0">/</span>:<span class="re1">$PYTHONPATH</span> <span class="sy0">/</span>usr<span class="sy0">/</span>bin<span class="sy0">/</span>python <span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>bin<span class="sy0">/</span>womenfacts <span class="co0"># JOB_ID_1</span></pre></div></div>


<p style="text-align: justify;">Какво означава това. Първата част <strong>*/5</strong> означава да бъде стартиран всеки пет минути. Ако е само 5 означава в петата минута на всеки час. Останалите параметри са за съответно: час, ден от месеца, месец, ден от седмицата (общо пет с първия параметър). Тъй като нашият пример е малко по-специфичен &#8211; налага се да работиме с графично приложение задаваме някои константи преди да изпълниме нашият скрипт чрез cron. Първата и най-важна е <strong>DISPLAY=:0</strong> означва, че ще използваме първия дисплей, останалите са свързани с пътищата да Python и използваната библиотека GTK и накрая пътят до нашият скрипт. За повече информация как да боравите с cron и как да разберете видовете настройки можете да прегледате информацията в wikipedia [<a href="http://en.wikipedia.org/wiki/Cron" target="_blank">http://en.wikipedia.org/wiki/Cron</a>] или прегледайте man страницата. За по-бързо разяснение:</p>
<pre>.---------------- минута (0 - 59)
|  .------------- час (0 - 23)
|  |  .---------- ден от месеца (1 - 31)
|  |  |  .------- месец (1 - 12) ИЛИ jan,feb,mar,apr ...
|  |  |  |  .---- ден от седмицата (0 - 7) (Неделя=0 или 7)  ИЛИ sun,mon,tue,wed,thu,fri,sat
|  |  |  |  |
*  *  *  *  *  команда, която да бъде изпълнена</pre>
<p style="text-align: justify;"><div class="note"><div class="noteclassic">Ако имате проблеми с разбирането на crontab или се страхувате от терминала, можете да пробвате приложението <a href="http://gnome-schedule.sourceforge.net/" target="_blank">gnome-schedule</a>, с което всичко това, можете да направите от графичен интерфейс.</div></div><br />
Надявам се урокът да ви е бил полезен. Под статията ще намерите и готовите файлове, но ще се радвам да споделите в коментарите и други приложения на скрипта или поне вие по какъв начин го използвате.<br />
<img src="http://imgur.com/b0SVe.png" border="0" /><a href="http://www.bultux.org/wp-content/plugins/download-monitor/download.php?id=13" title="Изтеглен 96 пъти"><strong>thewomen-tut</strong>  (8.78 KB)</a> 96 изтегляния</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bultux.org/code/da-razvedrim-denq-s-pynotify/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Собствен уеб-браузър с PyGTK и WebKit</title>
		<link>http://www.bultux.org/code/sobstven-web-browser-s-pygtk-i-webkit</link>
		<comments>http://www.bultux.org/code/sobstven-web-browser-s-pygtk-i-webkit#comments</comments>
		<pubDate>Wed, 12 May 2010 15:51:41 +0000</pubDate>
		<dc:creator>Владимир Колев</dc:creator>
				<category><![CDATA[Код]]></category>
		<category><![CDATA[pygtk]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[webkit]]></category>
		<category><![CDATA[браузър]]></category>

		<guid isPermaLink="false">http://www.bultux.org/?p=467</guid>
		<description><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/codes.png" width="22" height="22" alt="" title="Код" /><br/>Преглеждайки днес новостите по мрежата в любимия ми сайт TuxRadar попаднах на един нов видео урок, който за 20 минути ни показва как можем да използваме Python, Webkit и PyGTK, за да си направим просто браузър. За съжаление урока не беше пълен и всичкото ставаше от Python интерпретатора, затова реших да използвам видео урока за [...]]]></description>
			<content:encoded><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/codes.png" width="22" height="22" alt="" title="Код" /><br/><div id="attachment_468" class="wp-caption alignright" style="width: 310px"><a href="http://www.bultux.org/wp-content/uploads/2010/05/screenshot_049.png" class="highslide-image" onclick="return hs.expand(this);"><img class="size-medium wp-image-468" title="pybrowser_01" src="http://www.bultux.org/wp-content/uploads/2010/05/screenshot_049-300x218.png" alt="" width="300" height="218" /></a><p class="wp-caption-text">PyBrowser - уеб-браузър само в по-малко от 100 реда код</p></div>
<p style="text-align: justify;">Преглеждайки днес новостите по мрежата в любимия ми сайт <a href="http://www.tuxradar.com" target="_blank">TuxRadar</a> попаднах на един <a href="http://www.tuxradar.com/content/python-pygtk-webkit-20-minutes" target="_blank">нов видео урок</a>, който за 20 минути ни показва как можем да използваме <a href="http://www.python.org/" target="_blank">Python</a>, <a href="http://webkit.org/" target="_blank">Webkit</a> и <a href="http://www.pygtk.org/" target="_blank">PyGTK</a>, за да си направим просто браузър. За съжаление урока не беше пълен и всичкото ставаше от Python интерпретатора, затова реших да използвам видео урока за база и, доколкото е възможно да го разширя до нещо функциониращо. В този урок &#8211; ще ви покажа как да създадете от-до браузъра и съответно как да добавите, някои полезни функции. В края на урока ще добавя и препратки, в които можете да търсите повече информация за използването на webkit ако решите да разширите браузъра с повече възможности.</p>
<h2>Нека започнем</h2>
<p style="text-align: justify;">Какво ще ни бъде необходимо. Първо трябва да се уверите дали имате инсталирано всичко необходимо:</p>
<ul style="text-align: justify;">
<li>python</li>
<li>python-gtk2</li>
<li>python-webkit</li>
</ul>
<p style="text-align: justify;">Разбира се, за да пишете код ще ви е необходим и редактор &#8211; тук всичко остава във ваши ръце. Ще препоръчам само да не използвате среда за разработка като Eclipse или NetBeans, тъй като за начало е напълно излишно, тъй като ще бъде редактиран само един файл (функционален браузър в един файл &#8211; точно така). Разбира се можете да подготвите и три икони &#8211; една за прозореца, една за бутон Go и една за презареждане. Може и без тях, но аз не обичам да ползвам бутони с текст. В самия урок, ще добавя коментар, как можете да използвате и нормални бутони с текст или бутоните, включени в GNOME (което ще ви позволи и превод на интерфейса директно с писането на приложението).<br />
<span id="more-467"></span></p>
<h2>Вмъкване на всичко необходимо и първия прозорец</h2>
<p style="text-align: justify;">Нека започнем с писането. Първоначално е редно да добавим библиотеките, които ще използваме и да създадем скелета на приложението (класовете и методите). Започваме от вмъкването на необходимите библиотеки със следните 4 реда:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="kw1">import</span> gtk
<span class="co1"># Следващите два реда са необходими, за да не получавате грешка от Glibc при стартирането на приложението</span>
<span class="kw1">import</span> gobject
gobject.<span class="me1">threads_init</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="co1"># И разбира се добавяме webkit</span>
<span class="kw1">import</span> webkit
&nbsp;
<span class="kw1">class</span> PyBrowser:
    <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
        <span class="kw1">pass</span>
&nbsp;
    <span class="kw1">def</span> main<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
        <span class="co1"># тук стартираме основния метод на gtk</span>
        gtk.<span class="me1">main</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
    <span class="kw1">def</span> delete_event<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> widget<span class="sy0">,</span> data<span class="sy0">=</span><span class="kw2">None</span><span class="br0">&#41;</span>:
        <span class="co1"># тук ще дефинираме изхода от приложението, за което отново използваме метод от gtk</span>
        gtk.<span class="me1">main_quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
    <span class="kw1">def</span> enter_pressed<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> entry<span class="br0">&#41;</span>:
        <span class="co1"># оставяме място за действие при натискате на клавиша Enter в полето за писане</span>
&nbsp;
    <span class="kw1">def</span> go_clicked<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> btn<span class="br0">&#41;</span>:
        <span class="co1"># оставяме място да дефинираме действието на бутона Go!</span>
&nbsp;
    <span class="kw1">def</span> refresh_browser<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> btn<span class="br0">&#41;</span>:
        <span class="co1"># място за действието на бутона за презареждане на страницата</span>
&nbsp;
    <span class="kw1">def</span> title_changed<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> webview<span class="sy0">,</span> frame<span class="sy0">,</span> title<span class="br0">&#41;</span>:
        <span class="co1"># добре ще е разбира се да обновяваме заглавието на прозореца със заглавието на настоящата</span>
        <span class="co1"># страница</span>
&nbsp;
<span class="kw1">if</span> __name__ <span class="sy0">==</span> <span class="st0">&quot;__main__&quot;</span>:
    <span class="co1"># След като използваме класове трябва да ги прехвърлим към обект</span>
    browse <span class="sy0">=</span> PyBrowser<span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="co1"># и с този обект да извикаме основния метод main()</span>
    browse.<span class="me1">main</span><span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">Както виждате основната част на приложението е изключително интуитивна. Редно е да се поясни, че конструктора <code>__init__</code> ще ни служи за да построим самия прозорец на приложението и в него ще опишем всички действия, бутони, полета и самия браузър. Ако до момента не сте срещали подобен конструктор прегледайте <a href="http://www.penzilla.net/tutorials/python/classes/" target="_blank">http://www.penzilla.net/tutorials/python/classes/</a> &#8211; изключително добре описано с примери .Също така self обяснява, че това са лични методи към класът PyBrowser и за да ги извикваме ще трябва да пишем self пред името на всеки метод.</p>
<h2>Да създадем прозореца с джаджите</h2>
<p style="text-align: justify;">В gtk всяко нещо е widget, включително бутоните, полетата за текст и т.н. И те трябва да бъдат добавяни в съдържатели &#8211; било то фиксирани, вертикални кутии, хоризонтални кутии, таблици и т.н. В този урок ние ще използваме вертикални и хоризонтални кутии. Но преди това нека първо създадем нашия прозорец. Това става изключително лесно добавяме следното в __init__:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">        <span class="kw2">self</span>.<span class="me1">window</span> <span class="sy0">=</span> gtk.<span class="me1">Window</span><span class="br0">&#40;</span>gtk.<span class="me1">WINDOW_TOPLEVEL</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">window</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;delete_event&quot;</span><span class="sy0">,</span> <span class="kw2">self</span>.<span class="me1">delete_event</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">window</span>.<span class="me1">set_title</span><span class="br0">&#40;</span><span class="st0">&quot;PyBrowser v.0.1&quot;</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">window</span>.<span class="me1">set_icon_from_file</span><span class="br0">&#40;</span><span class="st0">&quot;icons/pybrowser_small.png&quot;</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">window</span>.<span class="me1">resize</span><span class="br0">&#40;</span><span class="nu0">600</span><span class="sy0">,</span> <span class="nu0">480</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">Да поясним какво сме направили &#8211; с първия ред създаваме нов прозорец, който да бъде първи в йерархията (в случай, че по-късно използваме още прозорци към приложението). Свързваме &#8220;delete_event&#8221; &#8211; с методът, който предварително сме дефинирали. Това е важно, за да кажем на нашето приложение, че при натискане на бутона X в заглавната лента на прозореца искаме приложението да спира да работи. След което с <strong>set_title</strong>, <strong>set_icon_from_file</strong> и <strong>resize</strong> определяме какво да бъде заглавието на нашето приложение, къде се намира иконата на прозореца (директорията <em>icons/</em> трябва да се намира при файла <strong><em>pybrowser.py</em></strong>) и определяме големината на прозореца по подразбиране 600&#215;480 пиксела.</p>
<p style="text-align: justify;">Време е да дефинираме и нашите съдържатели &#8211; ще използваме три: HBox, VBox и ScrolledWindow. Последният ще съдържа нашият браузър, за да можем при отварянето на страници, по-големи от нашият прозорец да използваме плъзгачи за скрол. С други думи добавяме следното:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">        <span class="co1"># контейнерът за webkit</span>
        <span class="kw2">self</span>.<span class="me1">scroller</span> <span class="sy0">=</span> gtk.<span class="me1">ScrolledWindow</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="co1"># hbox и vbox сътоветно за хоризонтална и вертикална подредба</span>
        <span class="kw2">self</span>.<span class="me1">vbox</span> <span class="sy0">=</span> gtk.<span class="me1">VBox</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">hbox</span> <span class="sy0">=</span> gtk.<span class="me1">HBox</span><span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">Няма никакво значение как ще ги подредите, тъй като самото им използване ще се случи малко по-надолу в кода. HBox ще използваме за текстовото поле, в което ще въвеждаме URL, бутонът за старт на зареждането и бутонът за презареждане. Остава да ги дефинираме и да ги добавим към съдържателя:<br />
Първо да създадем нашето текстово поле:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">        <span class="co1"># Дефинираме нашето поле с името urltext</span>
        <span class="kw2">self</span>.<span class="me1">urltext</span> <span class="sy0">=</span> gtk.<span class="me1">Entry</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="co1"># Задаваме на полето текст по подразбиране - не е задължително</span>
        <span class="co1"># но пък от друга страна е по-добре от празна кутия</span>
        <span class="kw2">self</span>.<span class="me1">urltext</span>.<span class="me1">set_text</span><span class="br0">&#40;</span><span class="st0">&quot;http://&quot;</span><span class="br0">&#41;</span>
        <span class="co1"># задаваме размер по подразбиране - първата стойност ще бъде пропусната по подразбиране</span>
        <span class="co1"># докато втората, ще се използва за задаване на височината, тъй като бутоните, които аз</span>
        <span class="co1"># използвам са с рамери 32x32. В случай, че използвате други размери, можете спокойно</span>
        <span class="co1"># да изтриете този ред</span>
        <span class="kw2">self</span>.<span class="me1">urltext</span>.<span class="me1">set_size_request</span><span class="br0">&#40;</span><span class="nu0">600</span><span class="sy0">,</span><span class="nu0">38</span><span class="br0">&#41;</span>
        <span class="co1"># Свързваме действие, когато потребителя въведе адрес и натисне клавиша Enter</span>
        <span class="co1"># нещо, което повечето хора правят дори несъзнателно</span>
        <span class="kw2">self</span>.<span class="me1">urltext</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;activate&quot;</span><span class="sy0">,</span> <span class="kw2">self</span>.<span class="me1">enter_pressed</span><span class="br0">&#41;</span></pre></div></div>


<p>След като имаме полето за текст остава да създадем и двата бутона:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">        <span class="co1"># Създаваме нов бутон с името gobutton</span>
        <span class="co1"># В случай, че решите да не използвате изображение, можете да изтриете</span>
        <span class="co1"># следните 3 реда и да промените този на:</span>
        <span class="co1">#self.gobutton = gtk.Button(&quot;Go!&quot;)</span>
        <span class="kw2">self</span>.<span class="me1">gobutton</span> <span class="sy0">=</span> gtk.<span class="me1">Button</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="co1"># Дефинираме обект за изображение goimage, в който ще запишем</span>
        <span class="co1"># изображението, което ще използваме за този бутон</span>
        <span class="kw2">self</span>.<span class="me1">goimage</span> <span class="sy0">=</span> gtk.<span class="me1">Image</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="co1"># задаваме пътят към изображението</span>
        <span class="kw2">self</span>.<span class="me1">goimage</span>.<span class="me1">set_from_file</span><span class="br0">&#40;</span><span class="st0">&quot;icons/go.png&quot;</span><span class="br0">&#41;</span>
        <span class="co1"># прикачаме изображението към бутона</span>
        <span class="kw2">self</span>.<span class="me1">gobutton</span>.<span class="me1">set_image</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">goimage</span><span class="br0">&#41;</span>
        <span class="co1"># Ако сте решили да не използвате изображения, тук трябва да спрете с триенето</span>
        <span class="co1"># Задаваме действие не бутона, когато той бъде натиснат искаме да се изпълни</span>
        <span class="co1"># методът go_clicked</span>
        <span class="kw2">self</span>.<span class="me1">gobutton</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;clicked&quot;</span><span class="sy0">,</span> <span class="kw2">self</span>.<span class="me1">go_clicked</span><span class="br0">&#41;</span> <span class="co1"># the Go! button</span>
&nbsp;
        <span class="co1"># Правим същото за бутонът за презареждане</span>
        <span class="kw2">self</span>.<span class="me1">refresh</span> <span class="sy0">=</span> gtk.<span class="me1">Button</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">refreshimage</span> <span class="sy0">=</span> gtk.<span class="me1">Image</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">refreshimage</span>.<span class="me1">set_from_file</span><span class="br0">&#40;</span><span class="st0">&quot;icons/reload.png&quot;</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">refresh</span>.<span class="me1">set_image</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">refreshimage</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">refresh</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;clicked&quot;</span><span class="sy0">,</span> <span class="kw2">self</span>.<span class="me1">refresh_browser</span><span class="br0">&#41;</span> <span class="co1"># The reload button</span>
&nbsp;
        <span class="co1"># След като сме създали текстовото поле и бутоните трябва</span>
        <span class="co1"># да ги добавим към хоризонталния съдържател HBox</span>
        <span class="kw2">self</span>.<span class="me1">hbox</span>.<span class="me1">pack_start</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">urltext</span><span class="br0">&#41;</span>
        <span class="co1"># Забележете вторият параметър False, той казва на Gtk</span>
        <span class="co1"># Че тези бутони трябва да използват минималното място,</span>
        <span class="co1"># от което се нуждаят за да бъдат показани</span>
        <span class="kw2">self</span>.<span class="me1">hbox</span>.<span class="me1">pack_start</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">gobutton</span><span class="sy0">,</span> <span class="kw2">False</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">hbox</span>.<span class="me1">pack_start</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">refresh</span><span class="sy0">,</span> <span class="kw2">False</span><span class="br0">&#41;</span></pre></div></div>


<p>Нека създадем и нашият браузър:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">        <span class="co1"># Дефинираме браузъра си като WebView - рамка за визуализиране</span>
        <span class="co1"># на HTML страници</span>
        <span class="kw2">self</span>.<span class="me1">browser</span> <span class="sy0">=</span> webkit.<span class="me1">WebView</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="co1"># Просто защото е забавно задаваме още тук браузърът да отвори google</span>
        <span class="co1"># По този начин си имаме първоначална страница за зареждане</span>
        <span class="co1"># Ако искате да използвате файл, можете да добавите следното, като</span>
        <span class="co1"># предварително добавите import os при вмъкването на библиотеките:</span>
        <span class="co1"># self.browser.open(&quot;file://%s/file.html&quot; % (os.getcwd()))</span>
        <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">&quot;http://www.google.com/webhp?hl=en&quot;</span><span class="br0">&#41;</span>
        <span class="co1"># Използваме слушател, който да стартира метода title_changed, щом</span>
        <span class="co1"># заглавието на страницата бъде променено</span>
        <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;title-changed&quot;</span><span class="sy0">,</span> <span class="kw2">self</span>.<span class="me1">title_changed</span><span class="br0">&#41;</span>
        <span class="co1"># Създаваме сигнал, който ще контролира нашата лента за зареждане</span>
        <span class="co1"># по този начин &quot;слушаме&quot; за промени</span>
        <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;load-progress-changed&quot;</span><span class="sy0">,</span> <span class="kw2">self</span>.<span class="me1">load_progress_changed</span><span class="br0">&#41;</span>
        <span class="co1"># дефинираме какво трябва да се случи при започване на зареждане</span>
        <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;load-started&quot;</span><span class="sy0">,</span> <span class="kw2">self</span>.<span class="me1">load_started</span><span class="br0">&#41;</span>
        <span class="co1"># дефинираме и какво трябва да се случи, когато страницата е заредена</span>
        <span class="co1"># тези методи ще създадем след малко</span>
        <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;load-finished&quot;</span><span class="sy0">,</span> <span class="kw2">self</span>.<span class="me1">load_finished</span><span class="br0">&#41;</span>
        <span class="co1"># Добавяме, както споменахме по-рано браузърът в ScrolledWindow съдържател</span>
        <span class="co1"># така можем да използваме плъзгачи, в случай, че страницата е по-голяма</span>
        <span class="co1"># от нашия прозорец</span>
        <span class="kw2">self</span>.<span class="me1">scroller</span>.<span class="me1">add</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">browser</span><span class="br0">&#41;</span></pre></div></div>


<p>В следващата част от нашият код, ще извършим няколко неща наведнъж, а именно:<br />
1. Ще създадем нашата лента за прогрес</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">        <span class="kw2">self</span>.<span class="me1">progress</span> <span class="sy0">=</span> gtk.<span class="me1">ProgressBar</span><span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">2. Ще добавиме всичките до сега дефинирани джаджи във вертикалния съдържател, като не трябва да забравяте, че този тип съдържатели, могат да съдържат и други съдържатели:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">        <span class="co1"># Първо добавяме нашата хоризонтална кутия, с текстовото поле</span>
        <span class="co1"># и бутоните. Помните вторият параметър (Flase), оказва съответната</span>
        <span class="co1"># джаджа да не се разпростира много, а да използва от прозореца</span>
        <span class="co1"># само толкова, колкото й трябва</span>
        <span class="kw2">self</span>.<span class="me1">vbox</span>.<span class="me1">pack_start</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">hbox</span><span class="sy0">,</span> <span class="kw2">False</span><span class="br0">&#41;</span>
        <span class="co1"># Под бутоните и текстовото поле бихме искали директно да виждаме</span>
        <span class="co1"># нашият браузър</span>
        <span class="kw2">self</span>.<span class="me1">vbox</span>.<span class="me1">pack_start</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">scroller</span><span class="br0">&#41;</span>
        <span class="co1"># И накрая добавяме лентата за прогрес, която по-късно ще скрием</span>
        <span class="kw2">self</span>.<span class="me1">vbox</span>.<span class="me1">pack_start</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">progress</span><span class="sy0">,</span> <span class="kw2">False</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">3. Последното, което остана при дефинирането на нашия прозорец е той да съдържа дефинираните до сега съдържатели и да бъде показан. Това правим по следния начин:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">        <span class="co1"># Vbox вече съдържа всичките джаджи, които сме дефинирали</span>
        <span class="kw2">self</span>.<span class="me1">window</span>.<span class="me1">add</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">vbox</span><span class="br0">&#41;</span>
        <span class="co1"># Казваме на нашият прозорец да покаже всичко, което сме му добавили,</span>
        <span class="co1"># включително и себе си</span>
        <span class="kw2">self</span>.<span class="me1">window</span>.<span class="me1">show_all</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="co1"># Just show everything</span></pre></div></div>


<h2>Малко действия</h2>
<p style="text-align: justify;">До тук това, което постигнахме е просто един прозорец, който в идеалния случай ще се зареди, но няма да бъде функционален, тъй като бутоните, и самите действия все още не са дефинирани. Прегледайте отново скелета на приложението. Ще разгледаме методите един по един. Като накрая ще добавим методите, който ще контролират нашата лента за прогрес (не мога да измисля по-точен превод на български, така че моля уважаемият читател да ме извини).</p>
<p style="text-align: justify;">Натискането на клавишът <strong>[Enter]</strong>:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="kw1">def</span> enter_pressed<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> entry<span class="br0">&#41;</span>:
        <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="kw2">open</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">urltext</span>.<span class="me1">get_text</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">Методът приема два параметъра &#8211; първо, че е част от класа, второто, че сигналът му е пратен от Entry &#8211; текстово поле. Това което казваме да се случи: нека браузърът (<strong>self.browser</strong>) отвори (<strong>open</strong>) съдържанието на текстовото поле. <strong>self.urltext</strong> &#8211; е нашето текстово поле и то има метод <strong><em>get_text()</em></strong>, който взима неговото съдържание. В Този метод можете да добавите и проверка, дали въведения адрес е валиден или пък ако искате при невалиден адрес, да отворите google търсачката. За целта нека ви покажа как можете да го направите по по-елементарния начин (без регулярни изрази):</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="kw1">def</span> enter_pressed<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> entry<span class="br0">&#41;</span>:
    <span class="co1"># съдържанието на текстово поле го записваме в променлива</span>
    theurl <span class="sy0">=</span> <span class="kw2">self</span>.<span class="me1">urltext</span>.<span class="me1">get_text</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="co1"># и започваме да проверяваме:</span>
    <span class="kw1">if</span> <span class="st0">&quot;http://&quot;</span> <span class="kw1">in</span> theurl <span class="kw1">or</span> <span class="st0">&quot;www.&quot;</span> <span class="kw1">in</span> theurl:
        <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="kw2">open</span><span class="br0">&#40;</span>theurl<span class="br0">&#41;</span>
    <span class="kw1">else</span>:
        <span class="co1"># Ако няма http или www в адреса, допускаме, че това е</span>
        <span class="co1"># просто някакъв текст, за да го превърнем в текст, който</span>
        <span class="co1"># да добавим към адреса на google за търсене заменяме празните</span>
        <span class="co1"># полета със знака +</span>
        searchterm <span class="sy0">=</span> theurl.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span><span class="sy0">,</span> <span class="st0">&quot;+&quot;</span><span class="br0">&#41;</span>
        <span class="co1"># предаваме нов адрес, в който е и нашето понятие за търсене</span>
        <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">&quot;http://www.google.com/search?sourceid=chrome&amp;ie=UTF-8&amp;q=%s&quot;</span> % searchterm<span class="br0">&#41;</span></pre></div></div>


<p>Идентичен е и метода при натискането на бутона <strong>Go!</strong>. Разликата е в това, че сигналът се изпраща от бутон:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="kw1">def</span> go_clicked<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> btn<span class="br0">&#41;</span>:
    <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="kw2">open</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">urltext</span>.<span class="me1">get_text</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">По същия начин описан по-горе, можете да си добавите и проверка. Би било добре тази проверка да я направите с регулярен израз, защото ще е по-смислено и по-практично.</p>
<p>Методът за нашият бутон за презареждане ще изглежда по следния начин:</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="kw1">def</span> refresh_browser<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> btn<span class="br0">&#41;</span>:
    <span class="co1"># За наше успокоение WebView от WebKit има тази функция вградена</span>
    <span class="co1"># и това, което трябва да направим е просто да я извикаме</span>
    <span class="kw2">self</span>.<span class="me1">browser</span>.<span class="kw2">reload</span><span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">Разбрахме се още в началото, че нашият браузър ще показва заглавието на настоящата страница &#8211; затова и добавихме сигнал при дефинирането на нашият браузър, това, което остава за нас е да кажем какво трябва да се случи.</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="kw1">def</span> title_changed<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> webview<span class="sy0">,</span> frame<span class="sy0">,</span> title<span class="br0">&#41;</span>:
     <span class="co1"># Тук това вече е част от нашият Gtk прозорец, затова и не извикваме</span>
     <span class="co1"># webkit на помощ, от него просто взимаме заглавието</span>
    <span class="kw2">self</span>.<span class="me1">window</span>.<span class="me1">set_title</span><span class="br0">&#40;</span>title<span class="br0">&#41;</span></pre></div></div>


<p style="text-align: justify;">Малкото, което остана е да дефинираме и три метода за нашата прогресна лента. Единият от тях трябва да разделя зареждането на стъпки. Другите два служат просто за прихващане на сигналите &#8211; &#8220;започване на зареждането&#8221; и &#8220;приключване на зареждането&#8221;. WebKit ни улеснява изключително много и в трите метода. Като ни предлага всичко готово. Това, което се изисква от нас е да определим как ще бъдат разделени стъпките, за да ги разбере GTK и какво трявбад а се случва при започване на зареждане и когато страницата бъде заредена.</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">    <span class="kw1">def</span> load_progress_changed<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> webview<span class="sy0">,</span> amount<span class="br0">&#41;</span>:
        <span class="co1"># Тук ще обясня какво е amount - това е цялото количество данни, които</span>
        <span class="co1"># ще бъдат изтеглени - това ни се подава от WebKit. За да работи</span>
        <span class="co1"># Нашата прогресна лента - трябва големината на данните, да разделим на 100.0</span>
        <span class="co1"># Нарочно не използваме integer - остава да подадем резултата на метода</span>
        <span class="co1"># set_fraction, който е част от gtk.ProgressBar</span>
        <span class="kw2">self</span>.<span class="me1">progress</span>.<span class="me1">set_fraction</span><span class="br0">&#40;</span>amount / <span class="nu0">100.0</span><span class="br0">&#41;</span>
&nbsp;
    <span class="kw1">def</span> load_started<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> webview<span class="sy0">,</span> frame<span class="br0">&#41;</span>:
        <span class="co1"># За да бъде по-интерактивен браузъра показваме</span>
        <span class="co1"># лентата за зарежда само, когато има зареждане</span>
        <span class="kw2">self</span>.<span class="me1">progress</span>.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
    <span class="kw1">def</span> load_finished<span class="br0">&#40;</span><span class="kw2">self</span><span class="sy0">,</span> webview<span class="sy0">,</span> frame<span class="br0">&#41;</span>:
        <span class="co1"># Щом зареждането приключи взимаме адреса на заредената</span>
        <span class="co1"># страница и го записваме в текстовото поле за адрес</span>
        <span class="co1"># след което скриваме лентата за зареждане, за да не ни пречи</span>
        <span class="kw2">self</span>.<span class="me1">urltext</span>.<span class="me1">set_text</span><span class="br0">&#40;</span>frame.<span class="me1">get_uri</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
        <span class="kw2">self</span>.<span class="me1">progress</span>.<span class="me1">hide</span><span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>


<h2>Край</h2>
<p style="text-align: justify;">Надявам се с този урок да сте разбрали колко е лесно да направите собствен браузър с Python и WebKit. Това, което можете да приемете като домашно е да разгледате другите методи, и действия, които ви предлага Webkit и просто да ги добавите във вашето приложение. Тъй като за момента не успях да намеря публично API, с python-webkit аз използвах това, което е за C &#8211; не се различават по нищо, тъй като ако не знаете, Python почти без проблем използва <a href="http://webkitgtk.org/reference/webkitgtk-WebKitWebView.html" target="_blank">WebKitWebView С-библиотеките</a> като собствени.</p>
<p style="text-align: justify;">Разбира се можете да изтеглите и крайният резултат в случай, че имате проблем с разбирането на целия текст.<br />
<img src="http://imgur.com/b0SVe.png" border="0" /><a href="http://www.bultux.org/wp-content/plugins/download-monitor/download.php?id=12" title="Изтеглен 125 пъти"><strong>PyBrowse </strong>  (13.08 KB)</a> 125 изтегляния</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bultux.org/code/sobstven-web-browser-s-pygtk-i-webkit/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

