Marco Islas Blog Software_Development http://islascruz.org/html/ markuz@islascruz.org (Marco Antonio Islas Cruz) 2005-2008, Marco Antonio Islas Cruz Sat, 20 Dec 2008 13:09:08 -0600 JAWS 0.8.6 <![CDATA[ An easy one. ]]>
I have two ways to iterate over sequence with a simple filter, one is making a filtered list and store it in a variable, then iterate over that filtered list, the second is put the mapping list in the for statement. Which one is faster and why?
TIMES = 10000
a = xrange(10000)
c = [k for k in a if (k % 2) == 0]
#
def iterate(c):
    for i in c:
        pass
     
def mapea():
    for i in [k for k in a if (k % 2) == 0]:
        pass
#
for i in xrange(TIMES):
    iterate(c)
#
for i in xrange(TIMES):
    mapea()
 
100 points for the first comment with the right answer.

Update: Zodman wins (even when he is not a python newbie)... the iterate function is making just one iteration over a list with the filterered items, the second (mapea) is creating this filtered list in every iteration, so, mapea uses two for cycles and that's why it is slower. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/An-easy-one. markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/An-easy-one. Fri, 19 Dec 2008 23:54:33 -0600
<![CDATA[ Christine 0.2.1 ]]>
As usual you may download from sourceforge.net, this are the links:
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.2.1 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.2.1 Thu, 18 Dec 2008 20:32:15 -0600
<![CDATA[ Christine 0.2.0 ]]> Im proud to announce the release of Christine 0.2.0. I have been working with it for several weeks and after fixing some bugs reported I feel it quite stable to be used for everyone.

What's the new?
  • This version makes use of the sqlite3 python module to store info in a SQLite 3 database file.
  • The item lists have been reworked and now they are faster than ever.
  • We have early support for plugins face-smile.png
  • Re worked TreeModel wich makes christine load faster
  • gconf dependency is removed.
  • Notify bubbles and TrayIcon are now plugins easy to be enabled/disabled.
  • Plugin for Pidgin.
  • Plugin for twitter (for those that want to tweet their songs)
Where can I have it?
Thank you to everyone who contribuite with this release, bug submitters, patch submitters, packagers and users. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.2.0 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.2.0 Sun, 07 Dec 2008 01:37:22 -0600
<![CDATA[ Debugging with pydev ]]>
My first attempt to create video tutorials face-smile.png ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Debugging-with-pydev markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Debugging-with-pydev Fri, 05 Dec 2008 17:52:43 -0600
<![CDATA[ Python 3000 ]]> Yeap.. Python 3000 or Py3k hit the streets. I'm more than glade to hear about the new version of this powerfull programming language. It seems that was yesterday when I watch a video where Guido Van Rossum was talking about the propossal for this new version and excusing the lack of compatiblity with the 2.x python series.

I like the idea that this language is evolving even with this move (which for me is too risky) where we are going to be forced to modify our programs if we want in the future be compatible with Python. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Python-3000 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python-3000 Thu, 04 Dec 2008 23:58:03 -0600
<![CDATA[ Just a few extra minutes ]]>
Relativity.. you bitch! ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Just-a-few-extra-minutes markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Just-a-few-extra-minutes Thu, 04 Dec 2008 19:34:27 -0600
<![CDATA[ Python Logging: RotatingFileHandler ]]> Whenever you write a computer program that is going be a service is recommended that this program saves somewhere what is doing, most of the popular services do it (Apache, Cherokee, MySQL, Put your service here:___________________), or maybe you have a desktop application where you want to write what is doing maybe for debug purposes.

Fortunately this is an easy task if you use Python's Logging module. This module have several handlers, some of them to write to the standardError, to a Socket, to the syslog and many others

One of my favorite handler is the
RotatingFileHandler This module creates a log file, when this file is full (if you set the maximum bytes per file flag) it is renamed, appending the .1 and a new file is created with the same name as main log file. You can set up the max number of files to be created.

This module (logging) is good, easy to use, but you have to use the RotatingFileHandler with care, or you will have two, three or more files being filled and then, your logs will be in N files..

When you create your Logger Object you can set the log level, which can be INFO, WARNING, DEBUG, ERROR, CRITICAL and EXCEPTION, you already realized which level prints what. You can set the Handler, and this is where using the RotatingFileHandler becomes a bit trickier.

In your applications you may want to have several loggers, one for each module you have in your application. If you plan to use the RotatingFileHandler you have to use the same handler for every Logger you are creating if you plan this Logger to use the same file. If you don't do this then you will end with something saving logs in your main file, and every other data will be stored somewhere else.

This is because when you try to save a something in your log, the handler check the log size, and if the file size is >= maxbytes makes the rollover, if you are using several handlers related to the same file, then the handler that realize first that the size of the log file reach its max size will do the rollover but this will not take effect in the other handlers, so, one handler will be logging in the newly created file while the others will be logging to the old file and now you have two files growing.

To avoid this, just use the same fucking handler for every logger you are creating if you plan to use the same file.

Another issue I face with logger what the fact that if you call two time s to the same logger.. I mean:

a = logging.getLogger('chanchanchan')
b = logging.getLogger('chanchanchan')
When you make something like this:

a.info('This is a test')
You'll se this:
This is a test
This is a test
Yes, you are calling a to write "This is a test" but in your log file appears two times (or N times you have created a logger with the same name). So, its better for you to have something like a manager that gives you the logger already created with that name if exists or create it for you.

Let's do an example:

This is a small program that logs something in a endless cycle:

#!/usr/bin/env python
# -*- encoding: latin-1 -*- import sys
import time
from logger1 import LoggerManager

a = LoggerManager().getLogger('a')
b = LoggerManager().getLogger('b')
c = LoggerManager().getLogger('c')
while 1:
        t = time.time()
        for index,i in enumerate((a,b,c)):
                msg = str(index) + repr(t)
                i.debug(msg)
                time.sleep(0.005)
 
And this is the logger class, singleton module can be downloaded from Here
#!/usr/bin/env python
import logging
import logging.handlers
from Singleton import Singleton
import os

if os.name == 'nt':
        LOGPATH = 'C:\\'
else:
        LOGPATH = './'
class LoggerManager(Singleton):
        def __init__(self):
                self.loggers = {}
                formatter = logging.Formatter('%(asctime)s:%(levelname)-8s:%(name)-10s:%(lineno)4s: %(message)-80s')
                level = 'DEBUG'
                nlevel = getattr(logging, level, None)
                if nlevel != None:
                        self.LOGGING_MODE = nlevel
                else:
                        self.LOGGING_MODE = logging.DEBUG
                self.LOGGING_HANDLER = logging.handlers.RotatingFileHandler(
                                        os.path.join(LOGPATH, 'log_event.log'),'a',524288, 10)
                self.ERROR_HANDLER = logging.handlers.RotatingFileHandler(
                                        os.path.join(LOGPATH,'log_error.log'),'a',524288, 10)
                self.LOGGING_HANDLER.setFormatter(formatter)
                self.LOGGING_HANDLER.setLevel(self.LOGGING_MODE)
       
        def getLogger(self, loggername):
                if not self.loggers.has_key(loggername):
                        logger = Logger(loggername,
                                        logging_handler= self.LOGGING_HANDLER,
                                        error_handler = self.ERROR_HANDLER,
                                        logging_mode = self.LOGGING_MODE)
                        self.loggers[loggername] = logger
                return self.loggers[loggername]
class Logger:
        '''
        Implements the christine logging facility.
        '
''
        def __init__(self, loggername, type = 'event', logging_handler= '', error_handler = '', logging_mode = ''):
                '''
                Constructor, construye una clase de logger.
               
                @param loggername: Nombre que el logger tendra.
                @param type: Tipo de logger. Los valores disponibles son : event y error
                                        por defecto apunta a event. En caso de utilizarse otro
                                        que no sea event o error se apuntara a event.
                '
''
                # Creating two logger, one for the info, debug and warnings and
                #other for errors, criticals and exceptions
                self.__Logger = logging.getLogger(loggername)
                self.__ErrorLogger = logging.getLogger('Error'+ loggername)
                # Setting Logger properties
                self.__Logger.addHandler(logging_handler)
                self.__Logger.setLevel(logging_mode)
                self.__ErrorLogger.addHandler(error_handler)
                self.__ErrorLogger.setLevel(logging_mode)
                self.info = self.__Logger.info
                self.debug = self.__Logger.debug
                self.warning = self.__Logger.warning
               
                self.critical = self.__ErrorLogger.critical
                self.error = self.__ErrorLogger.error
                self.exception = self.__ErrorLogger.exception
 
I hope this help you. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Python-Logging markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python-Logging Tue, 02 Dec 2008 22:30:22 -0600
<![CDATA[ Christine 0.2.0 alpha ]]> 7 months ago I make the 0.1.6 release of Christine media player. The project continues working on my free time and the free time of some friends. I'd like to work more on it but I just don't have all that time, and wait until everything gets perfect will take a lot. So I'm giving to the christine users the 0.2.0 alpha version. I have been using this "version" a couple weeks ago and seems to be working fine, but I'd like you to check it and report everything you find wrong in it. There are source packages in bz2 and gz and a .deb package for Ubuntu Intrepid.

This release include the SQite3 as data storage engine, the drop of gconf dependency, early support for plugins and more optimizations that make christine load and work faster.

C'mon, go and Get it!. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.2.0-alpha markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.2.0-alpha Wed, 26 Nov 2008 22:39:52 -0600
<![CDATA[ Call for testers and translators ]]> christine release, the christine development team have been working on improving christine, and think it is time to make a new release, but before, we want you to test it and report every single fail you detect. We also make use of launchpad's translation page.

You can find the code Here, the page for tracking bugs is Here, and the translations are Here. ]]> http://islascruz.org/html/index.php?Blog/SingleView/id/Call-for-testers-and-translators markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Call-for-testers-and-translators Fri, 21 Nov 2008 01:30:11 -0600 <![CDATA[ Netbeans 6.5 ]]> Netbeans 6.5 release shows an Early Access Netbeans IDE for Python ]]> http://islascruz.org/html/index.php?Blog/SingleView/id/Netbeans-6.5 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Netbeans-6.5 Thu, 20 Nov 2008 13:24:48 -0600 <![CDATA[ What's your favorite programmer cartoon? ]]>

What's your favorite programmer cartoon? ]]> http://islascruz.org/html/index.php?Blog/SingleView/id/What%27s-your-favorite-programmer-cartoon%3F markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/What%27s-your-favorite-programmer-cartoon%3F Wed, 19 Nov 2008 23:57:15 -0600 <![CDATA[ 2008-11-16 ]]>
In this week I have been pretty busy, bugfixing the Juvi desktop application. We don't want Banana products (those that mature with the user) and the test team is doing their best to hit every bug and report it to have a very stable application.

I have been also busy "porting" the Supramax Evo4 driver to run on windows, the port is quite easy to do since the program was written in Python and I have to fix some paths. In my tests I was doing to the driver I found a Not so funny issue with M2Crypto for MS Windows.

We have a parameter in the driver, as most Unix programs do the "-v" do a verbose run, spitting to the stdout the logs, if you don't use the verbose parameter then it saves it somewhere. Well, running on verbose mode was easy, it just run perfectly, storing the logs wasn't I had an error with OpenSSL... but wait.. we where talking about logs and not about OpenSSL.. what does OpenSSL has to be with logs?.

Well, there is an issue with M2Crypto and Python where it doesn't ship a special file and this causes OpenSSL crash if you use I/O. M2Crypto let you load a RSA key in pem format that you can use to crypt/decrypt something this method is called load_key and is part of the M2Crypto's RSA package, you only have to pass the path to the key as first argument and in the second argument a function (anything callable) that returns the password for the key (if it is private). Well, this I/O was crashing M2Crypto.

There are two workarrounds for this. The first, is to compile at least M2Crypto (I didn't do it, some blogs says that you have to compile python) against OpenSSL and include this specific file... at least Google points to blogs that says that... The other and easier way is just use RSA's function load_key_string where you pass as first argument the string that holds the key instead the path, doing this you will eliminate the I/O done by OpenSSL and then, there is no crash.

Last Thursday Cristina and I went to Maquiavelo's house to an informal meeting with xbitcarry, unfortunately Maquiavelo was too busy and the meeting wasn't really done but was nice to see xbitcarry again.

I think that's all for today my readers. Fortunately I don't have to work tomorrow and now I have to work a bit on christine ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/2008-11-16 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/2008-11-16 Sun, 16 Nov 2008 23:08:00 -0600
<![CDATA[ Playing with gtk.Calendar ]]>
I'm writing a desktop application for ICTC where the user must select a day in in a calendar. I start using gtk.Calendar because is an easy to use Calendar widget, but I this program also have to set the days available for the user to pick.

I didn't find this on the gtk.Calendar widget, but tought it may be easy to do by subclassing gtk.Calendar. And here is my first approximation:

#!/usr/bin/env python
import gtk
import calendar
class Calendar(gtk.Calendar):
        def __init__(self):
                gtk.Calendar.__init__(self)
                self.available_days = ()
                self.last_selected_day =  None
                self.connect('day-selected', self.__check_day_available)
                self.connect('map', lambda *args: self.__set_available_days())
               
       
        def set_available_days(self, *args):
                '
                Let you set the days availables on the month
                @args: days to be used.
                '

                nargs = [k for k in args if isinstance(k, int)]
                self.available_days = tuple(nargs)
        def __check_day_available(self, calendar):
                '
                Check if the selected day is available, if not,then
                try to select the last available day selected, and if can'
t
                then select the first available day in the available_days list
                '
                day = self.get_property('
day')
                if not day in self.available_days:
                        nday = False
                        if self.last_selected_day:
                                nday = self.last_selected_day
                        elif self.available_days:
                                nday = self.available_days[0]
                        if nday:
                                self.select_day(nday)
                print self.get_date()
       
        def __set_available_days(self):
                '

                Set a range of days that are not going to be marked and thus,
                free days for the user.
                '
                if not self.available_days:
                         self.set_sensitive(False)
                month = self.get_property('
month')
                days = calendar.mdays[month]
                for i in range(1,days+1):
                        if not i in self.available_days:
                                self.mark_day(i)
                #Force the calendar to select the first day available
                day = self.get_property('
day')
                self.select_day(day)

if __name__ == '
__main__':
        window = gtk.Window()
        window.connect('
destroy', gtk.main_quit)
        a = Calendar()
        a.set_available_days(1,2,3,5,8,13,21)
        window.add(a)
        window.show_all()
        gtk.main()
Update: Syntax Highlight sucks and change the code to a simple "pre" tag
Update: returned to Syntax highlight. in Jaws 0.8.6 is working fine again face-smile.png ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Playing-with-gtk.Calendar markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Playing-with-gtk.Calendar Fri, 17 Oct 2008 01:37:36 -0500
<![CDATA[ 2008 10 08 ]]> So, it is time to post again.. this time is to post about christine. Christine as many of you know is a small project of mine, it must be an easy to use and small (and cute) media player, It start as some gstreamer play and then it becomes the music player I use for my every day, no longer rhythmbox nor banshee, wich are fine, but, not for me.

The project is slow, mostly because I code on it when I need something else or just want to fix something that don't like me. Why? because I get almost no feedback. So, if you use christine or, you want to see this project to grow up, please, test it and fill bugs or request features so we can work on it or maybe you want to cooperate with this project in another way, like writing documents, doing artwork or something like that.

The last two weeks GaRaGeD have been working on christine too, on the Pidgin "plugin" which is a nice plugin and I have been doing my work too. This makes me fell good, when you are not the only one in the project it feels better, when you can discuss some point to other project mates and know what would be the better for the average user.
pidgin and christine

Well, I'm working on the plugin interface and in the last.fm plugin for christine, I already have the authorization part, and then create the configuration dialog for the plugin, this requires me to get familiar with last.fm but, if you already use last.fm and want some feature that you already have in another player, please comment here or on the feature request tracker for the christine project.

On the paid work side, I have been working a lot with Gtk, and reading about the Human Interface Guidelines, have you noted that the GNOME Human Interface Guidelines are quite similar to the Apple Human Interface Guidelines. Well, I hope this helps me to create more intuitive and very usable gtk interfaces.

On the personal side. Cristina and I are really happy, last friday we went to the gynecologist and we see our baby, he is three months right and everything looks right. I have nothing more to say, Im happy!
Just to close this post, if you use mac or compiz, how does looks likeyour desktop right now using the Exposé or the Scale plugin on compiz

Desktop
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/2008-10-08 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/2008-10-08 Wed, 08 Oct 2008 02:03:00 -0500
<![CDATA[ Tweeting the song from christine ]]>
Tweeting the song from christine, originally uploaded by markuz.

Inspired by GaRaGeD's pidgin "plugin" (christine still doesn't have a plugin API), I wrote my "plugin" to tweet the song on being played on christine.

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Tweetingthesongfromchristine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Tweetingthesongfromchristine Sat, 04 Oct 2008 00:03:49 -0500
<![CDATA[ Asi es la vida de un desarrollador... ]]>

Visto en el blog de Kraxbox ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Asi-es-la-vida-de-un-desarrollador markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Asi-es-la-vida-de-un-desarrollador Thu, 02 Oct 2008 13:18:36 -0500
<![CDATA[ About my life ]]>
Well, I think you just don't care abot my life, is quite boring for everyone that is not me. Why? just because this is not the blog of some kind of nerdy hacker that do lot of shiny new and amazing stuff, nor the guy that post every single fart that Apple, ubuntu nor Microsoft does.

So, what is about this blog? I think is a way to flush my mind. I wish I have all the time to write more posts, Several times I had Ideas to be written in the blog, but they didn't come to the blog because (again) there is no time.

Anyway, three paragraphs are enough for my complaints. So, what have I done since my last Post? (the christine love, the picture is not..a post) Well, let me see... let me see... Lot of work. I have been working on this project on ICTC, a desktop application using Python and PyGtk.

User interface design is a quite interesting challenge, and more if you need to design input forms, make them look good, being user friendly (mmm, user friendly... If user friendly means scratching the testicles {or your favorite scratch part of the body} of the users. This application in some forms, need to be fully functional without mouse and use only the key pad, which makes the challenge more interesting. Writing a form that makes input validation, key-press-event handling for every widget, looks good, be ultra-easy to use is... is sometimes castrating... (the more if the client want the application in this color: #FF00FF.)

Obviously I don't have to see the application in that color, but I also have to write a color chooser for this application, if I don't, then the client is going to ask me to change the colors after 15 days using the program or when it get almost blind.

Well. This is most of the work I have done, I'm trying to learn how to use django. I love python, and I want to use django (or another python based framework) to write web applications in the future. I have write some applications but nothing really functional by now. One of the first and small projects I want to do is a web page for christine.


And talking about christine, I'm still working on the new version. I'm refactoring modules. And by now is quite usefull. Just commit this night fixes for the bug #2122313 but I need people to test it to check it is working fine. I have also fixed the open remote dialog that wasn't working since I reallocate this methods.


Well, I thinks is enough for today. See you latter.

Update I forgot, If you like the season 1 of The Big Bang Theory you can the download links from Here, those rar files don't have the subtitles, I will post them there too. I have been watching this tv serie and I love it. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Aboutmylife markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Aboutmylife Fri, 26 Sep 2008 02:30:19 -0500
<![CDATA[ Giving love to christine ]]>
Giving love to christine, originally uploaded by markuz.

This is my desktop testing some changes I have done to christine in this night. Most of them code cleaning and some harmless optimizations.

Update: I have made a screencast, you can download it

here
Update: Maybe you want to see the full resolution video ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Givinglovetochristine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Givinglovetochristine Fri, 12 Sep 2008 00:52:54 -0500
<![CDATA[ HotKeys on Windows using Python ]]>
One of challenges for me in this application is that as it must run in the background there must be a way to raise it, the most easy way to do it is by force the user to click on the small icon in the notification area, but in this case, that was impossible because the computer don't have any mouse, everything is done with the keyboard.

So, I start googling for some way to use hot keys with GTK (PyGtk) in this case, I found that Gtk does have a way to represent the Display wich a way to get to your computer display resources. I just want to grab the keyboard presses and if the right key with the right modifier where pressed then the application arises.

Unfortunely for me, Gtk+ does have a way to do this, but the implementation in PyGTK has a bug where all the display events are ignored, I mean, every time you check of a pending event for the display pygtk will return None, so, no event, no catch, no working code.

Well, in linux you can do this by using the xlib bindings for python, but I have to do this on Windows, so a workmate point me to
This url. Wich shows how to register a hot key on windows.

That was easier than I thought!. But, there is a trick... As you can see in this piece of code:

try:
  msg = wintypes.MSG ()
  while user32.GetMessageA (byref (msg), None, 0, 0) != 0:
    if msg.message == win32con.WM_HOTKEY:
      action_to_take = HOTKEY_ACTIONS.get (msg.wParam)
      if action_to_take:
        action_to_take ()
    user32.TranslateMessage (byref (msg))
    user32.DispatchMessageA (byref (msg))
 
The method GetMessageA is the one that is listening to the messages in the system, and returns when there is a message. If you use a single threaded program, like... some text bassed application or just a "show something" application, then it will be nice, but, if you use Gtk, where the application's events are handled in the gtk main loop this is useless, why? because this method locks until it receives something, and then let your application work, but, if you have it in a while loop you will never leave that loop and then, your signals will never been emited and your handler will never do their job. Is something similar to the use of sockets. Ha... I forgot, you can't use the while gtk.events_pending(): gtk.main_iteration_do() stuff.. it doesn't work, keep reading if you wanna know why.

So, what can I do for this to work?, well, I thought: A thread, but, there is a problem. Windows documentation says that the hotkey registerd with the method RegisterHotKey will only be catched with GetMessageA if the "register" method and the "get message" are in the same thread.

So, what can I do? Put this on the same thread, and then use a flag to let the rest of your application know that the keys have been pressed, then, raise your application. But, why I can't make a gobject based class that emits a signal when this keys are pressed? Well, you should know that Gtk+ is thread aware, but not thread safe, this means, you cannot use Gtk accross the threads, and this is something inherited from gobject (AFAIK).

Here's the code that will let you register hot keys on windows and make your applications raise when you need them.

#!/usr/bin/env python import ctypes
import thread
import win32con
import gobject
from ctypes import wintypes

class keyhandler:
        def __init__(self):
                self.__emit = False
                thread.start_new_thread(self.__catchMsgs, tuple())
                gobject.timeout_add(5,self.checkEmit)
       
        def checkEmit(self):
                if self.__emit:
                        self.emit('keyhandler-keypress',self,self.__emit)
                        print 'Emitiendo senial..'
                        self.__emit = False
                return True
        def __catchMsgs(self, *args):
                byref = ctypes.byref
                user32 = ctypes.windll.user32
                self.HOTKEYS[1] = {'hotkey' : win32con.VK_F3,'modifiers': win32con.MOD_WIN}
                if not user32.RegisterHotKey (None, 1, win32con.MOD_WIN, win32con.VK_F3):
                        print "Unable to register id", 1
                while 1:
                        try:
                                msg = wintypes.MSG()
                                if user32.GetMessageA (byref (msg), None, 0, 0):
                                        if msg.message == win32con.WM_HOTKEY:
                                                if self.HOTKEYS.has_key(msg.wParam):
                                                        self.__emit = self.HOTKEYS[msg.wParam]
                                        user32.TranslateMessage (byref (msg))
                                        user32.DispatchMessageA (byref (msg))
                        except:
                                pass
 
]]> http://islascruz.org/html/index.php?Blog/SingleView/id/HotKeysonWindows markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/HotKeysonWindows Wed, 10 Sep 2008 01:03:05 -0500 <![CDATA[ Christine folder import ]]> .flickr-photo { border: solid 2px #000000; }
.flickr-yourcomment { }
.flickr-frame { text-align: left; padding: 3px; }
.flickr-caption { font-size: 0.8em; margin-top: 0px; }

christine, originally uploaded by markuz.

This is christine (trunk) importing a whole folder, about 1321 songs in just 1:07 mins.

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/christine-1 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/christine-1 Tue, 09 Sep 2008 16:27:34 -0500
<![CDATA[ Christine using 6Mb ]]>
screenshot3.png, originally uploaded by markuz.

This is a screenshot quite surprising for me, this is the gnome-system-monitor saying that christine uses just 6Mb of my RAM. I was looking for memory leaks in one of the applications that I'm currently developing in ICT Consulting, and I found that the memory used by one program, that memory that just belongs to the program is the Writeable memory and that is the memory you should be aware.

I have to say, christine was doing nothing, Just launch it and listen some music, then for one reason that I don't remember, just set it to pause and I get over another task, now, looking at the process table, christine is using more thatn 6 Mb.

btw.. Im using Christine 0.1.6.

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christineusing6Mb markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christineusing6Mb Sun, 17 Aug 2008 23:00:26 -0500
<![CDATA[ WTF! Recursive errors. ]]>
wtf !, originally uploaded by markuz.

An internal error ocurred while showing an internal error.

Update:
@shakaran: In Eclipse 3.4, trying to install some components. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/wtfrecursiveerrors markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/wtfrecursiveerrors Wed, 06 Aug 2008 16:27:32 -0500
<![CDATA[ Christine in launchpad ]]> sourceforge.net si no longer maintained, the reason: I cannot commit my changes to the svn repo, then, I cannot share the newest code.

Christine is now a registered project in Launchpad, well, christine has been a in launchpad for a while but never really use it. So, I will use the launchpad christine account. The bug tracker, the code (and all the good things that launchpad offers) will be hosted here.

As part of the change, christine no longer use Subversion, instead, will use Bazaar, you can get the code using this:

bzr branch lp:christine ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christineinlaunchpad markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christineinlaunchpad Sun, 03 Aug 2008 10:56:51 -0500
<![CDATA[ Christine love in the night ]]>
Christine love in the night, originally uploaded by markuz.

1:47 in the morning. Im still giving some love to christine, that personal proyect that I used to code frequently. Now, it takes some days before I can toch it.

I'm working on the sqlite3 storage layer, This should help me with a more unified data between multiple "sources" that should be renamed as playlists. This will be usefull for many other features, I'm thinkin in some kind of browser.

Anyway, I'm still in the process. I'd like to share the code I have, but SourceForge.net's SVN service is bothering me with a 403 (Forbidden) error that don't let me commit my changes. Now I'm seriously change the project host. What do you recommend?

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christineloveinthenight markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christineloveinthenight Thu, 24 Jul 2008 01:57:45 -0500
<![CDATA[ GNOME 3.0 (Everything with tabs) == Suck! ]]> I believe that GNOME as a project is a very great project, event with the fact that they are reinveing the wheel from time to time (galeon, epiphany => epiphany webkit?). Anyway, I think it's great and as desktop is great too. I use GNOME in my every day and most of the time I'm quite happy, c'mon, there is no desktop environment that have everythin that every user could need.

I love most of the applications that GNOME has as desktop and many others that are not part of the Desktop but integrates well with it. I use such applications because they solve at least one of my problems, being something for my work or just my day to day computer use, and in most of the cases they solve that problem in a very good way, making me feel like I own my computer. But, I also think that they should evolve to be better.

In latest posts on http://planet.gnome.org/ I have seen several posts about some projects that want have tabs everywhere, which for me is ridiculous, Not every application must have tabs. One example is the totem at least not in the way Wouter Bolsterlee is showing it. Another application that I think should not is the calculator. Nautilus is nice for me because it may improve the user's workflow, but does anyone plays two items at the same time?.

Another UGLY example is what Davyd Madeley proposes to the GNOME panel, he may have some point while some people don't know "...what the little grey and blue boxes on their panel are for..." But the users are not stupid, they click them and will know that are they for. And.. a panel with tabs is just UGLY uses more space and useleses (I don't use the workspace switcher applet... is useles at least for me).

I Hope the GNOME developers reconsider where they should or not use tabs in the applications. And if they are going to do that.. Christian Neumair. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/GNOME30EverythingwithtabsSuck markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/GNOME30EverythingwithtabsSuck Sun, 13 Jul 2008 14:48:58 -0500
<![CDATA[ Christine importing a folder. ]]>
Christine importing a folder., originally uploaded by markuz.

I had worked on christine weeks ago, this week I had no time to give it some love. I have been using this "development" version (I think every version of christine is a development version) for a while.

Christine is faster at the load time, starting in just 4 seconds with at least 1500 items in the list, and the search and sort is quite fast too. But working with something like 6889 items in another 'source' I had make it a bit slow.

I think this is because christine use 3 models in the main list. Yes, three models. One is the main model, the one that holds all the library data. then the filter model and then the sort model. I'll try to make a model that implements in some way the filter and sort to reduce the work.

I notice that when you use a filter or even worse a filter and sort model ever time you select or move your cursor, or do anything with a row this process has to be done for every model you have. I mean, in christine you have to do it three times because of the three models. I think this sucks.

Well, I hope to have the time to write a bit on christine in this week.

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christineimportingafolder markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christineimportingafolder Thu, 26 Jun 2008 23:19:17 -0500
<![CDATA[ What have I done in the last month ?? ]]> com, and that's ok. Anyway, islascruz.org is back again and I hope it never fails again.


Now, What have I done in the last month?, well, not blogging tongue.png . I have been using twitter but I had this need to post on my own site.


I had worked on christine, making it a little more usable, now,it loads in my computer in just a couple of seconds with a track list that is about 2600 rows, It uses a little less memory and I'm trying to make it better. But I'm working in some projects in the work (the paid work) and the idea to be working 8 hours in the office and get to the house to keep working isn't a very nice idea.


Christine in small view mode


dsc08103.jpgCristina and I get to the movies, we watch The Happening. Many people didn't like it, and I think this is because there is too much talk, too much death and almost no action. But the point in the movie is the message, we are hurting the planet, and we shouldn't. So, after the blablabla and the blood I like it, just by the message. We also watch Indiana Jones, and to be honest, I like it, but is not by far the most awesome movie I have seen.


As part of the "Leave the stress" activities cristina and I are doing, we are doing scented candles. We enjoy doing it, but the hard issue is cleaning the mess we do.


Well, I think I'm gonna leave this post here, my life is not that intersting. You should read somebody else personal posts.. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/WhathaveIdoneinthelastmonth markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/WhathaveIdoneinthelastmonth Wed, 18 Jun 2008 19:16:51 -0500
<![CDATA[ Creating a gtk custom model ]]> ICT Consulting. We found a problem with many many rows in gtk.ListStore. This is a common problem with Gtk's ListStore and TreeStore. Both are easy to implement and convenient if you are not going to work with too many values. I'm thinking in a couple of thousands. As far as this, the TreeModel is quite usable, but if you use a TreeFilterModel and/or TreeModelSort then you will experience some performance issues.


If what you want to do is just map the main application and then fill the model you can use the idle_add gobject function to iterate over your data and then store it in your model without freezing your application, but it is at the same way, the slowest. You can put chunks of 20 or so, then every time you application runs the callback function will run a small but faster insertion. Anyway, this is still a bit slow.


I have been doing tests with 100,000 rows, in the easy way there are just numbers using a for cycle via a range() result.I think in Gtk, the smaller is the data stored in the model, the faster it goes, because I can insert 100,000 rows in a gtk.ListStore in 7 seconds aprox. while in christine, inserting 2600 row in christine (with more data per cell) takes a lot more.


Anyway, the application that I'm developing shows a list of customers, this is a growing list as new customers are added, in our tests we need to show up to 17,000 customers. Using gtk.ListStore takes at least 17 seconds on my machine just to show it, but we also have a filter model becuse search in a list of 17000 items is not easy if you go looking every row by hand. So, usig the FilterModel takes almost the same time in searching something. Obviusly, waiting 17 seconds for the result is not an option, even worse, you made a mistake and wrote LOPEX instead LOPEZ.


So, I was searching over internet what can I do. I have already use the common 'tweaks' to improve the gtk.ListStore performance and I have reached the 8 - 9 seconds over those 17,000 items, but even with this, its too much time. The search points me to the gtk.GenericTreeModel. This generic model allows you to create a custom model where you can make your own tweaks to improve the performance of your model. In the link above gives you the way to use it. I have alreade created my own custom model and it really relly made the things better.


Now, one of the problems that gtk.GenericTreeModel have are the memory leaks. Using this model you may use lots of memory. This is because the GTM use to create a reference to the value that you are returning as Iter, e.g. you are using a list of lists, where you store the values, every item in the list is a row, then, the index if the iter wich references to the list you are storing in that row. The problem is that the GTM increase the reference count of you node (the list inside of the list) to aviod row destruction and then use the iter. This, in the best will make your values been refered until you destroy your model (and any reference to the data), in the worse the reference count of your data will never been unrefered and then the memory will never be freed.


You can use the invalidate_iters every time you modify the rows (add or delete) to make the rows invalid and then decrease the reference count of the row, and when your data have no more references then be deleted. But, I have the problem that the reference count was never decreased when I destroy the window or the model. Where is the trick here, use the Python's garbage collector, and your memory will be freed.


So, the new model based on PyGtk's GenericTreeModel actually works for us. Inserting 17,000 takes just 1 second, and the search (filter) is the same thing, 1 second is an option. I would like to see everything just appear when you request it, but one second is good for now. And testing with my current christine music list it takes just 0.06 seconds to show the list. Inserting 100,000 items (the easy way, just numbers) takes just 1.164 seconds to get filled with four columns and 2.36 seconds to show itself (creating a filter model and setting it to a treeview), so, for now this kind of optimizations will work for us, there are other optimizations on the Filter model and the treeview, My goal is to create something similar to wat Aaron bockover do with banshee.

Gtk Custom Model

Note: Test times are approximate, cache, cpu usage, load average and other may cause the times change, but at the end give us an idea of what is going on.
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Creating-a-custom-model markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Creating-a-custom-model Sat, 17 May 2008 10:24:50 -0500
<![CDATA[ Testing the new christineConf module ]]>
Testing the new christineConf module, originally uploaded by markuz.

I have been working in the configuration module for christine, something similar to gconf, but just for christine. Why? well, many people complains because christine needs the gnome-extras package, where gconf is, and to be honest, christine didn't use all the gconf power, so, there isn't a big reaons to keep gconf on christine.

This isn't the only thing I have been working on. I'm trying to improve many things for the next release. Most of the work wil be in the list, zodman gives me some nice ideas, and I will try to implement them.

Anyway, you are also invited to work with me in the christine development. You can join the maling list for the next release.

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/TestingthenewchristineConfmodule markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/TestingthenewchristineConfmodule Sat, 03 May 2008 23:38:30 -0500
<![CDATA[ Christine 0.1.6 ]]> christine 0.1.6
CLick to enlarge
This is the new release of Christine Media Player. This release include:

HelpMenu.png
  1. Some bugfixes
  2. Reworked code in Sources list
  3. Reworked display.
  4. Improved import code (no more freeze while looking for the media files)
  5. Multiple Sources list.
  6. Translate Christine and Report a bug menuitems
You can download it from sourceforge:
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-016 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-016 Tue, 29 Apr 2008 13:45:20 -0500
<![CDATA[ Nearshoring... The Movie! ]]>
]]> http://islascruz.org/html/index.php?Blog/SingleView/id/Nearshoring-The-Movie markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Nearshoring-The-Movie Fri, 18 Apr 2008 13:05:47 -0500 <![CDATA[ PyGTK y Threads ]]>
gtk.gdk.threads_init()
 
Esto lo tendras que hacer antes de iniciar algun thread. Y luego, al usar algun thread debes englobarlo dentro de

gtk.threads_enter()
thread.start_new(funcion, (arg1,arg2,argN))
gtk.threads_leave()
 
Solo recuerda que no debes manipular gtk fuera del thread en el que esta corriendo el ciclo principal (gtk.main_loop).

Si lo que necesitas es estar cachando informacion en un thread aparte y modificar la interfaz (ej. Leyendo un socket y mostrando informacion de cuanto llevas leido) entonces usa alguna bandera y modifica tu apariencia en el thread principal, de lo contrario tendras problemas con gobject y glib. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/PyGTK-y-Threads markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/PyGTK-y-Threads Thu, 10 Apr 2008 18:51:44 -0500
<![CDATA[ Algo de amor para cristine ]]> sources.pngBien, hoy ha sido un pequenio dia para dar amor a christine, Hoy he tenido un poco de tiempo libre para 'descansar', Ayer cristina y yo nos fuimos a conocer Guanajuato, pronto pondre las fotos y la rese??????±a.

Hoy, despues de hacer los quehaceres de la casa me sente un rato a cubrir una necesidad en especial que he tenido en Christine. Bien, pues resulta que a cristina le gusta mucho la musica en espa??????±ol, en particular la movida, mientras que a mi me gusta mas la musica en ingl??????©s, El problema es que la gran mayoria de la musica en espa??????±ol la he copiado de varios lugares y no la tengo en mi directorio de musica tipico, y tampoco lo tengo dentro de mi lista de canciones normal. Que pasa cuando cristina quiere escuchar su musica, tengo que entrar en ~/.christine y copiar el archivo music a algun otro, despues copiar el archivo de musica de cristina a music, y lo mismo cuando quiero poner mi lista de canciones. Un poco engorroso, aunque no lo hago muy seguido. Hoy he hecho un peque??????±o cambio a christine de forma que es posible selecionar la lista de canciones. Por hoy, en este lado es suficiente, aun le falta pulir, pero lo hace con mas tiempo y despues.

Tambien estuve trabajando un poco para corregir unos pequenios problemas con los menus, que no se muestran traducidos, esto debido a que en los archivos de descripcion de glade las etiquetas no tienen la propiedad translatable (en los menues). Tambien he agregado al SVN los archivos de traduccion creados en Launchpad. En fin, estos cambios ya estan disponibles en el SVN de christine.

newMenu1.png
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Algo-de-amor-para-cristine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Algo-de-amor-para-cristine Sat, 22 Mar 2008 21:43:11 -0500
<![CDATA[ Translation status ]]>
Translation status in christine

Wanna help? Translate christine HERE! ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Translation-status markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Translation-status Tue, 12 Feb 2008 16:57:22 -0600
<![CDATA[ christine 0.1.5 ]]> christine and I'm not so proud (because of the delay) of the fifth revision of the fifth revision of the 0.1 version.

This fixes some bugs that I have found since the 0.1.4 but to be honest, I don't remember them. You can download the source packages from Here. There is also an Ubuntu Gutsy Package there.

christine 0.1.5
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/christine-015 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/christine-015 Tue, 05 Feb 2008 15:34:41 -0600
<![CDATA[ Speed up gtk.ListStore ]]>
Se, que podria mostrar Christine y dejar que una llamada con idle_add haga la chamba, es decir, christine se mostraria en menos de 1 segundo, pero el idle_add me retrasa mas la carga de la lista a unos 2 minutos.

Alguien con algun comentario, enlace o similar, seria mas que apreciado. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Speed-up-gtkListStore markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Speed-up-gtkListStore Thu, 06 Dec 2007 15:24:50 -0600
<![CDATA[ Profiling Python ]]> Profiling and Optimizing Python ]]> http://islascruz.org/html/index.php?Blog/SingleView/id/Profiling-Python markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Profiling-Python Thu, 22 Nov 2007 08:40:15 -0600 <![CDATA[ Widgets 'recortados' en Gtk ]]> Gtk tienen una ventana asociada, y no precisamente la ventana con decoracion que todo mundo ve. Gtk adiere una propiedad llama "window" a los widgets al ser empacados, o emparentados a otro widget contenedor.

Generalmente estos widgets son de apariencia rectangular, pero es posible tunearlos para que tengan la forma que nosotros queremos. La forma mas facil de hacerlo es tomar una imagen un usarla como "Molde" para crar nuestro contenedor recortado. aunque tambien es posible dibujar lo que nosotros querramos usando las funciones de cairo sobre un contexto (Que en si, es lo que hacemos con la imagen molde, pero mucho mas sencillo).

Lo que hacemos es obtener un molde a partir de una imagen, es decir, abrimos la imagen y creamos un gtk.gdk.Pixbuf, que es el mostraremos, pero podemos obtener el gtk.gdk.Pixmap y la mascara de este Pixbuf de forma que podamos usar dicha mascara para crear el contorno de nuestro widget.

Los widgets, una vez empacados,como ya habia dicho obtienen una propiedad llamada window, que pertenece a la clase gtk.gdk.Window. Aquellos que ya se han puesto a dibuar algo con cairo se habran dado cuenta que se obtiene un contexto de un widget a partir de su gtk.gdk.Window.

Bien. tambien es posible obtener este contexto de cairo a partir de un pixmap, hacer el dibujo molde y luego pegarselo a la ventana para que gtk.gdk sepa que partes ha de dibujar y cuales no.

Veamos un pequenio ejemplo.

class shapedWindow(gtk.DrawingArea):
        def __init__(self):
                gtk.DrawingArea.__init__(self)
                self.__pixbuf =  gtk.gdk.pixbuf_new_from_file('./logo.png')
                self.connect('size-allocate',self.size_allocated)
                self.connect('expose-event',self.do_expose_event)
                self.set_size_request(self.__pixbuf.get_width(),
                                self.__pixbuf.get_height())
       
        def size_allocated(self,win,allocation):
                w,h = (allocation.width, allocation.height)
                self.bitmap = gtk.gdk.Pixmap(None,w,h,1)
                context = self.bitmap.cairo_create()
               

                self.do_expose_event(self,'',context)
                parent = self.get_parent()
                win.shape_combine_mask(self.bitmap,0,0)
                parent.shape_combine_mask(self.bitmap,0,0)
               
        def do_expose_event(self, widget, event,allocate = False):
                if allocate:
                        context = allocate
                else:
                        context = self.window.cairo_create()
                if allocate:
                        context.set_operator(cairo.OPERATOR_DEST_OUT)
                        w,h = (self.allocation.width, self.allocation.height)
                        context.rectangle(0,0,w,h)
                        context.set_source_rgb(1,1,1)
                        context.paint()
                context.move_to(0,0)
                context.set_operator(cairo.OPERATOR_OVER)
                if allocate:
                        pixmap,mask = self.__pixbuf.render_pixmap_and_mask()
                        context.set_source_pixmap(mask,0,0)
                else:
                        context.set_source_pixbuf(self.__pixbuf,0,0)
                context.paint()
       

if __name__ == '__main__':
        window = gtk.Window()
        window.set_decorated(False)
        a = shapedWindow()
        window.add(a)
        window.show_all()
        gtk.main()
       
 
Que es lo que hacemos aqui? bien, primero creamos un widget personalizado usando gtk.DrawingArea y conectamos la sennial size-allocate para poder establecer el tamanio de nuestro widget. Una vez llamada esta funcion creamos un pixmap vacio del tamanio de nuestro widget, que es el tamanio que nos ha dado el contenedor padre, este es un rectangulo como de costubre, con un ancho y alto. A este pixmap le sacaramos el cairo context, sobre el cual hemos de 'dibujar' nuestro molde.

Como en este ejemplo el widget y su molde de la misma forma estoy aprovechado el metodo do_expose_event para hacer el dibujo inicial y despues hacer las funciones de redibujado en caso de un evento de expose.

Quienes hacen la chamba aqui? bien, para el dibujo inicial de nuestro widget es context.set_source_from_pixmap(), aunque podriamos usar el mismo set_source_from_pixbuf he detectado problemas con colores en Windows, entonces no lo recomiendo.

Otro que entra en juego y es el que le dice al widget 'orale cabron, apegate a esta forma' es win.shape_combine_mask(self.bitmap,0,0).

De ahi, el ponerle contenido a nuestro widget no es mas que un amanipulacion de colores y demas dentro de nuestro contexto cairo. Que, es otro tema del que hablar, como 'dibujar' lo que queremos en nuestro widget usando su contexto cairo.

Shaped Window widget Tamanio Completo

Ciertamente, el logtipo de Christine es el widget 'recortado' face-smile.png ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Widgets-recordatos-en-Gtk markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Widgets-recordatos-en-Gtk Fri, 09 Nov 2007 17:19:06 -0600
<![CDATA[ Sockets ]]> GTK+ que es el que corresponde a la termina de la esquina inferior izquierda. Otro cliente es puro texto, que es el que esta en la parte superior, y el servidor es la terminal alargada que esta en el centro.

screenshot5.png

Lo que muestran las terminales no es mas que pura informacion loggeada usando el modulo logging de python
En los proximos dias, ya que tenga el codigo mas limpio vere la forma de ponerlo al publico. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Sockets markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Sockets Wed, 31 Oct 2007 18:22:09 -0500
<![CDATA[ Imprimir a un archivo PDF usando GTK. ]]> Perfecto. En esta semana me ha tocado estar trabajando sobre un programita que ando haciendo, el cual debe correr sobre Linux y MS Windows >= 2000. El desarrollo se esta haciendo en Python usando GTK para la interfaz grafica, pero me he encontrado uno que otro problemita con GTK, sobre todo con el manejo de ventanas, aunque el que mas tiempo me ha llevado ha sido el de impresion.

Gtk+ a partir de la version 2.10 incluye soporte para impreision en Linux y otros Unix'es gracias a CUPS, mientras que en Windows lo hace de manera nativa con el sistema de impresion de Windows.

Debo decir que en linux esta cosa es la maravilla, En windows no tanto, pero funciona decentemente si tus requerimientos no son tan especiales.

Los requerimientos para imprimir son estos:
  • Debe imprimir en la impresora por defecto
    • NO debe mostrar el dialogo de seleccion de impresora
  • Debe imprimir en el tamanio determinado por el programa
En linux, repito, esto es una maravilla, solo le digo imprime usando la constante gtk.PRINT_OPERATION_PRINT y con esto no me muestra el cuadro de dialogo, previamente he creado la operacion de impresion y le he dicho que seleccione la impresora por defecto, en linux, si en settings.set_printer() le pasas el parametro '' usa la impresora por defecto, es mas, si no usas el metodo set_printer usa la impresora por defecto.

Pero en Windows la cosa no es tan bonita. para empezar Siempre muestra el cuadro de seleccion de impresora (punto menos). Y para acabarla de amolar, aunque tengas una impresora predeterminada y esta impresora este seleccionada mandas imprimir (Alt +m o ENTER) habra un error porque GTK no ha configurado las cabeceras de impresion para mandarle el 'win32-driver', 'win32-driver-extra' y otros parametros fumados de los que Windows sabe. Obviamente, si seleccionas otra impresora y regresas a la que esta por defecto estos parametros son llenados y entonces la impresion funciona "bien". Obviamente, como no queremos que el usuario vea el cuadro de impresion esto no es opcion.

Lo siguiente es, obtener la impresora por defecto y mandar establecer los encabezados, para esto se pueden valer del modulo win32print

import win32print

printerName = win32print.GetDefaultPrinter()
printer = win32print.OpenPrinter(printerName)
printerValues = win32print.GetPrinter(printer,2)
dir(printerValues['pDevMode'])
 
Y pueden valerse del gtk.PrintSettings.set() para poner los encabezados.

Esto les sera util cuando ustedes quieran mostrar el cuadro de impresion, a fin de que lo muestre y espere una configuracion por parte del usuari, o en caso de que no se configure nada por parte del usuario, usar las configuraciones por defecto.

Hasta aqui todo bien, pero, Yo no quiero el cuadro de impresion!, solo quiero que imprima.

Bien, yo no queria hacerlo asi, pero pues bueno, no hay de otra.

if os.name == 'nt':
        filename = './ultimafactura.pdf'
        op.set_export_filename(filename)
        action = gtk.PRINT_OPERATION_ACTION_EXPORT
elif '-d' in sys.argv:
        action = gtk.PRINT_OPERATION_ACTION_PRINT_DIALO