Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Procal: A simple Qt-based programming calculator (github.com/fellerts)
173 points by fellerts on March 4, 2023 | hide | past | favorite | 90 comments


I love PyQt, I wrote lots of graphical user interfaces for my lab equipment during my PhD, was super easy to wire stuff up and replace Labview with Python. The design was similar to this app, simple frontend that allowed you to e.g. set microwave frequencies, toggle outputs or make measurements. My colleagues were initially quite skeptical but 10 years later they're still using the software and it spread to other labs, they even hired a full-time developer to work on it.


I use PyQt to write an entire interface to my self-built microscope. It's awesome. Personally, i design the UI in Qt Designer, then wire it up in code. The absolute gem of gems in Qt is the Graphics View Framework, which is a retained scene graph for 2D rendering with extraordinary power and performance. I can do realtime work with the scope including image processing all from python but at C++ speeds.


QGraphicsView is indeed awesome. I have been using it in the tile map editor of my hobby 2D game engine and it can easily handle thousands of objects. IIRC, it uses spatial partitioning to determine which objects need to be redrawn.


Flet (https://flet.dev) is a new GUI library for Python to write apps like that. It uses Flutter to render UI with a modern-looking Material design. Your app can be run as a desktop app and published as a web app (standalone with Pyodide or server-driven with built-in web server).


What's wrong with pyqt?


With PyQt you can't make web apps; with Flet you can.


I guess you can https://doc.qt.io/qt-5/webgl.html

But it's probably very inefficient and I'd advice to just write a web app if you need a web app.


Indeed! And with PyQtGraph you can create live graphs and visualizations that update at 100 Hz or more. It's really fun.


One feature that I'd love in a programming calculator is the ability to set arbitrary bit widths. 32bit or 64 bit is okay, but a lot of the time when I'm thinking about individual bits; it's because I'm doing embedded programming for 8 or 16 bit devices. Similarly, the ability to toggle signed and unsigned representations.


I once wrote a calculator that has five output displays: signed decimal, unsigned decimal, hexadecimal, octal and binary. I did it that way because I was tired of having to select the output mode. I also added the ability to select 8, 16, 32 or 64 bit output.


I've been using BitCalculator for Android[1] for that. It supports 8, 16, 32, and 64-bit integers, big or little endian byte ordering, signed or unsigned, as well as 32 and 64-bit floats with either endianness.

[1] https://play.google.com/store/apps/details?id=com.kebstudios...


I totally agree, which is why I included that in procal! Just right-click a cell to turn it into a sign bit.


Thats really convenient, but probably not the most discoverable.


Fair point. At least it's mentioned in the README. My goal was a lean and efficient tool without any extra fluff, so discoverability took a hit.


I did not notice that. I will have to download procal and give it a try.



I believe your license is incorrect. PyQt is licensed either commercial or GPL, so you would have to either purchase a license or license this under GPL verses the more permissive MIT license you are using.


I don't think that's right. The MIT license is compatible with the GPL. One can license the code using a GPL library using MIT. Only someone who wants to fork the code into a proprietary program would needs to purchase a license of the dual-licensed library.


IANAL, but the top answer in this thread seems to suggest otherwise: https://opensource.stackexchange.com/questions/1640/if-im-us...

> No; incorporating or linking against GPL requires that your project-as-a-whole be distributed under GPL. But you can include MIT licensed parts (or another GPL-compatible license) in the project. Also, it depends.


That answer is for a pure GPL library, not dual licensed.

As the quoted part says: the project as a whole (which includes the library itself) need to be GPL, but part of it can be MIT. So the code of the program on GitHub can be MIT.


The other half of the dual license is commercial. They can purchase a license and use it under the commercial terms, or use it for free under the GPL terms.

Under the GPL terms, the derived work becomes GPL (this is why people call GPL infectious or viral). The project may include unrelated MIT components alongside GPL components, but the project itself becomes GPL, along with any derived components (i.e. components making use of the GPL components). It’s kind of the entire point of the GPL. It’s also why we ended up with LGPL, which offers a linking exception.


I disagree. The GPL can't force a license on your code. It just force a license on the whole program that all its components must respect the freedom of the GPL. As long as the code that use the GPL is under a GPL compatible license (such as MIT), you're good. I.e: you're free to give more freedom in your code than the ones required by the GPL.

The virality is something else: It is that you must disclose the source of the whole program that use a GPL only library. And you're doing that with MIT


> The GPL can't force a license on your code.

It doesn't. It just doesn't give you permission to use the GPL licensed code unless you comply and use GPL.


You do have to license the whole program as GPL, but as you say, you are free to duel-license parts of the code with a more-permissive license.

https://www.gnu.org/licenses/gpl-faq.html#GPLModuleLicense


> you are free to duel-license parts of the code with a more-permissive license.

you don't need to dual license it - either it's compatible with the GPL (MIT is) and then can be shipped as part of a GPL program, or it isn't and then you cannot distribute the complete program.


> that all its components

I didn’t say all of its components, I said components making use of GPL licensed components or code. His math code could totally be licensed MIT, depending on how the program is put together. His UI code is inextricably derivative of QT though — you can’t separate the two. So even if that code itself could be licensed MIT (which is not clear to me), practically speaking, it can only be used alongside the GPL component and thus in a GPL work.

In some few situations, I suppose the distinction could matter, though.


I thought linking against GPL code was fine. I guess I'll have to re-read it.

That said, does it even count since he's not distributing it (Qt) at all?


You can use a library that has an MIT license with a library that has a GPL license, that's what it means to be compatible. But the end work would have to be under the GPL license.

Its the whole reason PySide exists, to have a Qt Python library hat is LGPL to allow works that use it not have to be GPL like PyQt does.


The reason PySide exist under LGPL is to allow proprietary program using the library. Here we are talking about MIT which is not proprietary.


IANAL. Legally the GPL doesn't care about proprietary or free software. What is cares about is that you license any combined works under the GPL. You could copy+paste the GPL, change the name and it wouldn't be a valid license for a "a work based on the Program".

> You must license the entire work, as a whole, under this License

https://www.gnu.org/licenses/gpl-3.0.html


See https://en.wikipedia.org/wiki/License_compatibility GPL Compatability

"That is, their code can be combined with a program under the GPL without conflict, and the new combination would have the GPL applied to the whole (but the other license would not so apply)."


So, for PyQT to exist, Python must be GPL’ed? That doesn’t seem reasonable.


Thanks! I changed the license to GPLv3.


Note your alternative would be to use the official "Qt for Python" (aka PySide) bindings. Those are LGPL, which is one of the main reasons they exist (PyQt was started earlier but unlike much of Qt is not LGPL).

This is from when Qt still cared about LGPL, i.e. the Nokia days when the aim was to be the commercial-friendly Nokia SDK.


Since pyside was discontinued once already, I tend to not trust it any longer.


Wasn't QT originally GPL-or-commercial by Trolltech? Which is what spawned GNOME and Gtk as a response to QT-using KDE?


Not exactly. It was originally licensed under its own Qt Free License which the K Desktop environment was using and becoming a large player in the DE space. It was not considered "free software", which spawned GTK.

Then it was released under its own QPL license, and KDE negotiated that if Qt went bankrupt it would change to an MIT license.

Finally it was released as GPL.


Right, thanks for the correction: my memory is at least approximately on point :)

FWIW, I think Gtk+ was independently extracted from Gimp as Gimp Toolkit, but KDE success drove GNOME creation based on LGPL-ed Gtk+, which, as you point out, later put pressure on Qt to be relicensed.


I don't think GTK+ exerted any pressure there - it has never been competitive with Qt, in terms of markets with money. The LGPL relicensing mainly happened because Nokia bought Qt and aimed to make it the SDK for all their phones going forward, which was compatible with permissive licensing business-wise.


Depends on how you define "markets with money": Sun based their pre-acquision Solaris on GNOME and put a lot of money into accessibility and HIG in the GNOME 2.0 days. Similarly, Nokia started Maemo (and their Internet Tablets N700 iirc) on Gtk+ before pivoting to Qt after the acquision (with their N810, N800 and N9). RedHat and SuSE invested heavily in GNOME as well, just like Canonical did who hired plenty from the GNOME community. KDE mostly never had that kind of money (basically SuSE and was it Mandrake?), though Qt is obviously a different thing (whereas Gtk+ is a core part of the GNOME project).

Both of these were struggling in the changing workstation/PC/mobile market, so I don't consider it against Gtk+: eg. Nokia was soon acquired by Microsoft and even Qt version barely hit the market.

Still, I do believe success of KDE and GNOME has had at least some of the effect on getting Qt LGPL-ed: there is little doubt KDE was great marketing for Qt (there was a plethora of Windows GUI toolkits: cross-platform, not so much).

OFC, I was in none of those boardrooms, so it's all speculative ;)


When it comes to funding for Gnome vs. KDE I'd it's probably a lot closer between the two than a lot of people realize, especially if you consider that KDE didn't have to shoulder the development of the GUI toolkit alone (even though it has contributed a lot of code to Qt and provided some maintainers). I don't think Sun's investment at the time was all that big in today's terms. Canonical also hired plenty from the KDE community (I'm sure you're aware Ubuntu Touch was done on Qt, and in terms of staff and expense a much larger project than Ubuntu Desktop; Kubuntu also had Canonical funding and paid devs for a while), as did Trolltech/Qt, as did Nokia, as did SuSE as you mention. There's also always been indirect funding (and hiring) through the consultancy ecosystem, e.g. KDAB's commercial contracts to maintain PIM for a while, and other such engagements, e.g. by the city government of Munich and other municipal and educational deployments large enough to pay contractors. Blue Systems has employed a significant team of core devs for closing in on a decade now, and Valve has engagements with them and others.

When it comes to Qt vs. GTK: I would guesstimate that at the peak, GTK+ perhaps had around 10 concurrent paid devs? The peak for Qt was in the 100s, from markets like embedded and automotive that GTK+ hasn't really been able to access (yes, I had all the Maemo devices too). And even for its core focus area, desktop apps, GTK+ hasn't seen a lot of adoption outside the Linux niche, whereas there's a seriously large amount of commercial Windows/Mac software using Qt. This is really what I meant.

Bottom line: Most PC users have a few copies of Qt on their computer, and perhaps own a device or two in their home and another in their garage that also has Qt on it. The same cannot be said for GTK+. A computer with GTK+ on it is relatively rare, perhaps in the tens of millions vs. billions.

It's also worth noting that users who migrate away from Qt do it to either Flutter (because of more permissive licensing - BSD - or mobile capabilities) or Electron (to share tech with their website) or Unity/Unreal (because of the rendering capabilities), but not to GTK+. Users who migrate away from GTK+ often migrate to Qt (e.g. Wireshark and a couple of others). I can't think of an example of anyone moving to GTK+ from really anything else (probably exists but likely minor). To me that means that while Qt has fierce competition, GTK+ is not really among it.


Oh, I was in no way suggesting that Gtk+ pushed Qt to more permissive licensing, but instead that both KDE and GNOME did. And even then, that it's just my feel of the situation from long ago :)

And it's certainly a valid claim that Qt is more omnipresent than Gtk+ today.

Thanks for the lovely chat, I enjoyed going back ~20 years :)


Qalculate! is my favourite GTK and Qt-based calculator that's great at accepting all sorts of inputs, even solving for X: https://github.com/Qalculate/qalculate-qt


I second that. Great program. Not only does Qalculate! also handle binary operations and numbers of any base of your choice (including hex, octal, binary), both for output and input (even when working in another base, e.g. when the output mode is set to decimal, you can just input hexadecimal values such as 0x1AF and Qalculate! will understand)…

… but most importantly it can calculate with units and show the result converted to your liking e.g. you can write

10 Nm×2pi×20/minute to W and Qalculate will show the result as 209,4395102 W. When you get used to that, you don't want to use any calculator that doesn't have that feature any more.


Second that also as a cli `qalc`. Use it nearly every day, to convert units and quickly qalculate that would take way longer when opening a gui or pulling out my phone.

e.g.

> 100 GB/minute to kB/s

https://github.com/Qalculate/libqalculate


Cool! Do you have any Web programming experience? If so, how would you compare/contrast the experience coding in Qt vs. JavaScript? I have ~1-2 years of experience programming in each, and I tend to prefer Qt because to me, it seems easier to make components that are truly reusable. On the other hand, there are numerous advantages to Web programming, such as the fact that it's easier to deliver content and it's ubiquitous.


Thanks! I come from the embedded world and my preferred language is C - hence the need for a calculator that can wield bits like this. I wrote this tool around 4 years ago and it was my first attempt at creating anything that wasn't a CLI tool or bare-metal firmware. In other words, I can't really compare this experience to anything!

I guess the reason I chose Qt over any web-based frameworks is I wanted a standalone app that would launch in a fraction of a second and just do its job. I don't think a webapp (if that's what they're called) would give me that. At the time, it seemed that Qt would work well and, as a bonus, be cross-platform. I had some Python experience to boot which helped.

Edit: I do have a personal site at https://www.fellerts.no/ but it's entirely static, no real js to speak of.


But Qt is a quite huge dependency, and has sort of turned into a commercial product. If you were starting to develop something similar today would you still choose Qt for it..


Qt is not turning into a commercial project. It has always been a project which is dual licensed under GPL (and later some of the modules were also licensed under LGPL) and a commercial license.

It's just that the Qt company always tries to make it non-clear that Qt is not open source to drive their sales.

Regarding bloat, Qt is quite modular and if you want just the widgets you only need QtBase and none of the additional modules.


most components are LGPL not GPL. also after I think it was Qt 5.6, they switched to LGPLv3 instead of v2, so the anti-tivoization clause applies.


Good question. If I want fast and cross-platform, GTK might be a more viable option today. What would you choose for a project like this in 2023?


Qt hands down. I don't consider GTK particularly usable or friendly, especially outside of Linux.


This is so bad, even on Linux, that the experience of trying to package a GTK4 libhandy application to the distro I use made me permanently switch from Gnome to KDE.


I'd pick the native toolkit for wherever I want to use it. If I want it on Windows, I'd use C++ & Win32 / WinRT. On mac, Swift + AppKit. For iOS, Swift + UIKit. For Linux, probably C and GTK (I mostly use Gnome-based distros).

I'd go 100% native because that's how you make the best app for that platform. I also enjoy working with different toolkits and if I wanted this on more than one platform, I think I would enjoy designing and building it for different environments. For example the version I'd make for my small screen touch-based phone would probably be significantly different than what I'd want on my keyboard and mouse equipped big screen desktop.

A multi-platform or web-based solution would have too many compromises.


Some years ago JavaFx would have been a reasonable choice.



Could you give an example (source code link) of a "truly reusable" component?


One that I have been thinking about lately is the `QEnumComboBox` [1]. It takes the concept of a combobox (i.e. drop down list/`select`) and combines it with a python `Enum` to produce a very commonly desired functionality: allowing the user to select a value and then converting it to an `Enum`. This to me seems easily reusable because it encapsulates that functionality in a clean way. I can't think of a corresponding example in a JavaScript framework, but I would love to see one. I think this might be more difficult because one can't really pass types at runtime.

I think instead of "truly reusable" I should have said something like "requires minimal configuration." I think Python's reflection capabilities allow one to supply less boilerplate when writing PyQt apps. This is just a subjective impression that I have, and unfortunately I am having trouble elaborating on this in a way that I think would be effective. That is why I asked the author what they thought, since I am wondering if anyone else has had this impression. However, I will think about this more, and I might provide more examples if I can think of them.

[1] https://pyapp-kit.github.io/superqt/widgets/qenumcombobox/


I'm sure there's a million things out in reactland for this, but even in vanilla JS it's pretty simple. I'd write it something like this: https://github.com/JacksonKearl/JSEnumComboBox/blob/main/ind..., demo at https://jacksonkearl.github.io/JSEnumComboBox/

Neither JS nor Python really have types at runtime or any other time, but you can approximate them with Objects and/or Classes (of course, I repeat myself ;) ). With some TS magic you can even get the `setEnumClass` call to be well typed, though if I were building it from scratch I'd make the EnumClass prop immutable, too many weird corner cases otherwise.

I've never worked extensively with Qt myself, but when helping out a friend making Maya plugins in Qt we'd occasionally hit SEGFAULTS from writing seemingly mundane Python that'd crash all of Maya. That was enough to turn me off of it, but looking through the docs you linked there are some compelling components. It's nice to have a component library separated from a specific framework (in the React/VUE/etc. sense)... I don't know of any in JS. Every framework seems to think their (incompatibile with everything else) approach to reactivity is the hold grail, and being modular across it would be impossible.

Though reconsidering, I suppose Qt is sorta the same... it's just another framework and their "signals" aren't Python. Ah well.

Diving deeper, signals are weird... they aren't even really part of the underlying C++! Some sort of strange new modifier Qt invented at the level of `private`/`public`/`protected` and such. https://doc.qt.io/qt-6/signalsandslots.html


I am not aware of Qt being the problem here, having built large Qt apps that run stable (coding in C++ only). I guess it is rather an issue with the Python to Qt interface.



Hmm doesn't seem to do 64bit very well: 0xdeadbeefcafebabe -> 0xdeadbeefcafeb800

Is the result by any means passing through a double? like in freakin' JS!


Good catch, that appears to be a bug! I'll have a look tomorrow.


Similar concept but more oriented for embedded development: https://www.heise.de/download/product/bitfummler-70589?hg=1&...

It includes a C interpreter and is very handy when manipulating registers.

Unfortunately not open-source.


Neat little project. Easy to setup and use.

Unfortunately with macOS's "Dark Mode" enabled the colors have little or no contrast. And the UI renders very small for my eyes (and compared to the demo gif). This is a criticism of Qt (or maybe its python bindings) rather than this project. (Screenshot: https://imgur.com/a/G9eAPoO)

I wonder if there's a way to shimmy in a "modern macOS Qt renderer" or something into an existing project like this without a rewrite?


> I wonder if there's a way to shimmy in a "modern macOS Qt renderer" or something into an existing project like this without a rewrite?

Apparently there is. I hacked something together in a new branch: https://github.com/fellerts/procal/tree/fredrik/theme. Feel free to check it out and let me know how it works for you.


I tried on macOS, yes dark mode works great now, thanks. But I needed to change all QFont('monospace', 10) occurrences to

    QFont('Monaco', 12)
in order to make it look nice.


Thanks for trying it out. If you wouldn't mind, I'd appreciate it if you could open an issue with a screenshot of how the default behavior looked.

Edit: merged a fix for this, thanks for reporting.


Shouldn't it be your operating system's job (or yours) to make the monospace font alias on your system point to a nice font?


In a perfect world, yes!

But in my experience with Qt, you always have to adjust font names separately for every OS. This is especially true for nice coding fonts.

If I had written that program, I would have brought my own font (like "Hack"), and simply set the pixel size of the font, to ensure it's exactly the same size on any OS (and I would have written it in QML, with heavy usage of Repeater, which would simplify the UI code a lot, but I digress...).


Thanks for checking it out.

You could play with the QT_SCALE_FACTOR environment variable to fix the scaling issue at least. Something like this could work:

    $ QT_SCALE_FACTOR=2 python procal.py
As for the colors, that's probably something this tool should handle. I'll take a look to see if this is an easy fix.


Cool link for the PyQt project example!

My daily calculator is `jupyter qtconsole` (formerly `ipython qtconsole`). I've had it binded to Meta+Q forever and it is very handy to have a full Python REPL which can occasionally display graphs and stuff that can pop up at hand.


I find it...mildly disconcerting that a calculator app where one of the key motivations is "it's a hassle to copy + paste things in" just chucks whatever you enter into eval().


An expression you author executes on your machine. It’s not wholly unreasonable to use eval().

If it were executing third party input on your machine, then it’s a completely different ball game.


This would be even better if it integrated with every desktop program out there.

E.g. if you want to compute the width of some object in Inkscape or Freecad, using some formula not supported by those programs.


I used to have xclip integration in procal that would copy any selected text into the input field for just this purpose. However I removed it because it wasn't particularly useful and got in the way of "normal calculating" (apparently I select text quite frequently). Let me know if you think of a usage pattern that would make sense!


LOL, nice! I wrote something quite similar a few years ago: https://github.com/os12/calc


Cool, thanks for sharing your github link.


I didn’t realize you can use Qt from Python!

How is the developer experience for that? Anyone able to contrast with Tkinter?


The developer experience is great, though its approach is much different from TKinter. The documentation is excellent, there aren't maddening incomplete corners like GTK, the results look good (if you think Qt looks good), and it's simple and straightforward. The main downside is that sometimes your code looks more like Qt and less like Python.


> The main downside is that sometimes your code looks more like Qt and less like Python.

This can be remedied to a degree: https://doc.qt.io/qtforpython/considerations.html#features


Adding the snake case does move it more to the Python idioms, for sure.


Wow I’m reading Hacker’s Delight and was just wondering if something like this existed.


Do you think to port the code to C++ or do you think to keep it in Python?


I wasn't planning on that, no. Is there a good reason to do so?


LOL, here is my C++ implementation of the same concept: https://github.com/os12/calc


I love that you include the BNF-ish grammar. Grammars are so straight-forward to read, I wish my eyes didn't glaze over during those times I've tried to sit down and create one.


What's wrong with Python? Do you find the calculator too slow?


Hi


This comment looks like it was written by ChatGPT!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: