Zwabel’s Weblog

November 3, 2008

KDevelop4: Find all uses of “…”

Filed under: Uncategorized — zwabel @ 4:11 am

Hi planet! I’ve been registered a long time ago, but sadly this is my first post here. I’ve been too busy with getting “real” stuff done on KDevelop.

One short statement about Qt Creator: Imo they seem to have nearly the same goals KDevelop4 has: Modularized, platform-independent, light-weight, C++ oriented, with good Qt support.. why do they have to re-invent everything? I would have preferred them putting some resources into KDevelop4 instead. One thing is for sure: Their app may be stable, but feature-wise they are far behind, although I am biased to see this mainly from a C++ support perspective.

But now to KDevelop:

In KDevelop4, we have a language-independent structure for abstract code-representation called Definition-Use-Chain, that has been invented by Hamish Rodda a few years ago. When I started hacking on it soon 2 years ago for my Google Summer of Code project, he had stopped hacking on it for quite some time, and it was in a state you can call “experimental” at best. Nearly 2 years of hacking have passed, which were really hard years of instability, without the target visible on the horizon, without even knowing whether this stuff I’m working on even just “can” work out. Hamish came back about a year ago, and since then has been a pushing force on KDevelop4 again, also helping me with the kate problems that I really didn’t have any insight to. Anyway it was a monster-task. I often had to work on 3 places at the same time: kate, kdevplatform(duchain), and kdevelop(C++ support), all with tons of code that was until then exclusively used by KDevelop’s until then unfunctional C++ support, which means that lots of this code was unfinished and unstable.

The good news: All the pain is starting to pay off. πŸ™‚ This April we had our Developer meeting in Munich, and since then the development has heated up, and I think we’re on track to get a stable release out within the next half year.

I have very high demands in the C++ support, and now they are starting to be satisfied. KDevelop4 has reached a state now, that I actually finally can suggest interested people to try it out. It’s important that you have recent kdelibs + kdevplatform + kdevelop, because all of them have seen some quite important changes in this area in the last weeks.

Since we got new competition from a direction from where I actually would have expected support instead, I feel motivated now to present you some of the nice features KDevelop4 has, so we don’t lose too much of the public interest.

The last days I have worked hard on finishing the basics for refactoring and use-searching, aka “find all calls of this function”, and got that ready. I’ve put it into a re-usable base-class, so functionalities that need this backward-searching are very easy to implement now. What mainly comes into mind is intelligent renaming/refactoring and call-graphs, which is just a matter of writing a user-interface for it with this in place.

Also I’ve continued polishing the widget to show this information.
Here you’ve got a nice screenshot:
Screenshot of KDevelop4 with the uses-widget

At the top you see the editor-window, and at the bottom the code-browser which currently shows the uses of KDevelop::DUContext. The buttons are used to expand/unexpand the uses in the file. Then each file is split up into “Contexts”, which are functions or class-declarations. This allows you to get a fast overview in what place the use occurs. A tooltip over the line shows also the surrounding lines of eeach use, and clicking on the link on the left side jumps to the use directly in the editor window.

Next time I’m going to present you another nice feature of KDevelop4. πŸ™‚



  1. Nice to see you blogging – you really need to show the people those amazing features!

    See the new Qt Creator positive: competition is a good thing.

    The greatest thing about kdevelop and its duchain is the language independence. Qt Creator doesn’t have that at all.


    Comment by Niko — November 3, 2008 @ 8:21 am

  2. > why do they have to re-invent everything?

    Well, IMHO you’ve given part of the answer to that question in your first sentence already:

    “this is my first post here. I’ve been too busy with getting β€œreal” stuff done on KDevelop.”

    That “real stuff” is absolutely useless

    – if you don’t get the message across about your work. The fact that you just subscribed looks like another indicator to me that this is a problem.

    – if you don’t establish a strong focus in your project on what’s important. Looking from the outside I currently don’t see any strong focus yet:
    Looking at the interface of previous stable versions it tries to do everything but does nothing too well. You say that this has improved drastically in the development version? Well, see your other problem of “getting the message across” regarding that. It doesn’t help if nobody is getting informed.

    – if your focus isn’t visible judging from the interface. Usually people are only interested in interfaces that are easy to use. These days I’d say there exist tools for all kinds of problems to solve. So piling up features doesn’t add much value if it’s not easy to use. Of course “ease of use” could be defined differently depending on your target group. If you’re targeting those people who want to be extremely efficient and consider it most efficient to choose from a long list of options then this could be “good enough” if your application is the only solution around. However being “good enough” won’t cut it in the future once even more people start to use Qt and demand for an excellent solution starts to arise.

    If I were to create an easy to use IDE I probably would start from scratch as well: Trying to change an existing open source project to “have focus” and to establish a viable vision will take enough time already. Getting all people involved to see usability as a #1 challenge in the right way could easily become a nightmare (because if people aren’t sensible for that the whole attempt could become endless sisphos work. It’s as much a headache as trying to herd some cats.
    With a small team that stays on focus it’s extremely likely that I’d be faster to reach my aim if I started mostly from scratch.

    I’m pretty sure that you won’t like my posting, but sorry I’m just the messenger. And of course I don’t want to discourage you. So here is my advice:

    – Try to create more focus in your project (not in terms of creating the 100001 plugin or framework extension but in terms of much more essential needs).

    – Usability, usability, usability. Make this your #1 focus. Looking at your screenshot I see that your menu has 11 top-menu items. That’s far more than anybody could easily “grok” at once without “reading” or “learning by heart”. I haven’t looked at the actual menu entries but already extrapolating from the 11 menu items I’d extrapolate that the app has still got lots of usability issues.

    – Inform your end-users more regularly about the current status of your application. Not so much from the current implementation details but about where you’re heading to.

    Comment by Torsten Rahn — November 3, 2008 @ 8:54 am

  3. Oh and to add another comment: Many applications have improved significantly during the work on KDE 4 in terms of usability (Gwenview is an example that comes to my mind). But there are still lots of others which imho need to do “their homework”. Otherwise they’ll risk that some other developer or organization or company will come along and create a possibly better replacement. Whining about the “other developer” not “reusing” or cooperating with your pet-project won’t help then (it just makes you look stupid).

    Again, I’m not keen on criticizing KDevelop: I’ve advertized KDevelop during it’s first years of existence very much (mostly at events together with “the other” Nolden: Ralf Nolden). And actually I’d like to be able to recommend KDevelop whole-heartedly e.g. to a beginner (which at the current stage I can’t do yet). So I honestly hope that you guys will get your act together and will be able to improve the KDevelop situation (again complaining and whining about Qt Creator won’t help a single bit: Rather try to improve KDevelop.

    Comment by Torsten Rahn — November 3, 2008 @ 9:21 am

  4. @Torsten:
    1. Nobody should measure KDevelop4 based on KDevelop3! Those don’t have much in common. We have a relatively clear vision of KDevelop4, and we do want to prevent what happended in the old version. We only want to ship ore core set of stable and well maintained plugins. We want to prevent a useless pile of not-fitting-together features.

    2. I do consider usability as a key problem.

    Of course it might be not easy to bring your own focus into an open source project, but the case of KDevelop4 within the last years is somewhat different. It has been completely rewritten, and the devs were absolutely open for a revolutionary new user-interface. The devs of Qt Creator have clearly taken the way that is easier, preventing any kind of discussion. But it’s probably not the way leading to the greatest benefit.

    Comment by zwabel — November 3, 2008 @ 9:30 am

  5. I must say that I really like the functionality that you are presenting, but Torsten is right about usability and visiblity. I do find the UI of KDevelop to be compelex. Just looking at the screenshot, there are tabs or tab-like objects on all four sides. Which one does what? That is not clear at first look. The same really goes for the buttons in the search view. If the list is really an expanding tree of searches and places where results for these searches was found, why not actually *make* it a tree. That is something people are familiar with and know how to use. Or, if that is somehow not desirable, why not name the button after what it does: expand when in collapsed state, and collapse when in expanded state? That way, the users don’t have to guess what the button does.

    Comment by Andre — November 3, 2008 @ 9:30 am

  6. @Andre:
    Seriously, how can you ask what those tabs do, have you cared to read their text? πŸ˜‰ It will be quite hard to come up with a user-interface that doesn’t require reading at all. Yes imo we need to find a way of making some of the tabs content a bit more discoverable, for example making them notify when their content has seen a big change, but in general I don’t see a problem with them. We just need to keep their count down.

    The “DUChain Viewer” on the right is a development plugin that won’t be there in a release.

    About the tree:
    That might be an option. But trees tend to be butt-ugly. Have you seen the “Zoom in” and “Zoom out” icons on the buttons? I prefer this over a text like “Collapse” and “Expand”, though the icons could be a bit clearer.

    Comment by zwabel — November 3, 2008 @ 9:42 am

  7. I’m sure they wrote their own for the following reasons:

    * Their UI is much nicer. E.g. no stupid vertical text.
    * They want to focus on Qt and avoid the added complexity of supporting many other languages/platforms (c.f. gameboy build toolbar in KDevelop 3).
    * Their code completion & debugging looks a lot better.
    * They want control.
    * I imagine their GUI code is actually quite small. Since they would probably need to rewrite a lot of KDevelop 4 to get it to the state of Qt Creator I doubt it would have been worth the effort.

    Comment by Tim — November 3, 2008 @ 9:56 am

  8. @Tim As I said, KDevelop4 is a completely new app. And btw. their code-completion looks nearly exactly like in KDevelop3, it’s just a plain list.

    About the vertical text: That’s a matter of taste. Sometimes I do think it sucks, but then again you only need to read it _once_, then you know it.

    Comment by zwabel — November 3, 2008 @ 10:08 am

  9. I like to see that a discussion has started here and I whish there was more blogging about KDevelop. After all, blogging on a regular basis not only keeps in touch with users but also spreads lots of good ideas and inspiration. Keep up the great work, I’m looking forward to KDevelop4!

    Comment by Bernhard — November 3, 2008 @ 10:11 am

  10. @6:
    Yes, I have read the text (awkward as it may be, the text it being vertical*). In fact, I used to use KDevelop frequently in the past when I was still hacking on a qt-based open source project, and I intend to resume using it again, so I also *know* what they do.
    So, while it is clear what it behind the view, it is not really clear how it relates to the screen as a whole. The tabs around the main area give no indication to what area of the screen they relate. If I click on “Documents”, will my current view disappear or not? And with that, will the currently open code be visible, or will there be something different in my main view? It is not clear from the screen to what part of the screen the tabs or buttons around the sides and bottom relate.
    So… while I *know* the answers to these questions by now (clicking on one of the side-tabs will expand a side-bar, clicking the lower left Code Browser button will collapse the area that is labeled (in the bottom-left corner, sideways again!) Code Browser and will expand the useswidget.cpp tab downwards), that is not at all immediately obvious. That is the problem I was trying to point out with the tabs.

    Yes, when looking very closely I could see that the two identical icons had a subtle difference in that one features a – and the other a +. That one is not easy to spot. I prefer to label buttons with an explicit text, and give them an icon if that fits and adds something. For this list-like layout, even right aligned expand link would probably do. For me, it is absolutely not obvious why there would be a file name on a button here.

    Anyway. I guess it is these kinds of problems with KDevelop’s interface that prompted Trolltech to create their own and try a different direction. Whether that will turn out to be better in the end remains to be seen. I will keep an eye on both IDE’s.

    *Though you are right that you don’t need to read it that often, and I don’t know a better solution off hand. The use of the vertical label for the Code Browser label in the lower left corner is terrible though. No one will look in the lower left corner of a window to look for a window title IMHO.

    Comment by Andre — November 3, 2008 @ 11:01 am

  11. I think the Qt Creator will move get more and more towards the Mobile Development. They don’t want to competit with KDevelop or Visual Stuido or Eclipse (all three IDEs have very good Qt Support). They create a Simple but useful IDE for new (small/medium) Desktop Projects as well as Mobile/Crossplattform Projects – with Nokia as “mother” they now create a S60 Port of Qt, we all know WinCE/WinMobile and Qt Extended – i’m waiting for iPhone and G1 Support πŸ˜‰ [mono is going to support the iPhone]. This is the focus: All these new Plattforms just “one compile” away πŸ˜‰

    Comment by loeppel — November 3, 2008 @ 11:04 am

  12. @Andre:
    Btw. the widget-based approach of the uses-widget has another big advantage: If there is enough horizontal room, the contexts can be aligned horizontally instead of vertically, which will be very handy in that crowded space down there. Not possible with a tree-view. You’re right, an “expand” icon aligned to left and only a file-label in the middle might be a good solution. It isn’t as unclear as you think though, since it does have a “context”: You search for uses of declaration. When you get a file-name, you expect that you get all uses of that declaration within that file if you click it..

    On thing is for sure: This widget is not the reason for the existence of Qt Creator. It just exists for a few days. πŸ˜‰

    About the vertical text: I think the vertical “Code Browser” label at the bottom is a good compromise. You don’t really need it, so it must not steal valuable vertical space. But if you reall need it, it’s there, even if hard to read. πŸ™‚ It could be removed though if the tool-view and the “Code Browser” button were optically connected a bit better.

    Comment by zwabel — November 3, 2008 @ 11:17 am

  13. I wanted to write something more general about KDevelop, but Torsten has exactly stated what I’m thinking as well. The key point is usability, not piling up features! Since I came to Linux/KDE more then 10 years ago, I have been looking for a nice IDE. And being with KDE almost since the beginning, KDevleop seemed like the natural choice … however I’m still stuck with Emacs. I tried KDevelop every once in a while, however I could never convince myself to use it or to whole heartly recommend it to others. I was just lost in this myriad of buttons, tabs, context and menu entries, options. It always felt just like a pile of features.

    You say KDevelop4 will be different. Ok, so there is hope πŸ™‚ However when I see all these tabs in your screenshot already, I kinda doubt. And no, vertical text is not a matter of taste, it’s obviously harder to read (at least in most of the world). And no, one doesn’t have to read it just once, especially when there is such a load of them. At least I, not being intimately used to KDevelop, have to read them again and again, in order to learn their position. (This is not just a problem of KDevelop btw.!)

    And, putting focus on usability means: questioning things, searching for solutions (although this is not an easy thing to do), instead of blindly defending what you have. Which I do understand, btw., but it doesn’t help to improve things.

    Oh, and please don’t take that too personal. I really don’t mean to offend anyone!! I’m just saying how I see it, looking at it from an outside perspective. And I’m still hoping to find an awesome IDE someday, allowing me to ditch my Emacs. And I’d love this to be KDevelop, and not some Java monster or Nokia tool!!

    Comment by Michael — November 3, 2008 @ 11:20 am

  14. @Michael: I defend the vertical tabs only for one reason: Because noone has ever come up with a useful alternative Idea. So either you come up with such an idea, or I’ll have to keep definding them… and as I said: We will try to keep the count of tool-views low, it has to be a tradeoff between feature-count and keeping a simple overview.

    Comment by zwabel — November 3, 2008 @ 11:29 am

  15. just for the record, I wanted to say I have no problem at all with the vertical tabs or reading vertical text. πŸ™‚ Maybe because I’m used to it due to my usage of IntelliJ (imo still the best java ide) for my job?

    Comment by mattie — November 3, 2008 @ 12:24 pm

  16. Well, I admit coming up with good usability solutions is the hard part and I’m not too much an expert in that field either nor have I put too much thought into designing IDEs. However vertical tabs/text is not a solution general, it’s at most a workaround… You could build houses with horizontal doors, technically you can get into the house as well, but nobody sane would come up with such an idea πŸ˜‰ I don’t think there is a concept with which you can replace all tabs 1:1. That said, one idea might be a treeview, like in XCode. Especially for things on the left (looking at a KDevelop3 screenshot..) like files, classes, bookmarks.. Generally looking what needs to be visible in a certian situation, in order to reduce what needs to be actually shown or outsourcing rarely used things into separate tools. Like when you don’t have certain tabs in the first place, you don’t need to scratch you head about how to show then. For instance when editing you don’t need anything related to debugging, so the Breakpoints and Valgrind tabs at the bottom can go. They are just cluttering and confusing when editing the code anyway. Also a key point is not to throw everything in what might be useful, but to make compromises, i.e. “to focus” as Torsten said.

    Comment by Michael — November 3, 2008 @ 12:25 pm

  17. After all the people complaining about usability I have to say that my experience is different: I stopped using KDevelop 3 because it plain *did not work*. Setting a breakpoint had no effect, clicking “Run” only worked every other time (seriously), and there was no thing like DUChain. The versions I tried were 3.3 and 3.4.
    Like everybody else, I want you to succeed this time πŸ™‚

    Comment by Andreas — November 3, 2008 @ 12:37 pm

  18. @Michael:
    In KDevelop4 we have separate “Areas” that are collections of tool-views. For example we have a separate area for debugging, so you don’t see the debugging-toolviews while hacking.

    Also we will only be showing the most needed/useful tool-views by default, so what you’re saying is exactly in line with our plans..

    You guys should finally stop measuring KDevelop4 on KDevelop3, because as already said a few times it’s a new application, we learned from the mistakes done in KDevelop3, and I’m slowly getting annoyed by again and again being blamed for KDevelop3’s UI shortcomings.

    Comment by zwabel — November 3, 2008 @ 12:41 pm

  19. It would be cool if Qt Creator adopted DUChain.

    Comment by Ian Monroe — November 3, 2008 @ 1:06 pm

  20. Hi, I think it’s a great thing you are blogging about KDevelop4, and that happened thanks to Nokia and their recent competition

    Yeah, I think QtCreator has a very different public from KDevelop, QtCreator is meant to be simple and easy to learn for all people that works with Qt, that’s mean Windows developers and Mac developers, and first, it’s a completely different mindset from linux developers, and secondly, it’s very difficult to get kde libs working on Mac for example, with Creator I just open a binary with the bundled qt libraries..

    About usability, there’s a rule on WIMP interfaces, that say the more widgets you have on screen more complex, in a nonlinear way, will be your application, and much more difficult will be to learn it too.. Seeing the screenshot, this new version seems to be much better then kdevelop3, but there’s still room for improvement

    oh, and that expand button is pretty confusing.. wouldn’t be better if the button was only the “zoom” icon, and the other text as labels? I also think better visual about the hierarchy would be nice..

    I made a crude mockup to demonstrate: (it’s very crude because I don’t have time right now to do something elaborated)

    Oh, it would be nice if you developers send more screenshots or mockups and ask for UI designers for help…

    Comment by Puelo — November 3, 2008 @ 1:51 pm

  21. @Puelo: That mockup looks nice. That’s about what Andre suggested. Although I don’t know how to make the hierarchy look that nice, without creating own painting-functions, which is too much hassle just for this widget. And also I don’t know how to make QLabel not underline the links “Line …” and the function-name, would be great if someone could assist with this. All the usual html tricks like setting a font or css parameters don’t seem to work in QLabel.

    Comment by zwabel — November 3, 2008 @ 2:00 pm

  22. As for complaining about KDevelop3, my comments are more of a general nature. Of course we can reference only KDevelop3 as we don’t know KDevelop4 yet. And by the time we know it, it’s too late for conceptual changes.
    You specifically asked about an alternative for vertical tabs (or too many tabs in general, for that matter). And I just used the KDevelop3 screenshot as a practical example. The only point I tried to bring across was, that in order to get rid of tabs, you most likely need a more general approach then simply replacing tabs bei something else. I certainly got that you want to change things πŸ™‚ The screenshot you posted, IMVHO just doesn’t look too promising, as far as the UI is concerned (menus, vertical tabs). But as I don’t know what you guys do or plan behind the scenes, I better shut up now πŸ˜‰ I don’t mean to bring you down or anything, I’m just concerned about the success of KDE software in general and KDevelop in particular. And user interfaces are a big part of that.

    Comment by Michael — November 3, 2008 @ 2:32 pm

  23. @zwabel hey, the underline on links are nice, i didn’t draw it because I was out of time… sorry

    Comment by Puelo — November 3, 2008 @ 2:48 pm

  24. Do you have an IRC channel for these type of talk? Actually I’m more a UI developer then UI designer (i’m finishing my computer science graduation)

    As soon as I deliver and present my thesis (24 Nov), I would be happy to help in things like better user interaction and overall beautifying of widgets πŸ˜‰

    Comment by Puelo — November 3, 2008 @ 3:19 pm

  25. @puelo: We hang around in the #kdevelop channel, feel free to drop by. Of course most useful would be an actually helping hand, so it would be great. πŸ™‚

    Comment by zwabel — November 3, 2008 @ 3:27 pm

  26. I like the mock-up by Puelo also, it is indeed much better than the current situation. As for removing the underlining, you actually *can* use CSS to do that. However, note that there are different things in Qt that you can style with CSS, and they are easily confused. I guess you tried to set a stylesheet on the widget. That will not work. You will need to set a stylesheet on the text to be rendered itself. Simply add style=”text-decoration: none;” to your tag in the QLabel and the underlining is gone. However, maybe it would be better to simply leave the underlining. Many people associate underlining with links, and if that is how they work, why break that association? Simply colouring the text will perhaps be less clear, as there is already a lot of coloured text in KDevelop: the code window above it is full of it, and they are not links either.

    By the way: do you know that you can recreate the mockup by using a QTreeView and creating an appropriate delegate for it? Granted, it will not be easy to combine that with making the contexts appear next to each other if there is space for that. I am not sure that is such a great idea anyway, as scanning a vertical list is easier on the mind than horizontally spread information. Alignment is easier to get right in the horizontal option, especially for lists like you have. Still, I don’t know if that is the easiest or the best solution in your case. There are more options…

    I do appreciate that the widget is not the reason for QtCreator’s existence. Again: I really like the functionality. I was more referring to the general cluttered and complicated view that your screenshot shows, which is a sharp contrast with QtCreator. Again: I am not saying that KDevelop is bad, it is not. I just wish it were much better, and I am pleased with any progress in that direction πŸ™‚ Your efforts *are* appreciated!

    Thanks for making KDevelop better!

    Comment by Andre — November 3, 2008 @ 4:04 pm

  27. “As for removing the underlining, you actually *can* use CSS to do that”

    please don’t do that! lol

    i dind’t draw it because I was too lazy to draw lines, for me every link should have a blue tone and a underline, because without that two visual clues unaware people can hardly recognize it as a link

    Comment by Puelo — November 3, 2008 @ 4:20 pm

  28. Really really cool feature πŸ™‚ I do a lot of searching of where functions are used and I usually use grep (or search in files from kdevelop) but that’s not reliable or sometime give too much answer.

    I tried kdevelop4 a few month ago and I must say it looks really promising (unfortunately I can’t test it anymore, I don’t want to compile kdelibs myself), and it was heading toward the good direction to be a great IDE for Qt4/KDE4/C++ developement. I also look forward to your other blog entries on future feature πŸ˜‰

    And yes there are way too many menus entries, but the number of “dockers” seems to be about the correct one in that version, compared to kdevelop3.

    Comment by Cyrille Berger — November 3, 2008 @ 6:12 pm

  29. IDE-development is very hard and after the initial hype is over things will become really difficult.

    To put it in another way: is QtCreator offically blessed by Nokia? Will Nokia invest manpower and financial resources in QtCreator? Or is QtCreator a Trolltech-solo-ride?

    Trolltech was aquired by Nokia only some months ago. But this IDE-project started at least 2 or 3 years before the aquisition. Nokia as strategic Eclipse-partner and cdt-supporter hopefully will do the right thing. I guess they will bet on the right horse and not on the wrong wannabee-race-horse.

    Comment by Arturo Toscano — November 3, 2008 @ 6:45 pm

  30. I’m following the progress of KDevelop4, and have to say it is very interesting and promising.
    Solid and advanced C++ support is something I’m really looking forward too, as well as CMake support.
    That said, I also think that KDevelop4 is far from a point at which it would be useable for me, I’m still using KDevelop3 for KDE4 development. However, it seems KDevelop4 is heading in the right direction and just needs the manpower to stablize and polish it. So go on, KDevelop developers!

    BTW, I think the whole vertical sidebar text discussion here is a waste, KDevelop4 has far more problems in other areas, and there has already been enough coding time spent on various UI rewrites. Please concentrate on the important things.

    David, you’re doing an amazing job, keep rocking! I really enjoy reading the commit messages and monitoring the progrss.

    Comment by Thomas McGuire — November 3, 2008 @ 7:02 pm

  31. Thanks first πŸ™‚

    i am using kdevelop4 in early stage but I think it will be a nice piece of cake !
    just wanted to tell you carry on it

    Comment by Girard Henri — November 23, 2008 @ 8:41 am

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at

%d bloggers like this: