Hello again, after many years away.
I am trying to figure out how Dolphin picks the name of a file that is dragged and dropped onto one of its windows.
Specifically: if I drag a message from the message list of KMail onto a Dolphin window, the file that results is named with a text representation of a number (and I don’t know what the number represents).
What I want to do is to implement something that will cause the dropped file to have a name based on the metadata of the dropped email message. I want the file to have the name “YYYY-MM-DD_HH_MM_[subject].eml”. Therefore, whatever process is responsible for creating the dropped file has be able to look into the message and inspect its metadata.
Problem is, I have no idea whether this is the responsibility of KMail (the origin of the dropped object) or Dolphin (the destination). I have spent hours going through the sources, but am none the wiser!
I hack my own version of Evolution to achieve this: all it requires is a few lines in em-utils.c. Files dropped from Evolution into Dolphin have just the name I want! I built my own version of Evolution (using it in KDE) to do this for years, but I have always wanted to be able to do the same with KMail, but cannot for the life of me figure out how to do it!
Any pointers would be most welcome!
Alistair
PS: Should have said: I have installed kde-builder and built Dolphin and KMail so can see the sources that I should need to hack on.
Hi, this is a bit more tricky in case of KMail.
The drag&drop is started from KMail, which sets the URL to something like “akonadi://?item=1234”. When you drop this into Dolphin, it invokes the KIO worker for “akonadi” protocol, which then effectively performs copy of the file from the virtual “akonadi” “filesystem” to your actual real filesystem.
So the right place to patch this would be in the Akonadi KIO Worker, which lives in kdepim-runtime repo, however the worker as it is now is content-type agnostic and would require a bit more work to actually get the payload (or at least envelope) of the Item if it’s an email, obtain the subject and then use it as the filename for the newly created file.
I was hoping to have this for a very long time by default in the KIO worker (also to extract contact name if the Item is contact, event summary if it’s an event etc.), never got around to implement it properly, though.
1 Like
Very many thanks, Daniel
I would not have figured that out in a million years!
I think that I have located the point in the source at which the drop name is set:
akonadiworker.cpp:206
entry.fastInsert(KIO::UDSEntry::UDS_NAME, QString::number(item.id()));
I changed this to set the name to an arbitrary constant value to see if I could change the name of the dropped file to something else, and rebuilt the kde-pim target (which seems to include the file I changed).
Now, I cannot figure out how to run kmail liked to my compiled version of akonadi. With kde-pim installed from ssytem packages, the system version of akonadi runs automatically, so my version is not used. I removed all of the native akonadi and pim packages (from Fedora 41), but now cannot figure out to run my compiled software, stored under ~/kde .
I tried adding $HOME/kde/usr/bin to my PATH, but I cannot get the akonadi server to run (it fails with “Did not find MySQL server default configuration (mysql-global.conf)”. This happens trying to start kmail or by using akonadictl directly.
I wonder if I have missed out an essential kde-builder target (I have built kde-pim), or if there is another “trick” to running a locally-built version of KDE/Plasma.
Alistair
Hello Again
I have figured out how to build and run my hacked code using the Arch build system instead.
I have also confirmed that I identified the correct line in akonadiworker.cpp. Now all I have to do is to figure out how to extract the metadata from the message and build a meaningful file name.
Thanks again
Alistair
2 Likes
Here’s a rough outline how to get the subject from Akonadi::Item
:
#include <KMime/Message>
...
std::optional<QString> subjectFromEmail(const Akonadi::Item &item)
{
if (item.hasPayload<KMime::Message::Ptr>()) {
const auto message = item.payload<KMime::Message::Ptr>();
if (const auto subject = message->subject(); subject) {
return subject->asUnicodeString();
}
}
return {};
}
You will probably need to link KPim6::Mime
library in CMake.
Hi Daniel
That is really helpful! I have started to make some progress, but still have a way to go. I am learning the language at the same time as learning the KDE software environment.
I will be away for about 10 days (with no development system), but will restart work on this on my return. Of course, I will let you and the other developers know if I produce any useful code.
Alistair
(PS: My first professional programming job was in 1984 and I have worked on at least C, Pascal, 6502, 6809 and Z80 assembler, COBOL (very badly!), Python and Lisp (best forgotten), but this is my first dig into C++. I am, quite literally, a greybeard, so it is great to still be learning something quite new and potentially doing something useful with it!)
2 Likes
Hi Alistair, feel free to reach out to me directly if you need any help
Daniel
1 Like
I have spent HOURS on this and got nowhere!
I construct a QString (called subjectString) and then pass it to:
entry.fastInsert(KIO::UDSEntry::UDS_NAME, subjectString);
When I then try the drag and drop, very rarely will it create a dropped file with a name created from my code; most of the time, it just ignores my created name and treats it as an empty string.
I like KMail, but not that much that I can spend more hours on it… so, sorry, I have given up.
KDE/Plasma is so, So SO difficult to hack on! I hate Gnome, but at least I can hack its apps to make them work as I want.
Sorry, again.
Alistair
Sorry to reply to myself, but I was just thinking: is it a problem with scope?
If I construct a QString inside the function:
KIO::UDSEntry AkonadiWorker::entryForItem(const Akonadi::Item &item)
using
QString subjectString = QString::fromStdString(“Message Exists”);
followed by
entry.fastInsert(KIO::UDSEntry::UDS_NAME, subjectString);
and the function then returns, does my subjectString still exist or has it gone out of scope and been garbage collected before it is used to create the drop file name? If so, what can I do?
I am an experienced programmer, but totally new to C++ (and am still amazed at how many times I have to type a semi-colon and almost always forget to do so )!