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.
 
 
 
 
 
 

394 lines
11 KiB

#include "XournalMain.h"
#include "Control.h"
#include "gui/GladeSearchpath.h"
#include "gui/MainWindow.h"
#include "gui/toolbarMenubar/model/ToolbarColorNames.h"
#include "gui/XournalView.h"
#include "pdf/popplerdirect/PdfExport.h"
#include "xojfile/LoadHandler.h"
#include <config.h>
#include <config-dev.h>
#include <config-paths.h>
#include <i18n.h>
#include <gtk/gtk.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
#include <boost/locale.hpp>
namespace bf = boost::filesystem;
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include <vector>
using std::vector;
XournalMain::XournalMain()
{
XOJ_INIT_TYPE(XournalMain);
}
XournalMain::~XournalMain()
{
XOJ_RELEASE_TYPE(XournalMain);
}
//it HAS to be done – otherwise such things like boost::algorithm::to_lower wont work, throwing casting exceptions
void XournalMain::initLocalisation()
{
XOJ_CHECK_TYPE(XournalMain);
//locale generator
boost::locale::generator gen;
#ifdef ENABLE_NLS
gen.add_messages_path(PACKAGE_LOCALE_DIR);
gen.add_messages_domain(GETTEXT_PACKAGE);
bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
textdomain(GETTEXT_PACKAGE);
#endif //ENABLE_NLS
std::locale::global(gen("")); //"" - system default locale
std::cout.imbue(std::locale());
}
void XournalMain::checkForErrorlog()
{
XOJ_CHECK_TYPE(XournalMain);
bf::path errorDir = Util::getConfigSubfolder(ERRORLOG_DIR);
bf::directory_iterator end_iter;
vector<string> errorList;
for (bf::directory_iterator dir_iter(errorDir); dir_iter != end_iter; ++dir_iter)
{
if (bf::is_regular_file(dir_iter->status()))
{
string name = dir_iter->path().filename().string();
if (boost::starts_with(name, "errorlog."))
{
errorList.push_back(name);
}
}
}
if (!errorList.empty())
{
std::sort(errorList.begin(), errorList.end());
string msg = errorList.size() == 1
? _("There is an errorlogfile from Xournal++. Please send a Bugreport, so the bug may be fixed.")
: _("There are errorlogfiles from Xournal++. Please send a Bugreport, so the bug may be fixed.");
msg += "\n";
#if defined(GIT_BRANCH) && defined(GIT_REPO_OWNER)
msg += FS(_F("You're using {1}/{2} branch. Send Bugreport will direct you to this repo's issue tracker.")
% GIT_REPO_OWNER % GIT_BRANCH);
msg += "\n";
#endif
msg += FS(_F("The most recent log file name: {1}") % errorList[0]);
GtkWidget* dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", msg.c_str());
gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Send Bugreport"), 1);
gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Open Logfile"), 2);
gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Open Logfile directory"), 3);
gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Delete Logfile"), 4);
gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Cancel"), 5);
int res = gtk_dialog_run(GTK_DIALOG(dialog));
path errorlogPath = Util::getConfigSubfolder(ERRORLOG_DIR);
errorlogPath /= errorList[0];
if (res == 1) // Send Bugreport
{
Util::openFileWithDefaultApplicaion(PROJECT_BUGREPORT);
Util::openFileWithDefaultApplicaion(errorlogPath);
}
else if (res == 2) // Open Logfile
{
Util::openFileWithDefaultApplicaion(errorlogPath);
}
else if (res == 3) // Open Logfile directory
{
Util::openFileWithFilebrowser(errorlogPath.parent_path());
}
else if (res == 4) // Delete Logfile
{
if (!bf::remove(errorlogPath))
{
GtkWidget* dlgError = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s",
FC(_F("Errorlog cannot be deleted. You have to do it manually.\nLogfile: {1}")
% errorlogPath.string()));
gtk_dialog_run(GTK_DIALOG(dlgError));
gtk_widget_destroy(dlgError);
}
}
else if (res == 5) // Cancel
{
// Nothing to do
}
gtk_widget_destroy(dialog);
}
}
void XournalMain::checkForEmergencySave() {
// TODO Check for emergency save document!
// gchar * filename = g_strconcat(g_get_home_dir(), G_DIR_SEPARATOR_S, CONFIG_DIR, G_DIR_SEPARATOR_S, "errorlog.log", NULL);
// if (g_file_test(filename, G_FILE_TEST_EXISTS)) {
// GtkWidget * dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _C(
// "There is an errorlogfile from Xournal++. Please send a Bugreport, so the bug may been fixed.\nLogfile: %s"), filename);
// gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Send Bugreport"), 1);
// gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Open Logfile"), 2);
// gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Delete Logfile"), 3);
// gtk_dialog_add_button(GTK_DIALOG(dialog), _C("Cancel"), 4);
//
// int res = gtk_dialog_run(GTK_DIALOG(dialog));
//
// if (res == 1) { // Send Bugreport
// Util::openFileWithDefaultApplicaion("http://sourceforge.net/tracker/?group_id=163434&atid=827733");
// } else if (res == 2) { // Open Logfile
// Util::openFileWithFilebrowser(filename);
// } else if (res == 3) { // Delete Logfile
// if (g_unlink(filename) != 0) {
// GtkWidget * dlgError = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", _C(
// "Errorlog could not be deleted. You have to delete it manually.\nLogfile: %s"), filename);
// gtk_dialog_run(GTK_DIALOG(dlgError));
// }
// } else if (res == 4) { // Cancel
// // Nothing to do
// }
//
// gtk_widget_destroy(dialog);
// }
}
int XournalMain::exportPdf(const char* input, const char* output)
{
XOJ_CHECK_TYPE(XournalMain);
LoadHandler loader;
Document* doc = loader.loadDocument(input);
if (doc == NULL)
{
cerr << loader.getLastError() << endl;
return -2;
}
GFile* file = g_file_new_for_commandline_arg(output);
PdfExport pdf(doc, NULL);
if (!pdf.createPdf(g_file_get_path(file)))
{
cerr << pdf.getLastError() << endl;
g_object_unref(file);
return -3;
}
g_object_unref(file);
cout << _("PDF file successfully created") << endl;
return 0; // no error
}
int XournalMain::run(int argc, char* argv[])
{
XOJ_CHECK_TYPE(XournalMain);
this->initLocalisation();
GError* error = NULL;
GOptionContext* context = g_option_context_new("FILE");
bool optNoPdfCompress = false;
gchar** optFilename = NULL;
gchar* pdfFilename = NULL;
int openAtPageNumber = -1;
string pdf_no_compress = _("Don't compress PDF files (for debugging)");
string create_pdf = _("PDF output filename");
string page_jump = _("Jump to Page (first Page: 1)");
GOptionEntry options[] = {
{ "pdf-no-compress", 0, 0, G_OPTION_ARG_NONE, &optNoPdfCompress, pdf_no_compress.c_str(), NULL },
{ "create-pdf", 'p', 0, G_OPTION_ARG_FILENAME, &pdfFilename, create_pdf.c_str(), NULL },
{ "page", 'n', 0, G_OPTION_ARG_INT, &openAtPageNumber, page_jump.c_str(), "N" },
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &optFilename, "<input>", NULL},
{NULL}
};
g_option_context_add_main_entries(context, options, GETTEXT_PACKAGE);
// parse options, so we don't need gtk_init, but don't init display (so we have a commandline mode)
g_option_context_add_group(context, gtk_get_option_group(false));
if (!g_option_context_parse(context, &argc, &argv, &error))
{
cerr << error->message << endl;
g_error_free(error);
gchar* help = g_option_context_get_help(context, true, NULL);
cout << help;
g_free(help);
error = NULL;
}
g_option_context_free(context);
if (optNoPdfCompress)
{
PdfWriter::setCompressPdfOutput(false);
}
if (pdfFilename && optFilename && *optFilename)
{
return exportPdf(*optFilename, pdfFilename);
}
// Init GTK Display
gdk_display_open_default_libgtk_only();
GladeSearchpath* gladePath = initPath(argv[0]);
// init singleton
string colorNameFile = Util::getConfigFile("colornames.ini").string();
ToolbarColorNames::getInstance().loadFile(colorNameFile);
Control* control = new Control(gladePath);
MainWindow* win = new MainWindow(gladePath, control);
control->initWindow(win);
win->show(NULL);
bool opened = false;
if (optFilename)
{
if (g_strv_length(optFilename) != 1)
{
GtkWidget* dialog = gtk_message_dialog_new((GtkWindow*) *win,
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
"%s", _C("Sorry, Xournal can only open one file from the command line.\n"
"Others are ignored."));
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(win->getWindow()));
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
GFile* file = g_file_new_for_commandline_arg(optFilename[0]);
char* filename = g_file_get_path(file);
char* uri = g_file_get_uri(file);
string sUri = uri;
g_free(uri);
g_object_unref(file);
if (ba::starts_with(sUri, "file://"))
{
opened = control->openFile(filename, openAtPageNumber);
g_free(filename);
}
else
{
GtkWidget* dialog = gtk_message_dialog_new((GtkWindow*) *win,
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
"%s", _C("Sorry, Xournal cannot open remote files at the moment.\n"
"You have to copy the file to a local directory."));
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(win->getWindow()));
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
}
control->getScheduler()->start();
if (!opened)
{
control->newFile();
}
checkForErrorlog();
checkForEmergencySave();
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
control->saveSettings();
win->getXournal()->clearSelection();
control->getScheduler()->stop();
delete win;
delete control;
delete gladePath;
ToolbarColorNames::getInstance().saveFile(colorNameFile);
ToolbarColorNames::freeInstance();
return 0;
}
/**
* Path for glade files and Pixmaps, first searches in the home folder, so you can customize glade files
*/
GladeSearchpath* XournalMain::initPath(const char* argv0)
{
XOJ_CHECK_TYPE(XournalMain);
GladeSearchpath* gladePath = new GladeSearchpath();
// Create config directory if not exists
path file = Util::getConfigSubfolder("");
bf::create_directories(file);
bf::permissions(file, bf::perms::owner_all);
// Add first home dir to search path, to add custom glade XMLs
{
path searchPath = Util::getConfigSubfolder("ui");
if (bf::exists(searchPath) && bf::is_directory(searchPath))
{
gladePath->addSearchDirectory(searchPath.c_str());
}
}
gchar* path = g_path_get_dirname(argv0);
gchar* searchPath = g_build_filename(path, "ui", NULL);
gladePath->addSearchDirectory(searchPath);
g_free(searchPath);
searchPath = g_build_filename(path, "..", "ui", NULL);
gladePath->addSearchDirectory(searchPath);
g_free(searchPath);
g_free(path);
char buffer[512] = { 0 };
path = getcwd(buffer, sizeof(buffer));
if (path == NULL)
{
return gladePath;
}
searchPath = g_build_filename(path, "ui", NULL);
gladePath->addSearchDirectory(searchPath);
g_free(searchPath);
searchPath = g_build_filename(path, "..", "ui", NULL);
gladePath->addSearchDirectory(searchPath);
g_free(searchPath);
searchPath = g_build_filename(PROJECT_SOURCE_DIR, "ui", NULL);
gladePath->addSearchDirectory(searchPath);
g_free(searchPath);
searchPath = g_build_filename(PACKAGE_DATA_DIR, PROJECT_PACKAGE, "ui", NULL);
gladePath->addSearchDirectory(searchPath);
g_free(searchPath);
return gladePath;
}