In the past, kdelibs has only officially provided date formatting methods that supported the locale short and long date formats. A number of apps found this rather restrictive and had to work around it with code like:
KLocale tmpLocale(*KGlobal::locale()); tmpLocale.setDateFormat("%d %b %Y"); QString dateString = tmpLocale.formatDate(aDate);
or worse like:
KLocale tmpLocale(*KGlobal::locale()); tmpLocale.setDateFormat("%d"); QString day = tmpLocale.formatDate(aDate); tmpLocale.setDateFormat("%b"); QString month = tmpLocale.formatDate(aDate); tmpLocale.setDateFormat("%Y"); QString year = tmpLocale.formatDate(aDate); QString text = i18nc("long day number, short month name, long year number", "blah %1 blah %2 blah %3", day, month, year);
or worst of all like:
const QString oldDateFormat = KGlobal::locale()->dateFormat(); KGlobal::locale()->setDateFormat("%Y %m %d"); QString dateString = KGlobal::locale()->formatDate(aDate); KGlobal::locale()->setDateFormat(oldDateFormat);
(Messing with the global locale is a big no-no, no matter how briefly! Code disguised to protect the guilty :-)
Well, in 4.4 your code can become a little simpler with native support for ISO date formats, more date component string methods, and a new formatDate() method that directly takes a C/POSIX/GNU standard format string without having to mess with a temp KLocale instance. This gives a great degree of power over date formatting, but like the saying goes, with great power comes great responsibility, so please use with care and follow a few simple rules.
So what's changed, and how to use it?
The ISO standard date formats ISO Date (YYYY-MM-DD), ISO Week Date (YYYY-Www-D), and ISO Ordinal Date (YYY-DDD) have become first class citizens alongside the locale/user configurable Short, Long, and Fancy formats. Use these whenever you want an ISO or RFC standard format date in the locale's Digit Set and Calendar System.
To output an ISO format date:
QDate testDate; KGlobal::locale()->calendar()->setDate(testDate, 2009, 12, 1); QString stringDate; stringDate = KGlobal::locale()->formatDate(testDate, KLocale::IsoDate); // "2009-12-01" stringDate = KGlobal::locale()->formatDate(testDate, KLocale::IsoWeekDate); // "2009-W49-2" stringDate = KGlobal::locale()->formatDate(testDate, KLocale::IsoOrdinalDate); // "2009-335"
To read in an ISO format date from a string:
testDate = KGlobal::locale()->readDate("2009-12-01", KLocale::IsoFormat); testDate = KGlobal::locale()->readDate("2009-W49-2", KLocale::IsoWeekFormat); testDate = KGlobal::locale()->readDate("2009-335", KLocale::IsoOrdinalFormat);
To directly set a date using the ISO Week and Ordinal dates:
KGlobal::locale()->calendar()->setDateIsoWeek(testDate, 2009, 49, 2); // Year, Week, Weekday KGlobal::locale()->calendar()->setDate(testDate, 2009, 335); // Year, Day of Year
To validate a ISO Week or Ordinal date:
KGlobal::locale()->calendar()->isValidIsoWeek(2009, 49, 2); // Year, Week, Weekday KGlobal::locale()->calendar()->isValid(2009, 335); // Year, Day of Year
The existing readDate() format string method has also been extended to read the ISO Week and Ordinal date components in any order or format:
testDate = KGlobal::locale()->readDate("Day 2 of Week 49, 2009", "Day %u of Week %V, %Y"); testDate = KGlobal::locale()->readDate("335/2009", "%j/%Y");
Note that historically readDate() is not strict in applying the format string and will make best efforts to interpret the users input while obeying the input order, i.e. extra spaces are ignored, if the format string has long month it will accept the short month if entered instead, and vice versa. I might implement a strict mode if there is demand.
If you just need a single date component as a string, such as day number or month name, in long or short format, then simply use the appropriate existing or new string method which will return the component in the users Calendar System and Language or Digit Set:
monthName() weekDayName() yearString() monthString() dayString() dayOfYearString() // New dayOfWeekString() // New weekNumberString() // New monthsInYearString() // New weeksInYearString() // New daysInYearString() // New daysInMonthString() // New daysInWeekString() // New
To output a single date component:
stringDate = KGlobal::locale()->calendar()->monthName(testDate, KCalendarSystem::ShortName); // "Dec" stringDate = KGlobal::locale()->calendar()->monthName(testDate, KCalendarSystem::LongName); // "December" stringDate = KGlobal::locale()->calendar()->dayString(testDate, KCalendarSystem::ShortFormat); // "1" stringDate = KGlobal::locale()->calendar()->dayString(testDate, KCalendarSystem::LongFormat); // "01"
Only if none of these options will meet your requirements should you use the new KCalendarSystem::dateFormat() routine. Please read the extensive apidox for all the options available, but it supports most of the C / POSIX standard component codes as well as the GNU extensions for modifying the padding character and the padding width. Note that a couple of the historic KDE format codes differ from the C/POSIX standard, in future I may add a fully compatible mode.
In use you should almost always translate the format string and include the kdedt-format keyword in the context:
QDate reportDate; KGlobal::locale()->calendar()->setDate(reportDate, reportYear, reportMonth, 1); dateFormat = i18nc("(kdedt-format) Report month and year in report header", "%B %Y")); dateString = KGlobal::locale()->calendar()->formatDate(reportDate, dateFormat);
If you have to write dates to file or wire in a standard interchange format that always requires requires Gregorian and Arabic digits, then the easiest solution is to use QDate directly:
QString standardDateString = QDate.toString(Qt::ISODate); or QString standardDateString = QDate.toString("yyyy-MM-dd");
Alternatively, use the temp KLocale trick, but be very careful about just copying the global locale to start with, it's probably better to create a default one from scratch:
KLocale *standardLocale = new KLocale(yourCatalog, "en_US", "us"); standardLocale->setDateFormat("%a, %d %b %Y"); standardLocale->setDateFormatShort("%Y-%m-%d");
Note that reading in numbers and dates in any Digit Set is seamless, it's just writing them out you need to think about.
In general, if you write dates and numbers to file or wire, you may want to write unit tests to check your code still works with an alternative Digit Set and Calendar System set in the global locale. If you use KMime's DateFormatter class for ISO and RFC dates then you should be OK.
The sharp-witted out there would have two thoughts going through their mind about the plea to always translate your date format strings:
Well, we did look at using enums, but there were just too many variables to make it work simply without giving the translators hundreds of pre-defined strings to do, and it still wouldn't meet all the use case (see the reviewboard). In the end it is better to trust people and encourage them to use the tools properly than to try impose restrictions they will just work-round anyway. And yes, it is a poor heuristic, but it affects fewer people than not translating at all. For 4.5 I am looking into a scheme to fully define the different rule sets for date formatting (e.g. American, International, European, ISO, Japanese, etc) and include these in each locale file to allow fully automatic construction of the format strings from enums with no pre- or post-translation required, but I'm not convinced it's possible or worth the effort for the few use cases we have so far.
I'll copy most of this onto TechBase for future reference.
Another update on the Calendar Systems. Last time I mentioned I was moving onto the Bahai'i calendar. Well, that proved to have some problems (see below) so I moved on to something easier, the Ethiopian and Coptic calendars which will be 4.4. These are nice, straightforward calendars based on the ancient Egyptian calendar. These have 12 months of 30 days followed by a separate epagomenal period (effectively a short 13th month) of 5 days or 6 days in leap years which are every 4 years, which makes the whole calculation very simple indeed.
The only differences between the Ethiopian and Coptic calendars are the epoch and the names of the months and weekdays, so it's effectively a two-for-one deal. The hardest part was finding the right English versions of the Coptic and Ge'ez names, which I hope I've got right as there were several versions to choose from (quick apologies to the translators for forgetting to give them a heads-up on the tricky strings involved). I don't know what the FOSS market-share is in the Ethiopian or Coptic communities (Google doesn't reveal anything much), and we don't have a Ethiopian translation project, but it's one less barrier they might have to negotiate in the future. It's highly unlikely we will ever have a Coptic translation with only 300 speakers worldwide, but the calendar itself has a wider use.
Pics of the Ethiopian and Coptic calendars, notice the short epagomenal period showing in the Coptic one.
Funnily, while OSX has locale support for different calendar systems including both Coptic and Ethiopian, Apple's own app programmers don't seem to have got the memo, spot the bugs in iCal:
One bug we did have that I've fixed for 4.4 is RTL support in the Plasma calendar table:
The Bahai'i calendar proved harder than I expected. It's interesting as it has 19 months of 19 days each, and a separate epagomenal period of 4 or 5 days. That would be easy enough, except the epagomenal days are not at the start or end of the year, they are placed between the 18th and 19th months and in practice appear to be written down as month 0. So how do we do that? We could just label the epagomenal days as month 19 and month 19 as 20, which is good maths but bad usability, as would treating the epagomenal days as part of the 18th month. It seems there's going to have to be some magic going on between the user interface and the actual calculations, but that could mean every widget that shows/reads dates will need rewriting to know what to do. Nope, that's out too. In emacs they treat them as prefixing the 19th month, so are entered as negative days in the 19th month, i.e. -03/19/2009, which would break all our existing validation and formatting code. Which is about when I gave up and moved on to something easier :-)
In the comments on my last blog, someone mentioned that supporting the Japanese Emperor Era calendar should be easy as it is just the Gregorian Calendar but with the year instead of being counted since the nominal birth of Christ (i.e. AD) being the number of years into an Emperors reign. If only it were that easy :-) The big problem is that everything in KCalendarSystem assumes an 'absolute' year' in a continuous integer range from -9999 to 9999 (with an optional year 0), we make no allowance for the entry or display of an era for the year to start counting from, nor does the C/POSIX format codes have a value for era. Supporting Era style calendars would require adding new virtual methods to the API for era() and eraYear(), code to convert between era years and absolute years, and changes to the date reading and formatting code to do the translation. That's a problem, as the KCalendarSystem base class has no virtual table slots left to add new API. There's ways around that, but it's going to take careful planning.
Finally, I've started planning for the lunar calendars in 4.5 by purchasing a copy of the bible of astronomical calculations which has special chapters devoted to calendars. I need to determine exactly what calculations we need to be able to perform, and how complex they are to implement and support. If they're relatively few and simple, then we can have our own or borrowed implementations directly in kdelibs, if not we need to either find existing implementations to (optionally) depend upon, or work with another project for them to support. Possible sources of code include KStars, the Plasma sunrise/sunset data engine, or libnova (which KStars already uses). Possible new homes could be a version of Marble in kdesupport (if that ever happens?), a separate library in kdesupport, or an outside project like libnova.
It's that time of the year again when the openSUSE RC's are hitting the net and I can enjoy a fresh re-install. This time round, I also had a fresh new copy of OS X Snow Leopard to upgrade to (no, I will NOT be upgrading my XP install to Win7 as well). The plan was just to upgrade in place, but my GPT partition table was somehow corrupted and Snow Leopard was throwing a fit refusing to recognise the partition (funny, openSUSE had no such problems) so I was forced to fully wipe the drive. This meant actually having to back stuff up (yes, I know...), and having no space left on my 5 other external drives (700Gb) I bought myself a new 2Tb external drive for the purpose. 2Tb. On my desk. Just sitting there not much bigger than a paperback. Man, I still remember my first ever hard drive, all of 20Mb that was, shoe-horned into my Amiga 1200. I remember my work sending me on a training course in the mid-90's for Teradata databases (special parallel hardware required!) and wondering what could possibly need that much storage. Fifteen years later I now know :-) Anyway, enough of the past: Snow Leopard purred on nicely albeit rather slower than openSUSE which took almost no time at all. Windows, well I'm not in a mood for that re-install re-boot hell quite yet...
openSUSE looks really slick, and does run a lot faster and smoother than 11.1 (but that could just have been my messed up GPT and all the residual crud from messing with stuff). The guys have done a brilliant job with this release. Where I'm disappointed once again is in the out-of-box hardware support for my Macbook which still falls short with few of the problems from 11.1 having been solved. I'm still investigating if this is a universal Linux thing or just openSUSE not configuring stuff right. The touchpad is not configured correctly (no right-click, let alone multi-touch), there's no keyboard lights, and the screen dimming appears to still only work via nvclock. Sound now works without messing with config settings, but the heaphone socket still doesn't cut the speakers. My biggest annoyance so far is that X doesn't correctly detect the Macbook's UK keyboard or my external Mac UK keyboard. Instead, I have to run sax2 and hit cancel and I get the right keymap again (at least until the next reboot, I don't want to click save as it screws up my dual monitor setup). I'm sure I'll be able to tweak the settings to get it all working eventually, but it's just annoying when I have better things to do with my time. Perhaps I need to gift one to the openSUSE team to play with? Just kidding, I can't afford that right now, maybe next hardware upgrade :-) As usual, I'll update the openSUSE on Macbook wiki page with my results. I've already cleaned up my general Linux/openSUSE on Mac notes which includes good info on partitioning and how to triple-boot Linux/OSX/Windows.
I haven't had much time to mess with Snow Leopard yet, but I did take a quick peek at the localisation options, and it looks like Apple have also been upgrading their Calendar System support by adding Coptic, Ethiopic, Indian National, Persian and Chinese. So, game on Mr Jobs :-)
As part of my current localisation obsession, I've decided to pickup on an old wish list item to add support for the ISO 4217 Currency Code standard to KLocale. Currently applications such as KSpread, KMyMoney, Skrooge, Kraft, KEuroCalc, and several Plasma currency converter widgets all have to maintain their own lists of codes and translations, which seems unnecessary duplication to me. I've posted a design on TechBase and an implementation on Review Board for people to have a look at, so if you work on one of the financial apps that might use this then please have a look and comment (I tried e-mailing everyone, but I've got some bounces).
One thing I learned that I never knew before (besides lots of esotoric facts about currencies like there are only two non-decimal currencies left) was that some countries group their digits in different size groups than thousands. In India for example, they group their digits in groups of two except for the smallest group which is a group of three, i.e. 00 00 00 000 instead of 000 000 000. In China and Japan they use groups of four. POSIX already has a format definition for this in LC_NUMERIC and LC_MONEY so Gnome probably supports it, and Windows supports it, so I guess that's another item on my TODO list :-)
ISO 4217 Currency Code standard
The other hat I wear around these parts besides Printing is Calendar Systems (just don't ask how I got interested, a long story...), and I've found a bit of time to put some more work into them, as well as the plasma Calendar and Clock widgets.
I've posted previously about giving the plasma Calendar and Clock widgets the ability to set what calendar system to display. This is now in trunk for people to play with, so I thought it was time to add to our already supported list of calendar systems that people can display on their desktop.
My first target was the Indian National calendar, the official government calender for India, albeit one apparently not widely used (the Gregorian is the common civil calendar). While the various Indian religious calendars might be more useful in daily life, unfortunately these require various astronomical calculations that we don't yet support, or local observations that we may not be able to support.
The Indian National calculations on the other hand are fairly straight forward as it is very closly linked to the Gregorian calendar, with there being a fixed 78 year difference in the year numbers, a fixed 80 day difference between the start of the respective years, and synchronised leap years. One interesting feature is that the first year in the calendar is Year 0, which required some changes to the base class to support as none of our current calenders have one.
The big problem though was that our exisiting Gregorian calendar class copies QDate in only actually doing Gregorian calculations after 15 October 1582, before then it uses the Julian calendar calculations. Any earlier dates in the Indian calendar would be calculated wrong if I used that, so I first had to implement a 'pure' version of the Gregorian calendar to use as a basis. And while I was at it I thought it would be remiss of me not to do a 'pure' Julian calendar, which may be useful for members of some Orthodox Christian churches.
The end result you can see below is full support for the Indian National calendar, currently from 0000-01-01 through to 9999-12-30.
Yes, I realise that the week numbers are wrong in the year 0, that's an existing bug in our ISO week number code for all years < 1 that I have to fix.
Could I ask all our friends in India to have a play with it and let me know if there are any glaring errors? Just update trunk kdelibs and kdebase then run "plasmoidviewer calendar" or "plasmoidviewer digital-clock", go into the widget settings and change the Calendar to Indian National. It passes the tests I have here, but they are not yet comprehensive.
The other thing I need to ask is to confirm the month and weekday name transliterations I have used from the net are 'correct' (i.e. current best practice), and that the short forms I have invented are OK and not something rude :-) Is there a standard set of 3 char abbreviations I should be using?
The month names I've used from Wikipedia along with my made-up abbreviations are:
The weekday names I've used from somewhere are (starting from Monday):
So our supported list of calendars is now:
Note that the 'pure' Gregorian won't yet be offered as a choice to users as I'm concerned about the possible confusion from seeing Gregorian twice in the list, and with inconsistencies arising with anything using the existing Gregorian or QDate stuff. However, it is there for apps to use if they need to.
Now, I'm a strong believer in our translation and localisation being one of our greatest strengths and selling points, not only something that could see us 'winning' in markets that the big players just can't be bothered with, but also helping bring the benfits of computers and the net to people who might not otherwise be able to access them. Providing as many local calendar systems as possible is part of that. So how do we compare at the moment to the competition?
OSX 10.5 lets you choose any of the following:
As the only OS to currently support the Buddist calendar, I suspect Steve Jobs was behind that feature :-)
Windows Vista and 7 has a real brain-dead scheme when it comes to Calendar Systems. Want an English desktop and the Hijri or Hebrew calendar? Sorry, no can do! You have to choose Arabic or Hebrew as your language, then it lets you choose which calendar system to use. It restricts what calendar(s) you are allowed to choose from based on first your language and second your country, which while good for choosing default values seems seriously restrictive for no good reason. And their desktop 'Gadget' will only display the global calendar. Fail. Anyway, according to MSDN the supported calendars are:
Actually, I'd better be careful with throwing the insults Microsofts way, because Gnome I'm sorry to say apparently gives you even less choice. Far as I can tell, Gnome sets all your regional settings based on your chosen language and gives you no way to adjust any of the settings: date formats, number formats, calendar system, nothing. You can manually edit the locale file but that's it. So far so Gnome, that's just their way. But I've tried poking around gnome.org and Googling to see what other calendar systems they support, but can't seem to find anything. Reading the code of Glib's GDate and Gtk's gtkcalendar.c would suggest however that they only support Gregorian as the system calendar! That can't be right, surely? Can anyone set me right?
So it looks a real mixed bag of supported systems with Windows having the lead, but it's something I'm determined we will lead in by KDE 4.6.
Next up is the Bahá'í calendar and possibly the Ethiopian calendar before the 4.4 feature freeze, then some bug fixing on the Jalali and Hebrew calendars and a new test suite for all the calendar systems. Then for 4.5 I hope to get around to the astronomical calculations required for lunar based calendars like the Chinese, Islamic religious, Indian religious, etc. I think I'll need to do some astronomy night classes before then :-)
If you do have a local calendar system that you use daily and would like supported, and it doesn't rely on astronomical calculations (new moon, sunset, etc) then drop me a line and I'll see what I can do before 4.4.
In System Settings / Regional / Date & Time we allow users to customise the Date and Time fomats used throughout KDE, a handy feature. Problem is the configuration is not very user-friendly, have a look at what I mean:
So we have some editable combo's allowing the user to either select from a few standard layouts or to type in their own layout. But what are the valid componants of a layout that the user can type in? It's not immediately obvious, and there's no help available I can find. I had to go look at the source code to find out. OK, we could fix that with some tool-tips and help doco, but it's a process still prone to error, the user is allowed to type in anything no matter how invalid or incomplete and it just gets treated as display text. It's how Windows still does it, surely we can come up with something simpler and more usable?
Well, as you might guess, Apple did. Have a look at their Date format 'editor':
All you do is drag some Elements around (those blue 'bubbles'), type any text you want in between and you're done, no knowledge of format codes required. They have something similar for time formats.
I would love to have a generic widget that does this in KDE for use in the Date and Time formats in System Settings and in the panel clock settings. Where else could we use something like this, any ideas? Problem is, I haven't a clue how to do the gui for this, I'm a plumber, not a painter, if you catch my drift. So anyone want to have a crack, or at least give me some pointers where to start? Anyone know of an existing widget I could adapt? We already have the KWin buttons editor which does something similar, but it lacks the line edit functionality.
The generic widget would combine a special Line Edit widget and a Pallette widget. The Line Edit would allow any text to be entered and edited and validated exactly as a standard KLineEdit. The Line Edit could also be a combo if we wanted standard formats available for easy selection. Element 'Bubbles' can be dragged from the Pallette onto the Line Edit and dropped in position, or dragged off to remove them. Once in place in the Line Edit, the Element Bubble would be treated exactly as any other glyph, i.e the cursor moves around them and they can be deleted or backspaced to remove them. API would allow the client to add Elements to the Pallette as required, setting the Element Label text, Element Example text (as goes in the Bubble), and Element Format text. Calling text() would return the contents of the Line Edit with the Element Bubbles replaced by their Element Format text equivalent. Accessability would require that either each Element has a key shortcut to insert it in-line, or that typing in the Element Format magically changes it into the Element Bubble. This makes me think that what the Line Edit requires is code to recognise when a particular text substring has been entered and replace that textual display with a graphical 'Bubble', and an API to give it the Example and Format text pairs. The drag-and-drop action would then be simply to insert the required format text and the Line Edit would convert it itself. I'm guessing the hard part is displaying the Bubble in place of the text and getting the cursor to treat it has a single entity.
In System Settings and the Clock widget, we could then simply have the current format displayed read-only with a little Wizard button next to it to launch the widget, keeping the config guis nice and clean and simple too.
Any suggestions / volunteers?
Or can someone come up with an even more user-friendly way than Apple?
Little tip I picked up the other day that I've never seen documented elsewhere. If you have a git clone of Qt and you're constantly switching between divergent branches such as master and qt4.6-stable, or following a fast changing branch, you will eventually run into compile issues where it looks like the build is broken because of missing headers or symbols and even a 'make clean' or './configure' doesn't solve it. Try run ./bin/syncqt to see if that solves your problems, this is a script that apparently fixes up all the installed qt headers and stuff like that. It took me a while to discover this, I actually deleted my local repository and re-cloned a couple of times in the mistaken belief that I had horribly corrupted it. Perhaps it could be added to the Qt Gitorious wiki that a 'git pull' or 'git checkout' should always be followed by a './bin/syncqt' to be safe?
Anyone else with any useful tips like this when hacking on Qt?
Hey, I'm actually finally getting my head around all this git stuff...
I promised an update on printing and here it is.
Just to recap, the branch at http://qt.gitorious.org/~odysseus/qt/odysseus-clone/commits/advanced-page-selection contains the Advanced Page Selection features such as Current Page, Odd/Even Pages, Server Side page selection, and non-continuous Page Ranges. The status of this is that it's API complete with just some polishing work required in the Unix dialog, although there are a couple of implementation details I'm reconsidering as being too ugly.
My next step was to add in support for file printing which you can find at http://qt.gitorious.org/~odysseus/qt/odysseus-clone/commits/print-from-file. This is useful for applications such as Okular where they have a high quality source file and don't want to paint it onto a QPainter (and possibly reduce the quality in the process) before printing it. This is a simple API where the application passes in the name of the source file to be printed, and if the filetype is supported by the print system the file gets printed using the settings from the QPrinter (and thus anything the user selected in QPrintDialog). Under CUPS you can print PDF, PS, TXT and various image formats while lpr will support just PS and TXT. It's still a little hacky in places, such as the filetype detection, but it works. And for the more observant of you, yes this will make a new kprinter utility a lot easier for someone to implement.
I've also made a start on adding all the available CUPS options into the Unix QPrintDialog. At the moment KDE adds these as extra aplication-level tabs on the dialog, but they are poorly integrated, e.g. choosing 'Print to File' doesn't disable them. The code for this is still very rough and so still rather ugly, but I've attached screenies below showing some options in a new Pages tab in the main dialog, with others in a new Job tab in the Properties dialog. Yes it looks just like the current KDE stuff as I've recycled the code I wrote for that. I must confess the more I try to mess with the QPrintDialog, the more tempted I am to re-write it from scratch, it shows obvious signs of cruft building up over years of having bits bolted on by several different people.
Last time I mentioned that the Qt 4.6 feature freeze was looming. Well in fact it had already long gone whizzing past with no-one much noticing, so sorry but these changes won't be in Qt 4.6 or KDE 4.4. This whole open Qt development thing is very new and the processes aren't really in place for contributing features (as opposed to bug-fixes) and I guess there's a few lessons to be learnt along the way. I should have been more pro-active in talking to the Trolls about the how and when, so lesson one is if you have a new feature grab your nearest passing troll and don't let go until they let you cross the bridge to graze in the summer pasture, er I mean until your stuff gets merged. From the Qt side I guess there needs to be more structure and documentation around the steps developers need to follow to propose, design and develop new features, who do you talk to first, what are the release schedules and milestones you need to meet, and what you need to include (unit tests, cross-platform support, documentation, etc).
It has been suggested that my patches could be packaged into Qt4.6 by some distros, but this is not going to be possible as I cannot guarantee that the API/ABI will remain unchaged through the Qt review process, or even that they will be merged for Qt 4.7.
However all is not lost as I have been able to re-use some of what I've done to add Odd/Even pages and Server Side page selection for KDE 4.4 using CUPS. Using a very very ugly hack, I've added the Odd/Even selection combo into the QPrintDialog and this gets passed through to CUPS if selected. A less ugly hack has also added Server Side page selection where CUPS will select the page range when the application can't, i.e. Kate and Khtml and all apps that embed them (KMail, Konqi, KWrite, etc) can now print page ranges! The main drawback is this only works under CUPS, and it doesn't intergate well, i.e. the Odd/Even combo doesn't disable when you choose 'Print to File' so we'll get plenty of bug reports that it doesn't work with 'Print to PDF'. However I think the users need for this outways the shortcomings. Also be warned that using them in conjunction with n-up will get unexpected results due to a quirk in CUPS where it applies the page selection to the sheets of paper and not the document pages. Screenie below showing KWrite with Odd/Even selection added and Page Ranges restored.
As an aside, I've been thinking about how to make kate and khtml support page ranges properly. At the moment they just paint the whole document as they don't know where the page breaks will be until after they have actually painted the content onto each page. Trying to calculate this in advance and to pick up the painting mid-stroke is I believe a very tricky proposition. Instead, I was thinking we could have two identical QPrinter's, a dummy QPrinter onto which the first few unwanted pages are painted, then once the first required page is reached a second 'real' QPrinter onto which only the required pages are painted. Not sure if it's feasible, but worth a crack?
Of course, the obvious perfect cross-platform solution would be if QPrinter itself directly supported page selection, i.e. you paint all the pages onto QPrinter then tell it which ones to keep and it deletes the rest internally before passing the document to the native print system. Something else to look into.
[Edit: fixed references to QPainter to be QPrinter]
So, where to from here? There's obviously going to be a bit of time now before these possibly make it into Qt 4.7 (whenever that may be), so I'm going to re-arrange my priorities. We have the KDE 4.4 feature freeze coming up next month, so I'm going to focus for a bit on doing some Calendar and Locale related hacking for that. Then for the Qt 4.6 release I need to work on some bug fixes for the current printing code. After that, and depending on when 4.7 is rumoured to be released, I'll get back onto finishing off all the above and also trying to sort out the situation with saving settings between jobs. And in-between all that, I need to get back in touch with the OpenPrinting guys to work out how KDE can help them in their quest to completely re-architect the way we do printing.
I haven't posted for a while, mainly because I've barely been home and rather busy for someone supposedly unemployed. Just after my last post one of my sisters arrived from back home in NZ to stay for a month, so I spent a week hanging out with her around London, before I went on an archaeological dig for 2 weeks. Archaeology is another passion of mine, I go digging several times a year and study part-time at uni with some thought of merging my digger side with my geek side as a career.
This dig was on an octagonal-shaped Roman bath house in Kent, complete with plunge pool, hypocaust, drains and lead piping (cue plenty of Life of Brian quotes...). It's only the third of it's kind found in the UK, there being only 70 or 80 examples across the rest of Europe. Not as exciting as the cemetary earlier in the year, but it was a real puzzle trying to sort out the different phases. Lots of hard physical labour shifting piles of dirt in the blazing sun, some delicate trowel work, and way too much drinking in the evening made for a great break from the usual geek lifestyle. 3G reception was non-existant so the net addiction abated for a while :-) Below is an aerial shot of the site using a boom mounted camera.
After the dig I took off to join my sister on her holiday in Croatia and Greece, with a couple of quick detours through Bosnia and Italy along the way. The weather was fantastic, sunny and 26-30 degree, and Croatia is a great country to visit. I only got to see Split and Dubrovnik and the coast in-between, places I've dreamt of since reading about them in a Hardy Boys adventure as a kid, so it's somewhere to definately go back to later.
All through this time I was trying to keeping up a training schedule for my first ever half marathon, which I ran last Sunday. Unfortunately things didn't go well and I finished about 30 minutes slower than my training times suggested, which means I'm going to have to figure out what went wrong and try it again in a few months time.
So, life is finally returning to semi-normal and I can get back into the important things, like deciding what I can hack on for KDE before the feature freeze kicks in, and I guess I should do something about finding a job. Thanks to a couple of fellow KDE hackers, I have talked to a couple of FOSS/Qt companies but unfortunately the opportunities didn't really fit. The contract market is still very dead, especially in the financial / mainframe sector I know best and it could be a while before something suitable comes along, so I'm starting to look at other options.
Next posts, I'll fill you all in on the status of printing, and what I've been doing with Calendar Systems and the Plasma Calendar.
I hear that Qt 4.6 goes into feature freeze at the end of this month, so that's like in 1 working days time. Eeep! I'd better get those printing changes pushed upstream then. Is there some official place where such dates are advertised I should have been watching?
I've pushed the latest version of my code to a new Gitorious branch http://qt.gitorious.org/~odysseus/qt/odysseus-clone/commits/advanced-pag..., and I may just have to put in a merge request even though it's not quite done. First the screenie:
As you can see I now have an editable range field that allows you to enter multiple page ranges, in addition to the Page Set and Current Page stuff I'd previously added. This will show up for all applications that enable it, or if you are running Cups as your print system, i.e. 99.99% of you out there. If you don't have Cups, then you get the traditional From/To page range entry. This is not enabled on Win or Mac as yet, but it should be possible and I've designed it so it can be added without altering the API and so it gracefully degardes to the maximum feature set supported by your platform without the app programmer having to do anything.
Status is that I think this is API complete and stable, the only thing missing is the validation of the Page Range input by the user and some other small clean-ups of the dialog layout (yes, that radio button glitch visible in the screenie is proving a pain to solve).
Like I said, I'll probably put in a merge request for this now and worry about patching the remaining issues later. I think I should also have the File Printing under Unix feature done in the next day, so that may also make it. Less likely are the additional Cups features (n-up, banners, job control, etc) depending on how far I get this weekend (but we already add those ourselves), and the rest like saving/restoring settings and virtual printers will have to wait for 4.7 (or the new OpenPrinting dialog, whichever comes first).