<commit_before>#include "shell.h"

#include <QPainter>
#include <QPaintEvent>
#include <QDebug>
#include <QDesktopWidget>
#include <QApplication>
#include <QKeyEvent>
#include "msgpackrequest.h"
#include "input.h"
#include "konsole_wcwidth.h"

namespace NeovimQt {

Shell::Shell(NeovimConnector *nvim, QWidget *parent)
:QWidget(parent), m_attached(false), m_nvim(nvim), m_rows(1), m_cols(1),
	m_font_bold(false), m_font_italic(false), m_font_underline(false), m_font_undercurl(false), m_fm(NULL),
	m_foreground(Qt::black), m_background(Qt::white),
	m_hg_foreground(Qt::black), m_hg_background(Qt::white),
	m_cursor_color(Qt::white), m_cursor_pos(0,0), m_insertMode(false),
	m_resizing(false), m_logo(QPixmap(":/neovim.png")),
	m_neovimBusy(false)
{
	setGuiFont("Monospace");

	m_image = QImage(neovimSize(), QImage::Format_ARGB32_Premultiplied);

	setAttribute(Qt::WA_KeyCompression, false);
	setAttribute(Qt::WA_OpaquePaintEvent, true);

	setFocusPolicy(Qt::StrongFocus);
	setMouseTracking(true);
	m_mouseclick_timer.setInterval(QApplication::doubleClickInterval());
	m_mouseclick_timer.setSingleShot(true);
	connect(&m_mouseclick_timer, &QTimer::timeout,
			this, &Shell::mouseClickReset);

	// IM Tooltip
	setAttribute(Qt::WA_InputMethodEnabled, true);
	m_tooltip = new QLabel(this);
	m_tooltip->setVisible(false);
	m_tooltip->setTextFormat(Qt::PlainText);
	m_tooltip->setTextInteractionFlags(Qt::NoTextInteraction);
	m_tooltip->setAutoFillBackground(true);

	if (m_nvim == NULL) {
		qWarning() << "Received NULL as Neovim Connector";
		return;
	}

	connect(m_nvim, &NeovimConnector::ready,
			this, &Shell::neovimIsReady);
	connect(m_nvim, &NeovimConnector::error,
			this, &Shell::neovimError);
	connect(m_nvim, &NeovimConnector::processExited,
			this, &Shell::neovimExited);

	if (m_nvim->isReady()) {
		neovimIsReady();
	}
}

/**
 * Set the GUI font, or display the current font
 */
bool Shell::setGuiFont(const QString& fdesc)
{
	if (fdesc.isEmpty()) {
		QFontInfo fi(m_font);
		QByteArray desc = m_nvim->encode(QString("%1:h%2\n").arg(fi.family()).arg(m_font.pointSize()));
		m_nvim->neovimObject()->vim_out_write(desc);
		return true;
	}
	QStringList attrs = fdesc.split(':');
	if (attrs.size() < 1) {
		m_nvim->neovimObject()->vim_report_error("Invalid font");
		return false;
	}

	QFont f;
	f.setStyleStrategy(QFont::StyleStrategy(QFont::PreferDefault | QFont::ForceIntegerMetrics) );
	f.setStyleHint(QFont::TypeWriter);
	f.setFamily(attrs.at(0));
	f.setFixedPitch(true);
	f.setKerning(false);
	f.setFixedPitch(true);

	foreach(QString attr, attrs) {
		if (attr.size() >= 2 && attr[0] == 'h') {
			bool ok = false;
			int height = attr.mid(1).toInt(&ok);
			if (!ok) {
				m_nvim->neovimObject()->vim_report_error("Invalid font height");
				return false;
			}
			f.setPointSize(height);
		}
	}

	QFontInfo fi(f);
	if (fi.family().compare(f.family(), Qt::CaseInsensitive) != 0 &&
			f.family().compare("Monospace", Qt::CaseInsensitive) != 0) {
		m_nvim->neovimObject()->vim_report_error("Unknown font");
		return false;
	}
	if ( !fi.fixedPitch() ) {
		m_nvim->neovimObject()->vim_report_error("Font needs to be a fixed pitch font");
		return false;
	}

	if (isBadMonospace(f)) {
		m_nvim->neovimObject()->vim_report_error("Font metrics are not fixed pitch for all variants");
		return false;
	}

	m_font = f;
	m_fm = new QFontMetrics(f);

	if (m_attached) {
		resizeNeovim(size());
	}
	return true;
}


Shell::~Shell()
{
	if (m_nvim && m_attached) {
		m_nvim->detachUi();
	}<commit_msg>GUI: Improve error messages for Guifont errors<commit_after>#include "shell.h"

#include <QPainter>
#include <QPaintEvent>
#include <QDebug>
#include <QDesktopWidget>
#include <QApplication>
#include <QKeyEvent>
#include "msgpackrequest.h"
#include "input.h"
#include "konsole_wcwidth.h"

namespace NeovimQt {

Shell::Shell(NeovimConnector *nvim, QWidget *parent)
:QWidget(parent), m_attached(false), m_nvim(nvim), m_rows(1), m_cols(1),
	m_font_bold(false), m_font_italic(false), m_font_underline(false), m_font_undercurl(false), m_fm(NULL),
	m_foreground(Qt::black), m_background(Qt::white),
	m_hg_foreground(Qt::black), m_hg_background(Qt::white),
	m_cursor_color(Qt::white), m_cursor_pos(0,0), m_insertMode(false),
	m_resizing(false), m_logo(QPixmap(":/neovim.png")),
	m_neovimBusy(false)
{
	setGuiFont("Monospace");

	m_image = QImage(neovimSize(), QImage::Format_ARGB32_Premultiplied);

	setAttribute(Qt::WA_KeyCompression, false);
	setAttribute(Qt::WA_OpaquePaintEvent, true);

	setFocusPolicy(Qt::StrongFocus);
	setMouseTracking(true);
	m_mouseclick_timer.setInterval(QApplication::doubleClickInterval());
	m_mouseclick_timer.setSingleShot(true);
	connect(&m_mouseclick_timer, &QTimer::timeout,
			this, &Shell::mouseClickReset);

	// IM Tooltip
	setAttribute(Qt::WA_InputMethodEnabled, true);
	m_tooltip = new QLabel(this);
	m_tooltip->setVisible(false);
	m_tooltip->setTextFormat(Qt::PlainText);
	m_tooltip->setTextInteractionFlags(Qt::NoTextInteraction);
	m_tooltip->setAutoFillBackground(true);

	if (m_nvim == NULL) {
		qWarning() << "Received NULL as Neovim Connector";
		return;
	}

	connect(m_nvim, &NeovimConnector::ready,
			this, &Shell::neovimIsReady);
	connect(m_nvim, &NeovimConnector::error,
			this, &Shell::neovimError);
	connect(m_nvim, &NeovimConnector::processExited,
			this, &Shell::neovimExited);

	if (m_nvim->isReady()) {
		neovimIsReady();
	}
}

/**
 * Set the GUI font, or display the current font
 */
bool Shell::setGuiFont(const QString& fdesc)
{
	if (fdesc.isEmpty()) {
		QFontInfo fi(m_font);
		QByteArray desc = m_nvim->encode(QString("%1:h%2\n").arg(fi.family()).arg(m_font.pointSize()));
		m_nvim->neovimObject()->vim_out_write(desc);
		return true;
	}
	QStringList attrs = fdesc.split(':');
	if (attrs.size() < 1) {
		m_nvim->neovimObject()->vim_report_error("Invalid font");
		return false;
	}

	QFont f;
	f.setStyleStrategy(QFont::StyleStrategy(QFont::PreferDefault | QFont::ForceIntegerMetrics) );
	f.setStyleHint(QFont::TypeWriter);
	f.setFamily(attrs.at(0));
	f.setFixedPitch(true);
	f.setKerning(false);
	f.setFixedPitch(true);

	foreach(QString attr, attrs) {
		if (attr.size() >= 2 && attr[0] == 'h') {
			bool ok = false;
			int height = attr.mid(1).toInt(&ok);
			if (!ok) {
				m_nvim->neovimObject()->vim_report_error("Invalid font height");
				return false;
			}
			f.setPointSize(height);
		}
	}

	QFontInfo fi(f);
	if (fi.family().compare(f.family(), Qt::CaseInsensitive) != 0 &&
			f.family().compare("Monospace", Qt::CaseInsensitive) != 0) {
		QString errmsg = QString("Unknown font: %1").arg(f.family());
		m_nvim->neovimObject()->vim_report_error(m_nvim->encode(errmsg));
		return false;
	}
	if ( !fi.fixedPitch() ) {
		QString errmsg = QString("%1 is not a fixed pitch font").arg(f.family());
		m_nvim->neovimObject()->vim_report_error(m_nvim->encode(errmsg));
		return false;
	}

	if (isBadMonospace(f)) {
		QString errmsg = QString("%1 has non fixed metrics for its variants").arg(f.family());
		m_nvim->neovimObject()->vim_report_error(m_nvim->encode(errmsg));
		return false;
	}

	m_font = f;
	m_fm = new QFontMetrics(f);

	if (m_attached) {
		resizeNeovim(size());
	}
	return true;
}


Shell::~Shell()
{
	if (m_nvim && m_attached) {
		m_nvim->detachUi();
	}
{'fraction_non_alphanumeric': 0.16735880398671096, 'fraction_numerical': 0.004568106312292359, 'mean_word_length': 6.275931520644511, 'pattern_counts': {'":': 2, '<': 21, '<?xml version=': 0, '>': 58, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4287760', 'n_tokens_mistral': 2938, 'n_tokens_neox': 2784, 'n_words': 444}