<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Technetium]]></title><description><![CDATA[Technetium là một hệ thống tiện ích dành riêng cho Windows, được xây dựng bằng C++ và Qt Widget. Ứng dụng tập hợp nhiều chức năng thường được sử dụng trong một ]]></description><link>https://technetium.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 26 Oct 2026 08:13:36 GMT</lastBuildDate><atom:link href="https://technetium.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Technetium]]></title><description><![CDATA[Every time I needed to rename a batch of files, clear out junk from my disk, or convert a folder of images to another format, I ended up either doing it…]]></description><link>https://technetium.hashnode.dev/technetium</link><guid isPermaLink="true">https://technetium.hashnode.dev/technetium</guid><category><![CDATA[Qt]]></category><category><![CDATA[Windows]]></category><category><![CDATA[Windows 10]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[buildinpublic]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[QPT QPT]]></dc:creator><pubDate>Sat, 24 Oct 2026 02:51:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6adc1c52e202a867ebe748ad/f3e1dd78-7c49-4fda-aa24-e29ebff7110b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>Technetium: A Portable Windows Utility Toolbox Built From Scratch With C++ and Qt</h1>
<h2>The problem I kept running into</h2>
<p>Every time I needed to rename a batch of files, clear out junk from my disk, or convert a folder of images to another format, I ended up either doing it manually or installing yet another bloated utility app — most of which come with ads, forced installers, or background telemetry I didn't ask for.</p>
<p>The open-source alternatives that <em>do</em> exist are often either abandoned, poorly maintained, or trying to do too much at once. So I decided to build my own, focused on exactly the handful of tasks I actually repeat often, nothing more.</p>
<p>That project became <strong>Technetium</strong> — a free, portable Windows utility built entirely with C++ and Qt Widgets.</p>
<h2>Design goals from day one</h2>
<ul>
<li><strong>No installer.</strong> Unzip, run the <code>.exe</code>, done.</li>
<li><strong>No ads, no telemetry, no dark patterns.</strong></li>
<li><strong>Safety first for anything destructive.</strong> Deleting files automatically should never happen silently or instantly.</li>
<li><strong>Small, focused feature set</strong> rather than trying to be an all-in-one system tool.</li>
</ul>
<p>With that in mind, here's what's inside.</p>
<h2>Feature breakdown</h2>
<h3>1. Batch Rename with full undo history</h3>
<p>Select a batch of files, apply prefixes, suffixes, sequential numbering, or find-and-replace rules, and preview the resulting filenames before committing anything.</p>
<p>What makes this more than a basic renamer: every operation is logged persistently (last 25 operations, saved to disk, surviving app restarts), and each one can be undone individually. If a file was since moved, deleted, or locked by another process, the undo process simply skips it instead of failing the whole batch — a small detail, but one that took a few iterations to get right.</p>
<h3>2. System Cleanup across 11 categories</h3>
<p>Scans and clears:</p>
<ul>
<li>Temporary files</li>
<li>Recycle Bin</li>
<li>Browser cache</li>
<li>Windows Update cache</li>
<li>Thumbnail cache</li>
<li>Prefetch data</li>
<li>Memory dump files</li>
<li>Shader cache</li>
<li>Delivery Optimization files</li>
<li>Windows Error Reporting files</li>
<li>Leftover driver installation files</li>
</ul>
<p>Sizes are calculated and shown <em>before</em> deletion, and every category can be toggled independently.</p>
<h3>3. Scheduled Cleanup — the feature I spent the most time on</h3>
<p>This is the part of the project I'm most proud of, and also where I hit the most interesting bug.</p>
<p>The idea: let the cleanup run automatically on a schedule (daily, weekly on specific weekdays, monthly on a specific date, or a simple "every N days" interval) — but do it <em>safely</em>. When the scheduled time hits, the app:</p>
<ol>
<li>Scans the selected categories first.</li>
<li>Shows a system tray notification.</li>
<li>Waits a full 60 seconds, during which the user can cancel.</li>
<li>Only then moves the files to the Recycle Bin — never permanent deletion through the automated path.</li>
</ol>
<p><strong>The bug:</strong> my first implementation of <code>calcNextRun()</code> tried to do two jobs at once — computing "the next scheduled time to display in the UI" and "deciding whether to run right now" — using the same function. Because the function always projected forward from the current moment, the condition <code>if (now &gt;= next)</code> inside the scheduler check could never be true, even when the scheduled time had clearly passed. The fix was splitting it into a pure calculation function (<code>computeNextRun(after)</code>) and a separate function that computes-and-persists the next run time to disk (<code>recomputeNextRun()</code>), so the actual trigger check compares against a <em>stored</em> value instead of recalculating a constantly-shifting target. Classic case of one function trying to serve two different callers with incompatible needs.</p>
<p>One limitation I'm upfront about: if the PC is fully shut down (not sleeping), there's no way for a background scheduler to fire — Windows just doesn't support that without BIOS-level wake timers, which felt like overkill for this project. On next launch, the app checks if a run was missed and catches up if so.</p>
<h3>4. Image Format Converter</h3>
<p>Batch-converts a folder of images (regardless of original extension) between PNG, JPG, BMP, and ICO, using <code>QImageReader::canRead()</code> to silently filter out non-image files rather than erroring out.</p>
<p>A few details that mattered more than I expected once real testing started:</p>
<ul>
<li>Filename collisions (e.g., <code>photo.png</code> and <code>photo.jpg</code> both converting to <code>.jpg</code>) needed automatic <code>_1</code>, <code>_2</code> suffixing instead of silently overwriting one of them.</li>
<li>ICO export only supports a single fixed resolution per file (16–256px) — not a multi-resolution bundle like dedicated icon tools produce. I decided this tradeoff was acceptable for the scope of the project rather than implementing multi-size ICO packing.</li>
</ul>
<h3>5. Basic multi-language support without rewriting the whole codebase</h3>
<p>The original translation system was a simple <code>Translator::t(viText, enText)</code> call sprinkled throughout the codebase — fine for two languages, but not scalable to more.</p>
<p>Rather than refactor every call site (which would have touched hundreds of lines across the project), I kept the existing <code>t(vi, en)</code> call signature completely untouched everywhere else, and changed the internal logic of <code>Translator::t()</code> instead:</p>
<ul>
<li>Vietnamese and English still return directly as before.</li>
<li>For six additional languages (Chinese, French, Spanish, Arabic, Russian, Hindi), the English string is used as a dictionary key to look up a translation. If no entry exists, it silently falls back to English instead of breaking or showing blank text.</li>
</ul>
<p>This was a deliberate tradeoff: full coverage for two languages, partial (and growing) coverage for the rest, achieved without touching the rest of the codebase. Translation contributions for the secondary languages are welcome.</p>
<h2>Tech stack</h2>
<ul>
<li><strong>Language:</strong> C++</li>
<li><strong>UI:</strong> Qt Widgets (Qt 6)</li>
<li><strong>Build system:</strong> CMake</li>
<li><strong>Compiler:</strong> MinGW 64-bit</li>
<li><strong>Platform:</strong> Windows only (for now)</li>
</ul>
<h2>Licensing note</h2>
<p>Technetium is source-available under a non-commercial license (PolyForm Noncommercial 1.0.0) — free to use, modify, and share for non-commercial purposes. Commercial use requires reaching out directly.</p>
<h2>What's next</h2>
<p>Still on the table for future iterations:</p>
<ul>
<li>Windows Explorer right-click context menu integration (open a folder directly into a specific tab)</li>
<li>A file-lock finder/unlocker built on the Restart Manager API</li>
<li>Deeper translation coverage for the secondary languages</li>
</ul>
<h2>Check it out</h2>
<p>This is a solo side project, built incrementally in my spare time — so bug reports, feedback, and translation contributions are genuinely welcome.</p>
<p><strong>GitHub:</strong> <a href="https://github.com/qptqpt199-prog/Technetium.git">github.com/qptqpt199-prog/Technetium</a></p>
<p>If you find it useful, there's a donation section in the README (currently set up for Vietnamese bank transfers / e-wallets via QR code — international donation options may come later).</p>
]]></content:encoded></item></channel></rss>