KDE

The Good, The Bad, And The Ugly

I promised an update on printing and here it is.

The Good

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.

Qt Cups Options 1

Qt Cups Options 2

The Bad

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.

The Ugly

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.

KDE 4.4 Print Dialog

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] 

Exit

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.

Geek on the run...

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.

Bax Farm Bath House

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.

A beach in Split

In Greece we only really went to Athens, somewhere I've been to before, but at least this time I got to see the Antikythera Mechanism, the oldest known mechanical calculator dating from around 100BC.  I'm sure I've heard about a javascript simulation, I wonder if we could get a plasmoid of it?

Antikythera Mechanism

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.

Running man

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 feel a chill breeze on the back of my neck...

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:

Qt Print Dialog with Print Ranges

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).

Git makes my head hurt...

So I cloned the Qt master repository on Gitorious as odysseus-clone a few months back, and then cloned odysseus-clone onto my laptop where I've been working away happily.  Now I want to make sure my work is still OK against the latest master before doing a merge request, so I think I need to update my odysseus-clone on gitorious first to the latest master, then do a fetch/rebase to update my local clone, then push my changes up to Gitorious. 

Thing is, I can't for the life of me figure out how to get my odysseus-clone on Gitorious to update to the current master.  Any clues?  Or have I got this all wrong?  1am is not the best time to be trying to figure this out :-)

Displacement Activity

I know, I know, I'm supposed to be working on the Print Dialog, but I've reached a tricky part and while my brain ticks away on that in the background I thought I would do something a little more fun.  Seeing as I'm the 'official' maintainer for Calendar Systems (i.e. I was the last person to work on them...), and to be part of the cool crowd hacking on Plasma, I thought I'd have a crack at fixing the Plasma Calendar and Clock widgets to allow the users to select which Calendar System to display, just like you can currently choose which timezone to display.  Long story short, here's what I now have:

Plasma Calendar Widgets

So that's the four different supported Calendar Systems (Gregorian, Hebrew, Hijri, Jalali) all being displayed at once in separate Calendar widgets.  Hmmm, I wonder if we need a label at the top of the widget to show which Calendar System is being displayed?

Plasma Digital Clock Widgets

And again, but this time in four Digital Clock widgets. The left-click pop-up calendar from each obviously also shows the correct Calendar System.

Plasma Calendar Config Widget

There's a common configuration widget used in both the Digital Clock and Calendar widgets.  In 'Use Calendar System' you can choose from Local, Gregorian, Hebrew, Hijri, or Jalali, where Local is the default and will use whatever the Locale setting is. The Holidays settings are the same as currently available in 4.3, but obviously you could choose to have different holiday regions on each Calendar or Clock widget.

Plasma Digital clock Copy Menu

Right-click on a Digital Clock widget and you can choose a 'Copy To Clipboard' menu option to which I've added the date in other Calendar Systems.

There's still a little polishing to be done, especially on the Digital Clock to sort out some date format localisation issues on the main widget and the copy menu, but look for this to pop-up on ReviewBoard in the next day or so.  I've got some thoughts on other improvements especially for Holidays, and there's a fairly long bug list in bko, but I'll get this sorted first.

Oh, and while I have my official maintainers hat on, could I just remind developers that you can't use most of QDate's methods like formatDate() or addMonths() as these only work on the Gregorian calendar system.  To ensure your KDE app localises the Calendar System displayed and performs the right date maths on it you need to use the methods provided by KCalendarSystem through KGlobal::locale() and KGlobal::locale()->calendar().  QDate is essentially only a storage medium that KCalendarSystem then interprets for you.  OK, the API is not very friendly and definately longer to type, but that's the way it is until either Qt5 or KDE5 comes along with Calendar System support built directly into QDate / KDate (and yes Trolls, that is an offer to help write it the correct way :-)

[Edit: For some reason comments were turned off, back on now if you want to add soemthing :-)]

Printing Advanced Page Ranges in Qt, Part 2

With Page Set (Odd/Even) and Selected Page done for X11, I thought I'd skip the OSX/Win stuff for now (it was doing my head in) and get the Advanced Page Range completed on X11  So here's my design for supporting user enterable non-continuous or broken page ranges such as "2,5-9,11".

[Just a reminder SimplePageSelection mode is designed to be 100% compatible with the existing API and apps will use these by default without having to be modified, an app has to be modifed to explicitly set AdvancedPageSelection mode to fully activate the new features and use PageList() to obtain the pages to print].

In SimplePageSelection mode, when CUPS is not available the Range edit will not be displayed but the From/To edit will.  The application will generate all pages between From and To and LPR will print all pages sent to it.

In SimplePageSelection mode, when CUPS is available the Range edit will be displayed, but will be validated to only allow strictly ascending non-repeating document page numbers as this is all CUPS supports (we could allow random order as CUPS sorts it first, but that would just mislead the user).  The application will generate all pages between From and To which are set to the lowest and highest page in the Range.  Qt will then adjust the Range to tell CUPS to ensure the correct pages are printed.  (Note that CUPS actually applies the Range on Output Pages, not Document Pages, which is why we need the adjustment, and why applying n-up at the same time produces results other than the user expects).

In AdvancedPageSelection mode the Range edit will be displayed and the user will be allowed to enter the page numbers in random and duplicated order and have those pages printed in exactly that order, e.g. "5,2,9,3-7,11-4".  The application will generate only the required pages in the required order and CUPS will print all pages sent to it.

Note that this means a user can enter a Range of "20-10" and have the pages printed in descending order, but if they also select the Reverse option at the same time the pages will come out in ascending order.  Slightly confusing but the only consistent way of dealing with it.

For Win, the native dialog does support an editiable Range and will be supported later on.

For OSX, the native dialog does not provide an editable Range and so will always default to the standard From/To range regardless of what mode the app sets.

This scheme provides the user with the maximum amount of functionality available at each level, but I am concerned about the inconsistancy between the Simple/CUPS and Advanced modes combination which users will use side-by-side depending on the app. This is because some apps may never be able to set Advanced mode, for example Kate and Konqueror don't really know about pages so may find it very difficult or inefficient to generate pages out of order by themselves.  Users could become confused by this inconsistency between apps without realising why they behave differently, but dropping the Simple/CUPS mode will prevent apps like Kate from printing broken ranges, and restricting the Advanced mode to only ascending pages would remove a useful feature.

So what do people think, which is better, consistency or features?

[Note to self: log and fix bugs in both Kate and Konqi which leave the From/To page range enabled in the print dialog when they in fact always ignore the users input and print the entire document].  

Do people also think it would be useful to continue to display the From/To Page Range entry at the same time as the Range edit entry?  Or would it just clutter things up?

I plan to use a RegEx with QRexExValidator to validate the users input into the Range line edit, but I haven't written a RegEx in years, so thought I'd ask the experts out there to have a look.  The general rules are as follows.

A valid Range is made up of one or more valid Sub-Ranges separated by commas, with no commas allowed at the start or end.

A valid Sub-Range is one of the following (where n is a number from 1 to MAXINT)

  • n
  • n-n
  • n-  [equivalent to n-MAXINT only allowed as final Sub-Range]
  • -n  [equivalent to 1-n only allowed as first Sub-Range]

And here's my attempt which I've yet to test to see if it even works:

^(?:(?:\-\d+,)?(?:\d+|\d+\-\d+,)*(?:\d+|\d+\-\d*))|\d*\-\d+$

Suggestions welcome, just remember it needs to be maintainable :-)  Note I'm using \d for digits so we get support for the different number sets we support, but it means I have to do an additional validation step afterwards for n!=0.

Calling All GSOC Bloggers...

Hey all you GSOC bloggers, I'm really enjoying all your blogs about the really cool stuff you're doing, it's real exciting to see what you're up to, and I'm more than just a little bit jealous.  But could an old memory-challenged fogey ask one small favour?  Could you just include the title of your GSOC project and the application at the top of your posts, with so many of you about it's a bit of a struggle to remember who's working on what, and it's not always immediately clear from the post contents.

Congrats to all of you for passing the mid-point review, and be sure to stick around afterwards, it's great to see so many new faces making such solid contributions to the community.

Highs and Lows

So I'm home from a fantastic 8 days at GCDS in Gran Canaria and a cultured but boiling hot weekend in Madrid.  There's so much to say about the experience, and so much to do as a result, but those will be for another blog.  Since getting home it's been going downhill rapidly.   Late flights, work production issues seeing me pulling 13 hour days, then to cap it off I get a call from my agent this morning to say my employer is terminating my contract effective end of this month.  It's not a total surprise given the current climate, but what $@%$£% me off is that my coward of a manager who's away on leave today didn't have the guts to tell me himself yesterday when he had ample opportunity.  Forget it being unprofessional, you just don't treat other people that way.

So I'm back in the job market again and its not a good time to be looking. If you know of anyone looking for an old-school mainframe programmer / designer / tech lead in the London area with experience in the banking, telco, and energy markets, then drop me a line.  Or if you're really really really desperate for a C++ hack (I wouldn't deign to label myself a programmer)...

Then again, this is the same disorganised outfit that rang me at 3pm on 24th December while I was at the pub enjoying my leaving drinks to offer me a contract renewal, so who knows what will happen.

Well, look on the bright side, I'm soon going to have all the time in the world to hack on KDE and Qt printing:-)

GCDS Photos

Rather than waste time wrestling with Drupal's image support, I've posted some of my GCDS/Akademy photos on Flickr.  There's more from the tourist trip with people messing about on the dunes, but I hit the 100Mb limit.

One photo Ade might like showing just how cool OpenSolaris really is :-)

We have code

All going well, my code for adding Current Page and Page Set selection (aka Odd/Even pages) to Qt should now be up on gitorious for all to see and try out.  For those of you not wanting the hassle of compiling, here's a screenie:

Qt Odd Even Pages

The Gitorious branch is at http://qt.gitorious.org/~odysseus/qt/odysseus-clone/commits/current-odd-even.  I still have a few bits of polish to add, like disabling Page Set if Current Page is selected, and the initialisation is something I'm not 100% happy with, but it's mostly there and working.  I've been testing the last couple of days witout a real printer, but it should still be OK. I also haven't tested it compiles under Windows or OSX, so I'd be grateful to someone did :-)

So what does it do?

  • If you're on X11 / LPR and running an app that hasn't been modified, then you see nothing new.
  • If you're on X11 / CUPS and running an app that hasn't been modified, then you see the Page Set combo and CUPS takes care of the odd/even page selection.
  • If you're on X11 with CUPS or LPR and running an app that has been modified, then you see the Current Page (if set by the app) and the Page Set and the app takes care of the odd/even page selection.
  • If you are on OSX or Windows then you see nothing new (as yet).  Good news on that front is I have just seen a commit that moves Qt to using the Win2k print dialog instead of the Win98 print dialog, which should make adding these new features way easier. I still need help here though!

So how to modify an app?  Easy.  To enable the Current Page, just call QPrinter::setCurrentPage() with whatever your current page number is before you exec the print dialog.  To enable Page Set fully, just call QPrinter::setPageSelectionMode(QPrinter::AdvancedPageSelection) before you exec the print dialog, then make sure you either use the new QPrinter::pageList() method to get a list of the pages to render (the easy way) or use QPrinter::pageSet() to figure it out yourself (the hard way).

For reference, the newly added QPrinter public api is:

			enum PrintRange { AllPages, Selection, PageRange, CurrentPage }; // Just added CurrentPage
	enum PageSelectionMode { SimplePageSelection, AdvancedPageSelection };
	enum PageSet { PageSetAllPages, PageSetOddPages, PageSetEvenPages };
	void setPageSet(PageSet);
	PageSet pageSet() const;
	void setCurrentPage(int);
	int currentPage() const;
	void setPageSelectionMode(PageSelectionMode);
	PageSelectionMode pageSelectionMode() const;
	QList<int> pageList() const;
	

 

So, have a look, have a play, and let me know when you find my bugs :-)

[EDIT: Just a reminder this is a change to Qt so depends on the Trolls accepting it, but I'm hoping it makes it into Qt4.6 which will be out before KDE 4.4 so that's the up side]

Syndicate content