<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Pablo Ariño Muñoz</title><link>https://pabloarino.com/</link><description>Recent content on Pablo Ariño Muñoz</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://pabloarino.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Weeks 7-13 on Merkuro (GSoC 2025)</title><link>https://pabloarino.com/p/weeks-7-13-on-merkuro-gsoc-2025/</link><pubDate>Thu, 28 Aug 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/weeks-7-13-on-merkuro-gsoc-2025/</guid><description>&lt;h2 id="catching-up"&gt;&lt;strong&gt;Catching Up&lt;/strong&gt;
&lt;/h2&gt;&lt;p&gt;These last few weeks have been pretty hectic due to me moving countries and such, so I have not had the time to write a blog post detailing my weekly progress, because of this I have decided to compress it all into a singular blog post talking about all the changes I have been working on and what I plan on doing in the future.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="the-newmailnotifier-agent"&gt;The NewMailNotifier Agent
&lt;/h3&gt;&lt;p&gt;In the last blog post I wrote I talked about the progress that had been made in the &lt;code&gt;newmailnotifier&lt;/code&gt; agent, and that in the following weeks I would finish implementing the changes and testing its funcionality. Well, it ended up taking quite a bit longer as I found that several other files had to also be moved to KMail from KDE-PIM Runtime, and these ones &lt;em&gt;were&lt;/em&gt; being used in the runtime repo. The files I have found so far and that I have been looking into are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;newmailnotificationhistorybrowsertext.cpp&lt;/li&gt;
&lt;li&gt;newmailnotificationhistorybrowsertext.h&lt;/li&gt;
&lt;li&gt;newmailnotificationhistorybrowsertextwidget.cpp&lt;/li&gt;
&lt;li&gt;newmailnotificationhistorybrowsertextwidget.h&lt;/li&gt;
&lt;li&gt;newmailnotificationhistorydialog.cpp&lt;/li&gt;
&lt;li&gt;newmailnotificationhistorydialog.h&lt;/li&gt;
&lt;li&gt;newmailnotificationhistorywidget.cpp&lt;/li&gt;
&lt;li&gt;newmailnotificationhistorywidget.h&lt;/li&gt;
&lt;li&gt;newmailnotifieropenfolderjob.cpp&lt;/li&gt;
&lt;li&gt;newmailnotifieropenfolderjob.h&lt;/li&gt;
&lt;li&gt;newmailnotifiershowmessagejob.cpp&lt;/li&gt;
&lt;li&gt;newmailnotifiershowmessagejob.h&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="the-troublesome-migration-agent"&gt;The Troublesome Migration Agent
&lt;/h3&gt;&lt;p&gt;The MR for the singleshot capability in the Akonadi repo was given the green light and just recently got merged. On the other hand, the MR with the changes for the agent received feedback and several improvements were requested.&lt;/p&gt;
&lt;p&gt;Most importantly, &lt;strong&gt;Carl&lt;/strong&gt; brought to my attention how recent MR&amp;rsquo;s by &lt;strong&gt;Nicolas Fella&lt;/strong&gt; removed the job tracker from the migration agent, thus making it unnecessary to add it as a temporary folder. Both the requested changes and the removal of the folder have been carried out, while doing so I even realized that in my singleshot MR I was missing the addition of the new &lt;code&gt;finished()&lt;/code&gt;signal in the agentbase header file, which I have now also added.&lt;/p&gt;
&lt;p&gt;After doing this though, I once again focused on the problem that persisted, the singleshot capability not working properly. The migration agent would initialize without issue when running the Akonadi server but would then not shut down after completing its tasks. I knew that the &lt;code&gt;isPluginOpen()&lt;/code&gt; method worked in sending the &lt;code&gt;finished&lt;/code&gt; signal, as when I opened and closed the plugin the agent would shut down correctly.&lt;/p&gt;
&lt;p&gt;With the help of my mentor &lt;strong&gt;Claudio&lt;/strong&gt;, we found that the migrations were in fact not even running, the agent would start but the jobs would fail to run, because of this the logic implemented to signal the finilization of a job never had the chance to run, and thus &lt;code&gt;isPluginOpen()&lt;/code&gt;remained untouched.&lt;/p&gt;
&lt;p&gt;Furthermore, the way I had designed the plugin letting the agent know that it was open had proven to be insufficient, as the migrations (once we get them to run as intended) would emit the &lt;code&gt;jobFinished()&lt;/code&gt; signal after concluding, thus triggering the &lt;code&gt;isPluginOpen()&lt;/code&gt; method with the default value of false and shutting down the agent, even if the plugin was still open.&lt;/p&gt;
&lt;p&gt;The times the singleshot capability &lt;em&gt;did&lt;/em&gt; work (when opening and closing the plugin), we also found that the status would show as &amp;ldquo;Broken&amp;rdquo; and the statusMessage as &amp;ldquo;Unable to start&amp;rdquo;, which may need changing, but most troubling was that the opening of the plugin would not restart the agent, therefore only showing an empty config window. I need to find a way to either restart from the agent itself or notify Akonadi so that it restarts it when the plugin runs.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="current-status-and-whats-next"&gt;Current Status and What&amp;rsquo;s Next
&lt;/h3&gt;&lt;p&gt;The GSOC concludes next week and these last few weeks have not seen any MR requests from my part, so my plan is to continue with the refactoring beyond the end of the programme, working on completing the NewMailNotifier and Migration agents, as well as dealing with a few of the agents in KMail, namely MailFilter, MailMerge and the UnifiedMailBox.&lt;/p&gt;
&lt;p&gt;As of now, the identified issues to solve regarding the Migration agent are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The agent not knowing if the plugin is open or closed when emitting the &lt;code&gt;finished()&lt;/code&gt; signal.&lt;/li&gt;
&lt;li&gt;The migrations not running.&lt;/li&gt;
&lt;li&gt;The status and statusMessage showing as &amp;ldquo;Broken&amp;rdquo; and &amp;ldquo;Unable to start&amp;rdquo;, respectively.&lt;/li&gt;
&lt;li&gt;The agent not being able to restart itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the case of the NewMailNotifier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete the transfer of the UI related logic to KMail&lt;/li&gt;
&lt;li&gt;Test the D-Bus connection and the modified slotShowNotificationHistory()&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While there’s still work ahead, I feel that these weeks have been invaluable in terms of learning, debugging, and understanding the bigger picture of how the different Akonadi agents fit together. The experience has been both challenging and rewarding, and I’m looking forward to tackling the remaining issues with a clearer path forward.&lt;/p&gt;
&lt;p&gt;Although GSoC is officially ending, this is just a milestone rather than a finish line, and I’m excited to continue contributing to Merkuro and the KDE ecosystem as a whole.&lt;/p&gt;</description></item><item><title>Week 6 on Merkuro (GSoC 2025)</title><link>https://pabloarino.com/p/week-6-on-merkuro-gsoc-2025/</link><pubDate>Sun, 13 Jul 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/week-6-on-merkuro-gsoc-2025/</guid><description>&lt;h2 id="refactoring-the-newmailnotifier-agent"&gt;&lt;strong&gt;Refactoring the NewMailNotifier Agent&lt;/strong&gt;
&lt;/h2&gt;&lt;p&gt;With the &lt;strong&gt;Migration Agent&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;SingleShot&lt;/code&gt; capability&lt;/strong&gt; now submitted for review, this week marked the halfway point of Google Summer of Code and a natural moment to shift focus to a new component: the &lt;strong&gt;NewMailNotifier Agent&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The goal remains the same—decoupling Akonadi agents from &lt;strong&gt;QtWidgets&lt;/strong&gt; to make them lighter, modular, and easier to integrate across different platforms.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="reviewing-the-architecture"&gt;Reviewing the Architecture
&lt;/h3&gt;&lt;p&gt;The NewMailNotifier Agent is responsible for generating notifications when new email arrives. Upon inspection, it became clear that significant progress had already been made in decoupling this agent: its configuration UI was already implemented as a standalone plugin. For the most part, the agent could run headlessly.&lt;/p&gt;
&lt;p&gt;However, one lingering QtWidgets dependency remained, preventing full decoupling. The focus this week was to identify and plan its removal.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="identifying-the-remaining-dependency"&gt;Identifying the Remaining Dependency
&lt;/h3&gt;&lt;p&gt;With guidance from my mentor Carl, I located the source of the issue: a method named &lt;code&gt;showNotNotificationHistoryDialog()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This method is exposed over D-Bus and instructs the agent to display a Qt-based dialog listing recent notification texts. While functionally useful, this forces the core agent process to link against QtWidgets—just to open a dialog. This runs counter to the goal of creating lightweight, headless agents.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="refactoring-toward-separation-of-concerns"&gt;Refactoring Toward Separation of Concerns
&lt;/h3&gt;&lt;p&gt;To address this, Carl proposed a more modular design that better separates responsibilities between the agent and user interface components. This week was dedicated to exploring and implementing that approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Revising the D-Bus Interface:&lt;/strong&gt;&lt;br&gt;
Instead of a method that opens a dialog, the agent will expose the notification history as a read-only &lt;strong&gt;D-Bus property&lt;/strong&gt;. This allows client applications to retrieve the data without triggering any UI logic.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Relocating UI Logic to KMail:&lt;/strong&gt;&lt;br&gt;
The dialog used to display the notification history will be moved from the agent (in &lt;code&gt;kdepim-runtime&lt;/code&gt;) to &lt;strong&gt;KMail&lt;/strong&gt;, the primary user-facing application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Delegating Presentation Responsibility:&lt;/strong&gt;&lt;br&gt;
Going forward, KMail (or any other compatible client) will read the history data via D-Bus and handle its own UI, enabling greater flexibility and maintaining a clean separation between data handling and presentation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id="current-status-and-whats-next"&gt;Current Status and What’s Next
&lt;/h3&gt;&lt;p&gt;The changes have already been started, and the updated D-Bus interface is mostly in place. Some parts of the dialog code have been moved to KMail, but the full integration still needs testing and a few finishing touches.&lt;/p&gt;
&lt;p&gt;Next week, I’ll focus on verifying that everything works correctly, polishing the implementation, and preparing the merge request for review.&lt;/p&gt;
&lt;p&gt;Once complete, this will remove the last QtWidgets dependency from the NewMailNotifier Agent and continue the ongoing effort to modularize KDE PIM components.&lt;/p&gt;</description></item><item><title>Week 5 on Merkuro (GSoC 2025)</title><link>https://pabloarino.com/p/week-5-on-merkuro-gsoc-2025/</link><pubDate>Sun, 06 Jul 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/week-5-on-merkuro-gsoc-2025/</guid><description>&lt;h2 id="a-temporary-solution-for-job-tracking"&gt;&lt;strong&gt;A Temporary Solution for Job Tracking&lt;/strong&gt;
&lt;/h2&gt;&lt;p&gt;This week, I revisited the &lt;code&gt;KUiServerJobTracker&lt;/code&gt; issue in the &lt;strong&gt;PIM Migration Agent&lt;/strong&gt;. After last week’s D-Bus debugging and architectural cleanup, it became clear that replacing it entirely was more complex than initially expected.&lt;/p&gt;
&lt;p&gt;After discussing with my mentor Carl, he summarized the situation in an email to the KDE PIM mailing list. In it, he outlined the limitations we were facing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The agent relies on KUiServerJobTracker, which aside from requiring a port to KUiServerV2JobTracker, also has the issue that it links to QtWidgets while not using QWidget itself.”&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The email resulted in feedback from &lt;strong&gt;Volker Krause&lt;/strong&gt;. In his response he agreed with one of Carl&amp;rsquo;s suggestion that I ultimately pursued: rather than remove the job tracker altogether or build an entirely new progress infrastructure, I created a local &lt;strong&gt;copy of &lt;code&gt;KUiServerV2JobTracker&lt;/code&gt;&lt;/strong&gt; inside the &lt;code&gt;kdepim-runtime&lt;/code&gt; repository and carefully stripped out its QtWidgets linkage.&lt;/p&gt;
&lt;p&gt;This forked version is temporary and self-contained, with a clear path to removal once the upstream KDE Frameworks address the QtWidgets dependency—likely by KF7. It allowed me to retain proper system tray integration for job tracking (which &lt;code&gt;AgentBase&lt;/code&gt;’s built-in D-Bus support cannot currently provide), while still meeting the goal of removing QtWidgets from the Migration Agent&amp;rsquo;s core.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="shedding-the-final-dependencies"&gt;Shedding the Final Dependencies
&lt;/h3&gt;&lt;p&gt;With the tracker replaced, I focused on removing the last traces of QtWidgets from the Migration Agent. This included cleaning up the custom D-Bus interface and eliminating now-redundant methods. The final dependencies were located in individual subcomponent &lt;code&gt;CMakeLists.txt&lt;/code&gt; files, which were still linking against QtWidgets.&lt;/p&gt;
&lt;p&gt;After updating those, the result is a fully decoupled agent:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The PIM Migration Agent’s core logic is now completely free of QtWidgets.&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;In addition, I integrated the manual migration tasks into the job executor, allowing them to report progress using the same job tracking mechanisms as the automated tasks.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="a-new-akonadi-capability-singleshot-agents"&gt;A New Akonadi Capability: &lt;code&gt;SingleShot&lt;/code&gt; Agents
&lt;/h3&gt;&lt;p&gt;The mailing list discussion also highlighted another inefficiency: the Migration Agent doesn&amp;rsquo;t need to run persistently. As Volker suggested:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Keep it as an agent but give it a special ‘SingleShot’ flag&amp;hellip; with Akonadi shutting it down again automatically once done.”&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Building on this idea, I introduced a new Akonadi capability: &lt;strong&gt;&lt;code&gt;SingleShot&lt;/code&gt; agents&lt;/strong&gt;. This lets agents perform their work once and automatically exit afterward, conserving system resources.&lt;/p&gt;
&lt;p&gt;The mechanism works as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;An agent declares &lt;code&gt;X-Akonadi-Capabilities=SingleShot&lt;/code&gt; in its &lt;code&gt;.desktop&lt;/code&gt; file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When launched, the agent does its work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once finished, it emits a new &lt;code&gt;finished()&lt;/code&gt; D-Bus signal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Akonadi manager listens for this signal and terminates the agent process.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This pattern fits well with agents like the Migration Agent that don’t need to remain active beyond their immediate tasks.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="current-status-and-whats-next"&gt;Current Status and What&amp;rsquo;s Next
&lt;/h3&gt;&lt;p&gt;Draft merge requests for both &lt;a class="link" href="https://invent.kde.org/pim/akonadi/-/merge_requests/269" target="_blank" rel="noopener"
&gt;akonadi&lt;/a&gt; and &lt;a class="link" href="https://invent.kde.org/pim/kdepim-runtime/-/merge_requests/257" target="_blank" rel="noopener"
&gt;kdepim-runtime&lt;/a&gt; are already open to gather feedback on the &lt;code&gt;SingleShot&lt;/code&gt; capability and the updated job tracking approach.&lt;/p&gt;
&lt;p&gt;The only remaining issue is that the &lt;code&gt;finished()&lt;/code&gt; signal doesn’t seem to shut down the agent as expected when testing through &lt;code&gt;akonadiconsole&lt;/code&gt;. Debugging this signal propagation is my focus for the upcoming week. Once resolved, the agent will fully behave as a lightweight, on-demand component.&lt;/p&gt;
&lt;p&gt;This week’s changes not only complete the agent’s QtWidgets decoupling but also introduce a meaningful architectural improvement to Akonadi itself—one that may benefit other agents in the future.&lt;/p&gt;</description></item><item><title>Week 4 on Merkuro (GSoC 2025)</title><link>https://pabloarino.com/p/week-4-on-merkuro-gsoc-2025/</link><pubDate>Sun, 29 Jun 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/week-4-on-merkuro-gsoc-2025/</guid><description>&lt;h2 id="etesync-resource-refactoring-merged"&gt;&lt;strong&gt;EteSync Resource Refactoring Merged&lt;/strong&gt;
&lt;/h2&gt;&lt;p&gt;This week, the &lt;a class="link" href="https://invent.kde.org/pim/kdepim-runtime/-/merge_requests/244" target="_blank" rel="noopener"
&gt;merge request for the EteSync resource&lt;/a&gt; has been reviewed and &lt;strong&gt;successfully merged!&lt;/strong&gt; This marks a key milestone in the project: EteSync is the first resource to be fully refactored, with its UI logic cleanly separated into a standalone configuration plugin.&lt;/p&gt;
&lt;p&gt;Based on feedback from my mentors, I made a few final revisions before the merge. One important addition was a &lt;code&gt;.notifyrc&lt;/code&gt; file for the EteSync resource. This allows the headless EteSync resource to make use of &lt;code&gt;KNotification&lt;/code&gt; for reporting errors or status updates, integrating with the user notification system in a way that doesn’t depend on a UI.&lt;/p&gt;
&lt;p&gt;With the resource no longer depending on QtWidgets, and its configuration interface now dynamically loaded, this change contributes to our broader goal of making the Merkuro suite lighter and more adaptable for mobile environments.&lt;/p&gt;
&lt;p&gt;After the merge, my mentor Carl checked the memory usage using System Monitor. The improvements were measurable: the EteSync resource now uses approximately &lt;strong&gt;9.5 MiB&lt;/strong&gt; of RAM, compared to the &lt;strong&gt;22 MiB&lt;/strong&gt; used prior to the refactor.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="the-job-tracker-and-a-d-bus-debugging"&gt;The Job Tracker and a D-Bus Debugging
&lt;/h3&gt;&lt;p&gt;With Etesync out of the way, I turned my full attention back to the &lt;strong&gt;PIM Migration Agent&lt;/strong&gt;. The next logical step was to resolve the &lt;code&gt;KUiServerJobTracker&lt;/code&gt; problem I identified last week. My initial plan was to replace it entirely with the progress-reporting tools built directly into Akonadi&amp;rsquo;s &lt;code&gt;AgentBase&lt;/code&gt;. But, while inspecting the Akonadi code, I realized this approach wouldn&amp;rsquo;t be viable for my use case.&lt;/p&gt;
&lt;p&gt;Although &lt;code&gt;AgentBase&lt;/code&gt; does provide D-Bus signals for job progress and status updates, these are low-level and do not integrate directly with the system tray or display persistent visual feedback to the user. In contrast, &lt;code&gt;KUiServerV2JobTracker&lt;/code&gt; automatically presents progress as desktop notifications or tray-based UI elements.&lt;/p&gt;
&lt;p&gt;Still, I implemented the changes, compiled the code, and launched &lt;code&gt;akonadiconsole&lt;/code&gt; to test. The good news: the refactored agent started and the configuration plugin loaded. The bad news: they weren’t talking to each other. The D-Bus communication I had set up last week was failing.&lt;/p&gt;
&lt;p&gt;This sent me down a debugging rabbit hole. My first hypothesis was that the agent needed its own &lt;code&gt;.service&lt;/code&gt; file to properly register on the D-Bus session bus. I spent a good chunk of time creating and tweaking one, but the D-Bus connection simply refused to work as intended. The plugin and the agent remained strangers.&lt;/p&gt;
&lt;p&gt;After much investigation I discovered the root cause, and it was a typical environment problem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;akonadiconsole&lt;/code&gt; was using the system D-Bus, while my development build of the agent was trying to register on the user session D-Bus managed by my Plasma desktop.&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;They were on two completely different communication networks! This immediately explained why my custom dbus interface had no effect—&lt;code&gt;akonadiconsole&lt;/code&gt; was never even looking for it in the user session. To solve this I ran:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;kde-builder - -run akonadictl restart&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;After this I ran the &lt;code&gt;akonadiconsole&lt;/code&gt; once again and this time the D-Bus connection worked as intended.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="whats-next"&gt;What&amp;rsquo;s Next?
&lt;/h3&gt;&lt;p&gt;For next week, the priorities are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Re-evaluate the job tracking solution for the Migration Agent, now with a proper understanding of the D-Bus context.&lt;/li&gt;
&lt;li&gt;Push forward with removing the final QtWidgets dependencies.&lt;/li&gt;
&lt;li&gt;Finalize the plugin-agent communication pathway with reliable, real-time interaction.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The refactor of EteSync and the progress made with D-Bus integration in the Migration Agent continue to move the project toward a more modular and future-proof codebase.&lt;/p&gt;</description></item><item><title>Week 3 on Merkuro (GSoC 2025)</title><link>https://pabloarino.com/p/week-3-on-merkuro-gsoc-2025/</link><pubDate>Sun, 22 Jun 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/week-3-on-merkuro-gsoc-2025/</guid><description>&lt;h2 id="tackling-the-migration-agent"&gt;&lt;strong&gt;Tackling the Migration Agent&lt;/strong&gt;
&lt;/h2&gt;&lt;p&gt;For week three, I finished resolving the configuration window issue for the EteSync resource by &lt;strong&gt;hiding the default configuration window&lt;/strong&gt; and programmatically linking the &lt;strong&gt;wizard’s “Accepted” and “Rejected” states&lt;/strong&gt; to the configuration window’s &lt;code&gt;accept()&lt;/code&gt; and &lt;code&gt;reject()&lt;/code&gt; methods. This ensured that the wizard cleanly replaced the built-in dialog without leaving a “zombie” window behind. I’ve submitted a &lt;a class="link" href="https://invent.kde.org/pim/kdepim-runtime/-/merge_requests/244" target="_blank" rel="noopener"
&gt;merge request&lt;/a&gt; for these changes so it can be reviewed and integrated upstream.&lt;/p&gt;
&lt;p&gt;With that resolved, I moved on to a new and intriguing component: the &lt;strong&gt;PIM Migration Agent&lt;/strong&gt;. This agent is responsible for managing data migrations between different Akonadi versions or formats — a critical part of ensuring smooth transitions when updating KDE PIM components.&lt;/p&gt;
&lt;p&gt;And like the other agents and resources, it was time for it to &lt;strong&gt;shed its QtWidgets dependency&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="decoupling-the-ui"&gt;Decoupling the UI
&lt;/h3&gt;&lt;p&gt;Following the established pattern, I began by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Creating a &lt;strong&gt;dedicated UI plugin&lt;/strong&gt; for the migration agent&amp;rsquo;s configuration dialog&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Removing the old &lt;code&gt;configure()&lt;/code&gt; method from the agent&amp;rsquo;s core logic&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Updating the relevant &lt;code&gt;CMakeLists.txt&lt;/code&gt; files to support the plugin and cleanly separate UI code from the core agent&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, while this transition was relatively smooth, the &lt;strong&gt;plugin-agent communication&lt;/strong&gt; needed more work to function correctly in this new structure.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="creating-a-d-bus-interface-for-plugin-agent-communication"&gt;Creating a D-Bus Interface for Plugin-Agent Communication
&lt;/h3&gt;&lt;p&gt;To enable proper communication between the configuration plugin and the migration agent, I created a new D-Bus interface:&lt;br&gt;
&lt;strong&gt;&lt;code&gt;org.kde.Akonadi.MigrationAgent&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This interface allows the plugin to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Receive status or configuration information&lt;/strong&gt; from the agent&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Send information back&lt;/strong&gt; if needed (e.g., configuration changes)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To support this, I also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Modified the &lt;code&gt;CMakeLists.txt&lt;/code&gt; to include the interface and generate the corresponding D-Bus adaptor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Updated both the &lt;code&gt;migrationagent&lt;/code&gt; and &lt;code&gt;migrationstatuswidget&lt;/code&gt; files to use the new D-Bus interface for interaction&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This ensures the plugin can communicate cleanly with the agent without relying on any hard-coded QtWidgets calls or tightly coupled logic.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="the-kuiserverjobtracker-problem-still-pending"&gt;The KUiServerJobTracker Problem (Still Pending)
&lt;/h3&gt;&lt;p&gt;While working on the migration agent, I encountered a significant QtWidget dependency:&lt;br&gt;
&lt;strong&gt;&lt;code&gt;KUiServerJobTracker&lt;/code&gt;&lt;/strong&gt;, which handles job progress display by showing dialogs and notifications automatically.&lt;/p&gt;
&lt;p&gt;Removing it is straightforward — but it leaves a gap:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How should the migration agent report progress to the user once &lt;code&gt;KUiServerJobTracker&lt;/code&gt; is gone?&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;m currently exploring options for replacing it, possibly using a &lt;strong&gt;D-Bus-based mechanism&lt;/strong&gt; where the agent broadcasts progress updates and a separate component (e.g., the plugin or a tray app) displays them. This would decouple the presentation layer from the agent&amp;rsquo;s logic, but I haven&amp;rsquo;t yet finalized the design.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="whats-next"&gt;What&amp;rsquo;s Next?
&lt;/h3&gt;&lt;p&gt;My immediate priority is to &lt;strong&gt;test the new plugin&lt;/strong&gt; and the communication logic to ensure everything works correctly. In parallel, I’ll continue thinking through a robust replacement for &lt;code&gt;KUiServerJobTracker&lt;/code&gt;, aiming for a modular, widget-free solution.&lt;/p&gt;
&lt;p&gt;This week introduced new architectural challenges, but also laid the groundwork for cleaner, more maintainable agents. I’m excited to keep building on this momentum next week!&lt;/p&gt;</description></item><item><title>Week 2 on Merkuro (GSoC 2025)</title><link>https://pabloarino.com/p/week-2-on-merkuro-gsoc-2025/</link><pubDate>Sun, 15 Jun 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/week-2-on-merkuro-gsoc-2025/</guid><description>&lt;h2 id="from-refactor-to-functioning-plugin"&gt;&lt;strong&gt;From Refactor to Functioning Plugin&lt;/strong&gt;
&lt;/h2&gt;&lt;p&gt;Hi again! Week two was all about turning last week’s refactored EteSync resource and newly separated configuration plugin into a fully working, stable component. While the initial plugin structure was in place, this week focused on making the pieces actually work together — and debugging some tricky issues that emerged during testing.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="removing-qtwidgets-dependencies-with-knotification"&gt;Removing QtWidgets Dependencies with KNotification
&lt;/h3&gt;&lt;p&gt;While testing, I discovered that the original EteSync resource code used &lt;code&gt;QDialog&lt;/code&gt; and &lt;code&gt;KMessageBox&lt;/code&gt; directly for showing error messages or status updates. These widget-based UI elements are too heavy for a background resource and conflict with the goal of keeping the resource lightweight and GUI-free.&lt;/p&gt;
&lt;p&gt;To address this, I replaced them with a much cleaner approach: creating &lt;code&gt;KNotification&lt;/code&gt; instances directly. This allows the resource to send system notifications (like “EteSync sync successful” or error messages) through the desktop’s notification system, without relying on any &lt;code&gt;QtWidgets&lt;/code&gt;. As a result, the resource is now fully compatible with non-GUI environments and no longer needs to link against the QtWidgets library.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="refactoring-settings-management-for-plugin-compatibility"&gt;Refactoring Settings Management for Plugin Compatibility
&lt;/h3&gt;&lt;p&gt;Another major change this week involved how the resource handles its settings.&lt;/p&gt;
&lt;p&gt;Previously, the configuration was implemented as a &lt;strong&gt;singleton&lt;/strong&gt;, meaning both the resource and its configuration plugin were sharing a single instance of the settings object. This worked in the old, tightly-coupled model, but caused conflicts in the new plugin-based architecture.&lt;/p&gt;
&lt;p&gt;To fix this, I updated the &lt;code&gt;settings.kcfgc&lt;/code&gt; file to set &lt;code&gt;singleton=false&lt;/code&gt;. This change allows the resource and the configuration plugin to maintain &lt;strong&gt;separate instances&lt;/strong&gt; of the settings object, avoiding interference. I also updated both &lt;code&gt;etesyncclientstate.cpp&lt;/code&gt; and &lt;code&gt;etesyncresource.cpp&lt;/code&gt; to properly manage their respective configurations.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="solving-the-zombie-window-issue"&gt;Solving the “Zombie Window” Issue
&lt;/h3&gt;&lt;p&gt;One final issue emerged after separating the UI: the &lt;strong&gt;configuration wizard&lt;/strong&gt; now appears in a separate window from the main Akonadi configuration dialog. When the wizard is completed and closes, the original configuration window — now empty and disconnected — remains open.&lt;/p&gt;
&lt;p&gt;Clicking buttons on this leftover window causes terminal errors, since it no longer communicates with a valid process. This results in a confusing and potentially buggy experience for users.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="whats-next"&gt;What’s Next?
&lt;/h3&gt;&lt;p&gt;My next task is to figure out a clean way to close the original parent window when the wizard completes, ensuring a smooth and error-free configuration flow. In addition to that, I’ll begin testing the full integration between the EteSync resource and its configuration plugin to ensure everything works correctly — from saving and applying settings to triggering synchronization. This will help verify that the decoupling is both functionally solid and user-friendly.&lt;/p&gt;</description></item><item><title>Week 1 on Merkuro (GSoC 2025)</title><link>https://pabloarino.com/p/week-1-on-merkuro-gsoc-2025/</link><pubDate>Sun, 08 Jun 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/week-1-on-merkuro-gsoc-2025/</guid><description>&lt;h2 id="kicking-off-with-etesync-and-ui-decoupling"&gt;&lt;strong&gt;Kicking Off with EteSync and UI Decoupling&lt;/strong&gt;
&lt;/h2&gt;&lt;p&gt;The first week of my Google Summer of Code journey with the KDE community has nearly come to an end, and it&amp;rsquo;s been an exciting start. As a quick reminder, my project — &lt;strong&gt;&amp;ldquo;Merkuro – Porting Away from QtWidgets&amp;rdquo;&lt;/strong&gt; — focuses on making Akonadi components leaner by &lt;strong&gt;decoupling their UI from core logic&lt;/strong&gt; and reducing dependencies on &lt;code&gt;QtWidgets&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="choosing-where-to-begin"&gt;Choosing Where to Begin
&lt;/h3&gt;&lt;p&gt;Originally, I planned to begin with the &lt;strong&gt;KMail agents&lt;/strong&gt;. However, after discussing it with one of my mentors, &lt;a class="link" href="https://claudiocambra.com/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Claudio&lt;/strong&gt;&lt;/a&gt;, we realized that these agents may benefit from more than just UI decoupling — they are &lt;strong&gt;prime candidates to be moved into the &lt;code&gt;kdepim-runtime&lt;/code&gt; repository&lt;/strong&gt;. This would help consolidate Akonadi agents and resources for better &lt;strong&gt;maintainability and cohesion&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Because this is a larger architectural change, we agreed it would be more effective to tackle it later in the project.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="refocusing-on-resources-within-kdepim-runtime"&gt;Refocusing on Resources Within &lt;code&gt;kdepim-runtime&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;I shifted my focus to the agents and resources already in &lt;code&gt;kdepim-runtime&lt;/code&gt;. I was pleased to see that some groundwork for decoupling had already been laid for resources like &lt;strong&gt;DAV&lt;/strong&gt;, &lt;strong&gt;Google&lt;/strong&gt;, and &lt;strong&gt;IMAP&lt;/strong&gt;, giving me a solid reference to work from.&lt;/p&gt;
&lt;p&gt;With a clear direction, I chose the &lt;strong&gt;EteSync resource&lt;/strong&gt; as my first decoupling target.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="decoupling-the-etesync-resource"&gt;Decoupling the EteSync Resource
&lt;/h3&gt;&lt;p&gt;This week, I carried out three main tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Refactoring the Core Code&lt;/strong&gt;&lt;br&gt;
I modified &lt;code&gt;etesyncresource.cpp/.h&lt;/code&gt; and &lt;code&gt;etesyncclientstate.cpp/.h&lt;/code&gt; to remove all UI-related logic previously embedded in the core functionality.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Updating the Build System&lt;/strong&gt;&lt;br&gt;
I adjusted the &lt;code&gt;CMakeLists.txt&lt;/code&gt; to ensure the resource no longer compiles or links against any &lt;code&gt;QtWidgets&lt;/code&gt;-based code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Creating the UI Plugin&lt;/strong&gt;&lt;br&gt;
I created a dedicated configuration plugin consisting of &lt;code&gt;etesyncconfig.cpp&lt;/code&gt; and its corresponding &lt;code&gt;.json&lt;/code&gt; metadata file. All UI-related code now lives in this separate plugin.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id="testing-with-akonadi-console"&gt;Testing with Akonadi Console
&lt;/h3&gt;&lt;p&gt;To verify my changes, I’ve been using the &lt;strong&gt;Akonadi Console&lt;/strong&gt;, a powerful tool that lets developers inspect and manage Akonadi agents and resources in real time. My goal is to ensure the refactored EteSync resource functions correctly in &lt;strong&gt;Merkuro&lt;/strong&gt;, &lt;strong&gt;Kontact&lt;/strong&gt;, and any other application that uses Akonadi.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="whats-next"&gt;What’s Next?
&lt;/h3&gt;&lt;p&gt;Before submitting a merge request, I plan to carry out thorough &lt;strong&gt;initial testing&lt;/strong&gt; to ensure everything is stable and there are no regressions. Once the EteSync resource is confirmed to work cleanly with the plugin, I’ll move on to the next target in the decoupling process.&lt;/p&gt;
&lt;p&gt;It’s been a productive first week, and I’m looking forward to building on this momentum in the weeks to come!&lt;/p&gt;</description></item><item><title>Start of GSoC 2025 Journey</title><link>https://pabloarino.com/p/start-of-gsoc-2025-journey/</link><pubDate>Thu, 08 May 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/start-of-gsoc-2025-journey/</guid><description>&lt;p&gt;I&amp;rsquo;m thrilled to announce that I&amp;rsquo;ll be participating in Google Summer of Code 2025 with the KDE community and my mentors &lt;strong&gt;Claudio Cambra&lt;/strong&gt;, &lt;strong&gt;Carl Schwan&lt;/strong&gt; and &lt;strong&gt;Aakarsh MJ&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;This summer, I’ll be working on the Merkuro suite with a focus on a project called &lt;strong&gt;Merkuro – Porting Away from QtWidgets&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="the-challenge-why-merkuro-needs-to-slim-down"&gt;The Challenge: Why Merkuro Needs to Slim Down
&lt;/h2&gt;&lt;p&gt;Merkuro is a KDE application suite, aiming to provide a seamless experience for email, calendaring, and contacts. At its core, it leverages Akonadi, KDE&amp;rsquo;s powerful PIM data storage framework.&lt;/p&gt;
&lt;p&gt;Currently, many Akonadi agents and resources (the components that fetch and manage your data from various services) load their configuration dialogs using QtWidgets. While QtWidgets is a robust UI toolkit, it&amp;rsquo;s also quite &amp;ldquo;heavy.&amp;rdquo; This means these components, by default, include substantial UI code, leading to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Increased Memory Footprint:&lt;/strong&gt; Each agent/resource can consume an extra 15-20 MiB of RAM just by including these UI elements, even when they&amp;rsquo;re not actively being configured.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance Hindrance on Mobile:&lt;/strong&gt; For Merkuro to truly shine on mobile devices, where resources are often constrained, this overhead is a significant bottleneck.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The goal is to make Merkuro lean, efficient, and perfectly suited for both desktop and mobile environments.&lt;/p&gt;
&lt;h2 id="my-objective-decoupling-ui-for-a-lighter-future"&gt;My Objective: Decoupling UI for a Lighter Future
&lt;/h2&gt;&lt;p&gt;The primary goal of my GSoC project is to refactor these Akonadi agents and resources by &lt;strong&gt;decoupling their configuration dialogs from their underlying logic&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The plan is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Separate UI from Logic:&lt;/strong&gt; I&amp;rsquo;ll move the QtWidgets-based configuration dialogs out of the core agent/resource code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamically Loaded Plugins:&lt;/strong&gt; These UI dialogs will become separate, dynamically loaded plugins. This means the core agent/resource can run without loading any UI code unless a host application (like Merkuro or KMail&amp;rsquo;s settings) specifically requests the configuration interface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced Dependencies:&lt;/strong&gt; By doing this, we can remove heavy QtWidgets header file inclusions from the core components. For example, we can switch from &lt;code&gt;QApplication&lt;/code&gt; (which pulls in all of QtWidgets) to the much lighter &lt;code&gt;QCoreApplication&lt;/code&gt; for the agent&amp;rsquo;s primary functionality.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This separation not only brings immediate benefits in terms of memory and performance but also lays crucial groundwork for the next big step: &lt;strong&gt;modernizing the user interface by transitioning to QtQuick/QML&lt;/strong&gt;. With a clear segregation, future efforts can focus on building sleek, modern QtQuick UIs without wrestling with embedded QtWidgets code.&lt;/p&gt;
&lt;h2 id="key-deliverables-what-ill-be-working-on"&gt;Key Deliverables: What I&amp;rsquo;ll Be Working On
&lt;/h2&gt;&lt;p&gt;Over the summer, I&amp;rsquo;ll be focusing on several key areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Refactoring Core Components:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Targeting specific Akonadi agents in &lt;strong&gt;KMail&lt;/strong&gt; (like &lt;code&gt;archivemail&lt;/code&gt;, &lt;code&gt;mailfilter&lt;/code&gt;, &lt;code&gt;sendlater&lt;/code&gt; agents) and resources in the &lt;strong&gt;KDE PIM Runtime&lt;/strong&gt; (like &lt;code&gt;pop3&lt;/code&gt;, &lt;code&gt;imap&lt;/code&gt;, &lt;code&gt;google&lt;/code&gt;, &lt;code&gt;ews&lt;/code&gt; resources).&lt;/li&gt;
&lt;li&gt;The main task here is to strip out embedded QtWidgets dependencies from their primary functionality.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modifying Build Configurations:&lt;/strong&gt; Updating CMake files to reflect these changes, ensuring unnecessary UI files are not compiled into the core components, and reducing overall dependencies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creating Dedicated Configuration Plugins:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Implementing plugin factory classes (conforming to &lt;code&gt;Akonadi::AgentConfigurationBase&lt;/code&gt; and &lt;code&gt;Akonadi::AgentConfigurationFactoryBase&lt;/code&gt; interfaces). This ensures that host applications can dynamically discover and load these new UI plugins.&lt;/li&gt;
&lt;li&gt;Providing accurate metadata (via JSON files) for each plugin to integrate smoothly with the existing Akonadi framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testing and Documentation:&lt;/strong&gt; Rigorously testing all changes to verify the memory usage reduction and ensure the new plugin-based system works flawlessly on both desktop and mobile. I&amp;rsquo;ll also be documenting the changes for future developers.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Welcome!</title><link>https://pabloarino.com/p/welcome/</link><pubDate>Sun, 06 Apr 2025 00:00:00 +0000</pubDate><guid>https://pabloarino.com/p/welcome/</guid><description>&lt;p&gt;This is my personal blog, a space where I plan to document various aspects of my work and interests. Thanks for stopping by.&lt;/p&gt;
&lt;p&gt;Primarily, this will be a journal for my participation in &lt;strong&gt;Google Summer of Code 2025&lt;/strong&gt;. I&amp;rsquo;ll be sharing weekly updates on my project: the progress made, challenges encountered, and lessons learned along the way.&lt;/p&gt;
&lt;p&gt;Beyond GSoC, I also intend to use this space to write about my ongoing &lt;strong&gt;coding journey&lt;/strong&gt;. This might include notes, tutorials, or thoughts on new technologies I&amp;rsquo;m exploring, such as Merkuro development, KDE projects, or C++ concepts.&lt;/p&gt;
&lt;p&gt;Occasionally, I might also share &lt;strong&gt;other thoughts or experiences&lt;/strong&gt; – perhaps related to tech, books, or other projects I&amp;rsquo;m tinkering with.&lt;/p&gt;
&lt;p&gt;During the GSoC period this summer, I aim to post at least weekly. Afterwards, updates will be more sporadic, as inspiration or notable progress dictates. The style will likely vary, from more technical pieces to informal reflections.&lt;/p&gt;
&lt;p&gt;While this blog serves mainly as a personal record, I hope that fellow GSoC participants, open-source enthusiasts, or anyone interested in these topics might find something of value or interest here.&lt;/p&gt;
&lt;p&gt;You can find my work and connect on platforms like &lt;a class="link" href="https://github.com/Pabarino" target="_blank" rel="noopener"
&gt;GitHub&lt;/a&gt; and &lt;a class="link" href="https://invent.kde.org/pabarino" target="_blank" rel="noopener"
&gt;GitLab&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;Code is like humor. When you have to explain it, it’s bad.&amp;rdquo;&lt;/em&gt;
– Cory House&lt;/p&gt;</description></item><item><title>Archives</title><link>https://pabloarino.com/archives/</link><pubDate>Sun, 06 Mar 2022 00:00:00 +0000</pubDate><guid>https://pabloarino.com/archives/</guid><description/></item><item><title>Links</title><link>https://pabloarino.com/links/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://pabloarino.com/links/</guid><description>&lt;p&gt;Here I curate a selection of my favorite tools, platforms, and resources that I find indispensable in my workflows. Feel free to explore each entry and discover more about the technologies I use and recommend.&lt;/p&gt;</description></item><item><title>Search</title><link>https://pabloarino.com/search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://pabloarino.com/search/</guid><description/></item></channel></rss>