Search Results: "spa"

31 July 2012

Russell Coker: ZFS on Debian/Wheezy

As storage capacities increase the probability of data corruption increases as does the amount of time required for a fsck on a traditional filesystem. Also the capacity of disks is increasing a lot faster than the contiguous IO speed which means that the RAID rebuild time is increasing, for example my first hard disk was 70M and had a transfer rate of 500K/s which meant that the entire contents could be read in a mere 140 seconds! The last time I did a test on a more recent disk a 1TB SATA disk gave contiguous transfer rates ranging from 112MB/s to 52MB/s which meant that reading the entire contents took 3 hours and 10 minutes, and that problem is worse with newer bigger disks. The long rebuild times make greater redundancy more desirable. BTRFS vs ZFS Both BTRFS and ZFS checksum all data to cover the case where a disk returns corrupt data, they don t need a fsck program, and the combination of checksums and built-in RAID means that they should have less risk of data loss due to a second failure during rebuild. ZFS supports RAID-Z which is essentially a RAID-5 with checksums on all blocks to handle the case of corrupt data as well as RAID-Z2 which is a similar equivalent to RAID-6. RAID-Z is quite important if you don t want to have half your disk space taken up by redundancy or if you want to have your data survive the loss or more than one disk, so until BTRFS has an equivalent feature ZFS offers significant benefits. Also BTRFS is still rather new which is a concern for software that is critical to data integrity. I am about to install a system to be a file server and Xen server which probably isn t going to be upgraded a lot over the next few years. It will have 4 disks so ZFS with RAID-Z offers a significant benefit over BTRFS for capacity and RAID-Z2 offers a significant benefit for redundancy. As it won t be upgraded a lot I ll start with Debian/Wheezy even though it isn t released yet because the system will be in use without much change well after Squeeze security updates end. ZFS on Wheezy Getting ZFS to basically work isn t particularly hard, the ZFSonLinux.org site has the code and reasonable instructions for doing it [1]. The zfsonlinux code doesn t compile out of the box on Wheezy although it works well on Squeeze. I found it easier to get a the latest Ubuntu working with ZFS and then I rebuilt the Ubuntu packages for Debian/Wheezy and they worked. This wasn t particularly difficult but it s a pity that the zfsonlinux site didn t support recent kernels. Root on ZFS The complication with root on ZFS is that the ZFS FAQ recommends using whole disks for best performance so you can avoid alignment problems on 4K sector disks (which is an issue for any disk large enough that you want to use it with ZFS) [2]. This means you have to either use /boot on ZFS (which seems a little too experimental for me) or have a separate boot device. Currently I have one server running with 4*3TB disks in a RAID-Z array and a single smaller disk for the root filesystem. Having a fifth disk attached by duct-tape to a system that is only designed for four disks isn t ideal, but when you have an OS image that is backed up (and not so important) and a data store that s business critical (but not needed every day) then a failure on the root device can be fixed the next day without serious problems. But I want to fix this and avoid creating more systems like it. There is some good documentation on using Ubuntu with root on ZFS [3]. I considered using Ubuntu LTS for the server in question, but as I prefer Debian and I can recompile Ubuntu packages for Debian it seems that Debian is the best choice for me. I compiled those packages for Wheezy, did the install and DKMS build, and got ZFS basically working without much effort. The problem then became getting ZFS to work for the root filesystem. The Ubuntu packages didn t work with the Debian initramfs for some reason and modules failed to load. This wasn t necessarily a show-stopper as I can modify such things myself, but it s another painful thing to manage and another way that the system can potentially break on upgrade. The next issue is the unusual way that ZFS mounts filesystems. Instead of having block devices to mount and entries in /etc/fstab the ZFS system does things for you. So if you want a ZFS volume to be mounted as root you configure the mountpoint via the zfs set mountpoint command. This of course means that it doesn t get mounted if you boot with a different root filesystem and adds some needless pain to the process. When I encountered this I decided that root on ZFS isn t a good option. So for this new server I ll install it with an Ext4 filesystem on a RAID-1 device for root and /boot and use ZFS for everything else. Correct Alignment After setting up the system with a 4 disk RAID-1 (or mirror for the pedants who insist that true RAID-1 has only two disks) for root and boot I then created partitions for ZFS. According to fdisk output the partitions /dev/sda2, /dev/sdb2 etc had their first sector address as a multiple of 2048 which I presume addresses the alignment requirement for a disk that has 4K sectors. Installing ZFS deb http://www.coker.com.au wheezy zfs I created the above APT repository (only AMD64) for ZFS packages based on Darik Horn s Ubuntu packages (thanks for the good work Darik). Installing zfs-dkms, spl-dkms, and zfsutils gave a working ZFS system. I could probably have used Darik s binary packages but I think it s best to rebuild Ubuntu packages to use on Debian. The server in question hasn t gone live in production yet (it turns out that we don t have agreement on what the server will do). But so far it seems to be working OK. Related posts:
  1. Discovering OS Bugs and Using Snapshots I m running Debian/Unstable on an EeePC 701, I ve got an...
  2. Starting with BTRFS Based on my investigation of RAID reliability [1] I have...
  3. ZFS vs BTRFS on Cheap Dell Servers I previously wrote about my first experiences with BTRFS [1]....

29 July 2012

Joey Hess: build a dynamic webapp in Yesod in just three days

This screencast shows what I built. Scroll down for my Yesod braindump. <video controls="controls" src="http://joeyh.name/screencasts/git-annex-webapp.ogg"></video> video link I've been astonished how quickly this went together. This is my first time using any sort of web framework, and I used a still unusual one, Yesod. It's my first time using Bootstrap too. It's also the first time I've done any AJAX programming! Bootstrap was something I'd heard of and seen some suspiciously similar looking sites built with, but it was really a pleasant surprise. Being able to make things that work and look good on the web without struggling with CSS is such a nice change. For the first time, it makes the web feel like a UI toolkit to me. As I've learned Yesod, I kept seeing problems the web framework solves that I either solved in an ad-hoc basis in Ikiwiki, or didn't realize were problems. In the former group are things like having a consistent way to store a URL to redirect to after an action (such as logging in) finishes, and generating urls programmatically in ways that avoid broken links. In the latter group are things like exploiting types to guarantee mistakes can't be made. And also the abstraction of widgets, which combine html, css, and javascript, in a way that can be composed with other widgets. Overall, I'm really enjoying Yesod, and it's making me productive in new ways. I also see a lot of potential in Yesod to improve from where it is.
    webpage = bootstrap Dynamic $ do
        setTitle "FooCorp"
        login <- getLogin
        navbar [FixedTop] $ do
            brand "FooCorp"
            link AboutR
            link BlogR
            nav [PullRight] $
                link . maybe LoginR ProfileR login
        div [ContainerFluid] $ content login
        where
            content Nothing = heroUnit $ do
                para $ "We're the FooCorp for you."
                button "Register Today" [Primary, Large] SignUpR
                carousel
                    [ amazingFeatures
                    , aboutFooCorp
                    , pricing
                    ]
            content (Just user)  = do
                para $ "Welcome back " ++ name user ++ "!"
                showProfile user

Jordi Mallach: GUADEC 2012

I've been in A Coru a for this year's GUADEC since Tuesday night, and it rocked. I did a late registration after my first week at Collabora, which is sponsoring my stay here.

I came one day early to participate, as Debian's representative, at the yearly GNOME Advisory Board meeting, for the first time. It was a positive experience, which helped me get a grasp of the big picture of what the GNOME Foundation does. I also had the pleasure of visiting Igalia's awesome offices in the city, and puting faces to many names during the meeting. I presented an overview of Debian's relation to GNOME, how our packaging team works and what are our goals and biggest problems as a GNOME downstream. We stirred some good debate as some other Advisory Board members share part of our problems. I should be posting a summary of what happened there for debian-project@ldo as soon as I have the time to scribble it. I've met with GNOME Hispano people I hadn't seen since 2004 or 2006 in the best case, and catched up with many of them. I've also met many GPUL members I had know for over a decade via IRC, but never had met in person, and it was about time. And of course, I've got to known a good number of my new workmates at Collabora, and had fun with them around the conference, the beach and the numerous post-conference events. Last, but not least, I ended up participating in the GNOME Olympics, substituting Rodrigo in Team B Core Dumped , along with Stefano, John, Bastien, Chema and Adam. WE WON, not thanks to me, but the statistics shine: I've won all FreeFA World Cups I've played :P so here's a PROtip: if you want to win next year, be sure to be my team mate, and more importantly, be sure Adam is not your rival. :) Unfortunately, I'm only attending the core days so tonight I'll be flying back to Madrid on my way home in Val ncia. See you next year! A Coru a is a city that has impressed me quite a bit, and I'm looking forward to coming back for some more standard vacation at some point. :)

28 July 2012

Vincent Bernat: Switching to the awesome window manager

I have happily used FVWM as my window manager for more than 10 years. However, I recently got tired of manually arranging windows and using the mouse so much. A window manager is one of the handful pieces of software getting in your way at every moment which explains why there are so many of them and why we might put so much time in it. I decided to try a tiling window manager. While i3 seemed pretty hot and powerful (watch the screencast!), I really wanted something configurable and extensible with some language. So far, the common choices are: I chose awesome, despite the fact that StumpWM vote for Lisp seemed a better fit (but it is more minimalist). I hope there is some parallel universe where I enjoy StumpWM. Visually, here is what I got so far: awesome dual screen setup

Awesome configuration Without a configuration file, awesome does nothing. It does not come with any hard-coded behavior: everything needs to be configured through its Lua configuration file. Of course, a default one is provided but you can also start from scratch. If you like to control your window manager, this is somewhat wonderful. awesome is well documented. The wiki provides a FAQ, a good introduction and the API reference is concise enough to be read from the top to the bottom. Knowing Lua is not mandatory since it is quite easy to dive into such a language. I have posted my configuration on GitHub. It should not be used as is but some snippets may be worth to be stolen and adapted into your own configuration. The following sections put light on some notable points.

Keybindings Ten years ago was the epoch of scavanger hunts to recover IBM Model M keyboards from waste containers. They were great to type on and they did not feature the infamous Windows keys. Nowadays, this is harder to get such a keyboard. All my keyboards now have Windows keys. This is a major change with respect to configure a window manager: the left Windows key is mapped to Mod4 and is usually unused by most applications and can therefore be dedicated to the window manager. The main problem with the ability to define many keybindings is to remember the less frequently used one. I have monkey-patched awful.key module to be able to attach a documentation string to a keybinding. I have documented the whole process on the awesome wiki. awesome online help

Quake console A Quake console is a drop-down terminal which can be toggled with some key. I was heavily relying on it in FVWM. I think this is still a useful addition to any awesome configuration. There are several possible solutions documented in the awesome wiki. I have added my own1 which works great for me. Quake console

XRandR XRandR is an extension which allows to dynamically reconfigure outputs: you plug an external screen to your laptop and you issue some command to enable it:
$ xrandr --output VGA-1 --auto --left-of LVDS-1
awesome detects the change and will restart automatically. Laptops usually come with a special key to enable/disable an external screen. Nowadays, this key does nothing unless configured appropriately. Out of the box, it is mapped to XF86Display symbol. I have associated this key to a function that will cycle through possible configurations depending on the plugged screens. For example, if I plug an external screen to my laptop, I can cycle through the following configurations:
  • only the internal screen,
  • only the external screen,
  • internal screen on the left, external screen on the right,
  • external screen on the left, internal screen on the right,
  • no change.
The proposed configuration is displayed using naughty, the notification system integrated in awesome. Notification of screen reconfiguration

Widgets I was previously using Conky to display various system-related information, like free space, CPU usage and network usage. awesome comes with widgets that can fit the same use. I am relying on vicious, a contributed widget manager, to manage most of them. It allows one to attach a function whose task is to fetch values to be displayed. This is quite powerful. Here is an example with a volume widget:
local volwidget = widget(  type = "textbox"  )
vicious.register(volwidget, vicious.widgets.volume,
         '<span font="Terminus 8">$2 $1%</span>',
        2, "Master")
volwidget:buttons(awful.util.table.join(
             awful.button(   , 1, volume.mixer),
             awful.button(   , 3, volume.toggle),
             awful.button(   , 4, volume.increase),
             awful.button(   , 5, volume.decrease)))
You can also use a function to format the text as you wish. For example, you can display a value in red if it is too low. Have a look at my battery widget for an example. Various widgets

Miscellaneous While I was working on my awesome configuration, I also changed some other desktop-related bits.

Keyboard configuration I happen to setup all my keyboards to use the QWERTY layout. I use a compose key to input special characters like . I have also recently use Caps Lock as a Control key. All this is perfectly supported since ages by X11 I am also mapping the Pause key to XF86ScreenSaver key symbol which will in turn be bound to a function that will trigger xautolock to lock the screen. Thanks to a great article about extending the X keyboard map with xkb, I discovered that X was able to switch from one layout to another using groups2. I finally opted for this simple configuration:
$ setxkbmap us,fr '' compose:rwin ctrl:nocaps grp:rctrl_rshift_toggle
$ xmodmap -e 'keysym Pause = XF86ScreenSaver'
I switch from us to fr by pressing both left Control and left Shift keys.

Getting rid of most GNOME stuff Less than one year ago, to take a step forward to the future, I started to heavily rely on some GNOME components like GNOME Display Manager, GNOME Power Manager, the screen saver, gnome-session, gnome-settings-daemon and others. I had numerous problems when I tried to setup everything without pulling the whole GNOME stack. At each GNOME update, something was broken: the screensaver didn t start automatically anymore until a full session restart or some keybindings were randomly hijacked by gnome-settings-daemon. Therefore, I have decided to get rid of most of those components. I have replaced GNOME Power Manager with system-level tools like sleepd and the PM utilities. I replaced the GNOME screensaver with i3lock and xautolock. GDM has been replaced by SLiM which now features ConsoleKit support3. I use ~/.gtkrc-2.0 and ~/.config/gtk-3.0/settings.ini to configure GTK+. The future will wait.

Terminal color scheme I am using rxvt-unicode as my terminal with a black background (and some light transparency). The default color scheme is suboptimal on the readability front. Sharing terminal color schemes seems a popular activity. I finally opted for the derp color scheme which brings a major improvement over the default configuration. Comparison of terminal color schemes I have also switched to Xft for font rendering using DejaVu Sans Mono as my default font (instead of fixed) with the following configuration in ~/.Xresources:
Xft.antialias: true
Xft.hinting: true
Xft.hintstyle: hintlight
Xft.rgba: rgb
URxvt.font: xft:DejaVu Sans Mono-8
URxvt.letterSpace: -1
The result is less crisp but seems a bit more readable. I may switch back in the future. Comparison of terminal fonts

Next steps My reliance to the mouse has been greatly reduced. However, I still need it for casual browsing. I am looking at luakit a WebKit-based browser extensible with Lua for this purpose.

  1. The console gets its own unique name. This allows awesome to reliably detect when it is spawned, even on restart. It is how the Quake console works in the mod of FVWM I was using.
  2. However, the layout is global, not per-window. If you are interested by a per-window layout, take a look at kbdd.
  3. Nowadays, you cannot really survive without ConsoleKit. Many PolicyKit policies do not rely on groups any more to grant access to your devices.

Martin-&#201;ric Racine: OpenWRT: SLAAC and DHCPv6 on White Russian

As I recently reported, I have been trying to configure my Linksys WRT54GL running the OpenWRT firmware (version 0.9 a.k.a. White Russian) to support SLAAC and DHCPv6 out of the box.Most of the feedback I got involved upgrading the OpenWRT firmware to a more recent release that might not fit the available storage capacity of the device, which felt like too risky of an operation to attempt.The solution I found instead involved adding ipkg sources to OpenWRT's backports repository, which offers a minimalistic DHCPv6 client. Although I haven't been able to find any proper documentation for this client, the content of its configuration file is mostly intelligible. What remains now is to actually configure it to cooperate with the kernel's native SLAAC implementation and, whenever an IPv6 network is found on the ISP side, to propagate the address space, DNS and routing information to my LAN using radvd.Would anyone located within the Helsinki metropolitan area happen to have an IPv6 testing environment that would at least allow me to configure and test my router?

27 July 2012

NOKUBI Takatsugu: RetroBSD on PIC32

Shozo TAKEOKA had described to work RetroBSD on PIC32 1chip micro computer in 14th JNUG BOF. The board is Chipkit MAX32 with SD card socket. He bought it 5,900 JPY. More detail is http://ameblo.jp/takeoka/entry-11308169137.html (Japanese). RetroBSD is based on 2.2 BSD (!), and work without MMU. So it can work only one process in their ram, other processes are in swap space. It was really funny presentation.

25 July 2012

Vincent Sanders: Fowlers Delight?

Fowler published his paper on Continuous Integration (CI) way back in 2000. Personally at the time I was a much more naive developer, I was not really an adherent to the whole XP community and had worked for a series of companies where the idea of a release build was of a month long process and the concept that the whole codebase could be built and tested on every commit was a comical notion at best.

By the time the time the 2006 edition of the paper came out however I was convinced. Ever since then I have tried to make the projects I worked on have as many CI features as possible. It is one reason I ran the ARM Kernel autobuilder for years as an attempt to provide at least build coverage.

I especially like the way these concepts mean that releases are much less "scary" events and release anxiety is reduced to a minimum. When every commit produces something that is of release quality a project really is doing it right.

The reason I mention any of this is I have recently set up the NetSurf projects CI server. The heavy lifting is being done by a Jenkins instance running on a VPS fulfilling the "Every Commit Should Build the Mainline on an Integration Machine" part of the Fowler guidelines.

Setting up Jenkins was much less trouble than many of the previous systems I have used. I have been a little underwhelmed by the support for plain old make based projects which you have to resort to shell scripts for, but leaving that aside the rest was straightforward. The documentation could do with a purge pass for the old hudson name and the error reporting (especially under memory pressure) is not great.

And there lies my one real issue with the tool, memory. The VPS has 512MByte RAM and runs nothing beyond a web server, jenkins and the C compiler to build the project components. One would hope that was plenty of memory, doing the builds by hand it did seem gcc is happy in that space, alas Jenkins is a Java application and guzzles RAM (over 60% of RSS right now) and causes itself out of memory exceptions with distressing frequency.

The project is left with the choices:
It is such a pity too, aside from the RAM issues it is all going well and it has already encouraged us to get the toolchains for the less commonly built targets (ppc amiga and windows for a start) working.

Michal &#268;iha&#345;: Weblate hacking #3

As you can see on github, there are currently no open issues for Weblate's 1.2 milestone. Looks like I've done most of my Hackweek VIII project faster than expected, but I might add some more improvements. Everything went quite smoothly, but anyway I've decided to postpone some issues. The major reason is that I'm not really sure whether these are good ideas and won't implement something until I'll get more feedback. You can find such issues labeled "needs decision". Comments there are especially welcome :-). On the code side, I've improved support for po file headers, did various improvements on maintenance scripts and improved about page. Also current code from git is now deployed at demo.weblate.org, so feel free to test it. I'm especially curious how the simple and stupid spam protection will work in reality. Now it's time for ice cream and then I'll think what to implement next :-).

Filed under: English Suse Weblate 0 comments Flattr this!

Diego Escalante Urrelo: A Coru a, d a uno

You can follow the latest GUADEC updates from @guadec and @diegoe.

Isa, Alejo, Laura, and Germ n stealing a mug.

GUADEC just started. Or at least, the arrangements for GUADEC.

The local team is hard at work at the GUADEC HQ of the Facultade de Inform tica, they are really working really hard to make sure that there is a proper wired network setup (yes, you read that right!), a great video setup to record all the talks and publish them as soon as possible and setting up the final details of rooms, info desk, accommodation

If you are staying at the Rialta, you can take the hourly bus to the Facultade (just ask the driver). The bus departs from the frontis of Block 3. Ask the driver to let you know when to get off the bus. He is aware of GUADEC so your gringo-spanish should suffice.

We will be holding a pre-registration party tonight at 21:00 (9pm) just outside the Rialta cafeteria. If you are already here drop by for the Queimada by Alejo, our galician wizard.

24 July 2012

Gunnar Wolf: Electronic voting: Talk delivered in Moquegua (Peru)

TitleElectronic voting: Talk delivered in Moquegua (Peru)
Publication TypeAudiovisual
Year of Publication2012
AuthorsWolf G
Date Published07/07/2012
CityMoquegua, Per
Full TextWhile we were at DebConf, all busy and in the organizing frenzy, I was supposed to deliver a talk in Moquegua, Per , on the evening of July 7. Of course, I was unable to attend. Nevertheless, I accepted, if the talk could be delivered as a pre-recorded video with a live Q&A session afterwards. And so it was.
The talk went quite smooth, and I think I will use bits of it. Video quality is far from great, but well... it was taken using nothing but a webcam and the laptop's integrated microphone. To my surprise, sound quality that's what matters! works quite well.
I mostly followed the attached presentation; the video is split in three parts to make it easier to download.
And yes, it's all in Spanish. Translations are, of course, welcome :)
AttachmentSize
Presentation slides (PDF)561.5 KB
Presentation video (1/3)76.57 MB
Presentation video (2/3)55.26 MB
Presentation video (3/3)137.46 MB

Gunnar Wolf: Ten theses in favor of free download of cultural goods on the Internet (by Enrique G. Gallegos)

This is one of the days where reading my everyday newspaper was worth more than just getting bitter at the news. I found this text in La Jornada, my usual newspaper. I liked it very much, and decided to translate it for a wider audience. Of course, if you can read Spanish, do yourself a favor and go to the original. It is not that the text is so easy to translate. And, after all, I'm not a native English writer. I'm trying to do a literal translation, even when disagreeing with the author. Ten theses in favor of free download of cultural goods on the Internet Enrique G. Gallegos Poet and philosopher. Currently a researcher in Universidad Aut noma Metropolitana-C
  1. Historical legacy. Criticists who promote the persecution of piracy and free downloads of cultural works from the Internet argue that the patrimonial rights have been wronged; they start off suposing that a cultural work is formed from a historical void, as if there was a "nothing" to begin with, and then a "something" appeared. Nothing more fallacious: All cultural products has its precedents, and thanks to these it generates part of its best forces.
  2. Opening towards the future. Human beings are projected into the future. As the main philosophies of the 20th century have explored, one of the singular characteristics of mankind is the ability to think and imagine the future. Products of culture are the best ways to think and project society, politics, love, hope, needs, failures A song, a poem, an essay, can trigger imaginary worlds with a transformative potential. To deny this to humanity with "patrimonial damage" as an argument is to mutilate man's temporal nature.
  3. Recognition of the present. Cultural works generate moments of reflection, criticism and pleasure; they can trigger actions demanding commitment, solidarity and strong indignation against injustice. If every cultural work is adscribed in some way to a historic tradition, and if cultural products anre necessary to imagine other possible worlds and open our future, it's not less true that they also allow us to recognize our present by making us more sensitive to others' ideas, sensations and emotions. Without culture, there is no present nor others' presence.
  4. Divulgation of the cultural heritage. If culture is "heritage of mankind", it should be also spread by any possible way. But not just spread, but actively sought for the biggest number of people to be able to effectively have access to it. In a potentially interconnected world, Internet is the most adequate world for it (despite its limitations). Therefore, penalizing free downloads means avoiding spreading it and restricting access to those groups who don't have enough economic resources.
  5. Preserving cultural heritage. If we agree that cultural works are heritage of mankind, we need to take every action needed to preserve them. But preserving culture does not only mean keeping the products in museums, galleries or never-polluted drawers; it rather means to keep them in the collective memory and in the flow of constant interpretations and appropiations. Said in other words, the genuine way to preserve culture is to allow universal access to cultural goods. That's why, holding that free copies and downloads of books, music, videos, etc. over the Internet are harmful, is an incompatible argument with the obligation to preserve cultural heritage.
  6. They are not goods. Cultural works are material and spiritual manifestations of mankind, concretions of its historicity; they are, also, expressions of emotions, ideas and projections of other lives and other worlds. That's why they cannot be equated to goods or inserted in patrimonialist logic. The market might want to cheat by giving a certain price to a painting by Orozco or auctioning a Baudelaire manuscript, but it will never be able to aprehend their true meaning as cultural works. And it's not that culture is not faluable, but taht its estimation criteria do not follow the rules of market, but those of the imponderable and unlimited.
  7. Price disproportion. Assuming we accept the possibility that intermediaries charge for the services they perform, the value of a book, record or movie should never exceed the daily wage of a worker or employee. But this ellection would only be one more option within the effective possibility that people opt to download or freely copy the cultural work. The final decision as to which media to go to should be a sovereign resolution of the culture-interested person.
  8. The principle of the most benefit. Even when copies and free downloads over Internet could generate a patrimonial "wrong" to third parties, the cultural benefit obtained by it will always be greater in as much that it carries out intensely the principle to foster, spread and access the cultural heritage of mankind. To think otherwise is to privilege the few over the many.
  9. The real evil is elsewhere. Murder, women- and children-trade, poverty and misery are the real evils that ache mankind. According to the United Nations, in 2010 there were 468 thousand murders in the world; the estimation is that 3500 million people live in poverty; in their 2009 inform, the UN found over 2400 victims of "people trade", kidnapped as sex slaves; in some regions in Africa, close to 30% of children suffer acute malnutrition and six people (between children and adults) die every day from hunger. That's why pretending that free download of cultural works is an evil is clearly a tricky and deceptive speech
  10. Against the intermediary-salesman. Culture does not need intermedieries that reduce cultural works to goods. Culture is too important to leavie it in the hands of salespeople that simplistly equate cultural goods with cakes. An intermediary of this kind will never understand the difference between a work of art and a disposable razor blade. What the world needs is more support from the government from every country to artists, creators and poets, as well as ensuring the conditions for the absolute mobility freedom for cultural works.

Dirk Eddelbuettel: RcppGSL 0.2.0

Earlier today, a minor update / maintenance release of RcppGSL---our interface package between R and the GNU GSL using our Rcpp package for seamless R and C++ integration---arrived on on CRAN. It contains a number of minor changes to accomodate changes in the CRAN Policies, as well as a few extension to the main example fastLm, a faster replacement for the standard lm function. The summary methods now provide more information, and we added a number of new regression tests. The NEWS file entry follows below:
Changes in version 0.2.0 (2012-07-22)
  • summary() for fastLm() now displays more information
  • fastLmPure() now uses same argument order as R's lm.fit()
  • Added more unit tests for fastLm() and related functions
  • Export and document S3 methods in NAMESPACE and manual page as such
  • Vignettes have been moved to the vignettes/ directory
  • Main vignette renamed to RcppGSL-intro.pdf to use a filename different from the package reference manual
  • NEWS file converted to .Rd format
  • inline support function no longer uses assignInNamespace
And courtesy of CRANberries, a summary of the changes to the previous release 0.1.1 is available too. More information is on the RcppGSL page. Questions, comments etc should go to the rcpp-devel mailing list off the R-Forge page.

23 July 2012

Michal &#268;iha&#345;: Weblate hacking #1

The first day of Hackweek VIII is about to end for me and it's time to share some of the results. As planned, I've started hacking on Weblate. The most prominent feature from today are email notifications. You can now monitor the translation in various ways - be informed about new strings to translate, new contributor, added suggestion or simply watch all translations. Another bigger change is rearranging of main page, which now provides instant access to per language stats, which were quite hidden before. Rest of time was spent on adding some sort of spam protection (need to deploy this to demo to see how successful it is) and one more promoting widget (88x31 pixels). There are 6 open issues targeted for 1.2 release, so there is still something to do in next days :-).

Filed under: English Suse Weblate 0 comments Flattr this!

22 July 2012

Evgeni Golov: RC bugs 2012/29

RCBW report for 2012/29 (16.7.-22.7.) The motto for this week was:
shut up and take my patches!
(Don t take it personally, it s just a meme :P)

Vasudev Kamath: Compiling Harfbuzz on Debian

Harfbuzz (more correctly harfbuzz-ng) is a Text Layout/shaping engine. Mostly supporting rendering of Text including complex scripts. A quote taken from Wikipedia which describes harfbuzz
HarfBuzz (in Persian: ) is a layout/shaping engine for OpenType fonts. Its purpose is to standardize text layout in FOSS; its code originally started as part of the FreeType project, was then developed separately in Qt and Pango, and finally merged back into a common repository. Both Qt and Pango currently use HarfBuzz; other standalone users include Firefox and Chromium, the open source project behind Google Chrome.
Coming directly to the point. You can get Harfbuzz from its Git repository hosted on Freedesktop. It requires following library and binary compilation
    1. ragel: Finite state machine code compiler
    2. libglib2.0-dev: Glib Development files
    3. libcairo2-dev : Cairo 2D graphics library development files
    4. libicu-dev: Development components for International components for Unicode
    5. libgraphite2-dev: Development files for libgraphite2
    6. libfreetype6-dev: Freetype 2 library development files
Once you install all the above package. Follow following commands to build the harfbuzz.
./autogen.sh
./configure --prefix=/usr
make
sudo make install
You can skip make install if you don't like it to be installed on system.I actually wanted to work on the Debian package of Harfbuzz but since there is some one already working on it. Probably I will wait till the guy completes package. I will write on testing the text rendering of your language using harfbuzz in my next post. Till then Cya.

21 July 2012

Siegfried Gevatter: A gentle introduction to Zeitgeist s Python API

In this post I ll make a quick introduction by example on how to use Zeitgeist s Python API for good and profit. If you re interested in using Zeitgeist from C instead, see the libzeitgeist examples; to use it with C++/Qt, Trever s a web browser in 4 steps may be of interest. First things first In case you re not familiar with Zeitgeist, it may prove helpful to first read Mikkel s introduction to Zeitgeist post. If that s too much to read, just should know that Zeitgeist is an event log. Like the history in your browser, it keeps track of what websites you open at which point in time. It also keeps track of when you close them, and of what browser you used, since it s a system-wide service. Furthermore, it does the same for files, conversations, e-mails, and anything else you want to insert into it. So Zeitgeist is a database of events, and an event can be pretty much anything. But what does it look like? It s main attributes are the following: Additionally, each event has one or more subjects, which have the following attributes: Retrieving recent data Okay, so let s say you want to know the last song you ve listened to (if you have a Zeitgeist-enabled music player). It s a simple as:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    if events:
        song = events[0]
        print "Last song: %s" % song.subjects[0].uri
    else:
        print "You haven't listened to any songs."
 
template = Event.new_for_values(subject_interpretation=Interpretation.AUDIO)
zeitgeist.find_events_for_template(template, on_events_received, num_events=1)
 
# Start a mainloop - note: the Qt mainloop also works
from gi.repository import GLib
GLib.MainLoop().run()
This may need some explaining. We start by importing the Zeitgeist client and some associated data structures (such as Event and Interpretation), and create an instance of the client. The ZeitgeistClient class is a wrapper around Zeitgeist s D-Bus API which not only makes it much nicer to use, but also makes it easy to install monitors (as we will see later) and provides convenient functionality such as automatic reconnection if the connection to the engine is lost. To query for the most recent song, we just need to create a template with the restrictions we want to impose and submit it to Zeitgeist using the find_events_for_template call. If you haven t read Mikkel s post yet, please do so, as it introduces the structure of events and subjects (in short: an event has a timestamp, some other properties, and one or more subjects representing the resources -files, websites, people - involved in the event). The Python API is inherently asynchronous (if for some reason you need a synchronous API, you may still use the lower level ZeitgeistDBusInterface class), so we need to define a callback function to handle the results we receive from the Zeitgeist engine. Finally, we need to create a main loop so the asynchronous functions can run.
Now this was a pretty simple example. Let s make it more interesting. One song isn t much, so let s get the 5 most recent songs. Also, now we want both songs and videos. The first part is pretty easy, we just need to change the num_events parameter. For the second extension, we have to change the event template. In fact, now we need two different event templates and the find_events_for_templates function, which takes an arbitrary number of event templates and ORs them. The result is as follows:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    for event in events:
        print "- %s" % event.subjects[0].uri
 
tmpl1 = Event.new_for_values(subject_interpretation=Interpretation.AUDIO)
tmpl2 = Event.new_for_values(subject_interpretation=Interpretation.VIDEO)
zeitgeist.find_events_for_templates([tmpl1, tmpl2],
                                    on_events_received, num_events=5)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
This will work, but unless you re lucky you re likely to get some duplicate line. Why is this? Well, other than that you may have used the same file twice, don t forget that what you are requesting are actually events. If you ve started playing a given song, you probably also stopped playing it, so that s actually two of them (an AccessEvent and a LeaveEvent). Since this isn t what we want, we ll change the query a bit:
zeitgeist.find_events_for_templates(
    [tmpl1, tmpl2],
    on_events_received,
    num_events=5,
    result_type=ResultType.MostRecentSubjects,
    storage_state=StorageState.Available)
By requesting the most recent subjects, vs. the most recent events, we can filter out events with duplicate URI. See the ResultType documentation for other modes you can use. Note particularly the MostPopularSubjects result type. I also used the chance to introduce the storage_state parameter. This one will filter out events for files Zeitgeist knows aren t available (this mostly means online resources won t be shown if you don t have a network connnection; there s also support for handling external storage media, but because of problems with GIO this is currently disabled). Last but not least, the find_events_for_* methods also accept a timerange parameter. It defaults to TimeRange.until_now(), but you may change it to TimeRange.always() (if for some reason you re working with events in the future) or to any other time range of your choice. Here it s important to note that Zeitgeist s timestamps use millisecond precision.
For more advanced queries, you can use more complex combinations of events and subject templates. The rule to keep in mind here is that events are OR d and subjects are ANDed. Additionally, some field (actor, origin, mimetype, uri and current_uri) may be prefixed with an exclamation mark ( ! ) for NOT, or you may append an asterisc ( * ) to them for prefix search. You can even combine the two operators together. Here s an example of a template you could build:
subj1 = Subject.new_for_values(interpretation=Interpretation.SOURCE_CODE,
                               uri="file:///home/rainct/Development/*")
subj2 = Subject.new_for_values(uri="!file:///home/rainct/Development/zeitgeist/*")
tmpl1 = Event.new_for_values(interpretation=Interpretation.MODIFY_EVENT,
                             subjects=[subj1, subj2])
templates = [tmpl1]
In my case, this template would fetch a list of the source code files I modified most recently but excluding those related to the Zeitgeist project. Working with big sets of data In case you re trying to do something crazy, you may end up with a Zeitgeist query complaining that it exceeded the memory limit. You re not supposed to do that. Instead, we provide some methods for working with large collections of events.
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    for event in events:
        print '- %s' % event.subjects[0].uri
 
def on_ids_received(event_ids):
    print 'A total of %d source code files were found.' % len(event_ids)
    print 'Fetching the first 100...'
    zeitgeist.get_events(event_ids[:100], on_events_received)
 
tmpl = Event.new_for_values(subject_interpretation=Interpretation.SOURCE_CODE)
zeitgeist.find_event_ids_for_templates(
    [tmpl],
    on_ids_received,
    num_events=10000, # you can use 0 for "all events", but do you really need to?
    timerange=TimeRange.from_seconds_ago(3600*24*30*3),
    result_type=ResultType.MostPopularSubjects)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
And there you have the source code files you worked with during the last 3 months, ordered from most to least popular (popularity is measured counting the number of events; for more precision, maybe you could limit the results to events with interpretation AccessEvent). Why do we provide this mechanism instead of querying with a simple offset? Well, this avoids problems when the log changes (events are inserted or deleted). Have you ever been exploring the latest posts in some website, and as you change to the next page some of the results from the previous page show up again (because new posts have been added in the meantime)? With Zeitgeist this won t happen. Receiving information in real time At this point you re an expert at requesting all sorts of data from Zeitgeist, but now you want to show a list of the last kitten images you ve viewed, updated in real time. Don t worry, Zeitgeist can provide for this:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_insert(time_range, events):
    # do awesome stuff with the events here
    print events
 
def on_delete(time_range, event_ids):
    # a previously inserted event was deleted
    print event_ids
 
templates = [Event.new_for_values(subject_uri='file:///home/user/kittens/*',
                                  subject_interpretation=Interpretation.IMAGE)]
zeitgeist.install_monitor(TimeRange.always(), templates, on_insert, on_delete)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
It s important to note that on_delete won t be called when an image is deleted (that d be a newly inserted event with interpretation=DELETE_EVENT); rather, it s called when a previously inserted event is deleted (for example, using the forget recent history option in Activity Log Manager). In case you re curious: for best performance, this doesn t actually use D-Bus signals. Instead, this little call will setup a D-Bus object behind the scenes and register it with the Zeitgeist engine, so it can notify said object when (and only when) an event of its interest is registered. To stop receiving notifications for a template, you ll need the save the object returned by the install_monitor call:
m = zeitgeist.install_monitor(TimeRange.always(), templates, on_insert, on_delete)
zeitgeist.remove_monitor(m)
Pro Tip: You can use the Zeitgeist Explorer GUI to quickly try out different queries (note: it s still work in progress, so much funcionality is missing, but it does work somewhat). Contextual awesomeness: finding related events By now you re familiar with retrieving events and keeping them up to date. Now it s time for a little secret:
import time
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_related_received(uris):
    print 'Related URIs:'
    for uri in uris:
        print ' - %s' % uri
 
query_templates = [Event.new_for_values(
    subject_interpretation=Interpretation.SOURCE_CODE,
    subject_uri='file:///home/rainct/Development/zeitgeist/*',
    subject_mimetype="text/x-vala")]
 
result_templates = [Event.new_for_values(
    subject_interpretation=Interpretation.WEBSITE,
    subject_manifestation=Manifestation.WEB_DATA_OBJECT)]
 
now = time.time()*1000
zeitgeist.find_related_uris_for_events(
    query_templates,
    on_related_received,
    time_range=TimeRange(now - 1000*3600*24*30*6, now),
    result_event_templates=result_templates,
    num_events=10)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
This little query example will return up to 10 websites I used at the same time as the Vala files inside my Zeitgeist directory, considering only data from the last 6 months. Nice, huh? This is an experimental feature, and it doesn t work well when operating on big inputs, so it s usually better to use the find_related_uris_for_uris variant (which replaces the first query_templates parameter with a list of URIs). Advanced searching: the FTS extension Some people think prefix searches aren t good enough for them, and this is why the Zeitgeist engine ships by default with a FTS (Full Text Search) extension. Using the methods provided by this extension you can perform more advanced queries against subjects current_uri and text properties (unlike the name may suggest, the FTS extension doesn t index the content of the files, but just the information in the event). This is exposed as zeitgeist_index_search in libzeitgeist (the C library), but unfortunately isn t currently available in the Python API. If you still need it, you ll have to fallback to pretty much using the D-Bus interface (you still get reconnection support, though). Here s an example:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
index = zeitgeist._iface.get_extension('Index', 'index/activity')
 
query            = 'hello' # search query
time_range       = TimeRange.always()
event_templates  = []
offset           = 0
num_events       = 10
result_type      = 100 # magic number for "relevancy" (ResultType.* also work)
 
def on_reply(events, num_estimated_matches):
    print 'Got %d out of ~%d results.' % (len(events), num_estimated_matches)
    events = map(Event, events)
    for event in events:
        print ' - %s' % event.subjects[0].uri
 
def on_error(exception):
    print 'Error from FTS:', exception
 
index.Search(query, time_range, event_templates,
             offset, num_events, result_type,
             reply_handler=on_reply, error_handler=on_error)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
The most interesting thing here is the query parameter. Quoting from the C documentation:
The default boolean operator is AND. Thus the query foo bar will
be interpreted as foo AND bar. To exclude a term from the result
set prepend it with a minus sign - eg foo -bar. Phrase queries
can be done by double quoting the string "foo is a bar". You can
truncate terms by appending a *.
There are a few keys you can prefix to a term or phrase to search
within a specific set of metadata. They are used like key:value.
The keys name and title search strictly within the text field of
the event subjects. The key app searches within the application
name or description that is found in the actor attribute of the
events. Lastly you can use the site key to search within the
domain name of the subject URIs.
You can also control the results with the boolean operators AND
and OR and you may use brackets, ( and ), to control the operator
precedence.
Modifying the log So far we ve only queried Zeitgeist for information, let s get a bit more active. You can delete events from Zeitgeist with the following query:
from zeitgeist.client import ZeitgeistClient
 
zeitgeist = ZeitgeistClient()
 
def on_deleted(timerange):
    print 'Deleted events going from %s to %s' % (timerange[0], timerange[1])
 
event_ids = [50] # put the IDs of the events you want to delete here
 
zeitgeist.delete_events(event_ids, on_deleted)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
The confirmation callback will receive a timerange going from the first to the last event. If no events were deleted (because they didn t exist), you ll get (-1, -1).
And now for the interesting part. If your application involves resources (files, websites, contacts, etc.) of any sort, you ll probably want to let Zeitgeist know that you re using them. It s time that you write a data-source! We start by registering the data-source. Here we go:
import time
from gi.repository import GLib
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_status_changed_callback(enabled):
    """ This method will be called whenever someone enables or disables
        the data-source. """
    if enabled:
        print 'Data-source enabled and ready to send events!'
    else:
        print 'Data-source disabled; don\'t send event, they\'ll be ignored.'
 
def register():
    # Always use the same unique_id. Name and description can change
    # freely.
    unique_id = 'com.example.your.data.source'
    name = 'user visible name (may be translated)'
    description = 'user visible description (may be translated)'
 
    # Describe what sort of events will be inserted (optional)
    subject_template = Subject()
    subject_template.interpretation = Interpretation.PLAIN_TEXT_DOCUMENT
    subject_template.manifestation = Manifestation.FILE_DATA_OBJECT
    templates = []
    for interp in (Interpretation.ACCESS_EVENT, Interpretation.LEAVE_EVENT):
        event_template = Event()
        event_template.interpretation = interp
        event_template.manifestation = Manifestation.USER_ACTIVITY
        event_template.append_subject(subject_template)
        templates.append(event_template)
 
    zeitgeist.register_data_source(unique_id, name, description, templates,
                                   on_status_changed_callback)
Once that s done (and if it is enabled), we are free to send our events:
def log(title, uri, opened):
    subject = Subject.new_for_values(
        uri=uri,
        interpretation=Interpretation.PLAIN_TEXT_DOCUMENT,
        manifestation=Manifestation.FILE_DATA_OBJECT,
        origin=GLib.path_get_dirname(uri),
        mimetype='text/plain',
        text=title)
    event = Event.new_for_values(
        timestamp=time.time()*1000,
        manifestation=Manifestation.USER_ACTIVITY,
        actor='application://your_application_name.desktop',
        subjects=[subject])
    if opened:
        event.interpretation = Interpretation.ACCESS_EVENT
    else:
        event.interpretation = Interpretation.LEAVE_EVENT
 
    def on_id_received(event_ids):
        print 'Logged %s (%d) with event id %d.' % (title, opened, event_ids[0])
 
    zeitgeist.insert_events([event], on_id_received)
 
if __name__ == '__main__':
    register()
 
    log('test.txt', 'file:///tmp/test.txt', opened=True)
    log('another_file.txt', 'file:///tmp/another_file.txt', opened=True)
    log('another_file.txt', 'file:///tmp/another_file.txt', opened=False)
    log('test.txt', 'file:///tmp/test.txt', opened=False)
 
    # Start a mainloop
    GLib.MainLoop().run()
If you don t know what interpretation and manifestation your subject should have, you can use the following utility methods:
from zeitgeist.mimetypes import *
 
print get_interpretation_for_mimetype('text/plain')
print get_manifestation_for_uri('file:///tmp/test.txt')
Event better, with Zeitgeist 0.9 you can just leave the subject (but not event!) interpretation and manifestation fields empty, and they ll be guessed the same way as if you used those utility methods. Pro Tip: You can examine all registered data-sources and toggle whether they are enabled or not using the zeitgeist-data-sources-gtk.py tool. Conclusion Wow, I m impressed if you ve got this far. By now you should have quite a good idea on how to use the Zeitgeist API, and I m looking forward to seeing what you do with it in your next awesome project. If you have any problem with Zeitgeist, feel free to visit us on IRC (#zeitgeist on irc.freenode.net), or join our mailing list. We ll also be at GUADEC next week, so if you re there make sure to say hi! In case you missed them, here are some useful links:
No comments
Siegfried-Angel Gevatter Pujals, 2012. Permalink License Post tags: ,
flattr this!

20 July 2012

David Paleino: Editable QComboBox with QAbstractTableModel

Dear Lazyweb, I'm working on a personal PyQt4 project for my parents' office, and I need to autocomplete an editable QComboBox. I can't use a standard Qt model (I need to store python objects in it), so I subclassed QAbstractTableModel. Here it is, it's a fairly generic subclass of QAbstractTableModel, with variable number of columns:
class QGenericTableModel(QAbstractTableModel):
    def __init__(self, columns, parent=None, *args):
        super(QGenericTableModel, self).__init__(parent, *args)
        self.columns = columns
        self.headers =  
        self.table = []
    def rowCount(self, parent=QModelIndex()):
        return len(self.table)
    def columnCount(self, parent):
        return self.columns
    def row(self, row):
        return self.table[row]
    def setData(self, index, value, role):
        if index.isValid() and role == Qt.EditRole:
            row = index.row()
            t = self.table[row]
            if index.column() >= self.columns:
                return False
            if isinstance(value, QVariant):
                t[index.column()] = value.toString().simplified()
            else:
                t[index.column()] = value
            self.emit(SIGNAL('dataChanged'), index, index)
            return True
        return False
    def data(self, index, role = Qt.DisplayRole):
        if not index.isValid():
            return QVariant()
        if (index.row() >= len(self.table)) or (index.row() < 0):
            return QVariant()
        if role == Qt.DisplayRole:
            return QVariant(self.table[index.row()][index.column()])
        return QVariant()
    def insertRow(self, row, parent=QModelIndex()):
        self.insertRows(row, 1, parent)
    def insertRows(self, row, count, parent=QModelIndex()):
        self.beginInsertRows(parent, row, row+count-1)
        for i in xrange(count):
            self.table.insert(row, ['',]*self.columns)
        self.endInsertRows()
        return True
    def removeRow(self, row, parent=QModelIndex()):
        self.removeRows(row, 1, parent)
    def removeRows(self, row, count, parent=QModelIndex()):
        self.beginRemoveRows(parent, row, row+count-1)
        for i in reversed(xrange(count)):
            self.table.pop(row+i)
        self.endRemoveRows()
        return True
    def flags(self, index):
        if not index.isValid():
            return Qt.ItemIsEnabled
        return super(QGenericTableModel, self).flags(index)   Qt.ItemIsEditable
    def headerData(self, column, orientation, role = Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            if column >= self.columns:
                return QVariant()
            return self.headers[column]
        return QVariant()
    def setHeaderData(self, column, orientation, value, role = Qt.EditRole):
        self.headers[column] = value
It might not be perfect, but it works, and it's all that matters at the moment (since it's my first serious PyQt4 project). Oh, well, it worked until I tried to use it with an editable QComboBox. And here's the app code (for the full working code, insert the above class right after the imports):
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
app = QApplication(sys.argv)
model = QStandardItemModel()
for i, word in enumerate(['saluton', 'gxis la revido', 'hello', 'goodbye']):
    item = QStandardItem(word)
    model.setItem(i, 0, item)
#model = QGenericTableModel(1)
#for i, word in enumerate(['saluton', 'gxis la revido', 'hello', 'goodbye']):
#    model.insertRow(i)
#    index = model.index(i, 0)
#    model.setData(index, word, Qt.EditRole)
combo = QComboBox()
filterModel = QSortFilterProxyModel(combo)
completer = QCompleter(combo)
filterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
filterModel.setSourceModel(model)
filterModel.setFilterKeyColumn(0)
completer.setModel(filterModel)
completer.setCompletionColumn(0)
completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
combo.setEditable(True)
combo.setCompleter(completer)
combo.setModel(model)
combo.setModelColumn(0)
if combo.isEditable():
    app.connect(combo.lineEdit(), SIGNAL('textEdited(QString)'), filterModel.setFilterFixedString)
combo.setModel(model)
combo.setModelColumn(0)
combo.show()
sys.exit(app.exec_())
Now, try running it. It works well when I use a QStandardItemModel. Then, try decommenting the part where I use my subclassed model: it just doesn't work: clicking on any item makes the QComboBox not change its currentIndex, and this only happens if the combobox is editable. I suspect I'm forgetting to override some function in my model, but I don't know what exactly to override, and Google didn't help me. This is also backed up by the fact that the exact same behaviour shows up when, instead of a QComboBox, I try to autocomplete on a QLineEdit. So, dear readers: can anyone explain what is happening? Thanks in advance! UPDATE: it turned out that the culprit was the following bit inside data():
        if role == Qt.DisplayRole:
            return QVariant(self.table[index.row()][index.column()])
Adding also Qt.EditRole to the list of possible choices fixed the bug. YAY!

Neil McGovern: DebConf 2012 Nicaragua

After 4 flights, about 15,000 miles, a beach, some To a and cheese and lots of geeks, I'm able to update my Places I've Been map by adding Nicaragua to it. I was speaking at DebConf12, entitled Bits from the Release Team. In case you missed it, it's been recorded by the wonderful DebConf video team and is available in high and low quality. It was great to catch up with people again, and do quite a bit of work on Debian itself, mostly on the Wheezy release. I even found an hour to take a basic Spanish class, although I'm fairly sure I've forgotten most of it by now. As usual, there were a number of Collaborans present, and it was good to meet them. I suspect I'll be seeing a few more at GUADEC in a weeks time. My photos are available, should anyone be interested.

18 July 2012

Jon Dowland: Debian Day #7

Very little done last night. Advocated a maintainer. My desktop computer is completely hosed as part of a wheezy update: many issues at once but one is GDM going into an infinite loop, spawning millions of X servers; another is something in the boot processes seemingly prodding /dev/sdc and failing. I'm not sure if I have time to get to the bottom of it, I might just reinstall from a d-i daily. Priority going forward should be to finish off the musicbrainz stuff. Pleased to see my gnome sushi patch merged upstream.

17 July 2012

Luciano Bello: there is no cabal.. but, what s a cabal?

In my long trip to Nicaragua I made progress in my reading: Quicksilver, by Neal Stephenson. In the Spanish edition the title is Azogue. But I m assuming that you are not a Spanish speaker. Here is a small fragment (in English) I found there:
You must remember that the planters are short-sighted. They re all desperate to get out of Jamaica they wake up every day expecting to find themselves, or their children, in the grip of some tropical fever. To import female Neegers would cost nearly as much as to import males, but the females cannot produce as much sugar particularly when they are breeding. Daniel had finally recognized this voice as belonging to Sir Richard Apthorp the second A in the CABAL.
It s a bit embarrassing when I discovered myself realizing where the word cabal comes from. And I m posting this as a head-up for everyone who know there is no cabal in Debian; but they don t know which is the origin of the word cabal. Stephenson changed the name of the historic cabal, a group of high councillers of King Charles II of England, Scotland and Ireland, in 1668. In the novel, they are: John Comstock (Earl of Epsom), Louis Anglesey (Duke of Gunfleet), Knott Bolstrood (Count Penistone), Sir Richard Apthorp and Hugh Lewis (Duke of Tweed). In the real world they had been:
Thomas Clifford, 1st Baron Clifford of Chudleigh (1630-1673). Henry Bennet, 1st Earl of Arlington (1618-1685). George Villiers, 2nd Duke of Buckingham (1628-1687). Anthony Ashley Cooper, 1st Baron Ashley of Wimborne St Giles (1621-1683). John Maitland, 1st Duke of Lauderdale (1616-1682).
This group shared the effective power in a royal council rather than the King.

Next.

Previous.