Commit 57875ed5 authored by Christoph Cullmann's avatar Christoph Cullmann 🐮
Browse files

simplify format, only plain text messages

parent 5228e657
......@@ -178,7 +178,7 @@ void KateExternalToolsPlugin::runTool(const KateExternalTool &tool, KTextEditor:
genericMessage.insert(QStringLiteral("category"), i18n("External Tools"));
genericMessage.insert(QStringLiteral("categoryIcon"), QIcon::fromTheme(QStringLiteral("system-run")));
genericMessage.insert(
QStringLiteral("plainText"),
QStringLiteral("text"),
i18n("Running external tool: %1\n- Executable: %2\n- Arguments: %3\n- Input: %4", copy->name, copy->executable, copy->arguments, copy->input));
Q_EMIT pluginView->message(genericMessage);
......@@ -283,7 +283,7 @@ void KateExternalToolsPlugin::handleToolFinished(KateToolRunner *runner, int exi
genericMessage.insert(QStringLiteral("type"), messageType);
genericMessage.insert(QStringLiteral("category"), i18n("External Tools"));
genericMessage.insert(QStringLiteral("categoryIcon"), QIcon::fromTheme(QStringLiteral("system-run")));
genericMessage.insert(QStringLiteral("plainText"), messageBody);
genericMessage.insert(QStringLiteral("text"), messageBody);
Q_EMIT pluginView->message(genericMessage);
// on successful execution => show output
......
......@@ -1980,7 +1980,7 @@ public:
// use generic output view
QVariantMap genericMessage;
genericMessage.insert(QStringLiteral("category"), category);
genericMessage.insert(QStringLiteral("plainText"), msg);
genericMessage.insert(QStringLiteral("text"), msg);
// translate level to the type keys
QString type;
......
......@@ -338,7 +338,7 @@ void BranchesDialog::sendMessage(const QString &plainText, bool warn)
genericMessage.insert(QStringLiteral("type"), warn ? QStringLiteral("Error") : QStringLiteral("Info"));
genericMessage.insert(QStringLiteral("category"), i18n("Git"));
genericMessage.insert(QStringLiteral("categoryIcon"), QIcon(QStringLiteral(":/icons/icons/sc-apps-git.svg")));
genericMessage.insert(QStringLiteral("plainText"), plainText);
genericMessage.insert(QStringLiteral("text"), plainText);
Q_EMIT m_pluginView->message(genericMessage);
}
......
......@@ -132,7 +132,7 @@ void GitWidget::sendMessage(const QString &plainText, bool warn)
genericMessage.insert(QStringLiteral("type"), warn ? QStringLiteral("Error") : QStringLiteral("Info"));
genericMessage.insert(QStringLiteral("category"), i18n("Git"));
genericMessage.insert(QStringLiteral("categoryIcon"), QIcon(QStringLiteral(":/icons/icons/sc-apps-git.svg")));
genericMessage.insert(QStringLiteral("plainText"), plainText);
genericMessage.insert(QStringLiteral("text"), plainText);
Q_EMIT m_pluginView->message(genericMessage);
}
......
......@@ -22,6 +22,20 @@
#include <kfts_fuzzy_match.h>
class KateOutputTreeView : public QTreeView
{
public:
KateOutputTreeView(QWidget *parent)
: QTreeView(parent)
{
}
void drawBranches(QPainter *, const QRect &, const QModelIndex &) const override
{
// we want no branches!
}
};
class OutputSortFilterProxyModel final : public QSortFilterProxyModel
{
public:
......@@ -57,7 +71,7 @@ protected:
const QString cat = idxCat.data().toString();
const QString typ = idxTyp.data().toString();
const QString bod = getText(idxBod);
const QString bod = idxBod.data().toString();
int scorec = 0;
int scoret = 0;
......@@ -72,82 +86,10 @@ protected:
}
private:
static QString getText(const QModelIndex &index)
{
QTextDocument doc;
/**
* fill in right variant of text
* we always trim spaces away, to avoid ugly empty line at the start/end
*/
const auto message = index.data(KateOutputMessageStyledDelegate::MessageRole).toMap();
if (message.contains(QStringLiteral("plainText"))) {
doc.setPlainText(message.value(QStringLiteral("plainText")).toString().trimmed());
} else if (message.contains(QStringLiteral("markDown"))) {
doc.setMarkdown(message.value(QStringLiteral("markDown")).toString().trimmed());
} else if (message.contains(QStringLiteral("html"))) {
doc.setHtml(message.value(QStringLiteral("html")).toString().trimmed());
}
return doc.toPlainText();
}
QString m_pattern;
static constexpr int WeightRole = Qt::UserRole + 1;
};
/**
* setup text document from data
*/
static void setupText(QTextDocument &doc, const QModelIndex &index)
{
/**
* fill in right variant of text
* we always trim spaces away, to avoid ugly empty line at the start/end
*/
const auto message = index.data(KateOutputMessageStyledDelegate::MessageRole).toMap();
if (message.contains(QStringLiteral("plainText"))) {
doc.setPlainText(message.value(QStringLiteral("plainText")).toString().trimmed());
} else if (message.contains(QStringLiteral("markDown"))) {
doc.setMarkdown(message.value(QStringLiteral("markDown")).toString().trimmed());
} else if (message.contains(QStringLiteral("html"))) {
doc.setHtml(message.value(QStringLiteral("html")).toString().trimmed());
}
}
void KateOutputMessageStyledDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
// ensure we recover state
painter->save();
QStyleOptionViewItem options = option;
initStyleOption(&options, index);
// paint background
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
} else {
painter->fillRect(option.rect, option.palette.base());
}
options.text = QString();
options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget);
painter->translate(option.rect.x(), option.rect.y());
QTextDocument doc;
setupText(doc, index);
doc.drawContents(painter);
// ensure we recover state
painter->restore();
}
QSize KateOutputMessageStyledDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIndex &index) const
{
QTextDocument doc;
setupText(doc, index);
return doc.size().toSize();
}
KateOutputView::KateOutputView(KateMainWindow *mainWindow, QWidget *parent)
: QWidget(parent)
, m_mainWindow(mainWindow)
......@@ -156,23 +98,23 @@ KateOutputView::KateOutputView(KateMainWindow *mainWindow, QWidget *parent)
m_filterLine.setHidden(true);
m_filterLine.installEventFilter(this);
OutputSortFilterProxyModel *proxyModel = new OutputSortFilterProxyModel(this);
proxyModel->setSourceModel(&m_messagesModel);
m_proxyModel = new OutputSortFilterProxyModel(this);
m_proxyModel->setSourceModel(&m_messagesModel);
connect(&m_filterLine, &QLineEdit::textChanged, proxyModel, &OutputSortFilterProxyModel::setFilterString);
connect(&m_filterLine, &QLineEdit::textChanged, static_cast<OutputSortFilterProxyModel *>(m_proxyModel), &OutputSortFilterProxyModel::setFilterString);
// simple vbox layout with just the tree view ATM
// TODO: e.g. filter and such!
QVBoxLayout *layout = new QVBoxLayout(this);
m_messagesTreeView = new QTreeView(this);
m_messagesTreeView = new KateOutputTreeView(this);
m_messagesTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_messagesTreeView->setHeaderHidden(true);
m_messagesTreeView->setRootIsDecorated(false);
m_messagesTreeView->setAlternatingRowColors(true);
m_messagesTreeView->setModel(proxyModel);
m_messagesTreeView->setUniformRowHeights(true);
m_messagesTreeView->setModel(m_proxyModel);
// buttons at top
QHBoxLayout *hLayout = new QHBoxLayout(this);
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->addStretch();
auto filter = new QToolButton(this);
filter->setToolTip(QStringLiteral("Filter"));
......@@ -197,10 +139,6 @@ KateOutputView::KateOutputView(KateMainWindow *mainWindow, QWidget *parent)
layout->addWidget(m_messagesTreeView);
layout->addWidget(&m_filterLine);
// we want a special delegate to render the message body, as that might be plain text
// mark down or HTML
m_messagesTreeView->setItemDelegateForColumn(3, &m_messageBodyDelegate);
// read config once
readConfig();
......@@ -217,6 +155,14 @@ void KateOutputView::readConfig()
void KateOutputView::slotMessage(const QVariantMap &message)
{
/**
* discard all messages without any real text
*/
const auto text = message.value(QStringLiteral("text")).toString().trimmed();
if (text.isEmpty()) {
return;
}
/**
* date time column: we want to know when a message arrived
* TODO: perhaps store full date time for more stuff later
......@@ -261,18 +207,28 @@ void KateOutputView::slotMessage(const QVariantMap &message)
}
/**
* body column, formatted text
* we just set the full message as attribute
* we have our KateOutputMessageStyledDelegate to render this!
* body column, plain text
* we ensured above that we have some
* split it into lines, we want nice fixed-height parts
* we will add extra rows for everything below the first line
*/
auto bodyColumn = new QStandardItem();
bodyColumn->setData(QVariant::fromValue(message), KateOutputMessageStyledDelegate::MessageRole);
const auto textLines = text.split(QLatin1Char('\n'));
Q_ASSERT(!textLines.empty());
auto bodyColumn = new QStandardItem(textLines.at(0));
for (int i = 1; i < textLines.size(); ++i) {
dateTimeColumn->appendRow({new QStandardItem(), new QStandardItem(), new QStandardItem(), new QStandardItem(textLines.at(i))});
}
/**
* add new message to model as one row
* add new message to model
*/
m_messagesModel.appendRow({dateTimeColumn, categoryColumn, typeColumn, bodyColumn});
/**
* expand the new thingy
*/
m_messagesTreeView->expand(m_proxyModel->mapFromSource(dateTimeColumn->index()));
/**
* ensure correct sizing
* OPTIMIZE: we can do that only if e.g. a first time a new type/category pops up
......
......@@ -13,28 +13,8 @@
#include <QWidget>
class KateMainWindow;
class QTreeView;
/**
* Delegate to render the message body.
*/
class KateOutputMessageStyledDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
/**
* the role for the message
*/
static constexpr int MessageRole = Qt::UserRole + 1;
public:
KateOutputMessageStyledDelegate() = default;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &index) const override;
};
class KateOutputTreeView;
class QSortFilterProxyModel;
/**
* Widget to output stuff e.g. for plugins.
......@@ -66,13 +46,11 @@ public Q_SLOTS:
* IMPORTANT: at the moment, most stuff is key/value with strings, if the format is more finalized, one can introduce better type for more efficiency/type
* safety
*
* message body, can have different formats, lookup order will be:
* message text, will be trimmed before output
*
* message["plainText"] => plain text string to display
* message["markDown"] => markdown string to display, we use QTextDocument with MarkdownDialectGitHub
* message["html"] => HTML string to display, we use QTextDocument, that means only a subset of HTML https://doc.qt.io/qt-5/richtext-html-subset.html
* message["text"] = i18n("your cool message")
*
* the first thing found will be used.
* the text will be split in lines, all lines beside the first can be collapsed away
*
* message type, we support at the moment
*
......@@ -110,7 +88,7 @@ private:
/**
* Internal tree view to display the messages we get
*/
QTreeView *m_messagesTreeView = nullptr;
KateOutputTreeView *m_messagesTreeView = nullptr;
/**
* Our message model, at the moment a standard item model
......@@ -118,10 +96,13 @@ private:
QStandardItemModel m_messagesModel;
/**
* Our special output delegate for the message body
* Our proxy model for filtering
*/
KateOutputMessageStyledDelegate m_messageBodyDelegate;
QSortFilterProxyModel *m_proxyModel = nullptr;
/**
* fuzzy filter line edit
*/
QLineEdit m_filterLine;
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment