You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
6.3 KiB
298 lines
6.3 KiB
#include "LatexController.h" |
|
|
|
#include "Control.h" |
|
|
|
#include "gui/XournalView.h" |
|
#include "gui/dialog/LatexDialog.h" |
|
#include "undo/InsertUndoAction.h" |
|
|
|
#include <i18n.h> |
|
#include <Util.h> |
|
#include <Stacktrace.h> |
|
|
|
#include <boost/filesystem.hpp> |
|
|
|
#include <iostream> |
|
using std::cout; |
|
using std::endl; |
|
|
|
|
|
LatexController::LatexController(Control* control) |
|
: control(control), |
|
texArea(0), |
|
// .png will be appended automatically => tex.png |
|
texImage(Util::getConfigFile("tex").string()), |
|
selectedTexImage(NULL), |
|
posx(0), |
|
posy(0), |
|
imgwidth(0), |
|
imgheight(0), |
|
doc(control->getDocument()), |
|
view(NULL), |
|
layer(NULL) |
|
{ |
|
XOJ_INIT_TYPE(LatexController); |
|
} |
|
|
|
LatexController::~LatexController() |
|
{ |
|
XOJ_CHECK_TYPE(LatexController); |
|
|
|
this->control = NULL; |
|
|
|
XOJ_RELEASE_TYPE(LatexController); |
|
} |
|
|
|
/** |
|
* Find the tex executable, return false if not found |
|
*/ |
|
bool LatexController::findTexExecutable() |
|
{ |
|
XOJ_CHECK_TYPE(LatexController); |
|
|
|
path exePath = Stacktrace::getExePath(); |
|
binTex = exePath.parent_path().string() + "/mathtex/mathtex-xournalpp.cgi"; |
|
|
|
if (boost::filesystem::exists(binTex)) |
|
{ |
|
// Found binary in relative path |
|
return true; |
|
} |
|
|
|
gchar* mathtex = g_find_program_in_path("mathtex-xournalpp.cgi"); |
|
if (!mathtex) |
|
{ |
|
return false; |
|
} |
|
|
|
binTex = mathtex; |
|
g_free(mathtex); |
|
|
|
return true; |
|
} |
|
|
|
|
|
/** |
|
* Run LaTeX Command |
|
*/ |
|
bool LatexController::runCommand() |
|
{ |
|
XOJ_CHECK_TYPE(LatexController); |
|
|
|
// can change font colour later with more features |
|
string fontcolour = "black"; |
|
// dpi 300 is a good balance |
|
string texres; |
|
if (this->texArea < 1000) |
|
{ |
|
texres = "300"; |
|
} |
|
else if (this->texArea < 4000) |
|
{ |
|
texres = "400"; |
|
} |
|
else if (this->texArea < 8000) |
|
{ |
|
texres = "500"; |
|
} |
|
else if (this->texArea < 16000) |
|
{ |
|
texres = "600"; |
|
} |
|
else if (this->texArea < 32000) |
|
{ |
|
texres = "800"; |
|
} |
|
else |
|
{ |
|
texres = "1000"; |
|
} |
|
|
|
string command = FS(bl::format("{1} -m 0 \"\\png\\usepackage{{color}}\\color{{{2}}}\\dpi{{{3}}}\\normalsize {4}\" -o {5}") |
|
% binTex % "black" % texres |
|
% g_strescape(currentTex.c_str(), NULL) % texImage); |
|
|
|
gint rt = 0; |
|
void(*texhandler)(int) = signal(SIGCHLD, SIG_DFL); |
|
gboolean success = g_spawn_command_line_sync(command.c_str(), NULL, NULL, &rt, NULL); |
|
signal(SIGCHLD, texhandler); |
|
|
|
return success; |
|
} |
|
|
|
/** |
|
* Find a selected tex element, and load it |
|
*/ |
|
void LatexController::findSelectedTexElement() |
|
{ |
|
XOJ_CHECK_TYPE(LatexController); |
|
|
|
doc->lock(); |
|
int pageNr = control->getCurrentPageNo(); |
|
if (pageNr == -1) |
|
{ |
|
doc->unlock(); |
|
return; |
|
} |
|
view = control->getWindow()->getXournal()->getViewFor(pageNr); |
|
if (view == NULL) |
|
{ |
|
doc->unlock(); |
|
return; |
|
} |
|
|
|
// we get the selection |
|
page = doc->getPage(pageNr); |
|
layer = page->getSelectedLayer(); |
|
|
|
selectedTexImage = view->getSelectedTex(); |
|
|
|
if (selectedTexImage) |
|
{ |
|
// this will get the position of the Latex properly |
|
EditSelection* theSelection = control->getWindow()->getXournal()->getSelection(); |
|
posx = theSelection->getXOnView(); |
|
posy = theSelection->getYOnView(); |
|
|
|
imgwidth = selectedTexImage->getElementWidth(); |
|
imgheight = selectedTexImage->getElementHeight(); |
|
|
|
texArea = imgwidth * imgheight; |
|
initalTex = selectedTexImage->getText(); |
|
} |
|
|
|
doc->unlock(); |
|
|
|
// need to do this otherwise we can't remove the image for its replacement |
|
control->clearSelectionEndText(); |
|
} |
|
|
|
void LatexController::showTexEditDialog() |
|
{ |
|
XOJ_CHECK_TYPE(LatexController); |
|
|
|
LatexDialog* dlg = new LatexDialog(control->getGladeSearchPath()); |
|
dlg->setTex(initalTex); |
|
dlg->show(GTK_WINDOW(control->getWindow()->getWindow())); |
|
currentTex = dlg->getTex(); |
|
|
|
delete dlg; |
|
} |
|
|
|
void LatexController::deleteOldImage() |
|
{ |
|
XOJ_CHECK_TYPE(LatexController); |
|
|
|
if (selectedTexImage) |
|
{ |
|
EditSelection* selection = new EditSelection(control->getUndoRedoHandler(), selectedTexImage, view, page); |
|
view->getXournal()->deleteSelection(selection); |
|
delete selection; |
|
selectedTexImage = NULL; |
|
} |
|
} |
|
|
|
void LatexController::insertTexImage() |
|
{ |
|
XOJ_CHECK_TYPE(LatexController); |
|
|
|
string imgPath = texImage + ".png"; |
|
|
|
GFile* mygfile = g_file_new_for_path(imgPath.c_str()); |
|
GError* err = NULL; |
|
GFileInputStream* in = g_file_read(mygfile, NULL, &err); |
|
g_object_unref(mygfile); |
|
|
|
if (err) |
|
{ |
|
Util::showErrorToUser(control->getGtkWindow(), FS(_F("Could not retrieve LaTeX image file: {1}") % err->message)); |
|
g_error_free(err); |
|
return; |
|
} |
|
|
|
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_stream(G_INPUT_STREAM(in), NULL, &err); |
|
g_input_stream_close(G_INPUT_STREAM(in), NULL, NULL); |
|
|
|
deleteOldImage(); |
|
|
|
TexImage* img = new TexImage(); |
|
img->setX(posx); |
|
img->setY(posy); |
|
img->setImage(pixbuf); |
|
img->setText(currentTex); |
|
|
|
if (imgheight) |
|
{ |
|
double ratio = (gdouble) gdk_pixbuf_get_width(pixbuf) / gdk_pixbuf_get_height(pixbuf); |
|
if (ratio == 0) |
|
{ |
|
if (imgwidth == 0) |
|
{ |
|
img->setWidth(10); |
|
} |
|
else |
|
{ |
|
img->setWidth(imgwidth); |
|
} |
|
} |
|
else |
|
{ |
|
img->setWidth(imgheight * ratio); |
|
} |
|
img->setHeight(imgheight); |
|
} |
|
else |
|
{ |
|
img->setWidth(gdk_pixbuf_get_width(pixbuf)); |
|
img->setHeight(gdk_pixbuf_get_height(pixbuf)); |
|
} |
|
|
|
doc->lock(); |
|
layer->addElement(img); |
|
view->rerenderElement(img); |
|
doc->unlock(); |
|
|
|
control->getUndoRedoHandler()->addUndoAction(new InsertUndoAction(page, layer, img)); |
|
} |
|
|
|
void LatexController::run() |
|
{ |
|
XOJ_CHECK_TYPE(LatexController); |
|
|
|
if (!findTexExecutable()) |
|
{ |
|
string msg = FS(_("Could not find Xournal++ LaTeX executable relative or in Path.\nSearched for: mathtex-xournalpp.cgi")); |
|
GtkWidget* dialog = gtk_message_dialog_new(control->getGtkWindow(), |
|
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", |
|
msg.c_str()); |
|
gtk_window_set_transient_for(GTK_WINDOW(dialog), control->getGtkWindow()); |
|
gtk_dialog_run(GTK_DIALOG(dialog)); |
|
gtk_widget_destroy(dialog); |
|
return; |
|
} |
|
|
|
findSelectedTexElement(); |
|
showTexEditDialog(); |
|
|
|
if (currentTex.empty() || initalTex == currentTex) |
|
{ |
|
// Nothing to insert / change |
|
return; |
|
} |
|
|
|
// now do all the LatexAction stuff |
|
if (!runCommand()) |
|
{ |
|
string msg = FS(_("Failed to generate LaTeX image!")); |
|
GtkWidget* dialog = gtk_message_dialog_new(control->getGtkWindow(), |
|
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", |
|
msg.c_str()); |
|
gtk_window_set_transient_for(GTK_WINDOW(dialog), control->getGtkWindow()); |
|
gtk_dialog_run(GTK_DIALOG(dialog)); |
|
gtk_widget_destroy(dialog); |
|
return; |
|
} |
|
|
|
insertTexImage(); |
|
} |
|
|
|
|