<?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; python</title>
	<atom:link href="http://www.bultux.org/tag/python/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>Десктоп клиент за grooveshark</title>
		<link>http://www.bultux.org/applications/desktop-klient-za-grooveshark</link>
		<comments>http://www.bultux.org/applications/desktop-klient-za-grooveshark#comments</comments>
		<pubDate>Sat, 21 May 2011 08:59:25 +0000</pubDate>
		<dc:creator>Владимир Колев</dc:creator>
				<category><![CDATA[Приложения]]></category>
		<category><![CDATA[grooveshark]]></category>
		<category><![CDATA[gSharkDown]]></category>
		<category><![CDATA[mp3]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[аудио]]></category>
		<category><![CDATA[изтегляне]]></category>

		<guid isPermaLink="false">http://www.bultux.org/?p=794</guid>
		<description><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/apps.png" width="22" height="22" alt="" title="Приложения" /><br/>Ако някога ви се е случвало да искате да изтеглите песен от grooveshark и не сте имали тази възможност може би с това приложение ще мога да ви помогна. gSharkDown е десктоп клиент за grooveshark повече ориентиран към прослушване не песните, но включващ и възможност за изтеглянето им и някои други полезни функции. Като цяло [...]]]></description>
			<content:encoded><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/apps.png" width="22" height="22" alt="" title="Приложения" /><br/><p style="text-align: justify;"><img class="alignleft size-full wp-image-795" title="gsharkdown_128" src="http://www.bultux.org/wp-content/uploads/2011/05/gsharkdown_128.png" alt="" width="128" height="128" />Ако някога ви се е случвало да искате да изтеглите песен от grooveshark и не сте имали тази възможност може би с това приложение ще мога да ви помогна. gSharkDown е десктоп клиент за grooveshark повече ориентиран към прослушване не песните, но включващ и възможност за изтеглянето им и някои други полезни функции. Като цяло клиентът беше предвиден за лично ползване, но след версия 0.2.2 сметнах, че мога да го споделя и с други.</p>
<p style="text-align: justify;">Приложението е написано на Python и използва <a href="http://www.pygtk.org/" target="_blank">pyGTK</a> за графичен интерфейс и <a href="http://pygstdocs.berlios.de/" target="_blank">GStreamer</a> за просвирване на песните директно от grooveshark без да бъдат изтегляни. Библиотеката, която се използва за търсене и изтегляне на песните е предоставена от проекта <a href="https://github.com/jacktheripper51/groove-dl" target="_blank">groove-dl</a> (друго wxPython приложение само за изтегляне на песни).<br />
<span id="more-794"></span> <span style="font-size: 20px; font-weight: bold;">С какво gSharkDown е по-различен</span></p>
<ul>
<li style="text-align: justify;">Търсене за песни в grooveshark с възможност за подсказване (запаметява търсенията и при следващото ползване ги предлага)</li>
<li style="text-align: justify;">Списък за просвирване, който можете да заредите с песни от резултатите от търсенето</li>
<li style="text-align: justify;">Вграден плейър, с все още не напълно функционираща опция за непрекъснато свирене (повторение на списъка), но очаквам скоро да коригирам проблема</li>
<li style="text-align: justify;">Информационен диалог за подробности относно дадена песен от списъка с резултати</li>
<li style="text-align: justify;">Бутон за изтегляне (изтегляне на песни една по една)</li>
<li style="text-align: justify;">Удобна статус икона в GNOME панела</li>
</ul>
<p><a href="http://www.bultux.org/wp-content/uploads/2011/05/Selection_011.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-medium wp-image-796" title="Selection_011" src="http://www.bultux.org/wp-content/uploads/2011/05/Selection_011-300x174.png" alt="" width="300" height="174" /></a></p>
<h2>Изтегляне и инсталиране на gSharkDown</h2>
<p style="text-align: justify;">Ако използвате Ubuntu или Debian базирана дистрибуция с GNOME можете да инсталирате gSharkDown с предоставения .deb пакет. Последната версия: <a href="https://bitbucket.org/vkolev/gsharkdown/downloads/gsharkdown_0.2.2_all.deb">gsharkdown_0.2.2_all.deb</a>. За други дистрибуции ще трябва да изтеглите програмата от mercurial хранилището и да я инсталирате ръчно:</p>


<div class="wp-geshi-highlight"><div class="bash"><pre class="de1">$ hg clone https:<span class="sy0">//</span>bitbucket.org<span class="sy0">/</span>vkolev<span class="sy0">/</span>gsharkdown
$ <span class="kw2">sudo</span> <span class="kw2">cp</span> <span class="re5">-rfp</span> gsharkdown <span class="sy0">/</span>opt<span class="sy0">/</span>
$ <span class="kw2">sudo</span> <span class="kw3">echo</span> <span class="st_h">'#!/bin/bash'</span> <span class="sy0">&gt;&gt;</span> <span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>bin<span class="sy0">/</span>gsharkdown
$ <span class="kw2">sudo</span> <span class="kw3">echo</span> <span class="st_h">'cd /opt/gsharkdown/ &amp;&amp; python gsharkdown.py'</span> <span class="sy0">&gt;&gt;</span> <span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>bin<span class="sy0">/</span>gsharkdown
$ <span class="kw2">sudo</span> <span class="kw2">chmod</span> +x <span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>bin<span class="sy0">/</span>gsharkdown</pre></div></div>


<p style="text-align: justify;">След което остава да добавите стартер в менюто, което в GNOME можете да направите от System -&gt; Preferences -&gt; Main Menu. Ако искате да следите развитието на приложението, да изтеглите последната версия или имате предложения  към развитието на приложението можете да посетите <a href="https://bitbucket.org/vkolev/gsharkdown">https://bitbucket.org/vkolev/gsharkdown</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bultux.org/applications/desktop-klient-za-grooveshark/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>pySteg &#8211; графичен интерфейс за steghide</title>
		<link>http://www.bultux.org/news/pysteg-gui-z%d0%b0-steghide</link>
		<comments>http://www.bultux.org/news/pysteg-gui-z%d0%b0-steghide#comments</comments>
		<pubDate>Mon, 14 Feb 2011 04:45:36 +0000</pubDate>
		<dc:creator>Владимир Колев</dc:creator>
				<category><![CDATA[Новини]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[pygtk]]></category>
		<category><![CDATA[pySteg]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[steghide]]></category>

		<guid isPermaLink="false">http://www.bultux.org/?p=680</guid>
		<description><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/bultux-22.png" width="22" height="22" alt="" title="Новини" /><br/>След статията относно скриването на файлове в изображения и аудио файлове се роди идеята за графичен интерфейс, който да улесни процеса и да съкрати писането в терминала. От тест на тест се появи и първата версия на pySteg &#8211; графичен интерфейс за steghide, който беше вдъхновен от Steghide UI за Windows. Като цяло разликата с [...]]]></description>
			<content:encoded><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/bultux-22.png" width="22" height="22" alt="" title="Новини" /><br/><p style="text-align: justify;"><img class="alignleft size-full wp-image-681" title="pySteg_128" src="http://www.bultux.org/wp-content/uploads/2011/02/pySteg_128.png" alt="" width="126" height="128" />След статията относно <a href="http://www.bultux.org/tutorials/skriti-poslania-w-izobrajenia-i-muzika">скриването на файлове в изображения и аудио файлове</a> се роди идеята за графичен интерфейс, който да улесни процеса и да съкрати писането в терминала. От тест на тест се появи и първата версия на <a href="https://github.com/vkolev/pySteg">pySteg</a> &#8211; графичен интерфейс за steghide, който беше вдъхновен от <a href="http://sourceforge.net/projects/steghideui/" target="_blank">Steghide UI</a> за Windows. Като цяло разликата с Windows приложението е минимална, с идеята да е удобно за хората, които използват и две операционни системи Windows и GNU/Linux. Причината за това е, че pySteg не се предполага, че някога ще има версия за Windows &#8211; просто не е предвидена, а и нямам желанието да правя такава. Като за първа версия се постарах все пак да включа повечето функции, които предлага steghide. Приложението е написано на python и използва GTK за графичния интерфейс, което позволява добра интеграция с <a href="http://www.gnome.org/">GNOME десктоп средата</a>.</p>
<p><span id="more-680"></span></p>
<h2>Особености на pySteg</h2>
<p style="text-align: justify;"><a href="http://www.bultux.org/wp-content/uploads/2011/02/PySteg-1.0-beta_052.png" class="highslide-image" onclick="return hs.expand(this);"><img class="alignright size-thumbnail wp-image-682" style="margin-left: 5px; margin-right: 5px;" title="PySteg 1.0 (beta)_052" src="http://www.bultux.org/wp-content/uploads/2011/02/PySteg-1.0-beta_052-150x150.png" alt="" width="150" height="150" /></a>pySteg предлага tab интерфейс, който е разделен на три основни части:</p>
<ul style="text-align: justify;">
<li>Вмъкване (Embeding) &#8211; включващо всичките функции за скриване на един файл в друг.</li>
<li>Извличане (Extracting) &#8211; извличането на информация, скрита във файл.</li>
<li>Терминал (Console) &#8211; директен достъп до steghide, както и информация за извършваните задачи</li>
</ul>
<p style="text-align: justify;">Повечето функции са само обясняващи се и ще ги разберете бързо ако сте чели <a href="http://www.bultux.org/tutorials/skriti-poslania-w-izobrajenia-i-muzika">статията относно stehide</a>.</p>
<h2>Недостатъци на pySteg</h2>
<ul>
<li style="text-align: justify;"><a href="http://www.bultux.org/wp-content/uploads/2011/02/PySteg-1.0-beta_053.png" class="highslide-image" onclick="return hs.expand(this);"><img class="alignright size-thumbnail wp-image-683" style="margin-left: 5px; margin-right: 5px;" title="PySteg 1.0 (beta)_053" src="http://www.bultux.org/wp-content/uploads/2011/02/PySteg-1.0-beta_053-150x150.png" alt="" width="150" height="150" /></a>pySteg за момента не проверява дали файлът, който сте избрали е достатъчно голям, за да побере информацията, която искате да скриете.</li>
<li style="text-align: justify;">За момента филтрирането на съдържащите файлове е не гарантира, че тези файлове ще могат да бъдат използвани от steghide. За пример скриването на информация в .mp3 файл не е възможна, но за целта съществува <a href="http://www.petitcolas.net/fabien/steganography/mp3stego/">mp3stego</a>, чиято поддръжка е планирана за следваща версия.</li>
<li style="text-align: justify;">Липсва статус икона, за бързо достъп, добавянето ѝ е предвидено за следващата версия.</li>
</ul>
<h2>Изтегляне</h2>
<p style="text-align: justify;"><a href="http://www.bultux.org/wp-content/uploads/2011/02/PySteg-1.0-beta_054.png" class="highslide-image" onclick="return hs.expand(this);"><img class="alignleft size-thumbnail wp-image-684" style="margin-left: 5px; margin-right: 5px;" title="PySteg 1.0 (beta)_054" src="http://www.bultux.org/wp-content/uploads/2011/02/PySteg-1.0-beta_054-150x150.png" alt="" width="150" height="150" /></a>Кодът на pySteg се съхранява в <a href="https://github.com/vkolev/pySteg/downloads/">github.com</a> и също от там можете да изтеглите архиви във форматите <a href="https://github.com/vkolev/pySteg/zipball/pySteg1.0">.zip</a> или <a href="https://github.com/vkolev/pySteg/tarball/pySteg1.0">tar.gz</a>. В хранилището е и мястото за съобщаване на грешки и проблеми с приложението, както и да предлагате нови функции и разширявания на приложението.</p>
<p style="text-align: justify;">Инсталацията за момента не е предвидена, но ако искате сами можете да преместите файловете и да направите съответните символични връзки или да изчакате, докато .deb пакета е готов. Както споменах и в предната публикация относно ImgurUp &#8211; пакетирането за други дистрибуции е проблемно за мен и за сега няма как да бъдат добавени, но ще се радвам ако някой може да ги направи.</p>
<h2>Планове</h2>
<p style="text-align: justify;">За този момент в списъка с неща, коти трябва да бъдат добавени/оправени стои следното:</p>
<ul style="text-align: justify;">
<li>Добавяне на възможност за превод на интерфейса</li>
<li>Добавяне на статус икона</li>
<li style="text-align: justify;">Потребителски настройки за приложението и предпочитаните настройки за криптиране</li>
</ul>
<p><a href="http://www.bultux.org/wp-content/uploads/2011/02/PySteg-1.0-beta_0551.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-686" title="PySteg 1.0 (beta)_055" src="http://www.bultux.org/wp-content/uploads/2011/02/PySteg-1.0-beta_0551.png" alt="" width="673" height="351" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bultux.org/news/pysteg-gui-z%d0%b0-steghide/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Представяме ImgurUp 1.0</title>
		<link>http://www.bultux.org/news/predstavqm-imgurup-1-0</link>
		<comments>http://www.bultux.org/news/predstavqm-imgurup-1-0#comments</comments>
		<pubDate>Sun, 13 Feb 2011 13:41:57 +0000</pubDate>
		<dc:creator>Владимир Колев</dc:creator>
				<category><![CDATA[Новини]]></category>
		<category><![CDATA[imgur]]></category>
		<category><![CDATA[ImgurUp]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[изображения]]></category>
		<category><![CDATA[споделяне]]></category>

		<guid isPermaLink="false">http://www.bultux.org/?p=667</guid>
		<description><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/bultux-22.png" width="22" height="22" alt="" title="Новини" /><br/>Често пишейки с приятели в Skype, във IRC или публикувайки публикации във форуми ми се налага да добавям изображения за целта вместо да качвам изображенията на мой хост използвам безплатни услуги от други страници. Тази, която най-често ползвам е Imgur.com. За да улесня процеса с качването на изображения и да си спестя регистрацията реших да [...]]]></description>
			<content:encoded><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/bultux-22.png" width="22" height="22" alt="" title="Новини" /><br/><p style="text-align: justify;"><img class="alignleft size-full wp-image-668" title="imgurup-logo" src="http://www.bultux.org/wp-content/uploads/2011/02/imgurup-logo.png" alt="" width="344" height="85" />Често пишейки с приятели в Skype, във IRC или публикувайки публикации във форуми ми се налага да добавям изображения за целта вместо да качвам изображенията на мой хост използвам безплатни услуги от други страници. Тази, която най-често ползвам е <a href="http://imgur.com">Imgur.com</a>. За да улесня процеса с качването на изображения и да си спестя регистрацията реших да направя едно малко приложение, което да върши тази работа вместо мен, като същевременно води и лог за качените от мен изображения, така че да мога да ги използвам и по-късно, както и да ги изтривам при необходимост. Така след случайно ровене по директориите на твърдия ми диск открих дизайн на подобно приложение, което бях правил на <a href="http://glade.gnome.org/">Glade</a>. Необходима бе малка редакция, след което добавянето на малко код, за да го накарам да работи. Така се роди ImgurUp.</p>
<p style="text-align: justify;"><div class="note"><div class="notewarning"><strong>Обновление:</strong> Програмата беше обновена до версия 1.1 &#8211; добавена е функция за снимане на екрана.<br />
<a href="http://www.bultux.org/wp-content/uploads/2011/02/download.png" class="highslide-image" onclick="return hs.expand(this);"><img class="alignnone size-full wp-image-678" title="download" src="http://www.bultux.org/wp-content/uploads/2011/02/download.png" alt="" width="20" height="20" /></a> Изтегляне от <a href="https://github.com/vkolev/ImgurUp/downloads/">github.com</a></div></div></p>
<p><span id="more-667"></span></p>
<h2>Какво прави ImgurUp</h2>
<p style="text-align: justify;"><a href="http://www.bultux.org/wp-content/uploads/2011/02/Images-log_048.png" class="highslide-image" onclick="return hs.expand(this);"><img class="alignleft size-thumbnail wp-image-670" style="margin-left: 5px; margin-right: 5px;" title="Images log_048" src="http://www.bultux.org/wp-content/uploads/2011/02/Images-log_048-150x150.png" alt="" width="150" height="150" /></a>Приложението ви предоставя лесен и удобен начин за качване на изображения с услугата на imgur.com. След като изберете изображение, заглавието му бива автоматично генерирано от името на файла &#8211; разбира се това можете да промените, но ако бързате е удобен начин просто да имате някакво заглавие, което да ви подсеща какво сте качили. След натискане на бутона Upload изображението бива изпратено към Imgur сайта и ви предоставя списък с връзки към изображението &#8211; основните биват същевременно записвани в базата данни на ImgurUp. Самото приложение разполага със статус икона, която стои през цялото време в лентата с активни приложения, което ви позволява да скриете прозореца на приложението и да го извикате при необходимост, за да качите следващото изображение. Лесно и просто.</p>
<h2>Добавяне на API ключ</h2>
<p style="text-align: justify;"><img class="alignright size-full wp-image-669" style="margin-left: 5px; margin-right: 5px;" title="imgurup.py_049" src="http://www.bultux.org/wp-content/uploads/2011/02/imgurup.py_049.png" alt="" width="228" height="110" />Тъй като ImgurUp се стреми да бъде лесно и просто приложение без излишна функционалност не сметнах за необходимо да добавям методи за идентификация тъй като информацията за изображенията се записва в локална база данни &#8211; по този начин се обезсмисля използването на наречения от Imgur.com &#8211; <em>&#8220;Authenticated API key&#8221;</em>, който позволява да използвате своя акаунт от Imgur и в него да се записва информацията за всяко качено изображение. За да добавите ключ, с който да използвате ImgurUp трябва да изпълните следните стъпки:</p>
<ul>
<li>Отидете на адрес: <a href="http://imgur.com/register/api_anon">http://imgur.com/register/api_anon</a></li>
<li>Въведете изискваните от страницата данни след, което ще получите вашият API ключ</li>
<li>Стартирайте ImgurUp, изберете с десен бутон на статус иконата и изберете опцията API Key</li>
<li>В появилия се диалог въведете ключа, който сте получили от Imgur.com и изберете опцията Save</li>
<li>Това е &#8211; можете да качвате снимки с ImgurUp.</li>
</ul>
<h2>За потребители</h2>
<p style="text-align: justify;"><a href="http://www.bultux.org/wp-content/uploads/2011/02/Image-links..._047.png" class="highslide-image" onclick="return hs.expand(this);"><img class="alignright size-medium wp-image-671" style="margin-left: 5px; margin-right: 5px;" title="Image links..._047" src="http://www.bultux.org/wp-content/uploads/2011/02/Image-links..._047-300x180.png" alt="" width="300" height="180" /></a>Ако се натъкнете на грешка или искате да предложите разширение на приложението с други възможности можете да направите това с коментар в тази публикация или на адреса за проблеми в github.com: <a href="https://github.com/vkolev/ImgurUp/issues">https://github.com/vkolev/ImgurUp/issues</a></p>
<p style="text-align: justify;">Имайте предвид, че след качване на изображение информацията, която се записва в локалната база данни е следната:</p>
<ul style="text-align: justify;">
<li>Връзка до страницата в Imgur.com на съответното изображение, то която можете да получите повече връзки за споделяне на изображението. Отварянето на този адрес става с двойно кликване на съответния ред в прозореца.</li>
<li>Заглавие на самото изображение, което сте задали при качването му &#8211; с цел подсещане какво точно сте качили</li>
<li style="text-align: justify;">Адрес за изтриване на изображението &#8211; можете да го използвате като изберете съответния запис и натиснете бутона Delete &#8211; имайте предвид, че по този начин записът веднага ще бъде изтрит от базата данни и ще бъдете пренасочени към страница в Imgur.com, от която ще трябва да потвърдите изтриването.</li>
</ul>
<h2 style="text-align: justify;">За разработчици</h2>
<p style="text-align: justify;">ImgurUp е лицензиран от MIT лиценз и може да бъде свободно редактиран. Приложението е написано на Python и за графичен интерфейс използва PyGTK. За да се сдобиете с изходния код на ImgurUp просто трябва да изтеглите кода от github.com:</p>
<pre style="text-align: justify;" lang="bash">git clone git@github.com:vkolev/ImgurUp.git</pre>
<p>Идеи и корекции за приложението са винаги добре дошли. Пакетиране на приложението за други дистрибуции е нещо, с което аз лично няма как да се справя, тъй като единствената дистрибуция, която използвам е Ubuntu.</p>
<p>ImgurUp зависи от следните библиотеки:</p>
<ul>
<li>python-gtk2</li>
<li>python-simplejson</li>
<li>python-dbus</li>
<li>python configobj</li>
<li>python-pysqlite2</li>
</ul>
<h2 style="text-align: justify;">Изтегляне</h2>
<p style="text-align: justify;">Можете да изтеглите приложението в няколко формата. За потребителите на Ubuntu/Debian е добавен .deb пакет. За останалите дистрибуции ще трябва да използват tar.gz или .zip архив, с който да инсталират приложението ръчно.</p>
<h3 style="text-align: justify;">.deb пакет</h3>
<p style="text-align: justify;"><img src="http://imgur.com/b0SVe.png" border="0" /><a href="http://www.bultux.org/wp-content/plugins/download-monitor/download.php?id=17" title="Изтеглен 66 пъти"><strong>ImgurUp</strong>  ()</a> 66 изтегляния</p>
<h3>.tar.gz архив</h3>
<p style="text-align: justify;"><img src="http://imgur.com/b0SVe.png" border="0" /><a href="http://www.bultux.org/wp-content/plugins/download-monitor/download.php?id=18" title="Изтеглен 63 пъти"><strong>ImgurUp tar.gz</strong>  ()</a> 63 изтегляния</p>
<h3>.zip архив</h3>
<img src="http://imgur.com/b0SVe.png" border="0" /><a href="http://www.bultux.org/wp-content/plugins/download-monitor/download.php?id=19" title="Изтеглен 107 пъти"><strong>ImgurUp .zip</strong>  ()</a> 107 изтегляния
]]></content:encoded>
			<wfw:commentRss>http://www.bultux.org/news/predstavqm-imgurup-1-0/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<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>
		<item>
		<title>Колко сигурни са паролите, които ползваме?</title>
		<link>http://www.bultux.org/tutorials/kolko-sigurni-sa-parolite-koito-polzwame</link>
		<comments>http://www.bultux.org/tutorials/kolko-sigurni-sa-parolite-koito-polzwame#comments</comments>
		<pubDate>Sat, 13 Mar 2010 19:47:15 +0000</pubDate>
		<dc:creator>Владимир Колев</dc:creator>
				<category><![CDATA[Уроци]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[генериране]]></category>
		<category><![CDATA[парола]]></category>
		<category><![CDATA[пароли]]></category>

		<guid isPermaLink="false">http://www.bultux.org/?p=388</guid>
		<description><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/tuts.png" width="22" height="22" alt="" title="Уроци" /><br/>Рядко човек се замисля дали паролата, която използва е сигурна. Всъщност масово хората използват пароли, които са лесни за запомняне. От гледна точка на сигурността това винаги е грешно, но е в самото мислене на човека. Доста често срещам хора, които ползват една и съща парола навсякъде, в най-добрия случай използват няколко пароли навсякъде и [...]]]></description>
			<content:encoded><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/tuts.png" width="22" height="22" alt="" title="Уроци" /><br/><div id="attachment_391" class="wp-caption alignright" style="width: 310px"><img class="size-full wp-image-391 " title="security_icon" src="http://www.bultux.org/wp-content/uploads/2010/03/security_icon.png" alt="" width="300" height="250" /><p class="wp-caption-text">Колко сигурна е пароалта ви?</p></div>
<p style="text-align: justify;">Рядко човек се замисля дали паролата, която използва е сигурна. Всъщност масово хората използват пароли, които са лесни за запомняне. От гледна точка на сигурността това винаги е грешно, но е в самото мислене на човека. Доста често срещам хора, които ползват една и съща парола навсякъде, в най-добрия случай използват няколко пароли навсякъде и то с идеята, че са лесни за запомняне и няма да ги забравят. Но колко сигурни са тези пароли? Изобщо би ли се досетил някой за тях. Хората, работещи по това да разбират чужди пароли за добро или лошо са измислили различни методи за разбиването им. Някои от тези методи са свързани с логика, друга част се базират на най-често използваните пароли или на списъци с такива. С тази статия ще се опитам да ви покажа какво трябва да имате предвид при избора на своята парола и какво трябва да избягвате.</p>
<h2 style="text-align: justify;">Най-честите грешки в избора на парола</h2>
<p style="text-align: justify;">Едно от основното правило при избора на парола, което не всички хора следват е използването само на малки букви или пък само на цифри. Много хора мислят, че използвайки за парола рождената си дата са се защитили. Донякъде е така, но в момента почти всеки е регистриран във Facebook &#8211; съответно всеки може да провери кога е вашият рожден ден &#8211; от там не е трудно да почне да тества пощата ви с различни комбинации. <span id="more-388"></span>Имена, думи и подобни пароли също не са особено трудни, тъй като се изисква малко мислене и налучкване или сдобиването с wordlist (обикновено текстов файл с огромен брой различни думи и имена), който се използва в комбинация с програма, която да върши тестването автоматично т.нар. <a href="http://en.wikipedia.org/wiki/Brute_force_attack" target="_blank">BruteForce</a> &#8211; програмата праща заявки към формата за име и парола със зададените потенциални пароли от списъка с думи, докато не уцели. В крайна сметка използването на цифри или обикновени за парола е изключително несигурно. Също толкова несигурно, колкото и използването на имена на домашни любимци и подобни.</p>
<p style="text-align: justify;">Тук бих искал да вмъкна и информацията за един инструмент наречен <a href="http://www.remote-exploit.org/wp-content/uploads/2010/01/cupp2.tar.gz" target="_blank">CUPP (Common User Passwords Profiler)</a>, който представлява един <a href="http://www.python.org" target="_blank">Python</a> скрипт, който на база информация за даден потребител &#8211; рождена дата, две/три имена, прякор, данни за близки и домашни любимци генерира списък с възможни пароли. Всеки използващ този инструмент и поровил се достатъчно в интернет, за да събере информация за вас би могъл да генерира списък, в който е възможно да присъства вашата парола. Всъщност самия инструмент е много полезен и за обикновените потребители, тъй като по този начин могат сами да тестват колко е сигурна паролата им. Но тук винаги трябва да имате предвид, че програмата може да направи грешка, тъй като не е перфектна.</p>
<p style="text-align: justify;">Друга грешка при използването на различни пароли е тяхното записване в каквато и да е форма с цел запомняне. Самото записване на пароли в тефтерчето, което &#8220;никой не вижда&#8221;, в телефона &#8220;който никой няма да прегледа&#8221; и т.н. е грешно. Замислете се над това, колко е сигурен вашият телефон? Много хора го смятат за изключително сигурен и неподлежащ на атака, но всъщност е толкова лесно, колкото не можете да си представите. Напълно е възможно някой да се свърже към телефона ви през Bluetooth и да извлече цялата информация от него. Повече информация по въпроса можете да прочетете в следния pdf документ: <a href="http://trifinite.org/Downloads/21c3_Bluetooth_Hacking.pdf" target="_blank">Bluetooth_Hacking.pdf</a>. Тефтерчето ви винаги може да попадне в чужди ръце дори, когато не подозирате. Опитвайте се да запомните паролите си. Или ако ги записвате &#8211; никога не ги записвайте на важен документ и никога не посочвайте, че това е парола &#8211; нека бъде просто някакъв текст някъде си, а ако използвате примерите за създаване на по-сигурна парола, не я записвайте със специалните знаци и цифрите &#8211; нека не личи, че това е парола.</p>
<h2 style="text-align: justify;">Как да изберем сигурна парола?</h2>
<p style="text-align: justify;">За да изберете сигурна парола имате в общи линии два избора:</p>
<ul style="text-align: justify;">
<li>Избор на парола, която по-лесно да запомните</li>
<li>Генериране на парола, която ще трябва да опитате да запомните</li>
</ul>
<p style="text-align: justify;">В първия случай трябва да изберете дума или фраза, която да преобразувате в парола. Това е може би най-лесния начин да си изберете сравнително сигурна и лесна за запомняне парола. Как обаче да го направите? Намислете си фраза, която често използвате или която харесвате. И я пренапишете, заменяйки буквите с цифри, големи букви и знаци. За примера ще използваме <strong><em>bultuxpassword</em></strong> &#8211; на пръв поглед изключително елементарна и лесна за досещане парола. Но как да преобразуваме тази толкова елементарна парола в нещо по-сложно? Следвайки принципа &#8211; големи/малки букви, цифри и символи ние започваме да заменяме, така че за краен резултат получаваме:</p>
<pre style="padding-left: 30px; text-align: justify;"><strong>Bu!TUx_p4sSW0rD</strong></pre>
<p style="text-align: justify;">Е тази парола няма да намерите в списъците с пароли и ще е достатъчно сигурна. Разбира се не е най-сигурната парола, но със сигурност ще е по-добре от различни други комбинации. Ще ви дам още няколко примера:</p>
<pre style="padding-left: 30px; text-align: justify;"><strong>godspower = g0d5_!p0w3r
Marlboro = m4r!b0rO_</strong>
и т.н.</pre>
<p style="text-align: justify;">Разбира се по-добрия и най-сигурен вариант за момента е използването на генерирана парола. Парола, която няма да е свързана с вас по никакъв начин и няма да има никакво значение. За целта можете да използвате различни приложения за генерирането на такива. Не съм се интересувал особено какви видео генератори на пароли има, но за тези от вас, които харесват езика за програмиране Python могат лесно и бързо сами да си спретнат един малък скрипт или пък да използват друг език за програмиране за да си направят малка програмка за целта. Принципа е следния според това каква парола искате да имате. Дали тя да бъде само от букви+цифри, дали да бъде букви+цифри+специални знаци, или пък да използвате шестнадесетичната бройна система. от там остава просто да създадете стринг и да използвате функцията за random във вашия език за програмиране, с който да изберете няколко символа от този стринг. Казах малко по-рано, че използвам Python за моя генератор, защото функцията string ми позволява да използвам и боравя с тези методи по-лесно. Следващото е само за тези, които се интересуват от това как става:<br />
1. Създаваме метод, който да разбурка даден стринг и да върне паролата с определена дължина:</p>
<p>[python]def generate_sample(choices, length):<br />
    return random.sample(choices * length, length)<br />
[/python]</p>
<p>2. Създаваме и след което можем да използваме този метод в нашия скрипт, като му подадем стринг от символи и дължината на паролата, която трябва да генерираме. Аз лично съм създал няколко метода в зависимост от това каква парола искам. За парола само от букви+цифри метода би изглеждал така:</p>
<p>[python]def alphanum(length):<br />
    sample = generate_sample(string.letters + string.digits, length)<br />
    return &#8221;.join(sample)[/python]</p>
<p>За да използвате тези методи предварително ще трябва да се добавили във вашия скрипт следните библиотеки: <code>random</code> и <code>string</code>.</p>
<p>Ако все пак ви потрябва приложението можете да го изтеглите от BulTux. За целта ще е нужно да имате инсталиран Python:<br />
<img src="http://imgur.com/b0SVe.png" border="0" /><a href="http://www.bultux.org/wp-content/plugins/download-monitor/download.php?id=10" title="Изтеглен 151 пъти"><strong>pyspgen</strong>  (64.36 KB)</a> 151 изтегляния</p>
<p>За почитателите на bash можете да погледнете и друго решение:</p>
<p>[bash]#!/bin/bash</p>
<p>charspool=(&#8216;a&#8217; &#8216;b&#8217; &#8216;c&#8217; &#8216;d&#8217; &#8216;e&#8217; &#8216;f&#8217; &#8216;g&#8217; &#8216;h&#8217; &#8216;i&#8217; &#8216;j&#8217; &#8216;k&#8217; &#8216;l&#8217; &#8216;m&#8217; &#8216;n&#8217; &#8216;o&#8217; &#8216;p&#8217;<br />
&#8216;q&#8217; &#8216;r&#8217; &#8216;s&#8217; &#8216;t&#8217; &#8216;u&#8217; &#8216;v&#8217; &#8216;w&#8217; &#8216;x&#8217; &#8216;y&#8217; &#8216;z&#8217; &#8217;0&#8242; &#8217;1&#8242; &#8217;2&#8242; &#8217;3&#8242; &#8217;4&#8242; &#8217;5&#8242; &#8217;6&#8242; &#8217;7&#8242;<br />
&#8217;8&#8242; &#8217;9&#8242; &#8217;0&#8242; &#8216;A&#8217; &#8216;B&#8217; &#8216;C&#8217; &#8216;D&#8217; &#8216;E&#8217; &#8216;F&#8217; &#8216;G&#8217; &#8216;H&#8217; &#8216;I&#8217; &#8216;J&#8217; &#8216;K&#8217; &#8216;L&#8217; &#8216;M&#8217; &#8216;N&#8217; &#8216;O&#8217;<br />
&#8216;P&#8217; &#8216;Q&#8217; &#8216;R&#8217; &#8216;S&#8217; &#8216;T&#8217; &#8216;U&#8217; &#8216;V&#8217; &#8216;W&#8217; &#8216;X&#8217; &#8216;Y&#8217; &#8216;Z&#8217; &#8216;!&#8217; &#8216;£&#8217; &#8216;$&#8217; &#8216;%&#8217; &#8216;&amp;&#8217; &#8216;=&#8217; &#8216;.&#8217; &#8216;,&#8217; &#8216;;&#8217; &#8216;:&#8217; &#8216;-&#8217; &#8216;_&#8217;);</p>
<p>len=${#charspool[*]}</p>
<p>if [ $# -lt 1 ]; then<br />
        num=6;<br />
else<br />
        num=$1;<br />
fi</p>
<p>echo -n &quot;password: &quot;<br />
for c in $(seq $num); do<br />
        echo -n ${charspool[$((RANDOM % len))]}<br />
done<br />
echo[/bash]</p>
<p><em>Скриптът е взет от: <a href="http://mydebian.blogdns.org/?p=190" target="_blank">My. Debian</a></em></p>
<p>Надявам се статията да ви е била полезна. Ако имате забележки или предложения за приложения, които да бъдат описания не се притеснявайте да ги запишете в коментарите.</p>
<p style="text-align: justify;">
]]></content:encoded>
			<wfw:commentRss>http://www.bultux.org/tutorials/kolko-sigurni-sa-parolite-koito-polzwame/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python: Актуалната песен в Clipboard</title>
		<link>http://www.bultux.org/terminal/python-aktualna-pesen-w-clipboard</link>
		<comments>http://www.bultux.org/terminal/python-aktualna-pesen-w-clipboard#comments</comments>
		<pubDate>Wed, 28 Oct 2009 16:02:52 +0000</pubDate>
		<dc:creator>Владимир Колев</dc:creator>
				<category><![CDATA[Терминал]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rhythmbox]]></category>

		<guid isPermaLink="false">http://bultux.sikomi.com/?p=38</guid>
		<description><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/scripts.png" width="22" height="22" alt="" title="Терминал" /><br/>За този урок ще са ви необходими елементарни познания по програмиране с Python, и разбиране на командите в Linux терминала. Урокът може лесно да бъде пренаписан и на други езици: perl, bash, и т.н. Ето и какво ще прави нашият малък скрипт: Ще проверим дали плейърът, който използваме е включен След като е включен ще [...]]]></description>
			<content:encoded><![CDATA[<img src="http://bultux.org/wp-content/plugins/category-icons/cats/scripts.png" width="22" height="22" alt="" title="Терминал" /><br/><p style="text-align: justify;">За този урок ще са ви необходими елементарни познания по програмиране с Python, и разбиране на командите в Linux терминала. Урокът може лесно да бъде пренаписан и на други езици: perl, bash, и т.н. Ето и какво ще прави нашият малък скрипт:</p>
<ol style="text-align: justify;">
<li>Ще проверим дали плейърът, който използваме е включен</li>
<li>След като е включен ще използваме команда, която да изведе информация за свирещата в моемнта песен, и нашият скрипт ще я прочете</li>
<li>Скрипта ще форматира прочетената информация, за да я подреди във формата &#8220;Изпълнител &#8211; Заглавие&#8221;</li>
<li>След което ще използваме gtk библиотеката, за да копираме песента в clipboard</li>
<li>Ще разширим скрипта, за да издава приятени съобщения, когато е копирана песен</li>
</ol>
<p style="text-align: justify;">Преди да започнем ще трябва да се уверим, че системата ни е готова, т.е. че разполагаме с необходимите библиотеки. За целта са ни необходими:</p>
<ul style="text-align: justify;">
<li>python &gt;=2.5</li>
<li>python-notify</li>
<li>python-gtk2</li>
</ul>
<p style="text-align: justify;">След като сте инсталирали необходимите пакети е време да се захванем за работа:</p>
<p style="text-align: justify;"><span id="more-38"></span></p>
<h2 style="text-align: justify;">Скелет на скрипта:</h2>
<p style="text-align: justify;">Ще започнем със създаването на скелет за нашият скрипт, който в последствие ще разширим. Първоначално ще създадем метод <strong>cur_song()</strong>, който ще проверява и събира информация за свирещата песен. Причината да правиме това, е за да можем да използваме скрипта и в други наши програми. След което ще инициализираме метода и ще го изпълним при стартиране на програмата с<strong> if __name__ = &#8220;__main__&#8221;: </strong>, където ще инициализираме и метода за записване в clipboard-а.</p>


<div class="wp-geshi-highlight"><div class="python"><ol><li class="li1"><pre class="de1"><span class="co1">#!/usr/bin/env python</span></pre></li><li class="li1"><pre class="de1">&nbsp;</pre></li><li class="li1"><pre class="de1"><span class="kw1">import</span> <span class="kw3">os</span></pre></li><li class="li1"><pre class="de1">&nbsp;</pre></li><li class="li1"><pre class="de1"><span class="kw1">def</span> cur_song<span class="br0">&#40;</span><span class="br0">&#41;</span>:</pre></li><li class="li1"><pre class="de1">&nbsp;</pre></li><li class="li1"><pre class="de1">	<span class="kw1">return</span> song</pre></li><li class="li1"><pre class="de1">&nbsp;</pre></li><li class="li1"><pre class="de1"><span class="kw1">if</span> __name__ <span class="sy0">==</span> <span class="st0">&quot;__main__&quot;</span>:</pre></li><li class="li1"><pre class="de1">	<span class="kw1">import</span> pygtk</pre></li><li class="li1"><pre class="de1">	<span class="kw1">import</span> gtk</pre></li><li class="li1"><pre class="de1">	<span class="kw1">print</span> cur_song<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></li></ol></div></div>


<p style="text-align: justify;">Така GTK ни предлага един много елементарен инструмент, който ще ни помогне за копиране на песента в Clipboard. За целта първо трябва да създадеме променилва clipboard, която да приеме метода за отваряне на clipboard, след което ще зададем променливата да приеме стойност от нашия метод cur_song(), и накрая ще запишеме промяната &#8211; три реда по-близко до целта ;) :</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">	clipboard <span class="sy0">=</span> gtk.<span class="me1">clipboard_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
	clipboard.<span class="me1">set_text</span><span class="br0">&#40;</span>cur_song<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
	clipboard.<span class="me1">store</span><span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>


<h2 style="text-align: justify;">Вземане на информацията от плейъра</h2>
<p style="text-align: justify;">За да вземем информацията от плейъра, първо трябва да определим, кой плейър ще използваме. Нека за примера вземем Rhythmbox, ще видите че метода е приложим и за други аудио плейъри като:  exaile, banschee, quodlibet, listen, mocp.</p>
<p style="text-align: justify;">Първо да разберем как всъщност функционира самия метод:</p>
<p style="text-align: justify;">1. Много добре знаем, че всяка стартирана програма създава процес и това кои процеси в работят в момента на компютъра можем да проверим с командата <strong>ps -A</strong>, и за да проверим за точно определена програма можем да използваме командатата <strong>grep &lt;име_на_програмата&gt;</strong>. Като резултат получаваме командния ред: ps -A | grep rhythmbox</p>
<p style="text-align: justify;">2. От нашият скрипт много лесно можем да добавим изпълнението на командата посредством метода exec, но така няма да можем да прочетем изхода от командата. За целта ще използваме библиотеката <strong>os</strong>, която съдържа и метода <strong>popen</strong>, с който да прочетем изхода от изпълнената команда.</p>
<p style="text-align: justify;">3. Към Rhythmbox има приложение с името<strong> rhythmbox-client,</strong> което ни предосравя достъп до Rhythmbox от командния ред. Добавяйки параметъра <strong>&#8211;print-playing </strong>получаваме точно това, което ни трябва &#8211; свирещата в момента песен.</p>
<p style="text-align: justify;">След като разполагаме с горните знания вече няма да ни бъде никак трудно да ги приложиме в нашия метод cur_song():</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1">	<span class="co1"># Проверяваме дали rhythmbox е включен</span>
	<span class="kw1">if</span> <span class="st0">&quot;rhythmbox&quot;</span> <span class="kw1">in</span> <span class="kw3">os</span>.<span class="me1">popen</span><span class="br0">&#40;</span><span class="st0">'ps -A | grep rhythmbox'</span><span class="br0">&#41;</span>.<span class="kw3">readline</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:
		<span class="co1"># Прочитаме свирещата в момента песен и премахваме новия ред от изхода, за да получиме само един ред</span>
		song <span class="sy0">=</span> <span class="kw3">os</span>.<span class="me1">popen</span><span class="br0">&#40;</span><span class="st0">'rhythmbox-client --print-playing'</span><span class="br0">&#41;</span>.<span class="kw3">readline</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">'<span class="es0">\n</span>'</span><span class="sy0">,</span> <span class="st0">''</span><span class="br0">&#41;</span>
	<span class="kw1">else</span>:
		<span class="kw1">return</span> <span class="st0">&quot;No song playing&quot;</span>
	<span class="co1"># Тъй като това е метод - връщаме съдържанието на променливата</span>
	<span class="kw1">return</span> song</pre></div></div>


<p style="text-align: justify;">И това е като цяло скрипта в няколко реда. При изпълнението му няма да се случи абсолютно нищо &#8211; т.е. нищо няма да видите, но ако отворите текстов редактор и изберете опцията paste, ще получите свирещата песен в момета :)</p>
<h2 style="text-align: justify;">Разширяване на скрипта</h2>
<p style="text-align: justify;"><a href="http://bultux.org/wp-content/uploads/2009/10/playcopy.png" class="highslide-image" onclick="return hs.expand(this);"><img class="alignright size-full wp-image-39" title="playcopy" src="http://bultux.org/wp-content/uploads/2009/10/playcopy.png" alt="playcopy" width="300" height="100" /></a>За да разширим нашият скрипт и да знаеме, дали работи правилно ще използваме библиотеката notify, която ни предоставя възможност да пращаме съобщения до notify системата на Linux. Преди това обаче, ще си добавиме възможност да включваме и изключваме системата за известия &#8211; за целта ще създаден след дефинирането на библиотеките глобална променлива show_notifications = 1. И в зависимост от това, дали стойността е 0 или 1, ще определяме дали известяването е включено или изключено. Първо ще ви покажа кодовия блок, който добавяме към края на скрипта &#8211; след clipboard.store():</p>


<div class="wp-geshi-highlight"><div class="python"><pre class="de1"><span class="kw1">if</span> show_notifications <span class="sy0">==</span> <span class="nu0">1</span>:
		<span class="kw1">try</span>:
			<span class="kw1">import</span> pynotify
			<span class="kw1">if</span> pynotify.<span class="me1">init</span><span class="br0">&#40;</span><span class="st0">&quot;playCopy&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;playCopy&quot;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>%s&quot;</span> % clipboard.<span class="me1">wait_for_text</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="st0">&quot;audio-volume-medium&quot;</span><span class="br0">&#41;</span>
				n.<span class="me1">show</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;You don't have pynotify installed!&quot;</span></pre></div></div>


<p style="text-align: justify;">Ето и какво се случва. Ако променливата ни show_notifications иа стойност 1, то тогава ще се опитаме да вмъкнеме библиотеката pynotify. Ако не е вмъкната, значи че не е инсталирана. След което следва условието pynotify.init(&#8220;playCopy&#8221;) &#8211; това е много важно, защото без него нашия скрипт няма да работи &#8211; това, което прави е да съобщи на notify, че нашия скрипт си има има playCopy, с което да го идентифицира. и след това взимаме съобщението, което последно нашият скрипт е записал в clipboard за да го покажеме n.show().</p>
<p style="text-align: justify;">Можете да изтеглите и пълния скрипт за програмата:</p>
<p style="text-align: center;"><img src="http://imgur.com/b0SVe.png" border="0" /><a href="http://www.bultux.org/wp-content/plugins/download-monitor/download.php?id=1" title="Изтеглен 120 пъти"><strong>PlayCopy Script</strong>  (33.37 KB)</a> 120 изтегляния</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bultux.org/terminal/python-aktualna-pesen-w-clipboard/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

