<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0"><channel><title>Hardcoded Software articles (python)</title><link>http://www.hardcoded.net/articles/</link><description>Pointless babbling of a Python developer</description><lastBuildDate>Fri, 20 Jan 2012 00:00:00 GMT</lastBuildDate><item><title>Using QTreeView with QAbstractItemModel</title><link>http://www.hardcoded.net/articles/using_qtreeview_with_qabstractitemmodel.htm</link><description>&lt;p&gt;For someone coming from the Cocoa world, understanding how &lt;code&gt;QTreeView&lt;/code&gt; and &lt;code&gt;QAbstractItemModel&lt;/code&gt; work can be quite hard. While the concept of an item model for a tree view also exists in Cocoa, the way &lt;code&gt;QAbstractItemModel&lt;/code&gt; works is quite different from &lt;code&gt;NSOutlineDatasource&lt;/code&gt;'s.&lt;/p&gt;
&lt;p&gt;The biggest difference between the two models is in the way they refer to cells. In Cocoa, we use an arbitrary identifier supplied by the model through &lt;code&gt;outlineView:child:ofItem:&lt;/code&gt;. Then, this identifier is used in combination with a &lt;code&gt;NSTableColumn&lt;/code&gt; instance for calls like &lt;code&gt;outlineView:objectValueForTableColumn:byItem:&lt;/code&gt; (which is supposed to return what must be displayed for a particular cell). On the Qt side, we use a &lt;code&gt;QModelIndex&lt;/code&gt; instance that is supplied by the &lt;code&gt;index(row, column, parent)&lt;/code&gt; method. The strange thing with &lt;code&gt;QModelIndex&lt;/code&gt; is that it not only holds an identifier, but it also holds a row and a column. Therefore, if &lt;code&gt;index(1, 2, parentId)&lt;/code&gt; is called on the model, what must be returned is a &lt;code&gt;QModelIndex(1, 2, childId)&lt;/code&gt; instance.&lt;/p&gt;
&lt;p&gt;To a Qt newbie, this requirement for the model to return redundant data (row and column) might seem stupid. They might even think that it's downright insane when they discover that subclassing &lt;code&gt;QAbstractItemModel&lt;/code&gt; also requires you to implement a &lt;code&gt;parent(index)&lt;/code&gt; method. After all, the view &lt;em&gt;knew&lt;/em&gt; what was the parent of that index when it asked for it in &lt;code&gt;index(row, column, parent)&lt;/code&gt;! The poor Qt newbie might spend quite some time wondering what the heck was TrollTech thinking when they designed this API.&lt;/p&gt;
&lt;p&gt;It turns out that there's a reason for this strange and complex API: &lt;a href="http://labs.trolltech.com/blogs/2008/10/24/itemviews-the-next-generation/"&gt;TrollTech over-engineered this part of the toolkit&lt;/a&gt;. They wanted to design their item model so that it would be possible for a single model instance to have table views and tree views connected to it &lt;em&gt;at the same time&lt;/em&gt;. While I'm sure that there are cases where this feature is very useful, there's a lot of &lt;code&gt;QTreeView&lt;/code&gt; users out there who have no need for it and are suffering because of this over-engineering.
&lt;a href="http://www.hardcoded.net/articles/using_qtreeview_with_qabstractitemmodel.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/using_qtreeview_with_qabstractitemmodel.htm</guid><pubDate>Sat, 26 Sep 2009 18:00:00 GMT</pubDate></item><item><title>Cross-Toolkit Software</title><link>http://www.hardcoded.net/articles/cross-toolkit-software.htm</link><description>&lt;p&gt;Developing cross-platform software is easy: use cross-platform libraries, and you're set! When GUIs are involved, however, things get a little trickier. Different platforms tend to have different ways of doing things, GUI-wise. There are libraries that attempt to abstract away these differences to allow developers to build "write once, deploy everywhere" GUI-enabled applications (&lt;a href="http://qt.nokia.com"&gt;Qt&lt;/a&gt;, &lt;a href="http://www.wxwidgets.org"&gt;wxWidgets&lt;/a&gt;, &lt;a href="http://www.gtk.org"&gt;GTK+&lt;/a&gt;, etc.), but they always seem to fall short when it comes to the "nativeness" of the look and feel, especially for Mac OS X. To have a cross-platform GUI-enabled application that looks and feels native on all platforms, one obvious solution is to have a cross-&lt;strong&gt;toolkit&lt;/strong&gt; design.&lt;/p&gt;
&lt;p&gt;By "cross-toolkit", I mean an application that uses more than one toolkit for the different platforms it supports. For example, my own applications use two toolkits: Cocoa (through &lt;a href="http://pyobjc.sourceforge.net/"&gt;PyObjC&lt;/a&gt;) under Mac OS X, and Qt (through &lt;a href="http://www.riverbankcomputing.com/"&gt;PyQt&lt;/a&gt;) under Windows.&lt;/p&gt;
&lt;p&gt;But going cross-toolkit, although it gives your software nativeness, brings its own share of problems. When you create a cross-toolkit software, you have to decide what code belongs to the core, and what code belongs to the toolkit-specific code. If you put too much code in the core, you end up re-writing your own little toolkit wrapper. Then, you realize you abstracted away too much when a platform's specificity forces you to either hack around your core design or rethink that design. If you don't give your core enough responsibilities, you end up with logic duplication among your different toolkit-specific codebases.&lt;/p&gt;
&lt;p&gt;In this article, I'm going to take a look at three softwares: A single-toolkit-cross-platform software (OpenOffice), a cross-toolkit software with logic duplication in it (Transmission), and then my own attempt a creating a great cross-toolkit software (moneyGuru).
&lt;a href="http://www.hardcoded.net/articles/cross-toolkit-software.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/cross-toolkit-software.htm</guid><pubDate>Sun, 20 Dec 2009 18:00:00 GMT</pubDate></item><item><title>How To Customize QTableView's Editing Behavior</title><link>http://www.hardcoded.net/articles/how-to-customize-qtableview-editing-behavior.htm</link><description>&lt;p&gt;&lt;code&gt;QTableView&lt;/code&gt;'s default editing behavior seems to have been designed with spreadsheet-like usage in mind. When your table needs a more "row-based" editing with some columns being read-only, it becomes rather difficult to customize &lt;code&gt;QTableView&lt;/code&gt; to support that. I recently needed to do it for &lt;a href="/moneyguru/"&gt;moneyGuru&lt;/a&gt; and this article explains how I did it.
&lt;a href="http://www.hardcoded.net/articles/how-to-customize-qtableview-editing-behavior.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/how-to-customize-qtableview-editing-behavior.htm</guid><pubDate>Mon, 28 Dec 2009 18:00:00 GMT</pubDate></item><item><title>Building 64-bit PyObjC Applications With Py2app</title><link>http://www.hardcoded.net/articles/building-64-bit-pyobjc-applications-with-py2app.htm</link><description>&lt;p&gt;64-bit is upon us and has been for a while now. With Mac OS X Snow Leopard putting so much emphasis on 64-bit applications, you don't want to be left behind with your py2app built applications, don't you? Well, it turns out you're not entirely out of luck! It requires a bit of tweaking, but building 64-bit Python based applications with py2app is possible.
&lt;a href="http://www.hardcoded.net/articles/building-64-bit-pyobjc-applications-with-py2app.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/building-64-bit-pyobjc-applications-with-py2app.htm</guid><pubDate>Tue, 19 Jan 2010 18:00:00 GMT</pubDate></item><item><title>Embedded PyObjC</title><link>http://www.hardcoded.net/articles/embedded-pyobjc.htm</link><description>&lt;p&gt;When people think of a &lt;a href="http://pyobjc.sourceforge.net/"&gt;PyObjC&lt;/a&gt; application, they usually think of a Python application that uses Objective-C libraries. However, it's also possible to do the opposite: An Objective-C application that embeds Python code through a plugin. Building an application this way has advantages (speed, integration and memory usage) and should be used more often. This article explains why and how to achieve this.
&lt;a href="http://www.hardcoded.net/articles/embedded-pyobjc.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/embedded-pyobjc.htm</guid><pubDate>Mon, 08 Feb 2010 18:00:00 GMT</pubDate></item><item><title>High Level Testing</title><link>http://www.hardcoded.net/articles/high-level-testing.htm</link><description>&lt;p&gt;Too often, developers new to unit testing see them as a liability. They're hard to write, and when you want to deeply refactor your code (for example, when you want to re-organize your classes' respective responsibilities), you have to change your unit tests. This then discourages you to refactor your code, making you &lt;em&gt;less agile&lt;/em&gt;. These developers will probably abandon unit testing and write on their blog that TDD sucks (because it's common knowledge that unit testing is &lt;em&gt;good&lt;/em&gt;, so you can't say that it sucks. It's easier to attack TDD, aka. too many unit tests).&lt;/p&gt;
&lt;p&gt;You know what? They're right. I think we do way too much &lt;a href="http://en.wikipedia.org/wiki/Unit_testing"&gt;unit testing&lt;/a&gt; when we should be doing &lt;a href="http://en.wikipedia.org/wiki/Integration_testing"&gt;integration testing&lt;/a&gt; instead. If you have a class that is all neat and cute and unit tested and that a new requirement in your application requires you to split that class in two (to do it correctly), you either have to change all your tests, or you implement a kludge that allows you to keep your former architecture (don't do that).&lt;/p&gt;
&lt;p&gt;What I've been doing for about 2 years (for &lt;a href="http://hg.hardcoded.net/moneyguru"&gt;moneyGuru's development&lt;/a&gt;, to be precise) is what I call &lt;em&gt;high level testing&lt;/em&gt;, which is like integration testing, but without (or very little) unit testing. It has some downsides, but it's been working great so far and has empowered me with nearly unlimited refactoring potential on the whole project. I'm under the impression that a lot of developers have a narrow view of unit testing, which prevents them from even considering this possibility. I hope, with this article, to broaden their horizon a little bit.
&lt;a href="http://www.hardcoded.net/articles/high-level-testing.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/high-level-testing.htm</guid><pubDate>Wed, 03 Mar 2010 18:00:00 GMT</pubDate></item><item><title>Send Files To Trash On All Platforms</title><link>http://www.hardcoded.net/articles/send-files-to-trash-on-all-platforms.htm</link><description>&lt;p&gt;If you've ever needed to send files to trash in your cross-platform application, you've probably noticed the painful void in your toolkit. It's just not there. You can copy, move, delete files, but you can't send them to the trash. There's no easy solution (until now) and you need to implement platform-specific code for Mac OS X, Windows and Linux.&lt;/p&gt;
&lt;p&gt;On Mac OS X, you have to call &lt;code&gt;FSMoveObjectToTrashSync&lt;/code&gt; (or its async friend) from &lt;code&gt;CoreServices&lt;/code&gt;. But then, either you have to make a C extension for it or you have to call it through &lt;a href="http://pyobjc.sourceforge.net"&gt;PyObjC&lt;/a&gt;. If your app is a Qt based app, you might dislike having to add such a big dependency just for a little &lt;code&gt;FSMoveObjectToTrashSync&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;On Windows, a &lt;code&gt;SHFileOperation&lt;/code&gt; (in fact, &lt;code&gt;SHFileOperationW&lt;/code&gt; if you're not stuck in the last unicode-less decade) is needed. Again, if you're not comfortable with C (or you don't want to touch the win32 API with a ten foot pole), you need a dependency on &lt;a href="http://sourceforge.net/projects/pywin32/"&gt;pywin32&lt;/a&gt; (and Tim Golden's &lt;a href="http://timgolden.me.uk/python/winshell.html"&gt;winshell&lt;/a&gt; if you want to make your life even easier).&lt;/p&gt;
&lt;p&gt;On Linux, it's free-for-all (pun intended... in hindsight). There's no unified API to send files to the trash. The convention seems to be that sending stuff in &lt;code&gt;~/.Trash&lt;/code&gt; is good enough, but then there's always the problem of external volumes (you don't want to copy files from external volumes on your main hard disk when you send them to the trash!) and systems with alternate trash conventions (Ubuntu makes further organization of the files inside the &lt;code&gt;.Trash&lt;/code&gt; folder).&lt;/p&gt;
&lt;p&gt;In other words, it's a mess. You thought you could code your cute Qt app once and run it everywhere, but that damn trash thing gets in your way. Well, if you use Python, you're in luck because there's a library for that now! Say hello to &lt;a href="http://hg.hardcoded.net/send2trash"&gt;send2trash&lt;/a&gt;. It's a cross-platform library that sends files to trash using native API calls (without external dependencies).&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;send2trash&lt;/span&gt; &lt;span class="nb"&gt;import&lt;/span&gt; &lt;span class="n"&gt;send2trash&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;send2trash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;some_file&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href="http://www.hardcoded.net/articles/send-files-to-trash-on-all-platforms.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/send-files-to-trash-on-all-platforms.htm</guid><pubDate>Mon, 03 May 2010 18:00:00 GMT</pubDate></item><item><title>Getting Started with Python GUI Applications</title><link>http://www.hardcoded.net/articles/getting-started-with-python-gui-applications.htm</link><description>&lt;p&gt;A recurrent question to Python developers is "Which GUI toolkit is the best? How do I get started?". The answer to this question is subjective, so we end up with a pretty long list of toolkits to try. But then, it's only a matter of playing with demos, picking the best toolkit and then creating our application by basing ourselves on demo code, right?&lt;/p&gt;
&lt;p&gt;There are several problems with this approach. First, demo code is usually contained within a demo showcase framework and is hardly an application by itself. The poor newbie often has no idea how to properly structure his application from scratch. Second, comparing toolkits side by side is not so easy to do when demos differ from one toolkit to another.&lt;/p&gt;
&lt;p&gt;Moreover, some GUI application designs are no so easy to start from scratch. I've been talking about &lt;a href="http://www.hardcoded.net/articles/cross-toolkit-software.htm"&gt;cross-toolkit design&lt;/a&gt; as well as &lt;a href="http://www.hardcoded.net/articles/embedded-pyobjc.htm"&gt;embedded PyObjC&lt;/a&gt; lately and these methods are hard to adopt unless you have a simple example in front of you.&lt;/p&gt;
&lt;p&gt;This is why I'm publishing &lt;a href="http://hg.hardcoded.net/guiskel"&gt;guiskel&lt;/a&gt;, a collection of GUI layer skeletons. It's a simple cross-toolkit application that does "Hello [name]!". To create a new application, all you have to do is to copy the project and remove toolkit layers you don't want.&lt;/p&gt;
&lt;p&gt;For now, it supports only two GUI layers (those I use myself), namely PyQt and embedded PyObjC, but I hope others will participate and add additional toolkits.
&lt;a href="http://www.hardcoded.net/articles/getting-started-with-python-gui-applications.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/getting-started-with-python-gui-applications.htm</guid><pubDate>Tue, 23 Nov 2010 18:00:00 GMT</pubDate></item><item><title>New py2app fork: pluginbuilder</title><link>http://www.hardcoded.net/articles/new-py2app-fork-pluginbuilder.htm</link><description>&lt;p&gt;Python 3.2 brought with it a couple of changes that broke &lt;a href="https://bitbucket.org/ronaldoussoren/py2app"&gt;py2app&lt;/a&gt;. It had been a while since I wanted to work on that project, but because the main command is distutils-based, I lacked the motivation to properly learn how its code works. I saw Python 3.2's breakage as a good opportunity to get my feet wet, since as far as I can tell, there's very few of us using the "plugin" feature of py2app, and I'm pretty sure to be alone to, additionally, use Python 3. Nobody was going to fix it except me.&lt;/p&gt;
&lt;p&gt;py2app being a distutils-based command brings needless complexity to the code. Unless you know how distutils commands work, you don't really know what's the main entry point or where options are stored. Because (1) fixing py2app involved code changes that I wasn't sure were backward compatible, (2) I'm one of a very few users of the "plugin" feature, and (3) distutils was increasingly getting on my nerves, I said "screw that, I'm tearing that package apart", and that's what I did. It felt rather good :)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What's different?&lt;/strong&gt; Apart from not supporting application building like py2app does and not being based on distutils' command, there's a few things that are different in pluginbuilder.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Invocation is simpler. Instead of having to go through distutils' &lt;code&gt;setup()&lt;/code&gt; to build your plugin, you can call &lt;code&gt;build_plugin()&lt;/code&gt; directly or use the &lt;code&gt;pluginbuilder&lt;/code&gt; command line script.&lt;/li&gt;
&lt;li&gt;The "main" binary file is compiled on your machine rather than being prebuilt. py2app ships with prebuilt binaries for all possible architectures combinations, but it never worked on my machine so I had to rebuild them anyway. A benefit from this is that it simplifies the code in "main.m" because dynamic symbol bindings aren't necessary anymore and &lt;code&gt;Python.h&lt;/code&gt; can be included directly.&lt;/li&gt;
&lt;li&gt;Collected source files aren't zipped. That's actually a drawback, but it was part of the fix for Python 3.2's breakage, which didn't like encodings-related modules to be in a zip file. I'm not sure yet, but I think that feature could come back if I use the newly introduced &lt;code&gt;Py_SetPath&lt;/code&gt; function.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Roadmap:&lt;/strong&gt; For the first release of pluginbuilder, I didn't modify a lot of code. I merely, step by step, refactored the thing until I could get rid of distutils' command. The code is not as clean as it should be and I'll probably slowly start to actually change the code. I'm also contemplating the removal of modulegraph's dependency (I think the additional complexity brought by this mechanism is not worth the convenience of not having to manually specify dependencies), but that's something I haven't thought through yet.&lt;/p&gt;
&lt;p&gt;That's all I have to say about this. Here's some links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://bitbucket.org/hsoft/pluginbuilder"&gt;Source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hardcoded.net/docs/pluginbuilder"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pypi.python.org/pypi/pluginbuilder/"&gt;PyPI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/new-py2app-fork-pluginbuilder.htm</guid><pubDate>Mon, 21 Feb 2011 18:00:00 GMT</pubDate></item><item><title>Embedding Python in Objective-C: Part 2</title><link>http://www.hardcoded.net/articles/embedding-python-in-objc.htm</link><description>&lt;p&gt;Two years ago, I wrote about how I &lt;a href="http://www.hardcoded.net/articles/embedded-pyobjc.htm"&gt;embedded Python in Objective-C through PyObjC&lt;/a&gt;.
It worked well and everything was fine. The only problem I had with PyObjC was that I felt that
such a massive library (&lt;code&gt;pyobjc-core&lt;/code&gt; has over 5,000 Python SLOC and over 55,000 Objective-C SLOC,
not counting tests) was overkill for what I used of it. The whole library was a black box to me and
that made me a bit uneasy.&lt;/p&gt;
&lt;p&gt;Then, a few weeks ago, I started getting report of weird crashes which seemed related to 64-bit and
the presence on the system of some 3rd party app with specific settings. I could never reproduce the
damn crashes on my computer, but they came around exactly at the same moment as
&lt;a href="http://www.hardcoded.net/dupeguru"&gt;dupeGuru&lt;/a&gt; 3.3.0 which updated PyObjC to fix another 64-bit
related crash, so I could only assume that PyObjC (and/or libffi, which is used by PyObjC) was the
cause. The problem was that I didn't know where to start the bug hunt because of my inability to
work within PyObjC's codebase.&lt;/p&gt;
&lt;p&gt;So, out of curiosity for its feasability and to know if it was going to fix my crashes, I started
working on &lt;a href="http://bitbucket.org/hsoft/objp"&gt;ObjP&lt;/a&gt;. Instead of dynamically dispatching function
call between Python and Objective-C, I would generate source code for static wrappers which would
simply use Python's C API. Early tests were encouraging because it fixed the crashes on my users'
machines, so I continued working on it and a few days ago I completed dupeGuru's conversion from
PyObjC to ObjP and published dupeGuru 3.3.2. So far I haven't heard from crashes, so I guess it
works well.
&lt;a href="http://www.hardcoded.net/articles/embedding-python-in-objc.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/embedding-python-in-objc.htm</guid><pubDate>Fri, 20 Jan 2012 09:57:28 GMT</pubDate></item></channel></rss>
