[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [ktp-text-ui/latex_filter] filters: Latex Filter
From: Andrea Scarpino <andrea () archlinux ! org>
Date: 2013-03-13 23:18:47
Message-ID: 20130313231847.380BDA604F () git ! kde ! org
[Download RAW message or body]
Git commit 4f893e79adca00e737e1da0068e9ae009232888d by Andrea Scarpino.
Committed on 14/03/2013 at 00:08.
Pushed by scarpino into branch 'latex_filter'.
Latex Filter
M +1 -0 filters/CMakeLists.txt
A +54 -0 filters/latex/CMakeLists.txt
A +9 -0 filters/latex/kcm_ktptextui_message_filter_latex.desktop
A +18 -0 filters/latex/ktptextui_message_filter_latex.desktop.cmake
A +40 -0 filters/latex/latex-config.cpp [License: LGPL (v2.1+)]
A +38 -0 filters/latex/latex-config.h [License: LGPL (v2.1+)]
A +61 -0 filters/latex/latex-config.ui
A +190 -0 filters/latex/latex-filter.cpp [License: LGPL (v2.1+)]
A +44 -0 filters/latex/latex-filter.h [License: LGPL (v2.1+)]
A +20 -0 filters/latex/latex.kcfg
A +4 -0 filters/latex/latexconfig.kcfgc
http://commits.kde.org/telepathy-text-ui/4f893e79adca00e737e1da0068e9ae009232888d
diff --git a/filters/CMakeLists.txt b/filters/CMakeLists.txt
index 62384cb..c66e773 100644
--- a/filters/CMakeLists.txt
+++ b/filters/CMakeLists.txt
@@ -2,6 +2,7 @@ add_subdirectory(bugzilla)
add_subdirectory(emoticons)
add_subdirectory(formatting)
add_subdirectory(images)
+add_subdirectory(latex)
add_subdirectory(searchexpansion)
add_subdirectory(youtube)
add_subdirectory(highlight)
diff --git a/filters/latex/CMakeLists.txt b/filters/latex/CMakeLists.txt
new file mode 100644
index 0000000..89b341b
--- /dev/null
+++ b/filters/latex/CMakeLists.txt
@@ -0,0 +1,54 @@
+set (ktptextui_message_filter_latex_SRCS
+ latex-filter.cpp
+)
+
+kde4_add_kcfg_files(ktptextui_message_filter_latex_SRCS latexconfig.kcfgc)
+
+kde4_add_plugin (ktptextui_message_filter_latex
+ ${ktptextui_message_filter_latex_SRCS}
+)
+
+target_link_libraries (ktptextui_message_filter_latex
+ ktpchat
+ ${QT_LIBRARIES}
+ ${QT_QTGUI_LIBRARY}
+ ${KDE4_KDECORE_LIBS}
+ ${KDE4_KDEUI_LIBS}
+ ${TELEPATHY_QT4_LIBRARIES}
+ ${KTP_LIBRARIES}
+)
+
+set (kcm_ktptextui_message_filter_latex_SRCS
+ latex-config.cpp
+)
+
+kde4_add_kcfg_files(kcm_ktptextui_message_filter_latex_SRCS latexconfig.kcfgc)
+
+kde4_add_ui_files (kcm_ktptextui_message_filter_latex_SRCS
+ latex-config.ui
+)
+
+kde4_add_plugin (kcm_ktptextui_message_filter_latex
+ ${kcm_ktptextui_message_filter_latex_SRCS}
+)
+
+target_link_libraries (kcm_ktptextui_message_filter_latex
+ ktpchat
+ ${QT_LIBRARIES}
+ ${KDE4_KDEUI_LIBS}
+)
+
+# Install:
+install (TARGETS ktptextui_message_filter_latex
+ kcm_ktptextui_message_filter_latex
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ktptextui_message_filter_latex.desktop.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/ktptextui_message_filter_latex.desktop
+ @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/ktptextui_message_filter_latex.desktop
+ ${CMAKE_CURRENT_SOURCE_DIR}/kcm_ktptextui_message_filter_latex.desktop
+ DESTINATION ${SERVICES_INSTALL_DIR}
+)
diff --git a/filters/latex/kcm_ktptextui_message_filter_latex.desktop \
b/filters/latex/kcm_ktptextui_message_filter_latex.desktop new file mode 100644
index 0000000..9644f9e
--- /dev/null
+++ b/filters/latex/kcm_ktptextui_message_filter_latex.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=KCModule
+
+X-KDE-Library=kcm_ktptextui_message_filter_latex
+X-KDE-ParentApp=latex
+X-KDE-ParentComponents=latex
+
+Name=Latex
\ No newline at end of file
diff --git a/filters/latex/ktptextui_message_filter_latex.desktop.cmake \
b/filters/latex/ktptextui_message_filter_latex.desktop.cmake new file mode 100644
index 0000000..3903553
--- /dev/null
+++ b/filters/latex/ktptextui_message_filter_latex.desktop.cmake
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=Service
+ServiceTypes=KTpTextUi/MessageFilter
+
+X-KDE-Library=ktptextui_message_filter_latex
+X-KDE-PluginInfo-Author=Lasath Fernando
+X-KDE-PluginInfo-Email=kde@lasath.org
+X-KDE-PluginInfo-Name=latex
+X-KDE-PluginInfo-Version=@KTP_TEXT_UI_VERSION@
+X-KDE-PluginInfo-Website=http://community.kde.org/KTp
+X-KDE-PluginInfo-License=GPL
+X-KDE-PluginInfo-EnabledByDefault=false
+X-KDE-PluginInfo-Weight=10
+X-KTp-PluginInfo-Version=@KTP_MESSAGE_FILTER_FRAMEWORK_VERSION@
+
+Name=Latex Renderer
+Comment=If incomming messages contain latex between $$, it will render it directly \
into the chat.
diff --git a/filters/latex/latex-config.cpp b/filters/latex/latex-config.cpp
new file mode 100644
index 0000000..1169c59
--- /dev/null
+++ b/filters/latex/latex-config.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 Andrea Scarpino <andrea@archlinux.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "latex-config.h"
+// KConfigSkeleton
+#include "latexconfig.h"
+
+#include <KPluginFactory>
+
+K_PLUGIN_FACTORY(LatexConfigFactory, registerPlugin<LatexFilterConfig>();)
+K_EXPORT_PLUGIN(LatexConfigFactory( "kcm_ktptextui_message_filter_latex" ))
+
+LatexFilterConfig::LatexFilterConfig(QWidget* parent, const QVariantList& args)
+ : KCModule(LatexConfigFactory::componentData(), parent, args)
+{
+ ui.setupUi(this);
+ addConfig(LatexConfig::self(), this);
+ load();
+}
+
+LatexFilterConfig::~LatexFilterConfig()
+{
+}
+
+#include "latex-config.moc"
\ No newline at end of file
diff --git a/filters/latex/latex-config.h b/filters/latex/latex-config.h
new file mode 100644
index 0000000..a0b7023
--- /dev/null
+++ b/filters/latex/latex-config.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 Andrea Scarpino <andrea@archlinux.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef LATEX_CONFIG_H
+#define LATEX_CONFIG_H
+
+#include <KCModule>
+
+#include "ui_latex-config.h"
+
+class LatexFilterConfig : public KCModule
+{
+ Q_OBJECT
+
+public:
+ explicit LatexFilterConfig(QWidget* parent = 0, const QVariantList& args = \
QVariantList()); + virtual ~LatexFilterConfig();
+
+private:
+ Ui::LatexConfig ui;
+};
+
+#endif // LATEX_CONFIG_H
\ No newline at end of file
diff --git a/filters/latex/latex-config.ui b/filters/latex/latex-config.ui
new file mode 100644
index 0000000..d0759c5
--- /dev/null
+++ b/filters/latex/latex-config.ui
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LatexConfig</class>
+ <widget class="QWidget" name="LatexConfig">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>470</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>LatexConfig</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Latex header:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="kcfg_LatexHeader">
+ <property name="plainText">
+ <string>\documentclass{standalone}
+\usepackage{color}
+\usepackage{amsmath,latexsym,amsfonts,amssymb,ulem}
+\usepackage{graphicx}
+\pagestyle{empty}
+</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Latex command line:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KLineEdit" name="kcfg_LatexCmd">
+ <property name="text">
+ <string>latex -interaction=batchmode -halt-on-error</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>klineedit.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/filters/latex/latex-filter.cpp b/filters/latex/latex-filter.cpp
new file mode 100644
index 0000000..a9bcb3f
--- /dev/null
+++ b/filters/latex/latex-filter.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2012 Lasath Fernando <kde@lasath.org>
+ * Copyright (C) 2013 Andrea Scarpino <andrea@archlinux.org>
+ *
+ * Copyright (c) 2004 by Duncan Mac-Vicar Prett <duncan@kde.org>
+ * Copyright (c) 2004-2005 by Olivier Goffart <ogoffart@kde. org>
+ * Kopete (c) 2001-2004 by the Kopete developers <kopete-devel@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "latex-filter.h"
+// KConfigSkeleton
+#include "latexconfig.h"
+
+#include <QImage>
+
+#include <KPluginFactory>
+#include <KDebug>
+#include <KStandardDirs>
+#include <KProcess>
+#include <X11/Xproto.h>
+
+LatexFilter::LatexFilter(QObject* parent, const QVariantList &)
+ : AbstractMessageFilter(parent)
+{
+}
+
+void LatexFilter::filterMessage(KTp::Message &message, const KTp::MessageContext \
&context) +{
+ Q_UNUSED(context);
+
+ const QString messageText = message.mainMessagePart();
+ if (!messageText.contains(QLatin1String("$$"))) {
+ return;
+ }
+
+ QRegExp rg(QLatin1String("\\$\\$.+\\$\\$"));
+ rg.setMinimal(true);
+
+ QMap<QString, QString> replaceMap;
+ int pos = 0;
+ while (pos >= 0 && pos < messageText.length()) {
+ pos = rg.indexIn(messageText, pos);
+
+ if (pos >= 0) {
+ const QString match = rg.cap(0);
+ pos += rg.matchedLength();
+
+ QString formul = match;
+ // first remove the $$ delimiters on start and end
+ formul.remove(QLatin1String("$$"));
+ // then trim the result, so we can skip totally empty/whitespace-only \
formulas + formul = formul.trimmed();
+ if (formul.isEmpty() || !securityCheck(formul)) {
+ continue;
+ }
+
+ // get the image and encode it with base64
+ replaceMap[match] = handleLatex(formul);
+ }
+ }
+
+ if (replaceMap.isEmpty()) {
+ // we haven't found any LaTeX strings
+ return;
+ }
+
+ for (QMap<QString, QString>::ConstIterator it = replaceMap.constBegin(); it != \
replaceMap.constEnd(); ++it) { + QImage theImage(*it);
+ if (theImage.isNull()) {
+ continue;
+ }
+
+ message.appendMessagePart(
+ QLatin1Literal("<br/>") %
+ QLatin1Literal("<img src=\"") %
+ (*it) %
+ QLatin1Literal("\" style=\"max-width:100%;margin-top:3px\" alt=\"") \
% + QLatin1Literal("\" />")
+ );
+ }
+}
+
+QString LatexFilter::handleLatex(const QString &latexFormula)
+{
+ QString latexText;
+ latexText.append(LatexConfig::latexHeader());
+ latexText.append(QLatin1String("\\begin{document}\n"));
+ latexText.append(QString(QLatin1String("$%1$\n"))
+ .arg(latexFormula));
+ latexText.append(QLatin1String("\\end{document}"));
+
+ KTemporaryFile *texFile(new KTemporaryFile);
+ texFile->setPrefix(QLatin1String("ktplatex-"));
+ texFile->setSuffix(QLatin1String(".tex"));
+ if (!texFile->open()) {
+ kError() << "Cannot create the TeX file";
+ return QString();
+ }
+ texFile->write(latexText.toAscii());
+ texFile->close();
+ m_tempFiles << texFile;
+
+ if (LatexConfig::latexCmd().isEmpty()) {
+ kError() << "No TeX compiler set!";
+ return QString();
+ }
+ const QStringList latexCmd = \
LatexConfig::latexCmd().split(QRegExp(QLatin1String("\\s+"))); +
+ QStringList latexArgs;
+ Q_FOREACH(const QString &cmd, latexCmd.mid(1, latexCmd.size())) {
+ latexArgs << cmd;
+ }
+ const KStandardDirs outputDir;
+ latexArgs << QString(QLatin1String("-output-directory=%1")).arg(outputDir.resourceDirs("tmp").first());
+ latexArgs << texFile->fileName();
+
+ if (KStandardDirs::findExe(latexCmd.first()).isEmpty()) {
+ kError() << "Cannot find the TeX" << latexCmd.first() << " program.\n;"
+ << "Please get the software from http://tug.org/texlive/"
+ << "or from your distribution's package manager.";
+ return QString();
+ }
+
+ kDebug() << "Running " << latexCmd.first() << latexArgs;
+
+ KProcess p;
+ p.execute(latexCmd.first(), latexArgs);
+ if (p.exitCode()) {
+ kError() << "Error compiling the TeX text";
+ return QString();
+ }
+
+ if (KStandardDirs::findExe(QLatin1String("dvipng")).isEmpty()) {
+ kError() << "Cannot find the TeX 'dvipng' program.\n;"
+ << "Please get the software from http://tug.org/texlive/"
+ << "or from your distribution's package manager.";
+ return QString();
+ }
+
+ const QString dviFile = \
texFile->fileName().replace(QLatin1String(".tex"),QLatin1String(".dvi")); + const \
QString imageFile = texFile->fileName().replace(QLatin1String(".tex"),QLatin1String(".png"));
+
+ QStringList dvipngArgs;
+ dvipngArgs << QLatin1String("-D300");
+ dvipngArgs << QLatin1String("-bgTransparent");
+ dvipngArgs << QString(QLatin1String("-o%1")).arg(imageFile);
+ dvipngArgs << dviFile;
+
+ kDebug() << "Rendering dvipng" << dvipngArgs;
+
+ p.execute(QLatin1String("dvipng"), dvipngArgs);
+ if (p.exitCode()){
+ kError() << "Error rendering the image to PNG";
+ return QString();
+ }
+
+ return imageFile;
+}
+
+bool LatexFilter::securityCheck(const QString &latexFormula)
+{
+ return !latexFormula.contains(QRegExp(QLatin1String(
+ "\\\\(def|let|futurelet|newcommand|renewcomment|else|fi|write|input|include"
+ "|chardef|catcode|makeatletter|noexpand|toksdef|every|errhelp|errorstopmode|scrollmode|nonstopmode|batchmode"
+ "|read|csname|newhelp|relax|afterground|afterassignment|expandafter|noexpand|special|command|loop|repeat|toks"
+ "|output|line|mathcode|name|item|section|mbox|DeclareRobustCommand)[^a-zA-Z]"
+ )));
+}
+
+LatexFilter::~LatexFilter()
+{
+ qDeleteAll(m_tempFiles);
+}
+
+K_PLUGIN_FACTORY(MessageFilterFactory, registerPlugin<LatexFilter>();)
+K_EXPORT_PLUGIN(MessageFilterFactory("ktptextui_message_filter_latex"))
\ No newline at end of file
diff --git a/filters/latex/latex-filter.h b/filters/latex/latex-filter.h
new file mode 100644
index 0000000..d2c3dde
--- /dev/null
+++ b/filters/latex/latex-filter.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 Lasath Fernando <kde@lasath.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef LATEX_FILTER_H
+#define LATEX_FILTER_H
+
+#include <QColor>
+
+#include <KTemporaryFile>
+
+#include <KTp/abstract-message-filter.h>
+
+class LatexFilter : public KTp::AbstractMessageFilter
+{
+Q_OBJECT
+
+public:
+ LatexFilter(QObject* parent = 0, const QVariantList &args = QVariantList());
+ virtual ~LatexFilter();
+ virtual void filterMessage(KTp::Message &message, const KTp::MessageContext \
&context); +
+private:
+ bool securityCheck(const QString &latexFormula);
+ QString handleLatex(const QString &latexFormula);
+ QList<KTemporaryFile *> m_tempFiles;
+
+};
+
+#endif // LATEX_FILTER_H
\ No newline at end of file
diff --git a/filters/latex/latex.kcfg b/filters/latex/latex.kcfg
new file mode 100644
index 0000000..97342a6
--- /dev/null
+++ b/filters/latex/latex.kcfg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="ktp-text-uirc"/>
+ <group name="Filter-Latex">
+ <entry name="LatexCmd" type="String">
+ <default>latex -interaction=batchmode -halt-on-error</default>
+ </entry>
+ <entry name="LatexHeader" type="String">
+ <default>\documentclass{standalone}
+\usepackage{color}
+\usepackage{amsmath,latexsym,amsfonts,amssymb,ulem}
+\usepackage{graphicx}
+\pagestyle{empty}
+</default>
+ </entry>
+ </group>
+</kcfg>
\ No newline at end of file
diff --git a/filters/latex/latexconfig.kcfgc b/filters/latex/latexconfig.kcfgc
new file mode 100644
index 0000000..f94b6dc
--- /dev/null
+++ b/filters/latex/latexconfig.kcfgc
@@ -0,0 +1,4 @@
+File=latex.kcfg
+ClassName=LatexConfig
+Singleton=true
+Mutators=true
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic