<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-7028181408582795486</id><updated>2009-11-10T22:34:03.853+13:00</updated><title type='text'>Coding with the enemy</title><subtitle type='html'>Mostly delphi and database programming with the occasional rant</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default?start-index=26&amp;max-results=25'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-4235925772316569032</id><published>2009-09-22T16:43:00.002+12:00</published><updated>2009-09-22T16:52:12.203+12:00</updated><title type='text'>D2010 suppport in tiOPF</title><content type='html'>tiOPF is a Object Persistence Framework. That is, it is a framework based around saving your objects to, and loading them from, databases and/or flat files.&lt;br /&gt;&lt;br /&gt;Delphi 2010 support has now been added to the latest repository version.&lt;br /&gt;&lt;br /&gt;No release has been made as of yet, so you need to to retrieve it from the subversion repository.  See &lt;a href="http://tiopf.sourceforge.net/SourceCodeRepository.shtml"&gt;here&lt;/a&gt; for instructions.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Notes&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Running unit tests requires copying the xdom.pas unit from Delphi 2009as this is no longer supplied&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There are a large number of failures with BDE paradox tests.  I haven't  investigated this yetas no-one uses paradox any more&lt;br /&gt;&lt;/li&gt;&lt;li&gt;tiVirtualTree and related components have been removed from the gui  controls as they don't work under D2009/D2010. &lt;/li&gt;&lt;li&gt;Unicode is still not supported :(&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Links&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://tiopf.sourceforge.net/"&gt;tiopf.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://tiopf.sourceforge.net/Doc/overview/index.shtml"&gt;tiopf overview&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-4235925772316569032?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/4235925772316569032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=4235925772316569032' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4235925772316569032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4235925772316569032'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/09/d2010-suppport-in-tiopf.html' title='D2010 suppport in tiOPF'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-2760353901953193940</id><published>2009-09-15T15:56:00.004+12:00</published><updated>2009-09-16T00:00:20.750+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MonoTouch'/><category scheme='http://www.blogger.com/atom/ns#' term='Mono'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>C# for the iPhone: Monotouch released</title><content type='html'>Novell's &lt;a href="http://monotouch.net/"&gt;MonoTouch&lt;/a&gt; product  has been released.  MonoTouch is mono for the iPhone.&lt;br /&gt;This allows compiling .net applications to native code and deploying to the iPhone.&lt;br /&gt;&lt;br /&gt;There are akready 200 apps in the app store using Mono via Unity so the underlying technology is fairly well tested.  MonoTouch adds Cocoa support and integration into MonoDevelop.&lt;br /&gt;&lt;br /&gt;MonoTouch has 2 main issues for some users, the $399US price point, and the logo.&lt;br /&gt;The price has disappointed a number of beta testers  and the logo is the second worst I have seen recently (worst is the &lt;a href="http://www.toastmasters.org.nz/index.cfm/Club_Finder.html"&gt;Toastmasters&lt;/a&gt; goatse).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-2760353901953193940?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/2760353901953193940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=2760353901953193940' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/2760353901953193940'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/2760353901953193940'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/09/c-for-iphone-monotouch-released.html' title='C# for the iPhone: Monotouch released'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-9129973550293285710</id><published>2009-08-28T14:44:00.004+12:00</published><updated>2009-08-29T10:47:23.153+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtual machines'/><category scheme='http://www.blogger.com/atom/ns#' term='delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='virtual box'/><category scheme='http://www.blogger.com/atom/ns#' term='vmware'/><title type='text'>When you install Delphi 2010, put it in a virtual machine</title><content type='html'>I recently compared the performance of virtual machines with the real hardware.  The figures were &lt;a href="http://sourceitsoftware.blogspot.com/2009/07/windows-performance-index-vmware.html"&gt;suprisingly good&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Shortly after that, disaster struck.  My laptop wouldn't turn on.  It took Dell 2 weeks to fix, replacing the motherboard and the video card.&lt;br /&gt;&lt;br /&gt;If I had delphi installed directly, I would have had 2 weeks of very limited productivity.  As it was, I ripped the hard drive out, stuck it in a usb caddy and continued working on another machine.  I was back up to speed the next day. &lt;br /&gt;&lt;span style="font-style: italic;"&gt;Edit: It didn't take a full day to get productive again, I did other work until it became apparent that it would be a while before my computer was fixed.  It only took about 30 minutes to transfer the data over and get going.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If it had been a hard drive problem, I would have restored the latest vm backup off a dvd, pulled the latest changes from the version control or the source backup and been back up to speed with limited data loss.&lt;br /&gt;&lt;br /&gt;I get a new laptop next month.  Installing delphi is going to be as easy as installing vmware and copying the vm files over.  30 minutes work, most of which is surfing the internet waiting for the files to copy.  The last time I actually had to install Delphi, it took hours.&lt;br /&gt;&lt;br /&gt;There are other advantages as well, my development backups fit on a single dual layer dvd, I get to run and test on multiple OSs and disaster recovery plan is much shorter.&lt;br /&gt;&lt;br /&gt;So make Delphi 2010 your starting point.  Download &lt;a href="http://www.virtualbox.org/"&gt;Virtual Box&lt;/a&gt;, &lt;a href="http://www.vmware.com/"&gt;VMWare Workstation ($$$)&lt;/a&gt; or &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=28C97D22-6EB8-4A09-A7F7-F6C7A1F000B5&amp;amp;displaylang=en"&gt;Virtual PC&lt;/a&gt; and use that for development.   If you are running Windows 7, you could look into Windows XP Mode and use that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-9129973550293285710?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/9129973550293285710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=9129973550293285710' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/9129973550293285710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/9129973550293285710'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/08/when-you-install-delphi-2010-put-it-in.html' title='When you install Delphi 2010, put it in a virtual machine'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-2788674242971189368</id><published>2009-08-14T09:56:00.002+12:00</published><updated>2009-08-14T10:36:44.798+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='excel'/><title type='text'>Changing Excel query connection strings</title><content type='html'>We use Excel and database queries extensively for reporting purposes.  It's quick and easy to set-up, and provides reports that our clients can manipulate.&lt;br /&gt;&lt;br /&gt;However I have recently run into a rather painful excel quirk with ODBC connections: Excel stores the database connection string internally.  Even if you change the ODBC connection on the computer, excel still uses the original connection from when the query was created.&lt;br /&gt;&lt;br /&gt;This bit us when moving the reports to a different machine.  Despite having the same ODBC connection set up, excel wouldn't refresh the query and gave the error "[Microsoft][ODBC SQL Server Driver][TCP/IP Sockets]SQL Server does not exist or access denied."&lt;br /&gt;&lt;br /&gt;Aside&lt;br /&gt;A similar problem can happen if you update the database from sql server 2000 to sql server 2005 or 2008.  In that case you may get the error  "[Microsoft][SQL Native Client][SQL Server]User 'DOMAIN\username' does not have permission to run DBCC TRACEON."  In that case, you need to alter the connection string to change "APP=Microsoft® Query" to something else.  Apparently MS hard coded a check for "Microsoft® Query" in sql server which then runs DBCC TRACEON for no apparent reason.  I suggest  "APP=WTFWYT"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Changing one query&lt;/span&gt;&lt;br /&gt;(from &lt;a href="http://social.msdn.microsoft.com/forums/en-US/sqldataaccess/thread/ad8ad177-65b3-4962-b0aa-530a2c9d6d86"&gt;here&lt;/a&gt;)&lt;br /&gt;"&lt;span style="font-style: italic;"&gt;Open the worksheet and place the cursor on a cell within the cell range of &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;the query.  Press Alt-F11 to open the VBEditor.  Press Ctrl-G to open the &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Intermediate window.  Type the command:  ? ActiveCell.QueryTable.Connection.   &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;The embedded connection string will be echoed back to the screen.  Put double &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;quotes around the string and update the connection information with the new &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;server info.  Move the cursor to the beginning of the connection string and &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;insert the following in front of the string:   &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ActiveCell.QueryTable.Connection =&lt;/span&gt;&lt;br /&gt;"&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Changing multiple queries in a spreadsheet&lt;/span&gt;&lt;br /&gt;(modified from &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/sqlanalysisservices/thread/a013c536-164e-4883-b989-93e9e33d8664"&gt;here&lt;/a&gt;)&lt;br /&gt;You need to create the following macro (change connection string to suit, see above) and run it in each spreadsheet requiring change.  (See the steps below). Once the macro has run successfully, delete it before saving the spreadsheet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Sub ChangeConnections()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     Dim sh As Worksheet, qy As QueryTable  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     For Each ws In ActiveWorkbook.Sheets&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       For Each qy In ws.QueryTables&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            qy.Connection = "..."&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            On Error Resume Next&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            qy.Refresh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            If Err.Number &lt;&gt; 0 Then MsgBox "Problem refreshing QueryTable: " &amp;amp; Err.Description&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       Next qy&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    Next ws&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;End Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Getting the new connection string&lt;/span&gt;&lt;br /&gt;The easiest way to find the new connections string is to create a new query and do the ?ActiveCell.QueryTable.Connection trick.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-2788674242971189368?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/2788674242971189368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=2788674242971189368' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/2788674242971189368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/2788674242971189368'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/08/changing-excel-query-connection-strings.html' title='Changing Excel query connection strings'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-7044704333267190276</id><published>2009-07-10T16:44:00.004+12:00</published><updated>2009-07-15T12:02:48.565+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtual machines'/><category scheme='http://www.blogger.com/atom/ns#' term='virtual box'/><category scheme='http://www.blogger.com/atom/ns#' term='vmware'/><title type='text'>Windows Performance Index - VMware workstation v Virtual Box</title><content type='html'>&lt;a href="http://www.virtualbox.org/"&gt;Virtual Box 3&lt;/a&gt; has been released.  I haven't used previous versions of VB, but it has a good rep. Version 3 now supports 3d acceleration.  I have been wanting to use Aero and Glass in  my virtual machines so that I could develop Vista specific applications so I gave it a try.&lt;br /&gt;&lt;br /&gt;First the bad news, VB doesn't support enough 3d features to run Aero (neither does VMware).  I did discover a work around though, connect to your virtual machine using Remote Desktop Connection from a Vista machine, turn all graphics options to high and volia.&lt;br /&gt;&lt;br /&gt;While I had VB installed, I did a quick and dirty comparision with VMware workstation using Windows Performance Index. Take these results with a grain of salt, I didn't spend much time playing with the setup and tweaking.  I couldn't get dual core to work on VB, it just blue-screened, and I didn't have the time to spend sorting it out.&lt;br /&gt;&lt;br /&gt;Windows Performance Index&lt;br /&gt;&lt;table style="border-collapse: collapse; width: 527pt;" border="0" cellpadding="0" cellspacing="0" width="702"&gt;&lt;col style="width: 111pt;" width="148"&gt;  &lt;col style="width: 101pt;" width="134"&gt;  &lt;col style="width: 93pt;" width="124"&gt;  &lt;col style="width: 111pt;" span="2" width="148"&gt;  &lt;tbody&gt;&lt;tr style="height: 15pt;" height="20"&gt;   &lt;td class="xl65" style="height: 15pt; width: 111pt; font-weight: bold;" height="20" width="148"&gt;&lt;br /&gt;&lt;/td&gt;   &lt;td class="xl68" style="width: 101pt; text-align: center; font-weight: bold;" width="134"&gt;Host&lt;/td&gt;   &lt;td class="xl68" style="width: 93pt; text-align: center; font-weight: bold;" width="124"&gt;VMware&lt;br /&gt;Single proc&lt;/td&gt;   &lt;td class="xl68" style="width: 111pt; text-align: center; font-weight: bold;" width="148"&gt;VMware&lt;br /&gt;Dual proc&lt;/td&gt;   &lt;td class="xl69" style="width: 111pt; text-align: center; font-weight: bold;" width="148"&gt;Virtual Box&lt;br /&gt;Single Proc&lt;/td&gt;  &lt;/tr&gt;  &lt;tr style="height: 15pt;" height="20"&gt;   &lt;td class="xl66" style="height: 15pt; font-weight: bold;" height="20"&gt;Processor&lt;/td&gt;   &lt;td style="text-align: center;" class="xl70"&gt;5.4&lt;/td&gt;   &lt;td style="text-align: center;" class="xl70"&gt;4.4&lt;/td&gt;   &lt;td style="text-align: center;" class="xl70"&gt;5.2&lt;/td&gt;   &lt;td style="text-align: center;" class="xl71"&gt;4.4&lt;/td&gt;  &lt;/tr&gt;  &lt;tr style="height: 15pt;" height="20"&gt;   &lt;td class="xl66" style="height: 15pt; font-weight: bold;" height="20"&gt;Memory&lt;/td&gt;   &lt;td style="text-align: center;" class="xl70"&gt;5.1&lt;/td&gt;   &lt;td style="text-align: center;" class="xl70"&gt;4.9&lt;/td&gt;   &lt;td style="text-align: center;" class="xl70"&gt;5.2&lt;/td&gt;   &lt;td style="text-align: center;" class="xl71"&gt;5.9&lt;/td&gt;  &lt;/tr&gt;  &lt;tr style="height: 15pt;" height="20"&gt;   &lt;td class="xl67" style="height: 15pt; font-weight: bold;" height="20"&gt;Primary Hard disk&lt;/td&gt;   &lt;td style="text-align: center;" class="xl72"&gt;5.4&lt;/td&gt;   &lt;td style="text-align: center;" class="xl72"&gt;5.3&lt;/td&gt;   &lt;td style="text-align: center;" class="xl72"&gt;5.4&lt;/td&gt;   &lt;td style="text-align: center;" class="xl73"&gt;4.7&lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;The memory figures are surprising, I am not sure if the VB figures of 5.9 are real or just a sign of something wrong somewhere.  Draw your own conclusions on that. &lt;br /&gt;&lt;br /&gt;VB is slower in hard drive, but otherwise up with the play processor wise.  Getting dual core working would probably give similar processor figures to VMware dual core.&lt;br /&gt;&lt;br /&gt;I was impressed with how well VMware matches up to the host system.  While VB doesn't seem to be quite there yet, it is still doing pretty well, and you can't beat the price.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-7044704333267190276?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/7044704333267190276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=7044704333267190276' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/7044704333267190276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/7044704333267190276'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/07/windows-performance-index-vmware.html' title='Windows Performance Index - VMware workstation v Virtual Box'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-4445880239341127148</id><published>2009-06-30T22:42:00.005+12:00</published><updated>2009-07-01T07:51:42.981+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone development'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='Mono'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>iPhone programming might be getting a whole lot easier</title><content type='html'>The mono project has announced &lt;a href="http://www.mono-project.com/MonoTouch"&gt;MonoTouch&lt;/a&gt;.   MonoTouch is Mono for the iPhone and the iPod touch.   Applications writen with MonoTouch work and non-jailbroken phones, and can be submitted to the app store.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://tirania.org/blog/archive/2009/Jun-29.html"&gt;Miguel's blog&lt;/a&gt; for additional details.  According to the comments, a beta should be released in August.&lt;br /&gt;&lt;br /&gt;Time to start brushing up my C# skills.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-4445880239341127148?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/4445880239341127148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=4445880239341127148' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4445880239341127148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4445880239341127148'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/06/iphone-programming-might-be-getting.html' title='iPhone programming might be getting a whole lot easier'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-1834218765419791531</id><published>2009-06-29T18:06:00.005+12:00</published><updated>2009-06-30T22:49:02.311+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Guido just doesn't get windows programming</title><content type='html'>Among the blogs I follow is that of &lt;a href="http://neopythonic.blogspot.com/"&gt;Guido van Rossum&lt;/a&gt;, the creator of Python.  Mostly they are interesting but his latest one (&lt;a href="http://neopythonic.blogspot.com/2009/06/ironpython-in-action-and-decline-of.html"&gt;IronPython in Action and the Decline of Windows&lt;/a&gt;) is a large pile of wtf.  Apparently programming windows apps is tedious and gui creation requires many lines of code.  Even more surprising to me, web apps are far easier to create.&lt;br /&gt;&lt;br /&gt;Wow, apparently he has never heard of delphi, visual studio or any of the other gui editors that have been about since at least the mid 80s.  The last time I laid a gui out in code, other than for eductational purposes, would have been about 1986.  I have no desire to do it again either.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-1834218765419791531?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/1834218765419791531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=1834218765419791531' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/1834218765419791531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/1834218765419791531'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/06/guido-just-doesnt-get-windows.html' title='Guido just doesn&apos;t get windows programming'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-3765983508947641971</id><published>2009-05-13T15:41:00.003+12:00</published><updated>2009-05-13T16:46:01.222+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone development'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>iPhone Dev: Zombie Mansion post mortem</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Overview&lt;/span&gt;&lt;br /&gt;I released Zombie Mansion in mid December 08.  It is a 1st person shooter, the 2nd available on the iPhone and the first one to be designed for mobile devices rather than being a pc port.  ZM was a port and extension of the work I had done previously on the &lt;a href="http://sourceitsoftware.com/yeti.html"&gt;Yeti engine&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Seeing as how every other iPhone developer is sharing their tales of mega success, or crushing failure, I though I would add my story.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sales&lt;/span&gt;&lt;br /&gt;ZM has sold steadily, if not spectacularly.   Unfortunately I have not made enough to pay off my house and buy a fast car.  On the other hand, it sold well enough to pay my mortgage payments for the 1st 3 months.  Sales are as you would expect: hundreds sold in the first couple of days, rapidly dropping off as ZM moved off the recent releases page.  My first update provided a brief blip but my second update was unnoticeable in terms of sales.&lt;br /&gt;&lt;br /&gt;I took 2 weeks leave to finish ZM, and I estimate that I spent the equivalent of another 2 weeks previously.  This doesn't include the original porting work I did moving the yeti engine to the pocket pc.&lt;br /&gt;&lt;br /&gt;As a return on time spent, ZM performed slightly better than working at my day job.  It was however considerably more fun.  It would have performed even better but I made a couple of bad design decisions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Programming&lt;/span&gt;&lt;br /&gt;Unusually, I did the bulk of the development in windows using visual studio rather than in xcode on OSX.  I already had an OpenGL ES port running on Windows Mobile and Windows so an iPhone port wasn't much of a problem.&lt;br /&gt;&lt;br /&gt;Coding was done in a mixture of C (yeti code) and C++ (my code).&lt;br /&gt;On the iPhone, I used the &lt;a href="http://oolongengine.com/"&gt;Oolong engine&lt;/a&gt; to handle the sound, input and 3d setup.  Oolong provides c++ wrapper classes for all this (and more).&lt;br /&gt;&lt;br /&gt;On the pc and windows mobile side, I used the &lt;a href="http://www.imgtec.com/powervr/insider/powervr-sdk.asp"&gt;PowerVr sdk&lt;/a&gt; to handle 3d setup.  Keyboard handling is trivial, and I used &lt;a href="http://www.shlzero.com/"&gt;Hekkus&lt;/a&gt; to provide sound support.&lt;br /&gt;&lt;br /&gt;Once I had this all set-up,I did most coding in visual studio.  At irregular intervals, I would reboot into OSX and compile with xcode.  I mostly used xcode for iPhone specific stuff and performance testing.  All my support tools (map editor, 3d importer etc.) are windows based (in c++ builder and Delphi) so that necessitated mostly using windows.  I prefer visual studio to xcode, so it wasn't much of a chore.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Mistakes&lt;/span&gt;&lt;br /&gt;I made a couple of mistakes.  The first, and most major was simplifying the weapons too much.  I went with one weapon, a staff, with upgrades rather than with multiple weapons.  In retrospect, a bad call.&lt;br /&gt;&lt;br /&gt;The second mistake was not putting some help tips around controls.  The controls work well if you leave your thumb on the d pad and slide it to control.  If you pick your thumb up and move it, the controls don't work as well.  Some easy way of explaining this to the player would have made their initial impressions better.&lt;br /&gt;&lt;br /&gt;The underlying problem is that perennial development favourite, I underestimated the time needed to write the software.  I ran out of annual leave and thus ran out of time.  While I enjoyed the game that I wrote, it would have been better if I had more time to add extra features and polish.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Dealing with Apple&lt;/span&gt;&lt;br /&gt;There are 3 major drawbacks to iPhone development: Apple, Apple and Apple.  I don't know if they are overworked, incompetent or just don't care.  Either way, developer support seems to be missing in action.&lt;br /&gt;&lt;br /&gt;Since I have had children, I have made a concious effort to improve my language, removing the more robust terms I picked up working in the abbottiors.   Three months of dealing with Apple has made a mockery of my self-betterment attempts, leaving me swearing like Gordon Ramsey on a bad day.&lt;br /&gt;&lt;br /&gt;Simply getting a paid developer contract took six weeks.  My first payment, for December, didn't get paid until late March.  Emails asking when money was going to arrive were ignored, or fobbed off with stock responses or outright lies.  Whenever I phoned, I was told they couldn't help and to email another department.&lt;br /&gt;&lt;br /&gt;Even when I did get paid, there was no notification.  Apple can email me every week, trying to sell me a second rate album farted out by a talentless boy band, but they can't be bothered sending me an email saying "We have now condescended to pay you".&lt;br /&gt;&lt;br /&gt;As a comparison, RegNow emailed me on Jan 4th letting me know my December payment had been released, and the money was in my account on Jan 6th.  Even now that Apple has decided to make my monthly payments on a monthly basis, they still take nearly 40 days longer than Regnow.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Random thoughts&lt;/span&gt;&lt;br /&gt;There is clearly still money to be made in iPhone dev.  ZM hasn't disturbed the sales charts, but it has still sold well enough to cover it's costs and my time.  I imagine that there are many developers in a similar position, not making riches, but making enough to get by and keep developing.   A small stable of good games/applications could provide a nice living without requiring a hit.&lt;br /&gt;&lt;br /&gt;It used to be that you could get a large amount of exposure and thus sales by releasing an update every couple of weeks.  However the volume of new applications has changed that.  There are so many apps being released each day that the initial rush of sales from being in the "what's new" charts is much smaller.  You need to get sales the hard way, with marketing; promotion and advertising.&lt;br /&gt;&lt;br /&gt;I also have a couple of windows shareware applications, Pics Print and Rental Property Manager.  While it is not easy to compare windows utilities and business applications with an iPhone, the return on time invested is far greater for these 2, particularly RPM, than for ZM.&lt;br /&gt;&lt;br /&gt;All this brings me full circle from where I started out six months ago.  There is money to be made in iPhone apps, but there is also money to be made in windows shareware as well.  If you are a windows developer, particularly if you are a Delphi developer, then you are probably better off developing windows shareware than iPhone apps. I know a lot more developers making money off windows than off iPhones.&lt;br /&gt;&lt;br /&gt;Oh, and &lt;a href="http://sourceitsoftware.blogspot.com/2008/08/programming-for-iphone-really-sucks.html"&gt;developing for iPhones still sucks&lt;/a&gt;!  Not as badly as I first thought, but still noticeably.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-3765983508947641971?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/3765983508947641971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=3765983508947641971' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/3765983508947641971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/3765983508947641971'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/05/iphone-dev-zombie-mansion-post-mortem.html' title='iPhone Dev: Zombie Mansion post mortem'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-6670334488267801199</id><published>2009-04-17T20:39:00.006+12:00</published><updated>2009-04-22T18:54:05.964+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>And Now for Something Completely Different</title><content type='html'>One of the pragmatic programmer tenets is to learn a new programming language every year.  I'm a bit behind on that, I haven't learn a new language since 2002 (I don't count objective C because I hate it and have only learnt the bare minimum necessary to get by).  Unfortunately the need to earn a living has gotten in the way of random learning.&lt;br /&gt;&lt;br /&gt;However I have now been programming in Delphi for 15 years.  It's starting to get a bit boring and it's time to kick-start the brain again.  While Delphi will be my main language for the near future, I am going to make the effort to learn something different.&lt;br /&gt;&lt;br /&gt;The main things I am looking for in my language de jour are&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Dynamically typed (I have done statically typed languages for decades)&lt;/li&gt;&lt;li&gt;Popular (general rule of thumb, should be at least as popular as delphi)&lt;/li&gt;&lt;li&gt;Object Orientated&lt;/li&gt;&lt;li&gt;Cross platform&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Batteries included&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;This pretty much narrows it down to Perl, Php, Python and Ruby.  I was initially tempted by Ruby as I don't yet have an R on my alphabetical list of programming languages.   However I have settled on Python instead.&lt;br /&gt;&lt;br /&gt;Part of the reason for going with Python is the presence of the            &lt;a href="http://code.google.com/p/python4delphi/"&gt;Python for Delphi&lt;/a&gt; components.  These promise to let you use python as a scripting language inside delphi apps.  These components are used in the &lt;a href="http://code.google.com/p/pyscripter/"&gt;PyScripter&lt;/a&gt; ide.&lt;br /&gt;&lt;br /&gt;The easiest way I have found to get started is to use &lt;a href="http://www.portablepython.com/"&gt;Portable Python&lt;/a&gt;.  This will put Python and a few tools (inc. PyScripter) into a portable drive along with a few tools and useful modules such as &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt;. This is considerably easier for a python newbie than sourcing and installing the packages separately.&lt;br /&gt;&lt;br /&gt;Some useful links to get started with:&lt;br /&gt;&lt;a href="http://python.org/"&gt;Official website&lt;/a&gt;&lt;br /&gt;&lt;a href="http://docs.python.org/tutorial/"&gt;Official python tutorial (v2.6)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://diveintopython.org/index.html"&gt;Dive onto python online book&lt;/a&gt; (useful but a bit old)&lt;br /&gt;&lt;a href="http://pycon.blip.tv/"&gt;Pycon US 2009 videos&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.reddit.com/r/Python/"&gt;Reddit python feed&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-6670334488267801199?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/6670334488267801199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=6670334488267801199' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/6670334488267801199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/6670334488267801199'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/04/and-now-for-something-completely.html' title='And Now for Something Completely Different'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-4950394657314321948</id><published>2009-03-09T12:52:00.009+13:00</published><updated>2009-03-17T15:16:05.983+13:00</updated><title type='text'>Filtering generic collections with anonymous methods</title><content type='html'>I have recently been adding generics to the ti Object Persistence Framework. As part of that I was asked to add enumerator filtering.  I did this using a similar technique to that shown &lt;a href="http://www.malcolmgroves.com/blog/?p=273"&gt;here&lt;/a&gt; by Malcolm Groves.&lt;br /&gt;&lt;br /&gt;I ended up with code used like this:&lt;br /&gt;&lt;pre class="sourcecode"&gt;&lt;code&gt;&lt;br /&gt;&lt;b&gt;for&lt;/b&gt; item &lt;b&gt;in&lt;/b&gt; Flist.FilteredEnumerator(&lt;b&gt;function&lt;/b&gt; (TestObject: TtiOPFTestIntegerProp): Boolean&lt;br /&gt;                                &lt;b&gt;begin&lt;/b&gt;&lt;br /&gt;                                  result:= TestObject.IntField &lt;b&gt;mod&lt;/b&gt; 2 = 1;&lt;br /&gt;                                &lt;b&gt;end&lt;/b&gt;) &lt;b&gt;do&lt;/b&gt;&lt;br /&gt;&lt;b&gt;begin&lt;/b&gt;&lt;br /&gt; inc(intCount);&lt;br /&gt; intSum:= intSum + item.IntField;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I was happy enough with the result, but I wasn't happy with the implementation.  I wanted something that was, well, more generic.  What I ended up doing was wrapping the existing enumerator into one containing a filter.  This will work with any generic collection that descends from TEnumerable&lt;t&gt;.  I.e. TList&lt;t&gt;, TQueue&lt;t&gt;, TStack&lt;t&gt;, TDictionary&lt;t&gt; and the TObjectXXX&lt;t&gt; variations&lt;br /&gt;&lt;br /&gt;To implement an enumerator, a class must have a GetEnumerator function.  This returns an object (or a record) that has the Current property and the MoveNext function.  Delphi does a fair amount of work behind the scenes to wrap this all up nicely.  See The Delphi Geek's series on enumerators &lt;a href="http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators.html"&gt;here&lt;/a&gt; for more background.&lt;br /&gt;&lt;br /&gt;Wrapping an existing enumerator meant I could use the existing GetCurrent and MoveNext for accessing the collection.  Filtering then becomes as simple as:&lt;br /&gt;&lt;br /&gt;&lt;pre class="sourcecode"&gt;&lt;code&gt;&lt;b&gt;function&lt;/b&gt; TFilteredEnumerator&amp;lt;T&amp;gt;.MoveNext: Boolean;&lt;br /&gt;&lt;b&gt;begin&lt;/b&gt;&lt;br /&gt;&lt;b&gt;  while&lt;/b&gt;  FEnumerator.MoveNext &lt;b&gt;do&lt;/b&gt;&lt;br /&gt;&lt;b&gt;  begin&lt;/b&gt;&lt;br /&gt;&lt;b&gt;    if&lt;/b&gt; FPredicate(FEnumerator.Current) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;     exit(true);&lt;br /&gt;&lt;b&gt;  end&lt;/b&gt;;&lt;br /&gt; result:= false;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt;;&lt;/code&gt;&lt;/pre&gt;The full code is as follows:&lt;br /&gt;&lt;pre class="sourcecode"&gt;&lt;span id="LabelHighlight"&gt;&lt;pre class="sourcecode"&gt;&lt;code class="keyword"&gt;unit&lt;/code&gt; FilteredEnumeratorU;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;interface&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;uses&lt;/code&gt; Sysutils, generics.collections;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;type&lt;/code&gt;&lt;br /&gt; TFilteredEnumerator&lt;t&gt; = &lt;code class="keyword"&gt;class&lt;/code&gt;&lt;br /&gt;&lt;code class="keyword"&gt;  private&lt;/code&gt;&lt;br /&gt;   FEnumerator: TEnumerator&lt;t&gt;;&lt;br /&gt;   FPredicate: TPredicate&lt;t&gt;;&lt;br /&gt;&lt;code class="keyword"&gt;  protected&lt;/code&gt;&lt;br /&gt;&lt;code class="keyword"&gt;    function&lt;/code&gt; DoGetCurrent: T;&lt;br /&gt;&lt;code class="keyword"&gt;  public&lt;/code&gt;&lt;br /&gt;&lt;code class="keyword"&gt;    constructor&lt;/code&gt; Create(AEnumerable: TEnumerable&lt;t&gt;; APredicate: TPredicate&lt;t&gt;);&lt;br /&gt;&lt;code class="keyword"&gt;    destructor&lt;/code&gt;  Destroy;&lt;br /&gt;&lt;code class="keyword"&gt;    function&lt;/code&gt; GetEnumerator: TFilteredEnumerator&lt;t&gt;;&lt;br /&gt;&lt;code class="keyword"&gt;    property&lt;/code&gt; Current: T &lt;code class="keyword"&gt;read&lt;/code&gt; DoGetCurrent;&lt;br /&gt;&lt;code class="keyword"&gt;    function&lt;/code&gt; MoveNext: Boolean;&lt;br /&gt;&lt;code class="keyword"&gt;  end&lt;/code&gt;;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;implementation&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code class="comment"&gt;{ TFilteredEnumerator&lt;t&gt; }&lt;/t&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;constructor&lt;/code&gt; TFilteredEnumerator&lt;t&gt;.Create(AEnumerable: TEnumerable&lt;t&gt;; APredicate: TPredicate&lt;t&gt;);&lt;br /&gt;&lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt;&lt;code class="keyword"&gt;  inherited&lt;/code&gt; create;&lt;br /&gt; FEnumerator:= AEnumerable.GetEnumerator;&lt;br /&gt; FPredicate:= APredicate;&lt;br /&gt;&lt;code class="keyword"&gt;end&lt;/code&gt;;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;destructor&lt;/code&gt; TFilteredEnumerator&lt;t&gt;.Destroy;&lt;br /&gt;&lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt; FEnumerator.Free;&lt;br /&gt;&lt;code class="keyword"&gt;  inherited&lt;/code&gt; Destroy;&lt;br /&gt;&lt;code class="keyword"&gt;end&lt;/code&gt;;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;function&lt;/code&gt; TFilteredEnumerator&lt;t&gt;.DoGetCurrent: T;&lt;br /&gt;&lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt; result:= FEnumerator.Current;&lt;br /&gt;&lt;code class="keyword"&gt;end&lt;/code&gt;;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;function&lt;/code&gt; TFilteredEnumerator&lt;t&gt;.GetEnumerator: TFilteredEnumerator&lt;t&gt;;&lt;br /&gt;&lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt; result:= self;&lt;br /&gt;&lt;code class="keyword"&gt;end&lt;/code&gt;;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;function&lt;/code&gt; TFilteredEnumerator&lt;t&gt;.MoveNext: Boolean;&lt;br /&gt;&lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt;&lt;code class="keyword"&gt;  while&lt;/code&gt;  FEnumerator.MoveNext &lt;code class="keyword"&gt;do&lt;/code&gt;&lt;br /&gt;&lt;code class="keyword"&gt;  begin&lt;/code&gt;&lt;br /&gt;&lt;code class="keyword"&gt;    if&lt;/code&gt; FPredicate(FEnumerator.Current) &lt;code class="keyword"&gt;then&lt;/code&gt;&lt;br /&gt;     exit(true);&lt;br /&gt;&lt;code class="keyword"&gt;  end&lt;/code&gt;;&lt;br /&gt; result:= false;&lt;br /&gt;&lt;code class="keyword"&gt;end&lt;/code&gt;;&lt;br /&gt;&lt;br /&gt;&lt;code class="keyword"&gt;end&lt;/code&gt;.&lt;br /&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;To use filtering in action, simply do something like:&lt;br /&gt;&lt;br /&gt;&lt;pre class="sourcecode"&gt;&lt;br /&gt;&lt;code class="keyword"&gt;for&lt;/code&gt; xxx &lt;code class="keyword"&gt;in&lt;/code&gt; TFilteredEnumerator&amp;lt;T&amp;gt;.Create(queue, &lt;code class="keyword"&gt;function&lt;/code&gt; (Arg1: T): Boolean&lt;br /&gt;                                                        &lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt;                                                          result:= ...;&lt;br /&gt;                                                        &lt;code class="keyword"&gt;end&lt;/code&gt;)&lt;br /&gt;&lt;code class="keyword"&gt;do&lt;/code&gt;&lt;br /&gt;  ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;eg&lt;br /&gt;&lt;br /&gt;&lt;pre class="sourcecode"&gt;&lt;br /&gt;&lt;code class="keyword"&gt;var&lt;/code&gt;&lt;br /&gt; queue: TQueue&amp;lt;&lt;code class="keyword"&gt;string&lt;/code&gt;&amp;gt;;&lt;br /&gt; cur, combined: &lt;code class="keyword"&gt;string&lt;/code&gt;;&lt;br /&gt; filter: TFilteredEnumerator&amp;lt;TTestObject&amp;gt;;&lt;br /&gt;&lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt; queue:= TQueue&amp;lt;&lt;code class="keyword"&gt;string&lt;/code&gt;&amp;gt;.Create;&lt;br /&gt;&lt;code class="keyword"&gt;  try&lt;/code&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;   &lt;code class="keyword"&gt;for&lt;/code&gt; cur &lt;code class="keyword"&gt;in&lt;/code&gt; TFilteredEnumerator&amp;lt;&lt;code class="keyword"&gt;string&lt;/code&gt;&amp;gt;.Create(queue, &lt;code class="keyword"&gt;function&lt;/code&gt; (Arg1: &lt;code class="keyword"&gt;string&lt;/code&gt;): Boolean&lt;br /&gt;                                                         &lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt;                                                           result:= Arg1 &amp;lt; &lt;code class="quote"&gt;'A'&lt;/code&gt;;&lt;br /&gt;                                                         &lt;code class="keyword"&gt;end&lt;/code&gt;)&lt;br /&gt;   &lt;code class="keyword"&gt;do&lt;/code&gt;&lt;br /&gt;   &lt;code class="keyword"&gt;begin&lt;/code&gt;&lt;br /&gt;     combined:= combined + cur;&lt;br /&gt;   &lt;code class="keyword"&gt;end&lt;/code&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you are deriving from a collection, you could also wrap this into a method:&lt;br /&gt;&lt;br /&gt;&lt;pre class="sourcecode"&gt;&lt;code&gt;&lt;br /&gt;&lt;b&gt;function&lt;/b&gt; TFilterableList.Filter(APredicate: TPredicate&amp;lt;ttestobject&amp;gt;): TFilteredEnumerator&amp;lt;ttestobject&amp;gt;;&lt;br /&gt;&lt;b&gt;begin&lt;/b&gt;&lt;br /&gt; result:= TFilteredEnumerator&amp;lt;ttestobject&amp;gt;.Create(self, APredicate);&lt;br /&gt;&lt;b&gt;end&lt;/b&gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Source can be downloaded from &lt;a href="http://www.sourceitsoftware.com/download/FilteredEnumerator.zip"&gt;here&lt;/a&gt;.&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-4950394657314321948?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/4950394657314321948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=4950394657314321948' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4950394657314321948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4950394657314321948'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/03/filtering-generic-collections-with.html' title='Filtering generic collections with anonymous methods'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-156011914271699070</id><published>2009-02-10T13:18:00.001+13:00</published><updated>2009-02-10T13:21:04.528+13:00</updated><title type='text'>Microsoft Study: TDD reduced defects by 40%-90%, increased dev time by 15% - 35%</title><content type='html'>Found via Reddit.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://research.microsoft.com/en-us/projects/esm/nagappan_tdd.pdf"&gt;here&lt;/a&gt; (pdf).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-156011914271699070?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/156011914271699070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=156011914271699070' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/156011914271699070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/156011914271699070'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/02/microsoft-study-tdd-reduced-defects-by.html' title='Microsoft Study: TDD reduced defects by 40%-90%, increased dev time by 15% - 35%'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-6022299214459176494</id><published>2009-01-19T10:02:00.004+13:00</published><updated>2009-01-19T13:08:29.818+13:00</updated><title type='text'>Garbage collection - it's not about lazyness</title><content type='html'>There seems to be a common belief amongst a number of Delphi programmers (and c++ programmers etc) that garbage collection is all about being too lazy to do your own clean-up.&lt;br /&gt;&lt;br /&gt;E.g. Babnik asks "&lt;a href="http://thedorictemple.blogspot.com/2009/01/what-is-it-about-garbage-collection.html"&gt;What is it about Garbage Collection?&lt;/a&gt;" (kudos for actually asking the question) and his post has the implicit assumption that advocates are trying to avoid doing a bit of minor work.&lt;br /&gt;&lt;br /&gt;Others have posted far more stronger comments (check the responses to Babnik's post) straight out stating that gc = lazyness, bad coding and a slack attitude to life.  I find this attitude condescending and offensive.  The reason I want gc, is not because I write bad code, but because i want to write better code.&lt;br /&gt;&lt;br /&gt;I would like to see garbage collection in native Delphi, not as a mandatory feature, but as an option.  It's not something I am holding my breath for, but if there was one thing I could add, that would be it.&lt;br /&gt;&lt;br /&gt;I know I am repeating myself, but here are my main reasons for wanting a gc (expanded from an earlier &lt;a href="http://sourceitsoftware.blogspot.com/2008/01/garbage-collection-in-delphi-win-32-why.html"&gt;post&lt;/a&gt; on the subject):&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Better code: In a non gc language, you end up with a number of idioms and practices to guard against memory leaks. Delphi has several of these.&lt;br /&gt;E.g.:&lt;br /&gt;It is rare to return an object from a function. Typically you would create an object and then pass it to a procedure to be modified.&lt;br /&gt;The use of assign rather than :=&lt;br /&gt;The use of Owner, Owned and the like to solve object destruction problems)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Less code: I performed a naive analysis on my most recent project by removing most .Free calls and the supporting destructors and try … finally blocks. The result was about 4% fewer lines of code.  More importantly, the code I removed was boring, boilerplate which solved no business problems and added no value (other than preventing leaks)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Faster development:  There are some minor time savings to be had simply by typing less code.  However when I was regularly programming in c# I found my productivity improved due to the change of coding style that gc allowed.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Fewer memory leaks: By reducing the need for manually freeing memory, a gc significantly reduces the scope for memory leaks. It is still possible to leak memory, but much harder.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;There are some problems that it is difficult to solve without a GC.   Linq is often given as an example.  Class operators (as opposed to record operators) is another&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;One of the main reasons I see for Delphi to have a gc, is that it's competitors have it.  If we are to persuade people to write applications in Delphi as opposed to C#, Java etc then requiring manual memory is at best a speed bump.&lt;br /&gt;&lt;br /&gt;Finally garbage collection definitely falls into the "Your kilometreage may vary" category.  If you are working in memory constrained environments then manual management is the way to go.  If you are writing database driven business apps or web apps (as I usually am) then manual management offers little or no advantage over a garbage collector.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-6022299214459176494?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/6022299214459176494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=6022299214459176494' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/6022299214459176494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/6022299214459176494'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2009/01/garbage-collection-its-not-about.html' title='Garbage collection - it&apos;s not about lazyness'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-5531134793739310080</id><published>2008-12-12T08:21:00.002+13:00</published><updated>2008-12-12T08:33:37.815+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Zombie Mansion released for the iPhone</title><content type='html'>Zombie Mansion is  first person shooter game I have been developing for the past few months (and the cause of my receding hairline).  It got finally got approved yesterday.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://www.sourceitsoftware.com/zombie.html"&gt;here&lt;/a&gt; for screenshots and more info.&lt;br /&gt;See &lt;a href="http://toucharcade.com/link/http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=297779095&amp;amp;mt=8"&gt;here&lt;/a&gt; for the App store page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-5531134793739310080?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/5531134793739310080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=5531134793739310080' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/5531134793739310080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/5531134793739310080'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/12/zombie-mansion-released-for-iphone.html' title='Zombie Mansion released for the iPhone'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-9183303179935598277</id><published>2008-11-23T16:35:00.003+13:00</published><updated>2008-11-24T10:02:39.194+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone development'/><title type='text'>iPhone Dev: "The binary you uploaded was invalid. The signature was invalid, or it was not signed with an Apple submission certificate."</title><content type='html'>I finally finished my iPhone game this week (&lt;a href="http://sourceitsoftware.com/zombie.html"&gt;Zombie Mansion&lt;/a&gt;).  All I had to do on Saturday was upload the it into the App store and spend the rest of the weekend relaxing at the beach.&lt;br /&gt;&lt;br /&gt;Not so fast.  I have spent all weekend battling the dreaded "The binary you uploaded was invalid. The signature was invalid, or it was not signed with an Apple submission certificate." error.  As is often the case with error messages, the message itself was on no use what so ever in solving the problem.  It was in fact a positive hindrance as I spent several hours redoing my distribution certificates, provisioning profiles  and waving dead chickens (frozen) over my keyboard.&lt;br /&gt;&lt;br /&gt;In the end I resolved it by moving my dev folder off the thumb drive (fat 32 formatted) and onto the main Mac partition (Mac OS ext format) and rebuilding.&lt;br /&gt;&lt;br /&gt;For the benefit of any other poor buggers in the same straits, here is a list of tips I picked up while investigating this:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Build on a Max OS Est formated drive (you only need to do this for the App store build)&lt;/li&gt;&lt;li&gt;Make sure you have a 57*57 icon called (case sensitive) "Icon.png"&lt;/li&gt;&lt;li&gt;Check the spelling of the code signing identity&lt;/li&gt;&lt;li&gt;make sure your bundle app id is correct&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Make sure the app bundle contains the following:&lt;br /&gt; CodeResources&lt;br /&gt; _CodeSignature&lt;br /&gt; embedded.mobileprovision&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;One think I found helpful was having an ad-hoc version.  That let me sort out problems with certificates much more easily than doing continuous uploads.&lt;br /&gt;&lt;br /&gt;Links:&lt;br /&gt;iPhone Dev forums discussion: &lt;a href="https://devforums.apple.com/message/12311#12311"&gt;https://devforums.apple.com/message/12311#12311&lt;/a&gt;&lt;br /&gt;Zombie Mansion: &lt;a href="http://sourceitsoftware.com/zombie.html"&gt;http://sourceitsoftware.com/zombie.html&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-9183303179935598277?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/9183303179935598277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=9183303179935598277' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/9183303179935598277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/9183303179935598277'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/11/iphone-dev-binary-you-uploaded-was.html' title='iPhone Dev: &quot;The binary you uploaded was invalid. The signature was invalid, or it was not signed with an Apple submission certificate.&quot;'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-1099384595661412938</id><published>2008-10-13T09:46:00.003+13:00</published><updated>2008-10-13T09:53:37.503+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi programming'/><category scheme='http://www.blogger.com/atom/ns#' term='dunit'/><title type='text'>Getting line numbers in dunit test</title><content type='html'>I forget this every time:(&lt;br /&gt;&lt;br /&gt;By default, dunit gives the the address of where your unit tests failed.&lt;br /&gt;To get the line numbers instead, do the following:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Install the JCL from http://sourceforge.net/projects/jcl&lt;/li&gt;&lt;li&gt;In your test project settings, add the conditional define USE_JEDI_JCL (Directories/Conditionals page)&lt;/li&gt;&lt;li&gt;In your test project settings, set Map File to detailed (Linker page)&lt;/li&gt;&lt;li&gt;Rebuild your project&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-1099384595661412938?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/1099384595661412938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=1099384595661412938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/1099384595661412938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/1099384595661412938'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/10/getting-line-numbers-in-dunit-test.html' title='Getting line numbers in dunit test'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-605433301474684377</id><published>2008-09-16T16:44:00.005+12:00</published><updated>2008-09-17T09:10:22.068+12:00</updated><title type='text'>Delphi 2009 = A good test of my backup strategy</title><content type='html'>I installed Delphi 2009 today.  In a fit of enthusiasm, I installed it onto my Delphi 2007 virtual machine...&lt;br /&gt;&lt;br /&gt;That turned out not to be such a smart move.  Not only did d09 fail to install (stopping 1/2 way through with a 'failed to find setup.msi' error), but it trashed my d07 install as well.  I don't know how bad the trashing was, I killed delphi after the 10th "package not found error" on start up.&lt;br /&gt;&lt;br /&gt;I am not blaming CodeGear for this, my D07 install was "customised" to fit on a small virtual machine, with several, possibly important, folders deleted, and with little free space remaining.&lt;br /&gt;&lt;br /&gt;One of the many nice things about using a virtual machine is the ease of backups and recovery.  In this case, it came down to a 2 step process&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Copy fridays backup onto the computer&lt;/li&gt;&lt;li&gt;Use subversion to retrieve all the files changed since friday&lt;/li&gt;&lt;/ol&gt;Total elapsed time to recover was about 10 minutes, most of which was spent making coffee while waiting for the files to copy.&lt;br /&gt;&lt;br /&gt;Moral of the story:  If you are installing D2009 (or any other version), put it in a virtual machine.&lt;br /&gt;And use version control&lt;br /&gt;And backup regularly&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-605433301474684377?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/605433301474684377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=605433301474684377' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/605433301474684377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/605433301474684377'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/09/delphi-2009-good-test-of-my-backup.html' title='Delphi 2009 = A good test of my backup strategy'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-7354295145871359535</id><published>2008-08-18T09:45:00.005+12:00</published><updated>2008-08-18T12:00:11.309+12:00</updated><title type='text'>Programming for the iphone really sucks</title><content type='html'>Ogrampray, ergo sum.  I program, therefore I am.&lt;br /&gt;&lt;br /&gt;I have wanted to program nearly every device that I own (except for video recorders).&lt;br /&gt;Now that I have an iPhone, I want to program that.  Unfortunately there are a number of roadblocks in the way...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;NDA&lt;/span&gt;&lt;br /&gt;The iPhone nda is ridiculously draconian.  There are enough posts on the subject that i won't do into details.  See &lt;a href="http://fuckingnda.com/"&gt;here&lt;/a&gt; if you want to know how developers feel about it.  Basically, you need to figure everything out yourself coz you can't ask anyone else.  There are still &lt;a href="http://groups.google.com/group/iphonesdkdevelopment?hl=en"&gt;discussion groups&lt;/a&gt;, but they may be gone tomorrow.  There is also a series of tutorials at &lt;a href="http://www.iphonesdkarticles.com/"&gt;IphoneSdkArticles.com&lt;/a&gt; but that may also disappear.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Objective C&lt;/span&gt;&lt;br /&gt;ATM, your choice of development language is Objective C or Objective C.&lt;br /&gt;If you are a windows developer, you first question is probably "Wtf is Objective C?".  The short answer is that it is yet another version of C with objects, designed by someone with an unholy fascination for square brackets.  The average line of code contains slightly more text than symbols, but only just.&lt;br /&gt;&lt;br /&gt;ObjC is primarily used on Apple machines, and sits at #42 in the &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;tiobe&lt;/a&gt; list, just below Erlang.&lt;br /&gt;&lt;br /&gt;Because it is Apple only, the development tools only run on OS X (you can use gcc on windows, see &lt;a href="http://wiki.iphonegameover.com/"&gt;here&lt;/a&gt;, but it's not easy).  The tools may be free, but you need a $1000 OS X machine to run it on.&lt;br /&gt;&lt;br /&gt;The sdk license expressly forbids interpretors, JITers and iPhone based compilers.  So the only way to get java or mono is if they develop an ahead of time complier.  Here's hoping.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Multitasking&lt;/span&gt;&lt;br /&gt;Nope, sorry, you don't need it.  Applications run full screen, single window.  When the user presses the home button, your app exits.  To get back to your app, the user needs to start it up all other again.  This immediately rules out a large number of interesting applications, and adds a certain amount of complication to development. As an aside, Windows Mobile does exactly the opposite and minimises applications rather than closing them, so they can reopen more quickly.  This approach is also arse.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Application sandbox&lt;/span&gt;&lt;br /&gt;Each application is stored in a single folder.  All files, settings and related documents are stored within that folder.  The application can only access the contents of their folder.  There is no concept of a user documents folder.  There is also no simple way to get documents onto the phone for use by your app.&lt;br /&gt;&lt;br /&gt;Example:  I have an ebook on my computer.  I would like to read it on my phone (I have kids, I spend a lot of time sitting in the car waiting).  On a windows mobile machine, a palm, or even my old Psion S5, you copy the file over onto your machine, and open it.  On a iPhone, it's not so easy,  Using ereader, I need to upload the ebook to their website, and then download it again on the iPhone.  Alternately, they helpfully suggest, I can run a web-server on my PC.&lt;br /&gt;On the other hand, the Stylus and Bookshelf book readers provide desktop software (50meg download, written in java) that will let you copy documents over using wi-fi.  If I ever need to transfer documents when I don't have a wi-fi router, I am in for a large amount of aggravation.&lt;br /&gt;&lt;br /&gt;So, if you are writing a app that needs to work with documents, you also need to write a client/server file transfer application, in a different programming language, just to get you document where you can use it!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Distribution&lt;/span&gt;&lt;br /&gt;As a means of getting your application to a large number of paying punters, App Store is not too bad.  The 30% commission is high compared to Paypal, Regnow, SwReg etc, but low compared to phone/pda specific sellers such as Handango.  However as a means of distributing your app to a specific group (ie company wide as opposed to world wide) it is less useful.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Positives&lt;/span&gt;&lt;br /&gt;There are some good points about iPhone development though.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The hardware is essentially the same (+/- 3g, gps) on every device.  This is a significant contrast to Windows Mobile where the screen size and orientation can change, there may or may not be a touch screen, camera, gps, wi-fi, internet etc).&lt;/li&gt;&lt;li&gt;Appstore makes purchasing applications dead easy.  I suspect that iPhone users will end up with more applications than windows mobile users.&lt;/li&gt;&lt;li&gt;The development tools are quite polished, and cheap if you already have an Apple machine.&lt;/li&gt;&lt;li&gt;The phone has lots of useful functionality.  GPS, wi-fi, accelerometers, camera etc.  I can't think of any other phone that has sold as well and has as many toys to play with. &lt;/li&gt;&lt;li&gt;The xcode development tools can also deal with C++ and C code, although the sdk is in Objective C.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;If you are a Apple developer, developing for the iPhone is a no-brainer.  For a windows developer, it is a much harder decision.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Links&lt;/span&gt;&lt;br /&gt;&lt;a href="http://fuckingnda.com/"&gt;NDA comments&lt;/a&gt;&lt;br /&gt;&lt;a href="http://groups.google.com/group/iphonesdkdevelopment?hl=en"&gt;SDK Discussion group&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.iphonesdkarticles.com/"&gt;iPhone SDK Articles&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Objective_c"&gt;Wikipedia on objective C&lt;br /&gt;&lt;/a&gt;&lt;a href="http://wiki.iphonegameover.com/"&gt;iPhone Development on Windows&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-7354295145871359535?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/7354295145871359535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=7354295145871359535' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/7354295145871359535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/7354295145871359535'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/08/programming-for-iphone-really-sucks.html' title='Programming for the iphone really sucks'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-5941413859656020338</id><published>2008-08-15T07:42:00.004+12:00</published><updated>2008-08-15T17:04:57.357+12:00</updated><title type='text'>Subversion add-ins for Delphi</title><content type='html'>Part 4 of a n part series on Subversion and delphi&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Subversion add-ins&lt;/span&gt;&lt;br /&gt;As we have already established, TortoiseSvn adds version control functionality to windows explorer.  This is all good, and the result is quite functional.  Many people need nothing more.   However for the rest of us, there are a number of ways to integrate subversion into delphi.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;File Browser&lt;/span&gt;&lt;br /&gt;If you have a recent version of delphi, and have TortoiseSvn installed then you get integration for free.  The File Browser window (View menu -&gt; File Browser) uses the Windows Explorer context menu so all TortoiseSvn commands also work with the File Browser&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_g2tNCh4si2M/SKUIqyX0pnI/AAAAAAAAAFY/zVc5yq1KjWs/s1600-h/DelphiFileExplorer.jpg"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_g2tNCh4si2M/SKUIqyX0pnI/AAAAAAAAAFY/zVc5yq1KjWs/s320/DelphiFileExplorer.jpg" alt="" id="BLOGGER_PHOTO_ID_5234599673057289842" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JCL Version&lt;/span&gt;&lt;br /&gt;The &lt;a href="http://homepages.codegear.com/jedi/jvcl/"&gt;jedi control library&lt;/a&gt; (jcl) includes a Tortoise (Svn and CVS) add-in that adds a JCL Version menu.  Most functionality is available, although I have never managed to get Diff working.  It requires Tortoise to be installed.  If you are already using Tortoise and the JCL, it's a bit of a no-brainer.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_g2tNCh4si2M/SKUIrGTKDXI/AAAAAAAAAFg/p0m3EJyeGkc/s1600-h/JclVersion.jpg"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_g2tNCh4si2M/SKUIrGTKDXI/AAAAAAAAAFg/p0m3EJyeGkc/s320/JclVersion.jpg" alt="" id="BLOGGER_PHOTO_ID_5234599678406430066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Others&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are a few others that I haven't used.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://sourceforge.net/projects/delphisvn/"&gt;Delphi Svn&lt;/a&gt; is available from SourceForge.  It looks like it doesn't need Tortoise to be installed.&lt;/li&gt;&lt;li&gt;The gloriously named &lt;a href="http://delphiaddinfortortoisesvn.tigris.org/"&gt;delphiaddinfortortoisesvn&lt;/a&gt; is available from tigris.org, home of TortoiseSvn.  As you might expect, it requires Tortoise to be installed.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Links&lt;/span&gt;&lt;br /&gt;&lt;a href="http://tortoisesvn.tigris.org/"&gt;Tortoise&lt;/a&gt;&lt;br /&gt;&lt;a href="http://homepages.codegear.com/jedi/jvcl/"&gt;Jedi Control Library&lt;/a&gt;&lt;span style="font-family:Georgia,serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://sourceforge.net/projects/delphisvn/"&gt;Delphi Svn&lt;/a&gt;&lt;br /&gt;&lt;a href="http://delphiaddinfortortoisesvn.tigris.org/"&gt;Delphi Addin (Tigris)&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-5941413859656020338?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/5941413859656020338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=5941413859656020338' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/5941413859656020338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/5941413859656020338'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/08/subversion-add-ins-for-delphi.html' title='Subversion add-ins for Delphi'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_g2tNCh4si2M/SKUIqyX0pnI/AAAAAAAAAFY/zVc5yq1KjWs/s72-c/DelphiFileExplorer.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-4363715716546115171</id><published>2008-07-28T10:00:00.004+12:00</published><updated>2008-08-07T22:54:14.914+12:00</updated><title type='text'>Common tasks with Subversion</title><content type='html'>Part 3 of an n part series.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;General workflow for version control&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The following descriptions all use TortoiseSVN and Explorer.  The steps can also be done using other Subversion clients such as DelphiSvn or JCL.&lt;br /&gt;&lt;br /&gt;The general workflow for changing code is:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Update&lt;/span&gt;. Right click on your base development folder and choose TortoiseSvn -&gt; Update.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Resolve conflicts&lt;/li&gt;&lt;li&gt;code like a demon...&lt;/li&gt;&lt;li&gt;Test, test and test&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;Update  &lt;/span&gt;(again).  As 1, just in case someone else has changed things&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Resolve conflicts (again)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Add &lt;/span&gt;(also &lt;span style="font-style: italic;"&gt;Delete &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;Ignore&lt;/span&gt; as required)&lt;br /&gt;&lt;/li&gt;&lt;li style="font-style: italic;"&gt;Commit&lt;/li&gt;&lt;/ol&gt;Notes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Solo developers can normally leave out steps 1,2,5,6&lt;/li&gt;&lt;li&gt;Steps 7 and 8 can be combined (check the "Show unversioned files" box in the commit dialog)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;For a solo developer, the process essentially comes down to&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Commit&lt;/span&gt;.  Do &lt;span style="font-style: italic;"&gt;Add&lt;/span&gt;s, &lt;span style="font-style: italic;"&gt;Delete&lt;/span&gt;s etc from commit dialog&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Now isn't that easier than zipping up all your source code and archiving it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Traps for young players&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Deletes and (particular) Renames should be done from within Explorer/Tortoise.&lt;/li&gt;&lt;li&gt;Do &lt;span style="font-style: italic;"&gt;commit&lt;/span&gt;s from the base directory where possible.  If you &lt;span style="font-style: italic;"&gt;commit &lt;/span&gt;further down the tree, then you need to do an &lt;span style="font-style: italic;"&gt;update &lt;/span&gt;before you can commit from the base.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;(Edit) Team Version Control&lt;/span&gt;&lt;br /&gt;One thing I didn't point out first time round (thanks Lars).&lt;br /&gt;The golden rule of team version control:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Only check in working code to the trunk.&lt;/span&gt;&lt;br /&gt;If you are working it a team environment, and you want to commit non working code then create a branch.  That will let you have all the benefits of version control without annoying everyone you work with.  Once you have completed your changes, merge your changes back into the trunk.  See the &lt;a href="http://tortoisesvn.net/docs/release/TortoiseSVN_en/index.html"&gt;manual&lt;/a&gt; for details.&lt;br /&gt;Also, Sean's rule number 2 (for team programming):&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Always update before you commit&lt;/span&gt; ()&lt;br /&gt;If you commit without an update first, the code in the repository may not be the same as your code.  That means that you don't know that the tests pass, and the code still compiles. &lt;br /&gt;&lt;br /&gt;E.g. Bob changes the signature of DoSomething to take an extra parameter.  It's in a file that you haven't touched, so there are no conflicts.  All of your code uses the old signature so when you commit, it won't compile any more.&lt;br /&gt;&lt;br /&gt;If you update first, you can catch the problem and avoid making a fool of yourself.  This sort of scenario can be quite common with larger teams.  Don't ask me how I know.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Manual&lt;/span&gt;&lt;br /&gt;All Tortoise commands are available from the Explorer context menu. See here for the &lt;a href="http://tortoisesvn.net/docs/release/TortoiseSVN_en/index.html"&gt;manual&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-4363715716546115171?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/4363715716546115171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=4363715716546115171' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4363715716546115171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4363715716546115171'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/07/common-tasks-with-subversion.html' title='Common tasks with Subversion'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-7233680244017094233</id><published>2008-07-26T15:22:00.003+12:00</published><updated>2008-07-26T15:44:43.492+12:00</updated><title type='text'>Subversion server options</title><content type='html'>I didn't cover subversion servers in my last &lt;a href="http://sourceitsoftware.blogspot.com/2008/07/starting-out-with-delphi-and-subversion.html"&gt;post&lt;/a&gt; as I don't use one any more.  However there have been some queries so here are a few ideas:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows installers&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.visualsvn.com/server/"&gt;VisualSVN Server&lt;/a&gt;&lt;br /&gt;&lt;a href="http://svn1clicksetup.tigris.org/"&gt;official Svn 1-click setup&lt;/a&gt;&lt;br /&gt;&lt;a href="http://subversion.tigris.org/"&gt;Other OS&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;VMWare appliances&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.vmware.com/appliances/directory/519"&gt;Subversion and WebSVN on Ubuntu Server&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ytechie.com/svn-vm"&gt;SVN VM&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.garghouti.co.uk/vmTrac/"&gt;vmTrac &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Online hosting&lt;br /&gt;&lt;/span&gt;&lt;a href="http://cvsdude.com/"&gt;Cvs Dude&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://www.google.co.nz/search?q=subversion+hosting&amp;amp;ie=utf-8&amp;amp;oe=utf-8&amp;amp;aq=t&amp;amp;rls=org.mozilla:en-GB:official&amp;amp;client=firefox-a"&gt;Google search&lt;br /&gt;&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;I am not endorsing any of these.  However, if I needed a server, I would probably go with one of the online solutions.&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-7233680244017094233?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/7233680244017094233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=7233680244017094233' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/7233680244017094233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/7233680244017094233'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/07/subversion-server-options.html' title='Subversion server options'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-2997035135586733179</id><published>2008-07-07T09:22:00.013+12:00</published><updated>2008-10-13T09:46:08.616+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi programming'/><category scheme='http://www.blogger.com/atom/ns#' term='version control'/><title type='text'>Starting out with Delphi and subversion</title><content type='html'>I am always disturbed by the number of programmers I run into who don't use version control.  A version control system (VCS) is one of the fundamental tools of a programmer, up there with the ide/compiler, bug tracking and backups.&lt;br /&gt;&lt;br /&gt;Subversion, together with the TortoiseSvn plugin for Explorer, is one of the better free VCS solutions available.  What follows is a quick guide to setting it up the easy way.&lt;br /&gt;&lt;br /&gt;Note:  This setup is not suitable if you have a large number of users, or need to provide access across the internet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tortoise and Subversion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt; is the actual VCS.  Typically you would run it as a service and then connect to it with client software such as &lt;a href="http://tortoisesvn.tigris.org/"&gt;Tortoise&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tortoise adds &lt;a href="http://tortoisesvn.tigris.org/ExplorerIntegration.html#contextmenus"&gt;context menus&lt;/a&gt; and &lt;a href="http://tortoisesvn.tigris.org/ExplorerIntegration.html#overlays"&gt;icon overlays&lt;/a&gt; to Explorer allowing control of the VCS.  These menus and overlays are also available in programs that use the Explorer menus and icons such as the Delphi File Explorer.&lt;br /&gt;&lt;br /&gt;Other clients for Subversion are also &lt;a href="http://subversion.tigris.org/links.html#clients"&gt;available&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you only have a limited number of users, and do not need remote access, you can use Tortoise without a subversion server.  This makes set-up much easier.  I am not going to cover setting up the server here, primarily because I haven't used one for 3 years.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;My file structure&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I have 2 base folders, D:\dev and d:\devother.&lt;br /&gt;&lt;br /&gt;D:\devother\ is used for files that are use different version control settings (ie open source projects that I update from their repository such as tiopf).&lt;br /&gt;D:\dev\ is used for everything else; my code, third party components, images etc.  Having everything under one folder makes version control easier.&lt;br /&gt;&lt;br /&gt;I recommend moving all source under a single base folder, if it is not already. If you have source on a network share, move it into a base folder on a local drive.  If you need to share source, place the repository on a shared folder.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Repository&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The repository is where the versions are stored.  It has a directory structure similar to a file structure.&lt;br /&gt;&lt;br /&gt;The subversion book recommends having the following directories at the repository root&lt;br /&gt;&lt;br /&gt;/branches/&lt;br /&gt;/trunk/&lt;br /&gt;/tags/&lt;br /&gt;&lt;br /&gt;With this layout, your main development takes place under /truck/.  Branches and tags go where you would expect.  I don't do a lot of branching and tagging, when I do I place the branch directories along side the main project directories instead.  Therefore I don't bother with the initial directories and create branch directories as required.&lt;br /&gt;&lt;br /&gt;My layout is more like&lt;br /&gt;&lt;br /&gt;/components/&lt;br /&gt;...&lt;br /&gt;/projects/&lt;br /&gt;/projects/project 1 v1/&lt;br /&gt;/projects/project 1 v2/&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;This maps to my file structure of&lt;br /&gt;&lt;br /&gt;d:\dev\&lt;br /&gt;d:\dev\components\&lt;br /&gt;...&lt;br /&gt;d:\dev\projects&lt;br /&gt;d:\dev\projects\project 1 v1\&lt;br /&gt;d:\dev\projects\project 1 v2\&lt;br /&gt;...&lt;br /&gt;etc&lt;br /&gt;&lt;br /&gt;It is reasonably easy to change from one repository layout to another if you change your mind, so choose whichever structure makes sense to you..&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Setup&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download and install Tortoise from &lt;a href="http://tortoisesvn.net/downloads"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Open Windows Explorer&lt;/li&gt;&lt;li&gt;Create an empty folder to serve as your repository.  This can be local or on a network drive.  The location needs to be reasonably safe and easy to back up. &lt;/li&gt;&lt;li&gt;Right click on the folder and click on "Create repository here"&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_g2tNCh4si2M/SIAh2cRH-2I/AAAAAAAAAEw/A7RgEYBDV9Q/s1600-h/1+Create+repository.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_g2tNCh4si2M/SIAh2cRH-2I/AAAAAAAAAEw/A7RgEYBDV9Q/s320/1+Create+repository.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212786934446946" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Choose "Native filesystem"&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_g2tNCh4si2M/SIAhsfVjUsI/AAAAAAAAAEI/iAlZAWCKVLU/s1600-h/2+file+system.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_g2tNCh4si2M/SIAhsfVjUsI/AAAAAAAAAEI/iAlZAWCKVLU/s320/2+file+system.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212615959630530" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;If you want to set up /branches/, /tags/ and /truck/ directories, right click on your repository folder and choose TortoiseSvn -&gt; Repo-browser.  Right click on the root directory and choose "Create Folder" for each of the initial directories.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Right click on any folder and choose TortoiseSvn -&gt; Settings&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_g2tNCh4si2M/SIAhs67izxI/AAAAAAAAAEY/76DA_DbBumU/s1600-h/4+settings.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_g2tNCh4si2M/SIAhs67izxI/AAAAAAAAAEY/76DA_DbBumU/s320/4+settings.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212623366737682" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;In the Global ignore patterns, enter in the file types that should be ignored by default.  Ie things like map files that will (almost) never need to be under version control.  I use "*.dcu *.~* dcu temp *.exe *.zip *.bkm *.ddp *.cfg *.dof *.dsk *.ini *.hlp *.gid *.bmp *.png *.gif ~* *.log bin debug release *.map *.chm *.bkf Thumbs.db *.mdb .obj *.elf *.stat *.ddp *.bpl *.map *.GID *.hlp *.opt *.dll *.raw *.BIN *.obj *.pdb *.scc Debug Release *.xml obj *.~* *.backup *.INI *.ArmLog *.KeyLog *.NanoLog *.Stats *.PreARM *.old *.drc *.*~ *.doc *.pdf *.bmp *.jpg *.MRW *.NEF *.ORF *.psd  *.X3F __history *.local *.identcache *.bak Thumbs.db *.ldb *.dex *.rar DllDcu *.lck CVS cvs *.txt *.TXT *.jdbg *.HLP *.KWF *.xls *.cnt *.dsm *.dti *.tmp *.lnk *.cbk *.mes"&lt;br /&gt;Note that the patterns are case sensitive.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_g2tNCh4si2M/SIAhtALlAdI/AAAAAAAAAEg/XQr-pqgNUgI/s1600-h/5+global+ignores.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_g2tNCh4si2M/SIAhtALlAdI/AAAAAAAAAEg/XQr-pqgNUgI/s320/5+global+ignores.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212624776167890" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Initial Import&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Back up your source code!&lt;/li&gt;&lt;li&gt;Right click on your base development folder (I use d:\dev\) and click on "SVN Checkout"&lt;/li&gt;&lt;li&gt;Click on the browse button beside URL and navigate to the repository directory (if you have set up a /trunk/ directory, navigate to this).&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_g2tNCh4si2M/SIAhs_7g8KI/AAAAAAAAAEQ/Azi2Z7hP5m8/s1600-h/3+checkout.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_g2tNCh4si2M/SIAhs_7g8KI/AAAAAAAAAEQ/Azi2Z7hP5m8/s320/3+checkout.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212624708792482" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Right click on your base development folder (d:\dev\ in my case) and choose TortoiseSVN-&gt;Add.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_g2tNCh4si2M/SIAhtUY9YqI/AAAAAAAAAEo/CZzQw4w6a44/s1600-h/6+Add.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_g2tNCh4si2M/SIAhtUY9YqI/AAAAAAAAAEo/CZzQw4w6a44/s320/6+Add.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212630201000610" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Wait for the Add dialog to populate.  The first time it is used, it can take a while to populate.  Work your way down the file/folder list.&lt;br /&gt;If there is something you don't want to add now, uncheck the selection box.&lt;br /&gt;If you never want to add it, right click on the item and choose "Add to ignore list"&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_g2tNCh4si2M/SIAhjUCzWTI/AAAAAAAAADg/g5FfNRM0WP0/s1600-h/7+add+to+ignore+list.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_g2tNCh4si2M/SIAhjUCzWTI/AAAAAAAAADg/g5FfNRM0WP0/s320/7+add+to+ignore+list.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212458309376306" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Once you are happy with the selected files and folders, click OK.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_g2tNCh4si2M/SIAhjTNoJcI/AAAAAAAAADo/rw7fjjWbiOw/s1600-h/8+adding.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_g2tNCh4si2M/SIAhjTNoJcI/AAAAAAAAADo/rw7fjjWbiOw/s320/8+adding.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212458086344130" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The files are now all added to version control.  However they have not yet been saved (committed).&lt;/li&gt;&lt;li&gt;Right click on the base development folder again and choose Commit.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_g2tNCh4si2M/SIAhjvHcQ_I/AAAAAAAAADw/Hdhmc5pWJrE/s1600-h/9+commit.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_g2tNCh4si2M/SIAhjvHcQ_I/AAAAAAAAADw/Hdhmc5pWJrE/s320/9+commit.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212465576592370" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Provide a message.  &lt;/li&gt;&lt;li&gt;Uncheck any files you don't want to commit at the moment and click OK.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_g2tNCh4si2M/SIAhjopJvKI/AAAAAAAAAD4/LnDC6jdkBH0/s1600-h/a+commit+diag.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_g2tNCh4si2M/SIAhjopJvKI/AAAAAAAAAD4/LnDC6jdkBH0/s320/a+commit+diag.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212463838936226" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Your files are now under version control.  You can revert to any version, perform diffs, see what files are changed and perform all other sorts of good things.&lt;br /&gt;&lt;br /&gt;Version controlled files are marked to indicate their status.  A full list is given &lt;a href="http://tortoisesvn.tigris.org/ExplorerIntegration.html#overlays"&gt;here&lt;/a&gt;. The main ones are&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Committed: Check mark&lt;/li&gt;&lt;li&gt;Added: +&lt;/li&gt;&lt;li&gt;Changed: !&lt;/li&gt;&lt;li&gt;Deleted: x&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_g2tNCh4si2M/SIAhj41JLmI/AAAAAAAAAEA/-nDekJwuc6o/s1600-h/b+icons.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_g2tNCh4si2M/SIAhj41JLmI/AAAAAAAAAEA/-nDekJwuc6o/s320/b+icons.jpg" alt="" id="BLOGGER_PHOTO_ID_5224212468184198754" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;To come&lt;/span&gt;&lt;br /&gt;I will do followup posts explaining&lt;br /&gt;&lt;ul&gt;&lt;li&gt;How to work with files on an ogoing basis&lt;/li&gt;&lt;li&gt;Various delphi integration options&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Links&lt;/span&gt;&lt;br /&gt;Subversion           &lt;a href="http://subversion.tigris.org/"&gt;http://subversion.tigris.org/&lt;/a&gt;&lt;br /&gt;Subversion book  &lt;a href="http://svnbook.red-bean.com/"&gt;http://svnbook.red-bean.com/&lt;/a&gt;&lt;br /&gt;Tortoise                &lt;a href="http://tortoisesvn.tigris.org/"&gt;http://tortoisesvn.tigris.org/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-2997035135586733179?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/2997035135586733179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=2997035135586733179' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/2997035135586733179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/2997035135586733179'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/07/starting-out-with-delphi-and-subversion.html' title='Starting out with Delphi and subversion'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_g2tNCh4si2M/SIAh2cRH-2I/AAAAAAAAAEw/A7RgEYBDV9Q/s72-c/1+Create+repository.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-838133429563114251</id><published>2008-06-21T09:29:00.003+12:00</published><updated>2008-06-21T12:16:46.180+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='tiopf'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>ti Object persistance framework updated</title><content type='html'>&lt;span style="font-weight: bold;"&gt;What's up?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;v2.50 of tiOPF is now available at http://tiopf.sourceforge.net/&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;So what's tiOPF?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;tiOPF is a Object Persistence Framework. That is, it is a framework based around saving your objects to, and loading them from, databases and/or flat files.  See the &lt;a href="http://tiopf.sourceforge.net/Doc/overview/index.shtml"&gt;overview&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;In a nutshell it lets you do things like:&lt;br /&gt;&lt;br /&gt;var&lt;br /&gt;  user: TMyuser;&lt;br /&gt;  userList: TUserList;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;  user:= Tuser.CreateNew;&lt;br /&gt;  user.FirstName:= 'Sean';&lt;br /&gt;  user.LastName:= 'cross';&lt;br /&gt;&lt;br /&gt;  user.Save;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;  userList:= TUserList.Create;&lt;br /&gt;  userList.Load;&lt;br /&gt;&lt;br /&gt;  for user in userList do&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;tiOPF handles the saving and loading of objects to databases and flat files.  You can swap between databases by initialising a new persistence layer.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Why should I care?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;tiOPF lets you code in objects rather than datasets (you can still use data aware controls though).  This gives you more object orientated code&lt;/li&gt;&lt;li&gt;tiOPF provides database independance&lt;/li&gt;&lt;li&gt;Better code reuse.  Because the persistance is separated out, you can use the same code across different databases and structures&lt;/li&gt;&lt;li&gt;Easier unit testing (in my experience anyway).  I find it much easier to setup objects and test them that to setup databases and test.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Links&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Home page:    &lt;a href="http://tiopf.sourceforge.net/"&gt;http://tiopf.sourceforge.net/&lt;/a&gt;&lt;br /&gt;Overview:      &lt;a href="http://tiopf.sourceforge.net/Doc/overview/index.shtml"&gt;http://tiopf.sourceforge.net/Doc/overview/index.shtml&lt;/a&gt;&lt;br /&gt;Newsgroups:  &lt;a href="http://tiopf.sourceforge.net/Support.shtml"&gt;http://tiopf.sourceforge.net/Support.shtml&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-838133429563114251?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/838133429563114251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=838133429563114251' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/838133429563114251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/838133429563114251'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/06/ti-object-persistance-framework-updated.html' title='ti Object persistance framework updated'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-5931460380729837463</id><published>2008-06-12T14:35:00.004+12:00</published><updated>2008-06-13T07:19:17.801+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>" Connection is busy with results for another hstmt"</title><content type='html'>One of the problems with working on the same program for years, is that you always end up paying for your sins.  In my case the sin in question is still using the bde and odbc.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.google.com/search?q=+Connection+is+busy+with+results+for+another+hstmt&amp;amp;ie=utf-8&amp;amp;oe=utf-8&amp;amp;aq=t&amp;amp;rls=org.mozilla:en-GB:official&amp;amp;client=firefox-a"&gt;"&lt;/a&gt;&lt;span id="thread_subject_site"&gt;&lt;a href="http://www.google.com/search?q=+Connection+is+busy+with+results+for+another+hstmt&amp;amp;ie=utf-8&amp;amp;oe=utf-8&amp;amp;aq=t&amp;amp;rls=org.mozilla:en-GB:official&amp;amp;client=firefox-a"&gt;Connection is busy with results for another hstmt"&lt;/a&gt; is a common error when connecting to ODBC databases.  It occurs because an OBDC connection can only have one active cursor at a time.  By default, odbc only retrieves the first 20 records for a query.  If the query contains more than 20 records, the rest are retrieved on demand.  That's all very well, but when you open a second query using same connection/session you get the dreaded hstmt error.&lt;br /&gt;&lt;br /&gt;I thought I had beaten it years ago, but my latest set of changes have resulted in the error reappearing.&lt;br /&gt;&lt;br /&gt;There are a few possible solutions to this error:&lt;br /&gt;&lt;/span&gt;&lt;ol&gt;&lt;li&gt;&lt;span id="thread_subject_site"&gt;Use TTable components.  These don't have the error as they open a new connection each time.  Not a very pretty solution :(&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span id="thread_subject_site"&gt;Put a FetchAll after each Open.  This forces the retrieval of all records.  Not practical in my case as I have around 250 tquery components to check.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span id="thread_subject_site"&gt;Use multiple connections.  Also not practical for me.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span id="thread_subject_site"&gt;Replace the BDE with something else that doesn't have the problem.  In progress but...&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span id="thread_subject_site"&gt;Cheat.  Set the odbc rowset size to a larger number.  If you set it to 200, then the first 200 records will be returned.  If you set it to -1 then ALL records will be returned.  This could have dire effects on performance if your queries return a lot of records.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;This time round I &lt;a href="http://groups.google.co.nz/group/borland.public.delphi.database.sqlservers/browse_thread/thread/962f220a8f7c3d08/9f2250500da34f5e?lnk=st&amp;amp;q=delphi+bde+hstmt+fetchall#9f2250500da34f5e"&gt;discovered&lt;/a&gt;, and went with option 5.&lt;br /&gt;&lt;br /&gt;To set the rowset size with the BDE, do the following:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Click on your TDatabase component&lt;/li&gt;&lt;li&gt;In the object inspector, expand Params&lt;/li&gt;&lt;li&gt;Put in a Key of "ROWSET SIZE"&lt;/li&gt;&lt;li&gt;Put in the desired value&lt;/li&gt;&lt;/ol&gt;Changing the rowset size should work with other odbc connection components as well.&lt;br /&gt;&lt;span id="thread_subject_site"&gt;&lt;br /&gt;Update:  As Otto has pointed out, the error can also be resolved, if you are using sql server 2005 or later, by using the SQL Native Client drivers.  See &lt;a href="http://msdn.microsoft.com/en-us/library/ms345109.aspx"&gt;Multiple Active Record Sets&lt;/a&gt; for more details.  Doesn't help me though :(&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-5931460380729837463?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/5931460380729837463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=5931460380729837463' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/5931460380729837463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/5931460380729837463'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/06/connection-is-busy-with-results-for.html' title='&quot; Connection is busy with results for another hstmt&quot;'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-4915212885804980666</id><published>2008-06-08T20:41:00.006+12:00</published><updated>2008-06-08T21:40:35.548+12:00</updated><title type='text'>Coverflow update</title><content type='html'>&lt;span style="font-weight: bold;"&gt;TMS GUIMotions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;TMS Software have released their 3d animation component, GUIMotions.  It includes a number of animations including a coverflow effect.  More info is available &lt;a href="http://www.tmssoftware.com/site/guimotions.asp"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;My GLScene example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I have updated my coverflow example.  I have included mirroring, multiple rows, vertical layout and a few other changes making easier to be reused.  I have also shown how to use standard vcl controls.&lt;br /&gt;&lt;br /&gt;You can download the latest version from &lt;a href="http://www.sourceitsoftware.com/download/delphi/CoverTest.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_g2tNCh4si2M/SEugrOIe2hI/AAAAAAAAABo/MBKAU3qGLqg/s1600-h/WithControl.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_g2tNCh4si2M/SEugrOIe2hI/AAAAAAAAABo/MBKAU3qGLqg/s320/WithControl.jpg" alt="" id="BLOGGER_PHOTO_ID_5209434058372602386" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Using an editable  TMemo control&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_g2tNCh4si2M/SEukc_i5FwI/AAAAAAAAACA/MdFXCvh24jk/s1600-h/Trans.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_g2tNCh4si2M/SEukc_i5FwI/AAAAAAAAACA/MdFXCvh24jk/s320/Trans.jpg" alt="" id="BLOGGER_PHOTO_ID_5209438211985184514" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;2x2, Transitioning from horizontal to vertical layout&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_g2tNCh4si2M/SEuiDdhnayI/AAAAAAAAAB4/dfjgwp2s77o/s1600-h/Vertical.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_g2tNCh4si2M/SEuiDdhnayI/AAAAAAAAAB4/dfjgwp2s77o/s320/Vertical.jpg" alt="" id="BLOGGER_PHOTO_ID_5209435574333041442" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Vertical layout, 2 across&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_g2tNCh4si2M/SEuiDLRWY4I/AAAAAAAAABw/8uFeigh2e68/s1600-h/Dual.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_g2tNCh4si2M/SEuiDLRWY4I/AAAAAAAAABw/8uFeigh2e68/s320/Dual.jpg" alt="" id="BLOGGER_PHOTO_ID_5209435569432978306" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Horizontal layout 2 across&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Links&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.tmssoftware.com/site/guimotions.asp"&gt;GuiMotions&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.sourceitsoftware.com/download/delphi/CoverTest.zip"&gt;GLScene coverflow demo&lt;/a&gt;&lt;br /&gt;&lt;a href="http://glscene.sourceforge.net/wikka/HomePage"&gt;GLScene&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-4915212885804980666?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/4915212885804980666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=4915212885804980666' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4915212885804980666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4915212885804980666'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/06/coverflow-update.html' title='Coverflow update'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_g2tNCh4si2M/SEugrOIe2hI/AAAAAAAAABo/MBKAU3qGLqg/s72-c/WithControl.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7028181408582795486.post-4462518182921163951</id><published>2008-05-16T09:24:00.010+12:00</published><updated>2008-05-30T23:03:01.168+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi'/><title type='text'>Coverflow example using Delphi and GLScene</title><content type='html'>Problem&lt;br /&gt;I am beginning work on &lt;a href="http://www.picsprint.com/"&gt;Pics Print 4&lt;/a&gt;.  One of the things I want to do with this release is make it significantly more slick.  To that end, I thought "Coverflow".  See &lt;a href="http://flashloaded.com/flashcomponents/photoflow/example1.html"&gt;here&lt;/a&gt; for an example&lt;br /&gt;&lt;br /&gt;The trouble is that there is not that much in the way of delphi examples.  I did find "Flying Cow", which is a Delphi implementation using OpenGl.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Flying Cow&lt;/span&gt;&lt;br /&gt;Flying Cow is a clone of Cover Flow written by Matías Andrés Moreno (&lt;a href="http://www.matiasmoreno.com.ar/"&gt;http://www.matiasmoreno.com.ar/&lt;/a&gt; website currently down)&lt;br /&gt;&lt;br /&gt;Changes to make Flying Cow compile under D2007, and download links, are listed in &lt;a href="http://www.aqua-soft.org/board/showthread.php?t=46566"&gt;http://www.aqua-soft.org/board/showthread.php?t=46566&lt;/a&gt; (website currently down as well)&lt;br /&gt;&lt;br /&gt;Flying Cow looks quite nice.  However it has one huge drawback from my point of view, it uses the GPL and is therefore unsuitable for my use.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_g2tNCh4si2M/SCyt6OrK25I/AAAAAAAAAA4/xyu2vjX8q6U/s1600-h/Coverflow.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_g2tNCh4si2M/SCyt6OrK25I/AAAAAAAAAA4/xyu2vjX8q6U/s400/Coverflow.jpg" alt="" id="BLOGGER_PHOTO_ID_5200722885589261202" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Flying Cow implementation&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GLScene implimentation&lt;/span&gt;&lt;br /&gt;I have created my own version using &lt;a href="http://glscene.sourceforge.net/wikka/HomePage"&gt;GLScene&lt;/a&gt;.  Considering that I haven't done any 3d work since 2005 (on a pda using C++ at that), it was remarkably easy to get going without cracking open my OpenGL books.&lt;br /&gt;&lt;br /&gt;Here is the result:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_g2tNCh4si2M/SCy2XerK27I/AAAAAAAAABI/Jl1SKpSJibs/s1600-h/CoverTest1.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_g2tNCh4si2M/SCy2XerK27I/AAAAAAAAABI/Jl1SKpSJibs/s320/CoverTest1.jpg" alt="" id="BLOGGER_PHOTO_ID_5200732184193457074" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Basic layout&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_g2tNCh4si2M/SCy2lurK28I/AAAAAAAAABQ/A5L1hban5Fg/s1600-h/CoverTest2.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_g2tNCh4si2M/SCy2lurK28I/AAAAAAAAABQ/A5L1hban5Fg/s320/CoverTest2.jpg" alt="" id="BLOGGER_PHOTO_ID_5200732429006592962" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Showing 2 images across, and using transparency on mouseover to show hidden images.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_g2tNCh4si2M/SCzsjurK29I/AAAAAAAAABY/rxFKXrmhLcY/s1600-h/CoverTest1.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_g2tNCh4si2M/SCzsjurK29I/AAAAAAAAABY/rxFKXrmhLcY/s320/CoverTest1.jpg" alt="" id="BLOGGER_PHOTO_ID_5200791768274754514" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Now with added mirroring goodness&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_g2tNCh4si2M/SD_cHr5-V3I/AAAAAAAAABg/L5obLTsumXQ/s1600-h/2x2.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_g2tNCh4si2M/SD_cHr5-V3I/AAAAAAAAABg/L5obLTsumXQ/s320/2x2.jpg" alt="" id="BLOGGER_PHOTO_ID_5206121718866663282" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;Now with vertical layout, showing 2 across and 2 down&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;You can download my source and the executable from &lt;a href="http://www.sourceitsoftware.com/download/delphi/CoverTest.zip"&gt;here&lt;/a&gt;.  It is written in D2007 but should be easily portable to earlier version (there may be a for ... in loop or two but that is about it).&lt;br /&gt;&lt;br /&gt;This is prototype code, not production code so be warned.  I take no responsibility if it eats your homework, backchats your mother-in-law or transfers all your money into my bank account.  On the plus side, it has a promiscuous license so you can use it in your own apps without problems.&lt;br /&gt;&lt;br /&gt;If you make any improvements, let me know and I will update source accordingly.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Update&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Mirroring added&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update 2 - May 30&lt;/span&gt;&lt;br /&gt;Code changed to use an object list instead of an array, removed Graphics32, given optional vertical layout, allows multiple rows, and demonstrates removing pages.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Links&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Javascript implimentation&lt;br /&gt;&lt;a href="http://flashloaded.com/flashcomponents/photoflow/example1.html"&gt;http://flashloaded.com/flashcomponents/photoflow/example1.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Flying cow  discussion thread&lt;br /&gt;&lt;a href="http://www.aqua-soft.org/board/showthread.php?t=46566"&gt;http://www.aqua-soft.org/board/showthread.php?t=46566&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;GLScene&lt;br /&gt;&lt;a href="http://glscene.sourceforge.net/wikka/HomePage"&gt;http://glscene.sourceforge.net/wikka/HomePage&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My version&lt;br /&gt;&lt;a href="http://www.sourceitsoftware.com/download/delphi/CoverTest.zip"&gt;http://www.sourceitsoftware.com/download/delphi/CoverTest.zip&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7028181408582795486-4462518182921163951?l=sourceitsoftware.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sourceitsoftware.blogspot.com/feeds/4462518182921163951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7028181408582795486&amp;postID=4462518182921163951' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4462518182921163951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7028181408582795486/posts/default/4462518182921163951'/><link rel='alternate' type='text/html' href='http://sourceitsoftware.blogspot.com/2008/05/coverflow-example-using-delphi-and.html' title='Coverflow example using Delphi and GLScene'/><author><name>Sean</name><uri>http://www.blogger.com/profile/09419639577416328173</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00721929486418285615'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_g2tNCh4si2M/SCyt6OrK25I/AAAAAAAAAA4/xyu2vjX8q6U/s72-c/Coverflow.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry></feed>