I'm now at http://estan.dose.se/
I got sick of Vox's bad blogging software and installed Wordpress on a server of my own. Much better.
So long Vox, you've been OK but in the end didn't cut it.
For those who read my blog in a stream reader, the stream URL is now http://estan.dose.se/feed.
Bye!
Yesterday I had two guests, Clémence and Adeline, from France (surprise!). They were couch surfing Sweden for 10 days. Two really sweet girls I must say. We cooked then they walked around to see Örebro, and then we had some beers with Anders, Tara and Karin. I didn't take any pictures unfortunately, but they were going to put up some of theirs on CS.
I'm having new surfers tonight already. Two gals from Germany this time, coming in from Oslo. I don't know when and they don't have a cell phone (gah!), but it'll work out. Too bad I'm broke, as I was thinking of taking them clubbing at Backstage on Saturday.
Anyway, that's all. Buhbye.
It's late and I should go to bed, but I have time for another technical post I wanted to write, so here it goes..
When I work in Scribus I sometimes have to change some common property for a number of objects in the document. Usually these objects are of the same type, or have similar names. If you never explicitly name your objects in Scribus, the name and type often coincide, as e.g. images will automatically be called Image1, Image2 et.c.
Scribus has an Outline palette where you can get an overview of all the objects in your document in a neat tree view. In the stable 1.3.3.x series it looks like this:
Unfortunately in the stable series this outline won't help you at all if you want to select multiple objects as it doesn't allow you to do e.g. Shift/Control+Click to do multiple selections.
This limitation has been remedied in the (to be 1.3.5) trunk version of Scribus, along with fixes for some other nuisances. But one thing I still missed was a way to filter/search in the Outline view.
Let's try to come up with a proper, albeit simplified, use case for such a thing. Say you have the following document:
This document contains some images and some other objects. Let's pretend that there are hundreds of them, scattered over a dosen pages. Maybe you forgot to set the default input color profile for images in your document, and they've now all been assigned the ECI-RGB profile, when what you really wanted was the sRGB one. Here a filter function would fit like a glove, allowing us to put a filter on the outline that only shows objects with names that contains "Bild" which we could then select all at once to change their color profiles in one go.
So lets see what we can do about it!
After some digging I found the code for the the outline palette:
astan@rubik:~/Kod/scribus$ find . -name "*outline*cpp"
./scribus/outlinepalette.cpp
The only thing in the palette at the time was the tree widget showing the objects, but after my changes there should be three widgets there; first a label saying "Filter:" followed by a line edit widget into which the user would type the filter criteria and then below that the original object tree widget. This called for a QGridLayout to stuff the widgets in. After some fiddling with margins I had the look I wanted:
Next I added a new function to the OutlinePalette class:
void OutlinePalette::filterTree(const QString& keyword)
{
OutlineTreeItem *item = NULL;
QTreeWidgetItemIterator it( reportDisplay );
while ( (*it) )
{
item = dynamic_cast<OutlineTreeItem*>(*it);
if (item != NULL) {
if ((item->type == 1) || (item->type == 3) || (item->type == 4)) {
if (item->PageItemObject->itemName().contains(QRegExp(keyword)))
item->setHidden(false);
else
item->setHidden(true);
} else
item->setHidden(false);
}
++it;
}
}
The function takes a keyword as argument, and using the nice iterator for QTreeWidgets, QTreeWidgetItemIterator, that comes bundled with Qt along with some trickery to get the name of the objects and match them against the keyword using QRegExp, it filters the outline using setHidden().
Now a new function is not enough, it must be called somewhere! So in the constructor of the OutlinePalette class, I added a connect() call that hooks up the textChanged signal emitted by the QLineEdit widget for the filter criteria to my new function. The call looks like this:
connect(filterEdit, SIGNAL(textChanged(const QString&)), this, SLOT(filterTree(const QString&)));
That's it folks! After this it just works:
When things go this easy, you can't help but love Qt. Of course I've simplified things in this post a bit, and you can read the entire 170 line patch here. But still, that wasn't too hard was it? It's under review now and will probably be commited to trunk shortly.
Take care.
*yAwn*
EDIT: I changed the look of the blog, and for some reason the <pre> sections with the code gets cut off unless your click the post title to read it on a page of its own. Sucky.
It seems I'm on a roll! New couch surfers coming in on the 17:th already! Clémence and Adeline from France are staying one night on their way through Sweden. I guess the surfer frequency is higher during summer.
Too bad I'm going to be completely broke when they're here, unless I get the pay for the calendar before they arrive.
Warning to non-techies; this post is a bit heavy on the techspeak.
(The subtitle for this post, had subtitles been supported by the blogging software, should have read "The Power of Open Source", or possibly "An action report" as I was still working with the calendar when I wrote it.)
A couple of weeks ago some friends of my moms wanted me to do the layout of a wall calendar for 2009. They have a little theater group and wanted something to sell at fairs et.c. All the material was ready, and I just needed to do the graphic design and type setting. So I fired up my good old friend Scribus, my DTP application of choice. The layout was pretty simple, and everything went smoothly. I even found some matching artwork under Public Domain at OpenClipart that I could use. The printer had promised to put in the actual calendar with name days,
holidays et.c. from a template they had, so all I had to do was to leave some empty space for it.
I uploaded the ready-to-print PDF to the printer on the day of the deadline (naturally) and immediately got that warm fuzzy feeling of relief that comes from a job well done. At this point I would like to put out my first big THANK YOU to the Scribus developers for an excellent application with a very bright future. There will be a more praises later on, stay tuned.
What now happened is that one of the guys at the printer called me the week after the deadline and explained that the guy that I'd had contact with before, and who was now on vacation, was all wrong; they were not prepared to add the actual calendar. He also explained that these are vacation times for them, and if they were to meet the deadline for the job, they needed a PDF, including the calendar days, holidays, name days, flag days and what-not ASAP (where ASAP meant this Wednesday at the very latest). This all just meant one thing; I was (or quite possibly still am) in a lot of doo doo.
So what did I do? First I despaired when I realized how much work I had left to do, in only a few days. Sweden has quite a few holidays, and together with the name days and the flag days (which in the calendar should be decorated with a little Swedish flag) it meant I had a significant amount of monkey work ahead of me. Then came some good news; Scribus apparently ships with this calendar wizard in the form of a Python script, which helps to do the grunt work of creating a calendar.
However, as I tried the wizard out, I realized it had no support for holidays, no support for the Swedish name days (in fact, no support for name days what so ever), and the final result from it was quite ugly for various reasons. The lack of support for name days worried me the most, as it meant i'd have to manually position 365 text frames into Scribus, and manually enter some 600+ names. Needless to say, I was not prepared to do this, and started looking for another solution. I took a dive into the 500+ line Python script.
This is not really true, because my first problem was how to get the list names into the script in the first place. Wikipedia to the rescue! At http://en.wikipedia.org/wiki/Swedish_name_day_list_of_2001 I found a table with the name days of Sweden, as published by the Swedish Academy. I quickly whipped up the following Bash script to convert the wiki text for the table of names into Python dictionary format.
#!/bin/bash
#
# Convert the wiki source of
#
# http://en.wikipedia.org/wiki/Swedish_name_day_list_of_2001
#
# into Python dictionary format.
#
if [ -z $1 ]; then
echo "Usage: mknamedays.sh [file]"
exit 1
fi
day=1
echo -n "["
cat $1 |
while read line
do
# End processing?
echo $line | grep "</table>" &> /dev/null
if [ $? -eq 0 ]; then
break
fi
if [ "${line:0:1}" = "#" ]; then
echo $line | grep "no name" &> /dev/null
if [ $? -eq 0 ]; then
names=""
else
names=`echo ${line:1} | sed -r 's/\[\[[^|]+\|([^]]+)\]\]/\1/g'`
names=`echo $names | sed -r 's/\[\[([^]]+)\]\]/\1/g'`
names=`echo $names | sed -r 's/\([^)]+\)//g'`
fi
echo -n "'$names',"
if [[ $((($day % 5))) -eq 0 ]]; then
echo ""
else
echo -n " "
fi
day=$(($day + 1))
fi
done
echo "]"
exit 0
The Python script for the calendar wizard wasn't the prettiest, but easy enough to understand, and after a few hours of hacking the wizard now contained a little check box labeled "Add name days", which when checked resulted in the user being prompted to choose a paragraph style to use for the name days. The names would be neatly added to each day in the calendar. My patch for CalendarWizard.py can be seen here. It will probably be included in Scribus trunk after some possible copyright issues with the name days are cleared, I might have to make the user supply the name day lists. And here's the fruit of the patch, illustrated by a screenshot showing the month of January, including name days.
Now, I was not completely happy with this, as the text in the little boxes for the days were all too close to the edge, and I wondered why the original author of the wizards script had not bothered with adding paddings, so I began investingating this as well. It turned out that setting the text distance properties of text frames using the Python Scripter API of Scribus was not supported. Bummer. I asked on the #scribus IRC channels if there were any undocumented API for doing this, but I was out of luck; it just wasn't possible. I thought for ten long seconds and then decided to try to add the missing Python functions myself. Everything went well, and after another few hours of hacking the Python scripting plugin of Scribus, I had two brand spanking new functions at my disposal, getTextDistances() and setTextDistances(left, right, top, bottom), the former returning a tuple with the four values. I filed a bug against Scribus' bug tracker and included my little 5 KB patch, which should be commited shortly if it's not already. You can see it here.
I augmented my patch for the wizard script to utilize these new functions and add some padding to the text frames for the day numbers and the names, and the final result can be seen in this screenshot:
Graphic designers over the world must think this is a horror story; "what's he doing? layout using obscure shell scripts, python programming and C++?!". But think about it, had Scribus been closed source, none of this would have been possible. And from now on, if someone wants to add name day support for their own country, all they need to do is to add the list of names and they're set. Me? I love doing graphic design using obscure hacks!
Let's just hope I can make that Wednesday deadline...
There was more, but I was in a hurry.
- The vomit color of the floor.
- People who think they're my best customers when they're actually my worst.
- The loose handle of the inner fridge.
- How the crappy positioning of the oven above the stove make me have to bend my back when I make sandwiches.
- How the sharp edge of the counter leaves marks and pain in my hands when I use it to support myself.
- The dust that the electrostatic surface of the LCD at the counter attracts.
- How hard it is to get the coffee stains out of the fiber cloth that I use to wipe the portafilter and steam pipe of the espresso machine.
- How the sun flower seeds from my sandwiches clogs the sinks.
- Customers who idly pluck the paper napkins into thousand little pieces and leave it at their table.
- Customers who use chewing gum.
- Customers who bend my spoons.
- Customers who, after they are finished, put their paper napkins into their half-full mugs of coffee/tea.
- The mechanism on the outer door for keeping the bolt open which always jams.
- How the back door does not fit properly into the frame.
- Reloading the whipped cream gas-driven bottle.
- How the wall that extends behind my back when I'm at the counter and try to do gymnastics to my 41 degree scoliosis is in the way.
- Customers who think I'm their friend and they're mine.
- Customers who feel a need to inform me about things happening in their life that I don't give a shit about.
- Customers who think they "understand" my work, almost to the point where they get delusional and think they're actually working there.
- Customers who want to borrow money.
- Customers who want my smokes.
- Alcoholics.
- Customers who ask questions about piece of shit literature.
- Customers who read fantasy and asks if I've read the latest piece of shit fantasy.
- People who come in and ask about piece of shit thrillers/crime and wants me to do searches for piece of shit thriller/crime author X's latest work "because they're not sure if they've read it or not". Stop reading fucking crap books from the same shitty author if you can't fucking tell if you've read a book or not. Or go fucking check yourself for dementia.
- When ruccola sallad gets stuck in the cutlery basket in the dish washer.
- How the detergent compartment of the dish washer clogs when you fill it up too much.
- How the dish racks above the dish washer are starting to come off the wall.
- When I slip on fucking oil on the kitchen floor.
- When people order sandwiches.
- How people, after I've fucking aced the milk on their fucking latte, take a spoon and violently stir the shit out of it, while talking about fucking day care or something equally uninteresting with their friend.
- The fact that I have to go through three locked doors to throw the trash.
- The idiotic piece of shit flyers for retarded events that people keep asking me to put up on the counter. Noone wants to go to your stupid shit so go wipe your ass with that shit instead of littering my counter.
- People who wants me to put up posters, but don't bring their own fucking tape. Had it been worth the tape I'd tape you to the wall and go medieval on your ass. Idiot.
- Customers who wants free coffee.
- Customers who complain about prices. What's the fucking deal, if you don't like it go to hell or fucking amazon, bokus or something. Or just make me a great favor and go kill yourself.
- Customers who pour milk too violently making splashes that soils the door of my fridge.
- Customers who don't finish their coffee. You fucking poured it yourself so drink it or I'll make you drink fucking sewege detergent.
- Coffee nutheads who ask what bean mix I use. I don't use coffee beans. I take small pieces of my own feces every morning and roast them in the oven you idiot. What, are you going somewhere else if I don't use you favourite mix?
- Cutting up the cheese cake while in a hurry.
- When the inner piece of a tomato slice falls off when I make a sandwich, making the sandwich look retarded.
- How much of the spoonfull of sun flower seeds I put on each sandwich falls off the side of the sandwich when I make it, and the sound it makes. Tick tick tick tick TICKC TICK TICK!
- How easy it is to accidently hit the START button on the dishwasher when the lid is open, and how equally easy it is to accidently hit the lid so that it closes and the dishwasher goes off.
- How my heels get numb when I stand at the counter.
- Idiot customers who behave like fucking hogs spreading the salad of the sandwiches around. Some day I'll cut you up and spread pieces of YOU around with the same amount of joy and vigor.
- People who ask what a "book café is".
- People who wants me to sell the piece of shit untalented so called book they claim they wrote. Seemingly typeset by their dog in some cute unreadable sans-serif font and printed at some shabby run-of-the-mill Internet print house, all I really do with it after saying "yes" is use it to wipe my ass.
- How the sun reflects in the windows so that I can't see if there's a stupid customer at the counter wanting something or another when I'm out smoking.
- Customers who think my café is a social welfare office, therapist, public toilet, free luggage storage, closet, after party venue, study room, conference center, library, day care center and general provider of social interaction, all at the same time.
- Customers who think they how the economy of selling books and coffee works, and people who in general have "great ideas" on how to improve the place.
- How making hot water in the coffee brewing machine produces a puddle of water around it.
- How the rug under the tables in the back of the café curls up under the chairs.
- Customers who move around the chair without putting them back.
- Customers who think I'm always up for a "quick chat" discussing interesting topics such as how the ticking sound from the library entrance across the street (there to guide the blind) is "preposterous", or how they're going to regain their failed marriage. I want nothing else than to kill you instantly.
- Customers who have been in like thrice in the last month and expect me to remember their stupid fucking custom combination of sandwich ingredients. I try very hard to forget all about you each time I see you, because the image of you poisons my dreams, that's why I don't remember you think ruccola is a "weed" and "don't eat weeds. heheh HEHEH". Idiot.
- Customers who disturb me when I'm in the middle of an important conversation on IRC. Drop dead you idiot. Helping a pimpled 15 year old wannabe KDE hacker from Ukraine getting his dev env together, or figuring out a witty topic for #greta is more important than you.
- Customers who ask me if the bread is dark. No it's white as your ass cheek, don't like it leave. All I want is to fuck up your digestion system with my evil white bread, so bring it on, you're a disgusting hog anyway and don't deny it.
- Customers who bring magazines and leave them. I don't want your piece of shit magazine. In fact, I don't want you so never come again. Idiot.
- The lonelyness of working by myself 10 hours a day, six days a week.
- How sometimes I'm so hungry at work I have to hold on to the counter from dizzyness.
- How every second day I'm so tired after work that I have to sit down and rest on the way home, there's no place to SIT!
- The stress-induced acid burn in my stomach when people order lots of sandwiches.
- How books come in every day and instead of unpacking and pricetagging them, all I can do is focus my vision on something, try to stay in touch with my surrounding an keep watching the clock on the wall.
- Telemarketers.
- Cash payments. Securitas routines for depositing money sucks ass. Cash sucks ass. Fuck it.
- The demoisturization of my hands due to repeated washing.
- How the mugs just barely fit under the second shelf in the upper drawer of the dish washer, making it a pain in the ass to put in mugs after you've put cappucino cups on the second shelf.
- How I never get any interesting e-mails when I really need them, around 13-17 CET.
- Regulars who are at the door at 09:45 expecting to be let in, and don't realize that they've just fucked up my entire day.
- Customers who place custom orders for books and never return to get them.
- Small pieces of wet ruccola salad on the tables that rolls up into little curls when you try to wipe the table with a cloth.
- How my work shows up in my dreams.
- How customers put books back in the wrong place.
- The apathy which working in a cramped space all days brings, seeing the same things, the same little details, the same WRONGNESS of it all.
- The heat from the oven during hot days.
- The pain in my back.
- How the regular drinking glasses are not all of the same model and stick to eachother when you pile them.
- How easily the sandwiches split in two when you make them.
- How easily the sandwiches tip over when you serve them.
- How hard it is to cut mozarella slices of consistent thickness.
- How easy it is to cut yourself when cutting salad.
- That 20 crates is the minimum order from Kopparbergs, making navigating the inner parts of the kitchen a fucking bitch, and getting in and out of the back door hell.
- That the brownies dry out so fast.
- That despite all the above, there's absolutely no money in this piece of crap line of work.
To be continued..
Okay. Going out to the airport in a little while. I will miss San Francisco a lot. Hope I'll be fit for work on Wednesday. I finally got that KOffice patch commited to SVN, only to get a request on the ML for three more fixes/features for the ruler. Great!
Bye.
It's 10:42. Today it rained a little bit in the morning, and my cold is worse than ever. I went up Cortland and had a great breakfast at some place called Moonlight Coffee I think. Today feels like an indoor day and I don't think I'll rent a scooter. I'll probably just do some KOffice hacking until the sun hopefully comes out. Marc is still asleep.
I'm also attaching a short video clip (unfortunately I didn't get the whole thing) of a crackhead who walked out in front of the bus and stood up close to it for five minutes demanding a dollar from the driver, who was very amused and finally gave him one. Sorry about the rotated video, I had no time to correct it.