From b63ef0b47ce0ab3de7ae5bd0dabdb7fbc2b45198 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sun, 12 Jul 2026 20:43:32 +0200 Subject: [PATCH] Add "New Denote File..." context menu action Shows when right-clicking a directory. Dialog asks for title, tags, signature, and extension (.org default). Creates the file with correct denote filename and frontmatter. --- fileitemaction/denote_fileitemaction.cpp | 90 ++++++++++++++++++++++-- fileitemaction/denote_fileitemaction.h | 1 + 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/fileitemaction/denote_fileitemaction.cpp b/fileitemaction/denote_fileitemaction.cpp index b5f9561..d0a128f 100644 --- a/fileitemaction/denote_fileitemaction.cpp +++ b/fileitemaction/denote_fileitemaction.cpp @@ -29,15 +29,24 @@ DenoteFileItemAction::DenoteFileItemAction(QObject *parent, const QVariantList & QList DenoteFileItemAction::actions(const KFileItemListProperties &fileItemInfos, QWidget *parentWidget) { - // Only show for single file selection that is NOT already a denote file if (fileItemInfos.items().count() != 1) return {}; const KFileItem item = fileItemInfos.items().first(); - if (item.isDir()) - return {}; - // Check if already a denote file + // Directory: show "New Denote File..." + if (item.isDir()) { + auto *action = new QAction(QStringLiteral("New Denote File..."), parentWidget); + action->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); + + const QString dirPath = item.localPath(); + connect(action, &QAction::triggered, this, [this, dirPath, parentWidget]() { + createDenoteFile(dirPath, parentWidget); + }); + return {action}; + } + + // Non-denote file: show "Rename with Denote..." Denote::Metadata meta = Denote::parseFilename(item.localPath()); if (meta.isValid()) return {}; @@ -159,4 +168,77 @@ void DenoteFileItemAction::renameWithDenote(const KFileItemList &items, QWidget } } +void DenoteFileItemAction::createDenoteFile(const QString &dirPath, QWidget *parentWidget) +{ + QDialog dialog(parentWidget); + dialog.setWindowTitle(QStringLiteral("New Denote File")); + if (auto *screen = dialog.screen()) { + dialog.setMinimumWidth(screen->availableGeometry().width() / 3); + } + + auto *layout = new QVBoxLayout(&dialog); + auto *form = new QFormLayout(); + + auto *titleEdit = new QLineEdit(); + titleEdit->setPlaceholderText(QStringLiteral("Note title")); + form->addRow(QStringLiteral("Title:"), titleEdit); + + auto *tagsEdit = new QLineEdit(); + tagsEdit->setPlaceholderText(QStringLiteral("tag1, tag2, tag3")); + form->addRow(QStringLiteral("Tags:"), tagsEdit); + + auto *sigEdit = new QLineEdit(); + sigEdit->setPlaceholderText(QStringLiteral("(optional)")); + form->addRow(QStringLiteral("Signature:"), sigEdit); + + auto *extEdit = new QLineEdit(QStringLiteral(".org")); + form->addRow(QStringLiteral("Extension:"), extEdit); + + layout->addLayout(form); + + auto *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + layout->addWidget(buttons); + + if (dialog.exec() != QDialog::Accepted) + return; + + const QString title = titleEdit->text().trimmed(); + if (title.isEmpty()) + return; + + QStringList tags; + const QString tagsText = tagsEdit->text().trimmed(); + if (!tagsText.isEmpty()) { + tags = tagsText.split(QLatin1Char(','), Qt::SkipEmptyParts); + for (auto &t : tags) + t = t.trimmed().toLower(); + } + + const QString signature = sigEdit->text().trimmed(); + QString ext = extEdit->text().trimmed(); + if (!ext.startsWith(QLatin1Char('.'))) + ext.prepend(QLatin1Char('.')); + + // Build filename and full path + const QString filename = Denote::buildFilename(title, tags, signature, ext); + const QString filePath = QDir(dirPath).filePath(filename); + + // Create file with frontmatter if supported + Denote::FileType fileType = Denote::fileTypeFromExtension(ext); + QFile file(filePath); + if (file.open(QIODevice::WriteOnly)) { + if (fileType != Denote::FileType::Unknown) { + Denote::FrontMatter fm; + fm.title = title; + fm.tags = tags; + fm.identifier = Denote::parseFilename(filePath).identifier; + fm.signature = signature; + file.write(Denote::marshalFrontMatter(fm, fileType)); + } + file.close(); + } +} + #include "denote_fileitemaction.moc" diff --git a/fileitemaction/denote_fileitemaction.h b/fileitemaction/denote_fileitemaction.h index 948530a..a0caa95 100644 --- a/fileitemaction/denote_fileitemaction.h +++ b/fileitemaction/denote_fileitemaction.h @@ -16,6 +16,7 @@ public: private: void renameWithDenote(const KFileItemList &items, QWidget *parentWidget); + void createDenoteFile(const QString &dirPath, QWidget *parentWidget); }; #endif // KDENOTE_FILEITEMACTION_H