kdenote/fileitemaction/denote_fileitemaction.cpp

158 lines
4.9 KiB
C++

#include "denote_fileitemaction.h"
#include "denote_frontmatter.h"
#include "denote_metadata.h"
#include <KFileItem>
#include <KPluginFactory>
#include <QAction>
#include <QDialog>
#include <QDialogButtonBox>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QFormLayout>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QWidget>
K_PLUGIN_CLASS_WITH_JSON(DenoteFileItemAction, "denote_fileitemaction.json")
DenoteFileItemAction::DenoteFileItemAction(QObject *parent, const QVariantList &)
: KAbstractFileItemActionPlugin(parent)
{
}
QList<QAction *> 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
Denote::Metadata meta = Denote::parseFilename(item.localPath());
if (meta.isValid())
return {};
auto *action = new QAction(QStringLiteral("Rename with Denote..."), parentWidget);
action->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename")));
const KFileItemList items = fileItemInfos.items();
connect(action, &QAction::triggered, this, [this, items, parentWidget]() {
renameWithDenote(items, parentWidget);
});
return {action};
}
void DenoteFileItemAction::renameWithDenote(const KFileItemList &items, QWidget *parentWidget)
{
if (items.isEmpty())
return;
const KFileItem item = items.first();
const QString path = item.localPath();
const QFileInfo fi(path);
// Pre-fill title from filename (without extension)
QString defaultTitle = fi.completeBaseName();
defaultTitle.replace(QLatin1Char('-'), QLatin1Char(' '));
defaultTitle.replace(QLatin1Char('_'), QLatin1Char(' '));
// Try to extract title from frontmatter if applicable
const QString ext = QStringLiteral(".") + fi.suffix();
Denote::FileType fileType = Denote::fileTypeFromExtension(ext);
if (fileType != Denote::FileType::Unknown) {
QFile file(path);
if (file.open(QIODevice::ReadOnly)) {
QByteArray content = file.readAll();
file.close();
Denote::FrontMatter fm = Denote::parseFrontMatter(content, fileType);
if (!fm.title.isEmpty())
defaultTitle = fm.title;
}
}
// Build dialog
QDialog dialog(parentWidget);
dialog.setWindowTitle(QStringLiteral("Rename with Denote"));
dialog.setMinimumWidth(480);
auto *layout = new QVBoxLayout(&dialog);
auto *form = new QFormLayout();
auto *titleEdit = new QLineEdit(defaultTitle);
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);
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();
// Build new filename
const QString newName = Denote::buildFilename(title, tags, signature, ext);
const QString newPath = fi.dir().filePath(newName);
// Rename
QFile::rename(path, newPath);
// Update frontmatter if supported
if (fileType != Denote::FileType::Unknown) {
QFile file(newPath);
if (file.open(QIODevice::ReadWrite)) {
QByteArray content = file.readAll();
Denote::FrontMatter fm;
fm.title = title;
fm.tags = tags;
fm.identifier = Denote::parseFilename(newPath).identifier;
fm.signature = signature;
// Replace or prepend frontmatter
QString body = Denote::extractBody(content, fileType);
QByteArray newContent = Denote::marshalFrontMatter(fm, fileType);
newContent += body.toUtf8();
file.seek(0);
file.resize(0);
file.write(newContent);
file.close();
}
}
}
#include "denote_fileitemaction.moc"