Skip to main content

Ralsina.Me — Roberto Alsina's website

Posts about qt (old posts, page 9)

A teaser for an idea

I have been think­ing on what I re­al­ly re­al­ly want in a word pro­ces­sor. And then what would it take to cre­ate such a thing.

A few min­utes of play­ing have led me the way of this teas­er (video here if you can't see it):

Could some­thing come out of it? Who knows.

Editor: a better QTextEdit

Writ­ing an ed­i­tor is rein­vent­ing the wheel. I know that. I tell my­self Mar­ave is a fine wheel, with dis­tinct fea­tures, and I think that is true, but, if you are rein­vent­ing the wheel, there's no need to rein­vent the axle and the spoke, too.

So, I refac­tored the stuff that I think a text ed­i­tor must pro­vide in­to a nice li­brary, so the next time some­one must in­vent a wheel, he can use Mar­ave's neat spokes and axles:

So, in­tro­duc­ing Ed­i­tor, the most-ob­vi­ous­ly named class ev­er! It's a text edit­ing wid­get for PyQt with ex­tra fea­tures, which you can use as a drop-in re­place­ment for a QTextE­d­it or QPlain­TextE­d­it.

Right now, it lives in­side Mar­ave's SVN but it may even move out some­day.

Here are its fea­tures:

  • Syn­­tax high­­­light­ing

    And I don't mean "in the­o­ry", like QTex­tE­d­it and com­­pa­ny do! Ed­i­­tor can high­­­light a bunch of lan­guages, be­­cause it us­es GNU source high­­­light via Loren­­zo Bet­­tini's Source High­­­light Qt.

  • Spell check­­ing

    If you have PyEn­chant in­­stalled and the right dic­­tio­­nar­ies, it will do on­­line spellcheck­­ing.

  • Search and Search+Re­­place wid­gets

    The Ed­i­­tor class can give you nice wid­gets for search or search and re­­place al­ready hooked with the ed­i­­tor wid­get, so you can add them to your ap­p's UI eas­i­­ly.

  • new/open/save/saveas meth­od­s:

    Don't im­­ple­­ment open­ing/sav­ing, etc your­­self! That's al­ways the same code!

Hope­ful­ly this will be help­ful for some­one else :-)

Are we really this clueless about software costs?

Here's what Ohloh has to say about the cost of de­vel­op­ing Mar­ave

Re­al­ly, Mar­ave is maybe a month of part-­time pro­gram­ming. How could that pos­si­ble be U$S71355, or "1 Per­son Years"?

Is this garbage the best we have to es­ti­mate cost­s? If that's the case, then when­ev­er you see some­thing about "Open source pro­gram X would take Y years and cost Z dol­lars to write", cut it down by a fac­tor of 10 or more.

Here's what Mar­ave re­al­ly cost­ed to de­vel­op:

  • Noth­ing.

Ok, here's what it would have cost­ed if I had charged for it:

I am guess­ing about 100 hours of my time. At my "I hope they pay me this much" rate of U$S 40/hour , that's U$S 4000, which means Ohloh is off by 1600%.

OTO­H, for that much free­lance work I would not charge you the full rate, I would prob­a­bly end charg­ing you more like U$S20/hour which would make Ohlo­h's guess over 3000% too high.

In con­clu­sion: if you like my code (and hey, you can see it for your­self), hire me, I am in­cred­i­bly cheap, or amaz­ing­ly fast!

Marave 0.6 is out

Ver­sion 0.6 of Mar­ave, my peace­ful, fullscreen text ed­i­tor is now avail­able at the usu­al place: http://­mar­ave.­google­code.­com

New stuff:

  • Syn­­tax high­­­lighter

  • Plug­ins

  • Bugs fixed

  • Nicer an­i­­ma­­tions

  • Code cleanup

Gra­tu­itous screen­shot:

The aha! moment

I had a small task to­day in Mar­ave. The goal was:

  1. Fade in a wid­get

  2. Set a var­i­able

  3. Fade in an­oth­er one

It's im­por­tant that things are done in that or­der and it's al­so im­por­tant that the app re­mains in­ter­ac­tive.

And here's the code to do that (sim­pli­fied):

def fadein(thing, target=1., thendo=None):
    """
    * thing is a QWidget
    * thing.proxy is a QGraphicsWidget
    * thendo is callable
    * target is the desired opacity
    """

    thing.anim=QtCore.QPropertyAnimation(thing.proxy, "opacity")
    thing.anim.setDuration(200)
    thing.anim.setStartValue(thing.proxy.opacity())
    thing.anim.setEndValue(target)
    thing.anim.start()
    thing.anim.finished.connect(thing.anim.deleteLater)
    if thendo:
        thing.anim.finished.connect(thendo)

And this is how you use it:

def later():
    avar=avalue
    fadein(widget2)

fadein(widget1, thendo=later)

Isn't that lovely? Having functions as first class objects means I can just take later as a closure, along with widget2 and avar, which need only be defined in the local scope, and the call chain will work just as I wanted!

Yes, many oth­er lan­guages can do this, and in Javascript it's one of the most com­mon trick­s, but con­sid­er that PyQt is a wrap­per for a C++ li­brary!

I think this kind of us­age shows the re­al added val­ue PyQt brings to the table, it's not just that python avoids the bor­ing com­piles, or that you have the awe­some stan­dard li­brary to use, but that the lan­guage it­self en­ables you to do things that are not prac­ti­cal in C++.

In C++ the only way I can think of is creating a slot that's the equivalent of later, then chaining the signals... which means that this throwaway later becomes part of the interface of a class!

I would have to define later somewhere else on the file, separate from its only usage (maybe even inlined in the header file).

Even then, that's not equivalent: avalue may be something that was only avalable before the first call to fadein, (for example, the time of the first fadein): I would have to create a place to store it, make it reachable by later... and wht happens if you try to do this again while the first fadein is in progress?... it gets hairy.

Pro­gram­ming is like a slap in the face some­times... you re­al­ize that things you use with­out even notic­ing are far from triv­ial.

So, re­mem­ber young padawan: you can choose you tool­s. Choose wise­ly.


Contents © 2000-2023 Roberto Alsina