From 8a61fa1bec0d7a8c7e51cae8533a4e90a082be34 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 22 Feb 2020 08:48:17 +0100 Subject: [PATCH 01/43] Adding monster autolinking test. --- build/test-autolinking.sh | 41 ++++++++++++++++++++++ build/test-lib-units.sh | 7 ++-- lib/src/app_info.h | 6 ++-- lib/test/src/ai/autolinking_cmark_test.cpp | 39 +++++++++++++++++++- 4 files changed, 86 insertions(+), 7 deletions(-) create mode 100755 build/test-autolinking.sh diff --git a/build/test-autolinking.sh b/build/test-autolinking.sh new file mode 100755 index 00000000..9f11092c --- /dev/null +++ b/build/test-autolinking.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# +# MindForger thinking notebook +# +# Copyright (C) 2016-2020 Martin Dvorak +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This script prepares autolinking data by creating cloning production +# MF repository to /tmp, then it runs lib unit test script which +# compiles/valgrinds/... monster autolinking unit test (autolinks +# each and every production repo section and tracks memory). + +export SCRIPT_DIR=`pwd` +export MONSTER_REPO_PATH="/tmp/mindforger-unit-test/monster-repository" + +if [[ -d ${MONSTER_REPO_PATH} ]] +then + echo "Monster directory exists: ${MONSTER_REPO_PATH}" + #rm -rvf ${MONSTER_REPO_PATH} +else + mkdir -p ${MONSTER_REPO_PATH} + cp -rvf ~/mf/* ${MONSTER_REPO_PATH} + rm -rvf ${MONSTER_REPO_PATH}/.git ${MONSTER_REPO_PATH}/import ${MONSTER_REPO_PATH}/limbo +fi + +# Run monster unit tests +# ./test-lib-units.sh TEST_NAME + +# eof diff --git a/build/test-lib-units.sh b/build/test-lib-units.sh index 34da6c18..fbba5069 100755 --- a/build/test-lib-units.sh +++ b/build/test-lib-units.sh @@ -17,9 +17,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -export OPTION_RUN_ALL_TESTS=yes # comment this line to run OPTION_TEST only +#export OPTION_RUN_ALL_TESTS=yes # comment this line to run OPTION_TEST only export OPTION_RECOMPILE=yes # recompile before running test(s) (comment this line to disable) -export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to disable) +#export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to disable) #export OPTION_RUN_GDB=yes # run test(s) w/ GDB (comment this line to disable) # benchmarks @@ -29,6 +29,7 @@ export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to d #export OPTION_TEST="MarkdownParserBenchmark.ParserMeta" # tests +export OPTION_TEST="AutolinkingCmarkTestCase.Monster" #export OPTION_TEST="AutolinkingCmarkTestCase.*" #export OPTION_TEST="AutolinkingCmarkTestCase.CmarkAstRowWalker" #export OPTION_TEST="AutolinkingCmarkTestCase.CmarkAstBlockTransformer" @@ -51,7 +52,7 @@ export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to d #export OPTION_TEST="AiNlpTestCase.Stemmer" #export OPTION_TEST="HtmlTestCase.*" #export OPTION_TEST="HtmlTestCase.Outline" -export OPTION_TEST="HtmlTestCase.TaskList" +#export OPTION_TEST="HtmlTestCase.TaskList" #export OPTION_TEST="HtmlTestCase.NoteLinks" #export OPTION_TEST="MarkdownParserTestCase.*" #export OPTION_TEST="MarkdownParserTestCase.Bug622Loop64kLinesOverflow" diff --git a/lib/src/app_info.h b/lib/src/app_info.h index 44d26bf1..ea5b460d 100644 --- a/lib/src/app_info.h +++ b/lib/src/app_info.h @@ -1,8 +1,8 @@ #define MINDFORGER_VERSION_MAJOR "1" -#define MINDFORGER_VERSION_MINOR "51" +#define MINDFORGER_VERSION_MINOR "52" #define MINDFORGER_VERSION_REVISION "0" -#define MINDFORGER_VERSION_STRING "1.51.0" -#define MINDFORGER_VERSION_DWORD 1,51,0,2 +#define MINDFORGER_VERSION_STRING "1.52.0" +#define MINDFORGER_VERSION_DWORD 1,52,0,2 #define MINDFORGER_APP_NAME "MindForger" #define MINDFORGER_APP_DESCRIPTION "MindForger Thinking Notebook" #define MINDFORGER_APP_AUTHOR "Martin Dvorak" diff --git a/lib/test/src/ai/autolinking_cmark_test.cpp b/lib/test/src/ai/autolinking_cmark_test.cpp index d410ea60..3aa420e7 100644 --- a/lib/test/src/ai/autolinking_cmark_test.cpp +++ b/lib/test/src/ai/autolinking_cmark_test.cpp @@ -31,6 +31,7 @@ #ifdef MF_MD_2_HTML_CMARK #include +#include "../../../src/gear/file_utils.h" #include "../../../src/mind/ai/autolinking/cmark_aho_corasick_block_autolinking_preprocessor.h" using namespace std; @@ -452,5 +453,41 @@ TEST(AutolinkingCmarkTestCase, BasicRepo) cout << "= BEGIN AUTO MD =" << endl << autolinkedMd << endl << "= END AUTO MD =" << endl; } +/** + * @brief Unit test which autolinks copy of production MF repository + * + * Autolinking is performed if MF repo exists in predefined location. + */ +TEST(AutolinkingCmarkTestCase, Monster) +{ + string repositoryPath{"/tmp/mindforger-unit-test/monster-repository"}; + if(m8r::isDirectoryOrFileExists(repositoryPath.c_str())) { + m8r::Configuration& config = m8r::Configuration::getInstance(); + config.clear(); + config.setConfigFilePath("/tmp/cfg-act-monster.md"); + config.setActiveRepository(config.addRepository(m8r::RepositoryIndexer::getRepositoryForPath(repositoryPath))); + m8r::Mind mind(config); + mind.learn(); + mind.think().get(); + cout << endl << "Statistics:"; + cout << endl << " Outlines: " << mind.remind().getOutlinesCount(); + cout << endl << " Bytes : " << mind.remind().getOutlineMarkdownsSize(); + ASSERT_LE(370, mind.remind().getOutlinesCount()); + m8r::CmarkAhoCorasickBlockAutolinkingPreprocessor autolinker{mind}; + + cout << endl << endl << "Testing MONSTER autolinking:" << endl; + for(m8r::Outline*const& o:mind.remind().getOutlines()) { + for(m8r::Note*const& n:o->getNotes()) { + cout << " " << n->getName() << endl; + string autolinkedMd{}; + autolinker.process(n->getDescription(), autolinkedMd); + cout << " DONE: " << autolinkedMd.size() << endl; + } + } + } else { + cout << "Skipping MONSTER autolinking: MF repository doesn't exist" << repositoryPath << endl; + } +} + #endif // MF_MD_2_HTML_CMARK -#endif // WINDOWS +#endif // !WINDOWS From 64d72edd2501a9f8a5d5ff7e2356e30c3c81c37e Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sun, 23 Feb 2020 10:24:45 +0100 Subject: [PATCH 02/43] Unit tests w/ autolinking in green (stemmer tests disabled due to leaks) #1038 --- build/test-lib-units.sh | 10 +++++----- lib/lib.pro | 5 +++++ lib/src/gear/string_utils.cpp | 2 +- ...aho_corasick_block_autolinking_preprocessor.cpp | 14 +++++++++----- lib/test/src/ai/nlp_test.cpp | 6 ++++-- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/build/test-lib-units.sh b/build/test-lib-units.sh index fbba5069..0ba8ade2 100755 --- a/build/test-lib-units.sh +++ b/build/test-lib-units.sh @@ -17,9 +17,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -#export OPTION_RUN_ALL_TESTS=yes # comment this line to run OPTION_TEST only +export OPTION_RUN_ALL_TESTS=yes # comment this line to run OPTION_TEST only export OPTION_RECOMPILE=yes # recompile before running test(s) (comment this line to disable) -#export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to disable) +export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to disable) #export OPTION_RUN_GDB=yes # run test(s) w/ GDB (comment this line to disable) # benchmarks @@ -29,7 +29,7 @@ export OPTION_RECOMPILE=yes # recompile before running test(s) (comment this lin #export OPTION_TEST="MarkdownParserBenchmark.ParserMeta" # tests -export OPTION_TEST="AutolinkingCmarkTestCase.Monster" +#export OPTION_TEST="AutolinkingCmarkTestCase.Monster" #export OPTION_TEST="AutolinkingCmarkTestCase.*" #export OPTION_TEST="AutolinkingCmarkTestCase.CmarkAstRowWalker" #export OPTION_TEST="AutolinkingCmarkTestCase.CmarkAstBlockTransformer" @@ -128,8 +128,8 @@ then then export M8R_VALGRIND="valgrind --vgdb=yes --vgdb-error=0 --track-origins=yes --tool=memcheck --leak-check=full --show-leak-kinds=all" else - export M8R_VALGRIND="valgrind --track-origins=yes --tool=memcheck --leak-check=full --show-leak-kinds=all" - #export M8R_VALGRIND="valgrind -v --track-origins=yes --tool=memcheck --leak-check=full --show-leak-kinds=all" + #export M8R_VALGRIND="valgrind --track-origins=yes --tool=memcheck --leak-check=full --show-leak-kinds=all" + export M8R_VALGRIND="valgrind -v --track-origins=yes --tool=memcheck --leak-check=full --show-leak-kinds=all" fi else export M8R_VALGRIND= diff --git a/lib/lib.pro b/lib/lib.pro index 356d2732..21db1d09 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -69,6 +69,11 @@ win32{ } else:!mfnocxx { QMAKE_CXX = ccache g++ } + + mfdebug|mfunits { + # debug info + QMAKE_CXXFLAGS += -g + } QMAKE_CXXFLAGS += -pedantic -std=c++11 } diff --git a/lib/src/gear/string_utils.cpp b/lib/src/gear/string_utils.cpp index c7f6eb7c..13f88a11 100644 --- a/lib/src/gear/string_utils.cpp +++ b/lib/src/gear/string_utils.cpp @@ -164,7 +164,7 @@ string normalizeToNcName(string name, char quoteChar) { void toString(const std::vector& ss, std::string& os) { if(!ss.empty()) { - for(std::string *s:ss) { + for(std::string* s:ss) { os += *s; os += "\n"; } diff --git a/lib/src/mind/ai/autolinking/cmark_aho_corasick_block_autolinking_preprocessor.cpp b/lib/src/mind/ai/autolinking/cmark_aho_corasick_block_autolinking_preprocessor.cpp index b4a87b04..59a5af85 100644 --- a/lib/src/mind/ai/autolinking/cmark_aho_corasick_block_autolinking_preprocessor.cpp +++ b/lib/src/mind/ai/autolinking/cmark_aho_corasick_block_autolinking_preprocessor.cpp @@ -119,8 +119,7 @@ cmark_node* injectAstTxtNode( return txtNode; } -void injectThingsLinks( - cmark_node* srcNode, Mind& mind) +void injectThingsLinks(cmark_node* srcNode, Mind& mind) { // copy w to t as it will be chopped word/match by word/match from head to tail string txt{cmark_node_get_literal(srcNode)}; @@ -139,9 +138,12 @@ void injectThingsLinks( while(preSize < txt.size()) { // check $$ to detect begin/end of math (MathJax) section to ignore it if(txt.size()>=2 && '$'==txt.at(0) && '$'==txt.at(1)) { - MF_DEBUG("MATH matched"); + MF_DEBUG("MATH matched" << endl); // TODO toggle math preSize+=2; + if(txt.size()==2) { + break; + } } if(CmarkAhoCorasickBlockAutolinkingPreprocessor::TRAILING_CHARS.find(txt.at(preSize)) != string::npos) { @@ -304,7 +306,8 @@ void CmarkAhoCorasickBlockAutolinkingPreprocessor::process( cmark_node* document = cmark_parse_document( mdsc, strlen(mdsc), - CMARK_OPT_DEFAULT); + CMARK_OPT_DEFAULT + ); cmark_iter* astWalker = cmark_iter_new(document); @@ -337,7 +340,8 @@ void CmarkAhoCorasickBlockAutolinkingPreprocessor::process( char* cmm = cmark_render_commonmark(document, 0, 0); if(cmm) { amd.assign(cmm); - delete cmm; + // TODO valgrind delete cmm; + free(cmm); amd.pop_back(); } else { amd.clear(); diff --git a/lib/test/src/ai/nlp_test.cpp b/lib/test/src/ai/nlp_test.cpp index 26162917..91294610 100644 --- a/lib/test/src/ai/nlp_test.cpp +++ b/lib/test/src/ai/nlp_test.cpp @@ -40,7 +40,8 @@ extern char* getMindforgerGitHomePath(); using namespace std; -TEST(AiNlpTestCase, Stemmer) +// DISABLED test because 3rd party stemmer has memory leaks() +TEST(AiNlpTestCase, DISABLED_Stemmer) { m8r::Stemmer stemmer{}; @@ -103,7 +104,8 @@ TEST(AiNlpTestCase, Lexicon) } -TEST(AiNlpTestCase, BowOutline) +// DISABLED test because 3rd party stemmer has memory leaks() +TEST(AiNlpTestCase, DISABLED_BowOutline) { // FOO outline m8r::OutlineType oType{m8r::OutlineType::KeyOutline(),nullptr,m8r::Color::RED()}; From 4fd155e3f3fe6fcb3eabf3ee93f185a3cc032c1b Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Mon, 24 Feb 2020 08:44:30 +0100 Subject: [PATCH 03/43] Also autolinked Ns have rendered title which resolves #1216 --- lib/src/debug.h | 2 +- .../markdown_outline_representation.cpp | 9 ++- .../memory/Autolinking.md | 55 +++++++++++++++++++ .../autolinking-links-repository/memory/O1.md | 7 +++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 lib/test/resources/autolinking-links-repository/memory/Autolinking.md create mode 100644 lib/test/resources/autolinking-links-repository/memory/O1.md diff --git a/lib/src/debug.h b/lib/src/debug.h index c40c8fd4..ca8dda8d 100644 --- a/lib/src/debug.h +++ b/lib/src/debug.h @@ -32,7 +32,7 @@ #define MF_DEBUG(x) do { std::cerr << x; } while (0) // enable/disable verbose debug of particular components - //#define MF_DEBUG_HTML + #define MF_DEBUG_HTML //#define MF_DEBUG_ASYNC_TASKS //#define MF_DEBUG_QRC //#define MF_DEBUG_L10N diff --git a/lib/src/representations/markdown/markdown_outline_representation.cpp b/lib/src/representations/markdown/markdown_outline_representation.cpp index f07b0e61..a6593c6e 100644 --- a/lib/src/representations/markdown/markdown_outline_representation.cpp +++ b/lib/src/representations/markdown/markdown_outline_representation.cpp @@ -492,7 +492,9 @@ string* MarkdownOutlineRepresentation::to(const Note* note, string* md, bool inc md->append("\n"); } + MF_DEBUG("BEFORE: " << md << endl); toDescription(note, md, autolinking); + MF_DEBUG("AFTER: " << md << endl); return md; } @@ -500,7 +502,12 @@ string* MarkdownOutlineRepresentation::to(const Note* note, string* md, bool inc string* MarkdownOutlineRepresentation::toDescription(const Note* note, string* md, bool autolinking) { if(descriptionInterceptor && autolinking) { - descriptionInterceptor->process(note->getDescription(), *md); + string amd{}; + amd.reserve(1000); + descriptionInterceptor->process(note->getDescription(), amd); + if(md) { + md->append(amd); + } } else { toString(note->getDescription(), *md); } diff --git a/lib/test/resources/autolinking-links-repository/memory/Autolinking.md b/lib/test/resources/autolinking-links-repository/memory/Autolinking.md new file mode 100644 index 00000000..ddd32d7c --- /dev/null +++ b/lib/test/resources/autolinking-links-repository/memory/Autolinking.md @@ -0,0 +1,55 @@ +# Autolinking +All the examples below to be autolinked. + +**This outline:** + +Example of Second note. + +Example of second note. + +Example of Two words note. + +Example of two words note. + +Example of A B C note. + +Example of ABBREV note. + +Example of Abbreviation note. + +Example of abbreviation note. + +Example of MULTIABBREV note. + +Example of Multiword abbreviation note. + +**Other outline:** + +Example of Outline1 outline. + +Example of Outline1Note1, Outline1Note2 and Outline1Note3 note. +# Note +Single note kills many links elsewhere as it breaks longer expressions +and it also seems to impact neighbour links. +# First +... and Second and Third. + +# Second +x First / +x Second y + +x Third ~ First y +# Third +x First ~ Second y + +Foo#Name +# ABBREV: Abbreviation + +## MULTIABBREV: Multiword abbreviation + +# Two words + +## A B C +Multi-word links. +# Foo#Name +Try O Autolinking. diff --git a/lib/test/resources/autolinking-links-repository/memory/O1.md b/lib/test/resources/autolinking-links-repository/memory/O1.md new file mode 100644 index 00000000..6877102a --- /dev/null +++ b/lib/test/resources/autolinking-links-repository/memory/O1.md @@ -0,0 +1,7 @@ +# Outline1 +# Outline1Note1 + +# Outline1Note2 + +# Outline1Note3 + From 76f4408b0fa45191611c59bdbdc82e6ce93a2c0f Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Mon, 24 Feb 2020 22:44:15 +0100 Subject: [PATCH 04/43] Adding MindForger user exception, runtime exception and error. --- lib/src/exceptions.h | 51 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/lib/src/exceptions.h b/lib/src/exceptions.h index 95a8a506..36cfecf4 100644 --- a/lib/src/exceptions.h +++ b/lib/src/exceptions.h @@ -19,22 +19,57 @@ #ifndef M8R_EXCEPTIONS_H #define M8R_EXCEPTIONS_H +#include +#include + namespace m8r { class MindForgerException : public std::exception { +private: + const std::string message; + public: - explicit MindForgerException(const char* message) throw() + explicit MindForgerException(const std::string& message) throw() : message(message) {} - ~MindForgerException() throw() { - // IMPROVE deleted by parent > remove the following line (unit test) - if(message) delete message; - } - const char *what() const throw() { return message; } + const char* what() const throw() { return message.c_str(); } +}; -private: - const char *message; +/** + * @brief MindForger user exception. + * + * User exception is caused by user configuration errors and can be fixed by users. + * This needs a very clear explanation of what the user did wrong and how to fix it. + */ +class MindForgerUserException : public MindForgerException +{ + explicit MindForgerUserException(const std::string& message) throw() + : MindForgerException(message) {} +}; + +/** + * @brief MindForger runtime exception. + * + * Runtime exception is caused by the system configuration/system state error and + * can be handled by a fallback or user action. + */ +class MindForgerRuntimeException : public MindForgerException +{ + explicit MindForgerRuntimeException(const std::string& message) throw() + : MindForgerException(message) {} +}; + +/** + * @brief MindForger error. + * + * Errors should not happen and can only be fixed by programmers ~ is an implementation + * error. MindForger error should *never* be caught. + */ +class MindForgerError: public MindForgerException +{ + explicit MindForgerError(const std::string& message) throw() + : MindForgerException(message) {} }; } From 39bcbe396e7620abe616bb597a1ebe17cc617226 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Tue, 25 Feb 2020 08:13:36 +0100 Subject: [PATCH 05/43] Adding autolinking handling of new, changed and just forgotten Ns/Os which resolves #1035 --- app/src/qt/main_window_presenter.cpp | 6 +-- app/src/qt/note_edit_presenter.cpp | 2 +- app/src/qt/outline_header_edit_presenter.cpp | 2 +- lib/src/debug.h | 2 +- lib/src/mind/memory.cpp | 4 +- lib/src/mind/mind.cpp | 47 ++++++++++++++++++-- lib/src/mind/mind.h | 15 +++++++ 7 files changed, 68 insertions(+), 10 deletions(-) diff --git a/app/src/qt/main_window_presenter.cpp b/app/src/qt/main_window_presenter.cpp index 4ec604cb..9027df5f 100644 --- a/app/src/qt/main_window_presenter.cpp +++ b/app/src/qt/main_window_presenter.cpp @@ -1823,7 +1823,7 @@ void MainWindowPresenter::handleNoteNew() newNoteDialog->getProgress(), newNoteDialog->getStencil()); if(note) { - mind->remind().remember(orloj->getOutlineView()->getCurrentOutline()->getKey()); + mind->remember(orloj->getOutlineView()->getCurrentOutline()->getKey()); // insert new N and select it in the tree orloj->getOutlineView()->insertAndSelect(note); @@ -2067,7 +2067,7 @@ void MainWindowPresenter::doActionNoteForget() QAbstractButton* choosen = msgBox.clickedButton(); if(yes == choosen) { Outline* outline = mind->noteForget(note); - mind->remind().remember(outline); + mind->remember(outline); orloj->showFacetOutline(orloj->getOutlineView()->getCurrentOutline()); } return; @@ -2116,7 +2116,7 @@ void MainWindowPresenter::doActionNoteExtract() mdRepresentation->description(&t, description); extractedNote->setDescription(description); - mind->remind().remember(orloj->getOutlineView()->getCurrentOutline()->getKey()); + mind->remember(orloj->getOutlineView()->getCurrentOutline()->getKey()); // IMPROVE smarter refresh of outline tree (do less then overall load) orloj->showFacetOutline(orloj->getOutlineView()->getCurrentOutline()); orloj->showFacetNoteEdit(extractedNote); diff --git a/app/src/qt/note_edit_presenter.cpp b/app/src/qt/note_edit_presenter.cpp index 35b2c0e5..34852c85 100644 --- a/app/src/qt/note_edit_presenter.cpp +++ b/app/src/qt/note_edit_presenter.cpp @@ -112,7 +112,7 @@ void NoteEditPresenter::slotSaveNote() currentNote->makeModified(); // remember - mwp->getMind()->remind().remember(currentNote->getOutlineKey()); + mwp->getMind()->remember(currentNote->getOutlineKey()); mwp->getStatusBar()->showInfo(tr("Note '%1' saved").arg(QString::fromStdString(currentNote->getName()))); } else { mwp->getStatusBar()->showError(tr("Attempt to save data from UI to Note, but no Note is set.")); diff --git a/app/src/qt/outline_header_edit_presenter.cpp b/app/src/qt/outline_header_edit_presenter.cpp index f410031b..634027a7 100644 --- a/app/src/qt/outline_header_edit_presenter.cpp +++ b/app/src/qt/outline_header_edit_presenter.cpp @@ -112,7 +112,7 @@ void OutlineHeaderEditPresenter::slotSaveOutlineHeader() } // remember - mwp->getMind()->remind().remember(currentOutline->getKey()); + mwp->getMind()->remember(currentOutline->getKey()); mwp->getStatusBar()->showInfo(tr("Notebook saved!")); } else { mwp->getStatusBar()->showError(tr("Attempt to save data from UI to Notebook, but no Notebook is set.")); diff --git a/lib/src/debug.h b/lib/src/debug.h index ca8dda8d..c40c8fd4 100644 --- a/lib/src/debug.h +++ b/lib/src/debug.h @@ -32,7 +32,7 @@ #define MF_DEBUG(x) do { std::cerr << x; } while (0) // enable/disable verbose debug of particular components - #define MF_DEBUG_HTML + //#define MF_DEBUG_HTML //#define MF_DEBUG_ASYNC_TASKS //#define MF_DEBUG_QRC //#define MF_DEBUG_L10N diff --git a/lib/src/mind/memory.cpp b/lib/src/mind/memory.cpp index ef024c6d..eec6cb92 100644 --- a/lib/src/mind/memory.cpp +++ b/lib/src/mind/memory.cpp @@ -202,7 +202,9 @@ void Memory::remember(const std::string& outlineKey) o->checkAndFixProperties(); persistence->save(o); } else { - throw MindForgerException{"Save: unable to find outline w/ given key"}; + throw MindForgerException{ + "Save: unable to find outline w/ given key (" + outlineKey + ") to save" + }; } } diff --git a/lib/src/mind/mind.cpp b/lib/src/mind/mind.cpp index 1ea8090a..5e6133f4 100644 --- a/lib/src/mind/mind.cpp +++ b/lib/src/mind/mind.cpp @@ -288,6 +288,47 @@ bool Mind::autolinkFindLongestPrefixWord(std::string& s, std::string& r) const * Remembering */ + +void Mind::remember(const std::string& outlineKey) +{ + memory.remember(outlineKey); + + // TODO onRemembering() + +#ifdef MF_MD_2_HTML_CMARK + if(config.isAutolinking()) { + autolinking->reindex(); + } +#endif +} + +void Mind::remember(Outline* outline) +{ + memory.remember(outline); + + // TODO onRemembering() + +#ifdef MF_MD_2_HTML_CMARK + if(config.isAutolinking()) { + autolinking->reindex(); + } +#endif +} + +void Mind::forget(Outline* outline) +{ + memory.forget(outline); + + // TODO onRemembering() + +#ifdef MF_MD_2_HTML_CMARK + if(config.isAutolinking()) { + autolinking->reindex(); + } +#endif +} + + const vector& Mind::getMemoryDwell(int pageSize) const { UNUSED_ARG(pageSize); @@ -832,7 +873,7 @@ string Mind::outlineNew( outline->addNote(note); } - memory.remember(outline); + remember(outline); onRemembering(); } else { throw MindForgerException("Unable to create new Outline!"); @@ -858,7 +899,7 @@ Outline* Mind::learnOutlineTWiki(const string& twikiFile) o->addTag(memory.getOntology().findOrCreateTag("twiki")); o->addTag(memory.getOntology().findOrCreateTag("import")); - memory.remember(o); + remember(o); onRemembering(); return o; } else { @@ -891,7 +932,7 @@ bool Mind::outlineForget(string outlineKey) if(o) { deleteWatermark++; - memory.forget(o); + forget(o); auto k = memory.createLimboKey(&o->getName()); o->setKey(k); moveFile(outlineKey, k); diff --git a/lib/src/mind/mind.h b/lib/src/mind/mind.h index d03244ab..bd8e0303 100644 --- a/lib/src/mind/mind.h +++ b/lib/src/mind/mind.h @@ -329,6 +329,21 @@ class Mind */ Memory& remind() { return memory; } + /** + * @brief Remember new Outline and update mind (indices if needed). + */ + void remember(Outline* outline); + + /** + * @brief Remember existing Outline and update mind (indices if needed). + */ + void remember(const std::string& outlineKey); + + /** + * @brief Forget Outline and update mind (indices if needed). + */ + void forget(Outline* outline); + /** * @brief Get ontology. */ From 64c3d989d6e14a64b2727d99871f30a9872375ac Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Wed, 26 Feb 2020 07:48:34 +0100 Subject: [PATCH 06/43] Autolinking not available if cmark not available which resolves #1033 --- app/app.pro | 1 + app/src/qt/main_menu_view.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/app.pro b/app/app.pro index ecf23a24..b10d8004 100644 --- a/app/app.pro +++ b/app/app.pro @@ -76,6 +76,7 @@ win32 { LIBS += -L$$OUT_PWD/../deps/discount -ldiscount } else { # cmark-gfm + DEFINES += MF_MD_2_HTML_CMARK # cmark-gfm to be built by qmake to enable clean system build for Launchpad debuild libcmark-gfm.target = libcmark-gfm diff --git a/app/src/qt/main_menu_view.cpp b/app/src/qt/main_menu_view.cpp index 17328869..bd283516 100644 --- a/app/src/qt/main_menu_view.cpp +++ b/app/src/qt/main_menu_view.cpp @@ -76,7 +76,7 @@ MainMenuView::MainMenuView(MainWindowView& mainWindowView) // think ... toggle mental processes ~ enable associations/similarity/search based suggestions on searching/reading/writing notes actionMindAutolink = new QAction(QIcon(":/menu-icons/link.svg"), tr("&Autolink"), mainWindow); -#ifdef DO_MF_DEBUG +#ifdef MF_MD_2_HTML_CMARK actionMindAutolink->setCheckable(true); actionMindAutolink->setStatusTip(tr("Automatically inject links to relevant Notebooks and Notes when browsing HTML preview")); actionMindAutolink->setShortcut(QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_A)); From aec336658755f421a6b874e8ff53aa4196386b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Dvo=C5=99=C3=A1k?= Date: Thu, 5 Mar 2020 23:18:50 +0100 Subject: [PATCH 07/43] Improving keyboard shortcuts UX on macOS --- app/src/qt/main_menu_view.cpp | 15 +++++++++++++-- app/src/qt/note_edit_view.cpp | 14 ++++++++++---- app/src/qt/note_view.cpp | 5 +++++ app/src/qt/outline_header_edit_view.cpp | 14 ++++++++++---- app/src/qt/outline_tree_view.cpp | 11 +++++++++++ app/src/qt/widgets/edit_buttons_panel.cpp | 8 ++++++++ 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/app/src/qt/main_menu_view.cpp b/app/src/qt/main_menu_view.cpp index bd283516..328b4550 100644 --- a/app/src/qt/main_menu_view.cpp +++ b/app/src/qt/main_menu_view.cpp @@ -279,11 +279,18 @@ MainMenuView::MainMenuView(MainWindowView& mainWindowView) menuView->addAction(actionViewFullscreen); // menu: navigator - +#ifdef __APPLE__ + actionNavigatorEdgesStretch = new QAction(tr("Str&etch edges"), mainWindow); +#else actionNavigatorEdgesStretch = new QAction(tr("Str&etch edges\te | mouse wheel"), mainWindow); +#endif actionNavigatorEdgesStretch->setStatusTip(tr("Stretch knowledge graph edges")); +#ifdef __APPLE__ + actionNavigatorEdgesShrink= new QAction(tr("&Sh&rink edge"), mainWindow); +#else actionNavigatorEdgesShrink= new QAction(tr("&Sh&rink edge\tE | mouse wheel"), mainWindow); +#endif actionNavigatorEdgesShrink->setStatusTip(tr("Shring knowledge graph edges")); actionNavigatorZoomIn = new QAction(tr("Zoom &in\tz"), mainWindow); @@ -378,11 +385,15 @@ MainMenuView::MainMenuView(MainWindowView& mainWindowView) actionNoteSave = new QAction(QIcon(":/menu-icons/save.svg"), tr("Remember\tCtrl+S"), mainWindow); // Ctrl+S is handled elsewhere and I don't want menu to handle it actionNoteSave->setStatusTip(tr("Save Note being edited")); +#ifdef __APPLE__ + actionNoteForget = new QAction(QIcon(":/menu-icons/delete.svg"), tr("&Forget\tCtrl+D"), mainWindow); +#else actionNoteForget = new QAction(QIcon(":/menu-icons/delete.svg"), tr("&Forget\tDel"), mainWindow); // Delete is handled elsewhere and I don't want menu to handle it +#endif actionNoteForget->setStatusTip(tr("Forget Note")); #ifdef __APPLE__ - actionNoteClose = new QAction(QIcon(":/menu-icons/save.svg"), tr("Leave\t⌘+Left"), mainWindow); // Alt+Left is handled elsewhere and I don't want menu to handle it + actionNoteClose = new QAction(QIcon(":/menu-icons/save.svg"), tr("Save and Leave\tCtrl+L"), mainWindow); #else actionNoteClose = new QAction(QIcon(":/menu-icons/save.svg"), tr("Leave\tAlt+Left"), mainWindow); // Alt+Left is handled elsewhere and I don't want menu to handle it #endif diff --git a/app/src/qt/note_edit_view.cpp b/app/src/qt/note_edit_view.cpp index 166a90b2..c07218a1 100644 --- a/app/src/qt/note_edit_view.cpp +++ b/app/src/qt/note_edit_view.cpp @@ -40,17 +40,23 @@ NoteEditView::NoteEditView(QWidget* parent) setLayout(layout); // signals +#ifdef __APPLE__ new QShortcut( - QKeySequence(QKeySequence(Qt::ALT+Qt::Key_Left)), + QKeySequence(Qt::CTRL+Qt::Key_L), this, SLOT(slotSaveAndCloseEditor())); +#else new QShortcut( - QKeySequence(QKeySequence(Qt::CTRL+Qt::Key_G)), + QKeySequence(Qt::ALT+Qt::Key_Left), + this, SLOT(slotSaveAndCloseEditor())); +#endif + new QShortcut( + QKeySequence(Qt::CTRL+Qt::Key_G), this, SLOT(slotCloseEditor())); new QShortcut( - QKeySequence(QKeySequence(Qt::ALT+Qt::Key_Return)), + QKeySequence(Qt::ALT+Qt::Key_Return), this, SLOT(slotOpenNotePropertiesEditor())); new QShortcut( - QKeySequence(QKeySequence(Qt::CTRL+Qt::Key_S)), + QKeySequence(Qt::CTRL+Qt::Key_S), this, SLOT(slotSaveNote())); QObject::connect( bottomButtonsPanel->getRememberButton(), SIGNAL(clicked()), diff --git a/app/src/qt/note_view.cpp b/app/src/qt/note_view.cpp index 7e889cc2..8194fa29 100644 --- a/app/src/qt/note_view.cpp +++ b/app/src/qt/note_view.cpp @@ -72,8 +72,13 @@ bool NoteViewerView::eventFilter(QObject* obj, QEvent *event) void NoteViewerView::keyPressEvent(QKeyEvent* event) { +#ifdef __APPLE__ + if(event->modifiers() & Qt::ControlModifier){ + if(event->key()==Qt::Key_L) { +#else if(event->modifiers() & Qt::AltModifier){ if(event->key()==Qt::Key_Left) { +#endif emit signalFromViewNoteToOutlines(); } } diff --git a/app/src/qt/outline_header_edit_view.cpp b/app/src/qt/outline_header_edit_view.cpp index 15d6b95d..8d8dc76d 100644 --- a/app/src/qt/outline_header_edit_view.cpp +++ b/app/src/qt/outline_header_edit_view.cpp @@ -38,17 +38,23 @@ OutlineHeaderEditView::OutlineHeaderEditView(QWidget* parent) setLayout(layout); // signals +#ifdef __APPLE__ new QShortcut( - QKeySequence(QKeySequence(Qt::ALT+Qt::Key_Left)), + QKeySequence(Qt::CTRL+Qt::Key_L), this, SLOT(slotSaveAndCloseEditor())); +#else new QShortcut( - QKeySequence(QKeySequence(Qt::CTRL+Qt::Key_G)), + QKeySequence(Qt::ALT+Qt::Key_Left), + this, SLOT(slotSaveAndCloseEditor())); +#endif + new QShortcut( + QKeySequence(Qt::CTRL+Qt::Key_G), this, SLOT(slotCloseEditor())); new QShortcut( - QKeySequence(QKeySequence(Qt::ALT+Qt::Key_Return)), + QKeySequence(Qt::ALT+Qt::Key_Return), this, SLOT(slotOpenOutlineHeaderPropertiesEditor())); new QShortcut( - QKeySequence(QKeySequence(Qt::CTRL+Qt::Key_S)), + QKeySequence(Qt::CTRL+Qt::Key_S), this, SLOT(slotSaveOutlineHeader())); QObject::connect( bottomButtonsPanel->getRememberButton(), SIGNAL(clicked()), diff --git a/app/src/qt/outline_tree_view.cpp b/app/src/qt/outline_tree_view.cpp index 1ae6b571..55d2ddc3 100644 --- a/app/src/qt/outline_tree_view.cpp +++ b/app/src/qt/outline_tree_view.cpp @@ -42,8 +42,13 @@ OutlineTreeView::OutlineTreeView(QWidget* parent) void OutlineTreeView::keyPressEvent(QKeyEvent* event) { // leave note view navigation +#ifdef __APPLE__ + if(event->modifiers() & Qt::ControlModifier){ + if(event->key()==Qt::Key_L) { +#else if(event->modifiers() & Qt::AltModifier){ if(event->key()==Qt::Key_Left) { +#endif signalFromOutlineTreeToOutlines(); } } else { @@ -73,6 +78,10 @@ void OutlineTreeView::keyPressEvent(QKeyEvent* event) case Qt::Key_Right: emit signalChangeDemote(); break; +#else + case Qt::Key_D: + emit signalForget(); + break; #endif case Qt::Key_E: emit signalOutlineOrNoteEdit(); @@ -102,9 +111,11 @@ void OutlineTreeView::keyPressEvent(QKeyEvent* event) case Qt::Key_Right: emit signalEdit(); break; +#ifndef __APPLE__ case Qt::Key_Delete: emit signalForget(); break; +#endif case Qt::Key_Left: signalFromOutlineTreeToOutlines(); break; diff --git a/app/src/qt/widgets/edit_buttons_panel.cpp b/app/src/qt/widgets/edit_buttons_panel.cpp index 38b62b22..44f55132 100644 --- a/app/src/qt/widgets/edit_buttons_panel.cpp +++ b/app/src/qt/widgets/edit_buttons_panel.cpp @@ -31,9 +31,17 @@ EditButtonsPanel::EditButtonsPanel(MfWidgetMode mode, QWidget* parent) moreButton = new QPushButton{tr("Properties"), this}; moreButton->setToolTip("Alt+Enter"); rememberButton = new QPushButton{tr("Remember"), this}; +#ifdef __APPLE__ + rememberButton->setToolTip("⌘+L"); +#else rememberButton->setToolTip("Alt+Left"); +#endif cancelButton = new QPushButton{tr("Cancel"), this}; +#ifdef __APPLE__ + cancelButton->setToolTip("⌘+G"); +#else cancelButton->setToolTip("Ctrl+G"); +#endif // assembly layout = new QHBoxLayout{this}; From 98c317e2833ac1be70b62fc0c4032e53e9ef86d1 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Fri, 6 Mar 2020 06:15:12 +0100 Subject: [PATCH 08/43] Full preview option/toggling #1081 --- app/src/qt/dialogs/configuration_dialog.cpp | 6 +++ app/src/qt/dialogs/configuration_dialog.h | 1 + app/src/qt/orloj_presenter.cpp | 54 ++++++------------- app/src/qt/orloj_presenter.h | 1 + app/src/qt/outline_header_view.cpp | 2 +- app/src/qt/outline_header_view_presenter.cpp | 33 +++++++----- app/src/qt/outline_header_view_presenter.h | 8 ++- .../qt/widgets/view_to_edit_buttons_panel.cpp | 7 ++- .../qt/widgets/view_to_edit_buttons_panel.h | 2 + lib/src/config/configuration.cpp | 3 +- lib/src/config/configuration.h | 4 ++ .../persistence/filesystem_persistence.cpp | 9 +++- .../html/html_outline_representation.cpp | 46 ++++++++++++++-- .../html/html_outline_representation.h | 33 ++++++++++-- .../markdown_configuration_representation.cpp | 10 ++++ .../markdown_outline_representation.cpp | 9 +++- 16 files changed, 163 insertions(+), 65 deletions(-) diff --git a/app/src/qt/dialogs/configuration_dialog.cpp b/app/src/qt/dialogs/configuration_dialog.cpp index cce1d655..753c24ba 100644 --- a/app/src/qt/dialogs/configuration_dialog.cpp +++ b/app/src/qt/dialogs/configuration_dialog.cpp @@ -192,6 +192,8 @@ ConfigurationDialog::ViewerTab::ViewerTab(QWidget *parent) mathSupportCheck = new QCheckBox{tr("math support"), this}; + fullOPreviewCheck = new QCheckBox{tr("whole notebook preview"), this}; + diagramSupportLabel = new QLabel(tr("Diagram support")+":", this), diagramSupportCombo = new QComboBox{this}; diagramSupportCombo->addItem(QString{"disable"}); @@ -208,6 +210,7 @@ ConfigurationDialog::ViewerTab::ViewerTab(QWidget *parent) viewerLayout->addWidget(diagramSupportCombo); viewerLayout->addWidget(srcCodeHighlightSupportCheck); viewerLayout->addWidget(mathSupportCheck); + viewerLayout->addWidget(fullOPreviewCheck); viewerGroup->setLayout(viewerLayout); QVBoxLayout* boxesLayout = new QVBoxLayout{this}; @@ -224,6 +227,7 @@ ConfigurationDialog::ViewerTab::~ViewerTab() delete zoomSpin; delete srcCodeHighlightSupportCheck; delete mathSupportCheck; + delete fullOPreviewCheck; delete diagramSupportLabel; delete diagramSupportCombo; } @@ -238,6 +242,7 @@ void ConfigurationDialog::ViewerTab::refresh() zoomSpin->setValue(config.getUiHtmlZoom()); srcCodeHighlightSupportCheck->setChecked(config.isUiEnableSrcHighlightInMd()); mathSupportCheck->setChecked(config.isUiEnableMathInMd()); + fullOPreviewCheck->setChecked(config.isUiFullOPreview()); diagramSupportCombo->setCurrentIndex(config.getUiEnableDiagramsInMd()); } @@ -247,6 +252,7 @@ void ConfigurationDialog::ViewerTab::save() config.setUiHtmlZoom(zoomSpin->value()); config.setUiEnableSrcHighlightInMd(srcCodeHighlightSupportCheck->isChecked()); config.setUiEnableMathInMd(mathSupportCheck->isChecked()); + config.setUiFullOPreview(fullOPreviewCheck->isChecked()); config.setUiEnableDiagramsInMd(static_cast(diagramSupportCombo->currentIndex())); } diff --git a/app/src/qt/dialogs/configuration_dialog.h b/app/src/qt/dialogs/configuration_dialog.h index ce0b4bf9..b070795e 100644 --- a/app/src/qt/dialogs/configuration_dialog.h +++ b/app/src/qt/dialogs/configuration_dialog.h @@ -157,6 +157,7 @@ class ConfigurationDialog::ViewerTab : public QWidget QLabel* zoomLabel; QSpinBox* zoomSpin; QCheckBox* mathSupportCheck; + QCheckBox* fullOPreviewCheck; QLabel* diagramSupportLabel; QComboBox* diagramSupportCombo; QCheckBox* srcCodeHighlightSupportCheck; diff --git a/app/src/qt/orloj_presenter.cpp b/app/src/qt/orloj_presenter.cpp index f6f7344c..5ede130a 100644 --- a/app/src/qt/orloj_presenter.cpp +++ b/app/src/qt/orloj_presenter.cpp @@ -127,41 +127,10 @@ OrlojPresenter::OrlojPresenter(MainWindowPresenter* mainPresenter, QObject::connect( view->getOutlinesTable()->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(slotOutlinesTableSorted(int))); - - /* - * ... former click-to-view BEFORE switch to keyboard-only - */ - - /* - // click Outline in Outlines to view Outline detail - QObject::connect( - view->getOutlinesTable()->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(slotShowOutline(const QItemSelection&, const QItemSelection&))); - // click Tag in Tags to view Recall by Tag detail - QObject::connect( - view->getTagCloud()->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(slotShowTagRecallDialog(const QItemSelection&, const QItemSelection&))); - QObject::connect( - view->getDashboard()->getTagsDashboardlet()->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(slotShowTagRecallDialog(const QItemSelection&, const QItemSelection&))); - // click recent N/O in recent Os/Ns to view O/N detail + // toggle full O HTML preview QObject::connect( - view->getRecentNotesTable()->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(slotShowRecentNote(const QItemSelection&, const QItemSelection&))); - QObject::connect( - view->getDashboard()->getRecentDashboardlet()->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(slotShowRecentNote(const QItemSelection&, const QItemSelection&))); - */ + view->getOutlineHeaderView()->getEditPanel()->getFullOPreviewButton(), SIGNAL(clicked()), + this, SLOT(slotToggleFullOutlinePreview())); } int dialogSaveOrCancel() @@ -812,7 +781,8 @@ void OrlojPresenter::refreshLiveNotePreview() } } -void OrlojPresenter::slotRefreshCurrentNotePreview() { +void OrlojPresenter::slotRefreshCurrentNotePreview() +{ MF_DEBUG("Slot to refresh live preview: " << getFacet() << " hoist: " << config.isUiHoistedMode() << endl); if(!config.isUiHoistedMode()) { if(isFacetActive(OrlojPresenterFacets::FACET_EDIT_NOTE)) { @@ -821,7 +791,7 @@ void OrlojPresenter::slotRefreshCurrentNotePreview() { getNoteEdit()->getView()->getNoteEditor()->setFocus(); #endif } else if(isFacetActive(OrlojPresenterFacets::FACET_EDIT_OUTLINE_HEADER)) { - outlineHeaderViewPresenter->refreshCurrent(); + outlineHeaderViewPresenter->refreshLivePreview(); #if defined(__APPLE__) || defined(_WIN32) getOutlineHeaderEdit()->getView()->getHeaderEditor()->setFocus(); #endif @@ -829,7 +799,8 @@ void OrlojPresenter::slotRefreshCurrentNotePreview() { } } -void OrlojPresenter::slotOutlinesTableSorted(int column) { +void OrlojPresenter::slotOutlinesTableSorted(int column) +{ Qt::SortOrder order = view->getOutlinesTable()->horizontalHeader()->sortIndicatorOrder(); MF_DEBUG("Os table sorted: " << column << " descending: " << order << endl); @@ -839,4 +810,13 @@ void OrlojPresenter::slotOutlinesTableSorted(int column) { mainPresenter->getConfigRepresentation()->save(config); } +void OrlojPresenter::slotToggleFullOutlinePreview() +{ + config.setUiFullOPreview(!config.isUiFullOPreview()); + mainPresenter->getConfigRepresentation()->save(config); + + // refresh O header view + getOutlineHeaderView()->refreshCurrent(); +} + } // m8r namespace diff --git a/app/src/qt/orloj_presenter.h b/app/src/qt/orloj_presenter.h index 62828080..a745bc01 100644 --- a/app/src/qt/orloj_presenter.h +++ b/app/src/qt/orloj_presenter.h @@ -207,6 +207,7 @@ public slots: void slotGetLinksForPattern(const QString& pattern); void slotRefreshCurrentNotePreview(); void slotOutlinesTableSorted(int column); + void slotToggleFullOutlinePreview(); signals: void signalLinksForPattern(const QString& completionPrefix, std::vector* links); diff --git a/app/src/qt/outline_header_view.cpp b/app/src/qt/outline_header_view.cpp index 6daffbac..3b5ab82c 100644 --- a/app/src/qt/outline_header_view.cpp +++ b/app/src/qt/outline_header_view.cpp @@ -147,7 +147,7 @@ OutlineHeaderView::OutlineHeaderView(QWidget* parent) // assembly QVBoxLayout* layout = new QVBoxLayout{this}; - // ensure that wont be extra space around member widgets + // ensure that will not be extra space around member widgets layout->setContentsMargins(QMargins(0,0,0,0)); layout->addWidget(headerViewer); view2EditPanel->setFixedHeight(2*view2EditPanel->getEditButton()->height()); diff --git a/app/src/qt/outline_header_view_presenter.cpp b/app/src/qt/outline_header_view_presenter.cpp index ff27c401..a8436b20 100644 --- a/app/src/qt/outline_header_view_presenter.cpp +++ b/app/src/qt/outline_header_view_presenter.cpp @@ -58,7 +58,7 @@ OutlineHeaderViewPresenter::OutlineHeaderViewPresenter( orloj, SLOT(slotShowOutlines())); } -void OutlineHeaderViewPresenter::refreshCurrent() +void OutlineHeaderViewPresenter::refreshLivePreview() { MF_DEBUG("Refreshing O header HTML preview from editor: " << this->currentOutline->getName() << endl); @@ -87,7 +87,15 @@ void OutlineHeaderViewPresenter::refreshCurrent() #endif MF_DEBUG("SCROLL offset: " << yScrollPct << endl); // refresh HTML view (autolinking intentionally disabled) - htmlRepresentation->toHeader(&auxOutline, &html, false, false, static_cast(yScrollPct)); + htmlRepresentation->to( + &auxOutline, + &html, + false, + false, + false, + true, + static_cast(yScrollPct) + ); view->setHtml(QString::fromStdString(html)); // IMPROVE share code between O header and N @@ -113,17 +121,16 @@ void OutlineHeaderViewPresenter::refresh(Outline* outline) { currentOutline = outline; - if(Configuration::getInstance().isUiHoistedMode()) { - // TODO inject TOC - // TODO full O rendering doesn't support autolinking (consider performance) - htmlRepresentation->to(outline, &html); - } else { - htmlRepresentation->toHeader( - outline, - &html, - false, - Configuration::getInstance().isAutolinking()); - } + // IMPROVE consider TOC injection + htmlRepresentation->to( + outline, + &html, + false, + Configuration::getInstance().isAutolinking(), + Configuration::getInstance().isUiFullOPreview(), + true + ); + view->setHtml(QString::fromStdString(html)); // leaderboard diff --git a/app/src/qt/outline_header_view_presenter.h b/app/src/qt/outline_header_view_presenter.h index ac4c331c..fcd1458e 100644 --- a/app/src/qt/outline_header_view_presenter.h +++ b/app/src/qt/outline_header_view_presenter.h @@ -54,9 +54,13 @@ class OutlineHeaderViewPresenter : public QObject OutlineHeaderViewPresenter &operator=(const OutlineHeaderViewPresenter&&) = delete; ~OutlineHeaderViewPresenter() = default; - void refreshCurrent(); - void refresh(Outline* outline); + /** + * @brief Refresh live preview. + */ + void refreshLivePreview(); + void refresh(Outline* outline); + void refreshCurrent() { refresh(currentOutline); } public slots: void slotLinkClicked(const QUrl& url); diff --git a/app/src/qt/widgets/view_to_edit_buttons_panel.cpp b/app/src/qt/widgets/view_to_edit_buttons_panel.cpp index e12cd168..a6b23e0d 100644 --- a/app/src/qt/widgets/view_to_edit_buttons_panel.cpp +++ b/app/src/qt/widgets/view_to_edit_buttons_panel.cpp @@ -29,11 +29,16 @@ ViewToEditEditButtonsPanel::ViewToEditEditButtonsPanel(MfWidgetMode mode, QWidge editButton = new QPushButton{tr("Edit"), this}; editButton->setToolTip("Ctrl+E"); - // TODO Show whole Notebook OR Show Notebook description (toggle buttons) + if(MfWidgetMode::OUTLINE_MODE == mode) { + toggleFullOPreviewButton = new QPushButton{tr("Toggle Full Preview"), this}; + toggleFullOPreviewButton->setToolTip(tr( + "Toggle full Notebook preview (only header is shown by default)")); + } // assembly layout = new QHBoxLayout{this}; layout->addStretch(1); + layout->addWidget(toggleFullOPreviewButton); layout->addWidget(editButton); setLayout(layout); } diff --git a/app/src/qt/widgets/view_to_edit_buttons_panel.h b/app/src/qt/widgets/view_to_edit_buttons_panel.h index 803e391b..ebb7ec59 100644 --- a/app/src/qt/widgets/view_to_edit_buttons_panel.h +++ b/app/src/qt/widgets/view_to_edit_buttons_panel.h @@ -34,6 +34,7 @@ class ViewToEditEditButtonsPanel : public QWidget QHBoxLayout* layout; QPushButton* editButton; + QPushButton* toggleFullOPreviewButton; // expert mode (no buttons) setting @ frontend bool expertMode; @@ -51,6 +52,7 @@ class ViewToEditEditButtonsPanel : public QWidget public: QPushButton* getEditButton() const { return editButton; } + QPushButton* getFullOPreviewButton() const { return toggleFullOPreviewButton; } }; } diff --git a/lib/src/config/configuration.cpp b/lib/src/config/configuration.cpp index 6ed15e4d..204e1b51 100644 --- a/lib/src/config/configuration.cpp +++ b/lib/src/config/configuration.cpp @@ -60,7 +60,8 @@ Configuration::Configuration() uiEditorAutocomplete{}, navigatorMaxNodes{}, uiEditorTabsAsSpaces{}, - uiEditorAutosave{}, + uiEditorAutosave{DEFAULT_EDITOR_AUTOSAVE}, + uiFullOPreview{DEFAULT_FULL_O_PREVIEW}, uiShowToolbar{}, uiExpertMode{}, uiDistractionFreeMode{}, diff --git a/lib/src/config/configuration.h b/lib/src/config/configuration.h index c84feeb0..ed9a7a9e 100644 --- a/lib/src/config/configuration.h +++ b/lib/src/config/configuration.h @@ -175,6 +175,7 @@ class Configuration { static constexpr const bool DEFAULT_EDITOR_AUTOCOMPLETE = true; static constexpr const bool DEFAULT_EDITOR_TABS_AS_SPACES = true; static constexpr const bool DEFAULT_EDITOR_AUTOSAVE = false; + static constexpr const bool DEFAULT_FULL_O_PREVIEW = false; static constexpr const bool DEFAULT_MD_QUOTE_SECTIONS = true; static constexpr const bool DEFAULT_MD_HIGHLIGHT = true; static constexpr const bool DEFAULT_MD_MATH = false; @@ -241,6 +242,7 @@ class Configuration { int navigatorMaxNodes; bool uiEditorTabsAsSpaces; bool uiEditorAutosave; + bool uiFullOPreview; bool uiShowToolbar; bool uiExpertMode; bool uiDistractionFreeMode; // fullscreen, no split, hidden toolbar + menu @@ -418,6 +420,8 @@ class Configuration { void setUiEditorTabsAsSpaces(bool uiEditorTabsAsSpaces){ this->uiEditorTabsAsSpaces = uiEditorTabsAsSpaces; } bool isUiEditorAutosave() const { return uiEditorAutosave; } void setUiEditorAutosave(bool uiEditorAutosave){ this->uiEditorAutosave = uiEditorAutosave; } + bool isUiFullOPreview() const { return uiFullOPreview; } + void setUiFullOPreview(bool fullPreview){ this->uiFullOPreview = fullPreview; } bool isUiShowToolbar() const { return uiShowToolbar; } void setUiShowToolbar(bool showToolbar){ this->uiShowToolbar = showToolbar; } bool isUiExpertMode() const { return uiExpertMode; } diff --git a/lib/src/persistence/filesystem_persistence.cpp b/lib/src/persistence/filesystem_persistence.cpp index 464c7949..82b5a30d 100644 --- a/lib/src/persistence/filesystem_persistence.cpp +++ b/lib/src/persistence/filesystem_persistence.cpp @@ -82,7 +82,14 @@ void FilesystemPersistence::save(Outline* outline) void FilesystemPersistence::saveAsHtml(Outline* outline, const string& fileName) { string* text = new string{}; - htmlRepresentation.to(outline, text, true); + htmlRepresentation.to( + outline, + text, + true, + false, + true, + false + ); std::ofstream out(fileName); out << *text; out.close(); diff --git a/lib/src/representations/html/html_outline_representation.cpp b/lib/src/representations/html/html_outline_representation.cpp index 8da4b777..a0e52a1e 100644 --- a/lib/src/representations/html/html_outline_representation.cpp +++ b/lib/src/representations/html/html_outline_representation.cpp @@ -297,17 +297,29 @@ string* HtmlOutlineRepresentation::to(const string* markdown, string* html, stri return html; } -string* HtmlOutlineRepresentation::to(const Outline* outline, string* html, bool standalone, int yScrollTo) +string* HtmlOutlineRepresentation::toNoMeta(const Outline* outline, string* html, bool standalone, int yScrollTo) { // IMPROVE markdown can be processed by Mind to be enriched with various links and relationships - string* markdown = markdownRepresentation.to(outline); + string* markdown = markdownRepresentation.to(outline); to(markdown, html, nullptr, standalone, yScrollTo); delete markdown; return html; } -string* HtmlOutlineRepresentation::toHeader(Outline* outline, string* html, bool standalone, bool autolinking, int yScrollTo) +string* HtmlOutlineRepresentation::to( + Outline* outline, + std::string* html, + bool standalone, + bool autolinking, + bool whole, + bool metadata, + int yScrollTo) { + if(!metadata) { + return toNoMeta(outline, html, standalone, yScrollTo); + } + + if(!config.isUiHtmlTheme()) { header(*html, nullptr, standalone, 0); string markdown{"# "}; @@ -409,6 +421,7 @@ string* HtmlOutlineRepresentation::toHeader(Outline* outline, string* html, bool string outlineMd{}; string path, file; pathToDirectoryAndFile(outline->getKey(), path, file); + // Oheader if(autolinking) { markdownRepresentation.toDescription( outline->getOutlineDescriptorAsNote(), @@ -417,6 +430,27 @@ string* HtmlOutlineRepresentation::toHeader(Outline* outline, string* html, bool } else { outlineMd.append(outline->getOutlineDescriptorAsNote()->getDescriptionAsString()); } + // Ns + if(whole) { + const vector& notes=outline->getNotes(); + if(notes.size()) { + string noteMd{}; + for(Note* note:notes) { + outlineMd.append("\n"); + // TODO MD representation to render also tags as HTML injected code (under section) + markdownRepresentation.to( + note, + ¬eMd, + outline->getFormat()==MarkdownDocument::Format::MINDFORGER, + autolinking + ); + outlineMd.append(noteMd); + noteMd.clear(); + } + } + } + + // MD 2 HTML to(&outlineMd, html, &path, false, yScrollTo); // inject custom HTML header html->replace( @@ -433,7 +467,11 @@ string* HtmlOutlineRepresentation::toHeader(Outline* outline, string* html, bool return html; } -string* HtmlOutlineRepresentation::to(const Note* note, string* html, bool autolinking, int yScrollTo) +string* HtmlOutlineRepresentation::to( + const Note* note, + string* html, + bool autolinking, + int yScrollTo) { string* markdown = new string{}; markdown->reserve(MarkdownOutlineRepresentation::AVG_NOTE_SIZE); diff --git a/lib/src/representations/html/html_outline_representation.h b/lib/src/representations/html/html_outline_representation.h index 42bf1f2b..8e628385 100644 --- a/lib/src/representations/html/html_outline_representation.h +++ b/lib/src/representations/html/html_outline_representation.h @@ -102,16 +102,39 @@ class HtmlOutlineRepresentation std::string* html, std::string* basePath=nullptr, bool standalone=false, - int yScrollTo=0); + int yScrollTo=0 + ); /** * @brief Export Outline to HTML. * * Outline is rendered to be shown in MF, standalone option indicates HTML export. + * + * @param outline O whose HTML representation will be created. + * @param html Resulting HTML representation. + * @param standalone Is it O export? + * @param autolinking Inject (auto) links. + * @param whole Rendere whole O or just header. + * @param metadata Render (tags, timestamps, reads/writes) metadata. + * No metadata (fast) rendering is used by live preview. + * @param yScrollTo Inject JavaScript which scrolls HTML to given % on page load. + * @return Pointer to O HTML representation. */ - std::string* to(const Outline* outline, std::string* html, bool standalone=false, int yScrollTo=0); - std::string* toHeader(Outline* outline, std::string* html, bool standalone=false, bool autolinking=false, int yScrollTo=0); - std::string* to(const Note* note, std::string* html, bool autolinking=false, int yScrollTo=0); + std::string* to( + Outline* outline, + std::string* html, + bool standalone=false, + bool autolinking=false, + bool whole=false, + bool metadata=false, + int yScrollTo=0 + ); + std::string* to( + const Note* note, + std::string* html, + bool autolinking=false, + int yScrollTo=0 + ); /** * @brief Append "color: 0x...; background-color: 0x...;" @@ -127,6 +150,8 @@ class HtmlOutlineRepresentation private: void header(std::string& html, std::string* basePath, bool standalone, int yScrollTo); void footer(std::string& html); + + std::string* toNoMeta(const Outline* outline, std::string* html, bool standalone, int yScrollTo); }; } // m8r namespace diff --git a/lib/src/representations/markdown/markdown_configuration_representation.cpp b/lib/src/representations/markdown/markdown_configuration_representation.cpp index 4bf45dd4..6b1cdbbd 100644 --- a/lib/src/representations/markdown/markdown_configuration_representation.cpp +++ b/lib/src/representations/markdown/markdown_configuration_representation.cpp @@ -50,6 +50,7 @@ constexpr const auto CONFIG_SETTING_UI_EDITOR_AUTOCOMPLETE_LABEL = "* Editor au constexpr const auto CONFIG_SETTING_UI_EDITOR_TAB_WIDTH_LABEL = "* Editor TAB width: "; constexpr const auto CONFIG_SETTING_UI_EDITOR_TABS_AS_SPACES_LABEL = "* Editor insert SPACEs for TAB: "; constexpr const auto CONFIG_SETTING_UI_EDITOR_AUTOSAVE_LABEL = "* Editor autosave on close: "; +constexpr const auto CONFIG_SETTING_UI_FULL_O_PREVIEW_LABEL = "* Full Outline preview: "; constexpr const auto CONFIG_SETTING_NAVIGATOR_MAX_GRAPH_NODES_LABEL = "* Navigator max knowledge graph nodes: "; constexpr const auto CONFIG_SETTING_MD_HIGHLIGHT_LABEL = "* Enable source code syntax highlighting support in Markdown: "; constexpr const auto CONFIG_SETTING_MD_MATH_LABEL = "* Enable math support in Markdown: "; @@ -225,6 +226,12 @@ void MarkdownConfigurationRepresentation::configuration(string* title, vectorfind(CONFIG_SETTING_UI_FULL_O_PREVIEW_LABEL) != std::string::npos) { + if(line->find("yes") != std::string::npos) { + c.setUiFullOPreview(true); + } else { + c.setUiFullOPreview(false); + } } else if(line->find(CONFIG_SETTING_UI_EDITOR_KEY_BINDING_LABEL) != std::string::npos) { if(line->find(UI_EDITOR_KEY_BINDING_EMACS) != std::string::npos) { c.setEditorKeyBinding(Configuration::EditorKeyBindingMode::EMACS); @@ -471,6 +478,9 @@ string& MarkdownConfigurationRepresentation::to(Configuration* c, string& md) " * Examples: yes, no" << endl << CONFIG_SETTING_UI_EDITOR_AUTOSAVE_LABEL << (c?(c->isUiEditorAutosave()?"yes":"no"):(Configuration::DEFAULT_EDITOR_AUTOSAVE?"yes":"no")) << endl << " * Examples: yes, no" << endl << + CONFIG_SETTING_UI_FULL_O_PREVIEW_LABEL << (c?(c->isUiFullOPreview()?"yes":"no"):(Configuration::DEFAULT_FULL_O_PREVIEW?"yes":"no")) << endl << + " * Show whole Notebook preview (yes) or Notebook header only (no)." << endl << + " * Examples: yes, no" << endl << CONFIG_SETTING_UI_EDITOR_KEY_BINDING_LABEL << (c?c->getEditorKeyBindingAsString():Configuration::editorKeyBindingToString(Configuration::EditorKeyBindingMode::WINDOWS)) << endl << " * Examples: emacs, vim, windows" << endl << CONFIG_SETTING_UI_EDITOR_FONT_LABEL << (c?c->getEditorFont():Configuration::DEFAULT_EDITOR_FONT) << endl << diff --git a/lib/src/representations/markdown/markdown_outline_representation.cpp b/lib/src/representations/markdown/markdown_outline_representation.cpp index a6593c6e..02d6485b 100644 --- a/lib/src/representations/markdown/markdown_outline_representation.cpp +++ b/lib/src/representations/markdown/markdown_outline_representation.cpp @@ -381,7 +381,14 @@ string* MarkdownOutlineRepresentation::to(const Outline* outline, string* md) if(notes.size()) { string noteMd{}; for(Note *note:notes) { - to(note, ¬eMd, outline->getFormat()==MarkdownDocument::Format::MINDFORGER); + md->append("\n"); + to( + note, + ¬eMd, + outline->getFormat()==MarkdownDocument::Format::MINDFORGER, + // full O rendering w/o autolinking (performance) + false + ); md->append(noteMd); noteMd.clear(); } From 723f66f0c49c680e7fc30a6301ce17b972840524 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Fri, 6 Mar 2020 06:34:51 +0100 Subject: [PATCH 09/43] Updating live preview on view/edit switch #1081 --- app/src/qt/note_view_presenter.cpp | 2 +- app/src/qt/note_view_presenter.h | 2 +- app/src/qt/orloj_presenter.cpp | 12 +++++++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/src/qt/note_view_presenter.cpp b/app/src/qt/note_view_presenter.cpp index 75760f34..1120db4d 100644 --- a/app/src/qt/note_view_presenter.cpp +++ b/app/src/qt/note_view_presenter.cpp @@ -73,7 +73,7 @@ NoteViewPresenter::~NoteViewPresenter() if(htmlRepresentation) delete htmlRepresentation; } -void NoteViewPresenter::refreshCurrent() +void NoteViewPresenter::refreshLivePreview() { MF_DEBUG("Refreshing N HTML preview from editor: " << this->currentNote->getName() << endl); diff --git a/app/src/qt/note_view_presenter.h b/app/src/qt/note_view_presenter.h index f92968bb..5fb310f7 100644 --- a/app/src/qt/note_view_presenter.h +++ b/app/src/qt/note_view_presenter.h @@ -72,7 +72,7 @@ class NoteViewPresenter : public QObject NoteView* getView() const { return view; } Note* getCurrentNote() { return currentNote; } - void refreshCurrent(); + void refreshLivePreview(); void refresh(Note* note); void clearSearchExpression() { searchExpression.clear(); } diff --git a/app/src/qt/orloj_presenter.cpp b/app/src/qt/orloj_presenter.cpp index 5ede130a..e6a61ed0 100644 --- a/app/src/qt/orloj_presenter.cpp +++ b/app/src/qt/orloj_presenter.cpp @@ -463,6 +463,11 @@ void OrlojPresenter::showFacetNoteEdit(Note* note) view->showFacetNoteEdit(); setFacet(OrlojPresenterFacets::FACET_EDIT_NOTE); mainPresenter->getMainMenu()->showFacetNoteEdit(); + + // refresh live preview to ensure on/off autolinking, full O vs. header, ... + if(config.isUiLiveNotePreview()) { + noteViewPresenter->refreshLivePreview(); + } } void OrlojPresenter::showFacetOutlineHeaderEdit(Outline* outline) @@ -475,6 +480,11 @@ void OrlojPresenter::showFacetOutlineHeaderEdit(Outline* outline) view->showFacetOutlineHeaderEdit(); setFacet(OrlojPresenterFacets::FACET_EDIT_OUTLINE_HEADER); mainPresenter->getMainMenu()->showFacetNoteEdit(); + + // refresh live preview to ensure on/off autolinking, full O vs. header, ... + if(config.isUiLiveNotePreview()) { + outlineHeaderViewPresenter->refreshLivePreview(); + } } bool OrlojPresenter::applyFacetHoisting() @@ -786,7 +796,7 @@ void OrlojPresenter::slotRefreshCurrentNotePreview() MF_DEBUG("Slot to refresh live preview: " << getFacet() << " hoist: " << config.isUiHoistedMode() << endl); if(!config.isUiHoistedMode()) { if(isFacetActive(OrlojPresenterFacets::FACET_EDIT_NOTE)) { - noteViewPresenter->refreshCurrent(); + noteViewPresenter->refreshLivePreview(); #if defined(__APPLE__) || defined(_WIN32) getNoteEdit()->getView()->getNoteEditor()->setFocus(); #endif From f7d0156eb7b388c4b54f36dd70c26ff4b46c8cf6 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 07:40:05 +0100 Subject: [PATCH 10/43] Making "copy to repository" default for attaching resources and images which resolves #1235 --- app/src/qt/dialogs/insert_link_dialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/qt/dialogs/insert_link_dialog.cpp b/app/src/qt/dialogs/insert_link_dialog.cpp index 7e5066c6..c8c274ce 100644 --- a/app/src/qt/dialogs/insert_link_dialog.cpp +++ b/app/src/qt/dialogs/insert_link_dialog.cpp @@ -37,6 +37,7 @@ InsertLinkDialog::InsertLinkDialog(QWidget* parent) findDirectoryButton = new QPushButton{tr("Directory")}; copyToRepoCheckBox = new QCheckBox{tr("copy link target to repository")}; + copyToRepoCheckBox->setChecked(true); copyToRepoCheckBox->setEnabled(true); // IMPROVE disable/enable find button if text/path is valid: freedom vs validation From 768ea4950887a7136268768aca9211cee1b842f6 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 08:12:33 +0100 Subject: [PATCH 11/43] D&D can distinquish image from an attachment #1235 --- app/src/qt/dialogs/insert_image_dialog.cpp | 14 +++++++- app/src/qt/dialogs/insert_image_dialog.h | 1 + app/src/qt/main_window_presenter.cpp | 37 +++++++++++++++------- app/src/qt/main_window_presenter.h | 2 +- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/app/src/qt/dialogs/insert_image_dialog.cpp b/app/src/qt/dialogs/insert_image_dialog.cpp index 21b276e3..f97fb834 100644 --- a/app/src/qt/dialogs/insert_image_dialog.cpp +++ b/app/src/qt/dialogs/insert_image_dialog.cpp @@ -31,6 +31,7 @@ InsertImageDialog::InsertImageDialog(QWidget* parent) findFileButton = new QPushButton{tr("File")}; copyToRepoCheckBox = new QCheckBox{tr("copy image to repository")}; + copyToRepoCheckBox->setChecked(true); copyToRepoCheckBox->setEnabled(true); // IMPROVE disable/enable find button if text/path is valid: freedom vs validation @@ -73,7 +74,8 @@ InsertImageDialog::~InsertImageDialog() { } -void InsertImageDialog::show() { +void InsertImageDialog::show() +{ alternateTextEdit->setText(tr("Image")); alternateTextEdit->selectAll(); alternateTextEdit->setFocus(); @@ -82,6 +84,16 @@ void InsertImageDialog::show() { QDialog::show(); } +void InsertImageDialog::show(const QString& text, const QString& link) +{ + pathEdit->setText(link); + alternateTextEdit->setText(text); + alternateTextEdit->selectAll(); + alternateTextEdit->setFocus(); + + QDialog::show(); +} + void InsertImageDialog::handleFindFile() { QString homeDirectory diff --git a/app/src/qt/dialogs/insert_image_dialog.h b/app/src/qt/dialogs/insert_image_dialog.h index 5e9cd72a..6b01a82d 100644 --- a/app/src/qt/dialogs/insert_image_dialog.h +++ b/app/src/qt/dialogs/insert_image_dialog.h @@ -49,6 +49,7 @@ class InsertImageDialog : public QDialog ~InsertImageDialog(); void show(); + void show(const QString& text, const QString& link); QPushButton* getInsertButton() const { return insertButton; } QString getAlternateText() { return alternateTextEdit->text(); } QString getPathText() { return pathEdit->text(); } diff --git a/app/src/qt/main_window_presenter.cpp b/app/src/qt/main_window_presenter.cpp index 9027df5f..25bd4273 100644 --- a/app/src/qt/main_window_presenter.cpp +++ b/app/src/qt/main_window_presenter.cpp @@ -96,11 +96,11 @@ MainWindowPresenter::MainWindowPresenter(MainWindowView& view) ); QObject::connect( orloj->getNoteEdit()->getView()->getNoteEditor(), SIGNAL(signalDnDropUrl(QString)), - this, SLOT(doActionFormatLink(QString)) + this, SLOT(doActionFormatLinkOrImage(QString)) ); QObject::connect( orloj->getOutlineHeaderEdit()->getView()->getHeaderEditor(), SIGNAL(signalDnDropUrl(QString)), - this, SLOT(doActionFormatLink(QString)) + this, SLOT(doActionFormatLinkOrImage(QString)) ); // wire toolbar signals QObject::connect(view.getToolBar()->actionNewOutlineOrNote, SIGNAL(triggered()), this, SLOT(doActionOutlineOrNoteNew())); @@ -1531,7 +1531,7 @@ void MainWindowPresenter::doActionFormatTable() } } -void MainWindowPresenter::doActionFormatLink(QString link) +void MainWindowPresenter::doActionFormatLinkOrImage(QString link) { // IMPROVE rebuild model ONLY if dirty i.e. an outline name was changed on save vector oss{mind->getOutlines()}; @@ -1555,18 +1555,33 @@ void MainWindowPresenter::doActionFormatLink(QString link) insertLinkDialog->getCopyCheckBox()->setEnabled(false); } - insertLinkDialog->show( - config.getActiveRepository(), - orloj->getOutlineView()->getCurrentOutline(), - os, - ns, - selectedText, - link); + if(link.size() && ( + link.endsWith(".png") || + link.endsWith(".gif") || + link.endsWith(".jpg") || + link.endsWith(".jpeg") || + link.endsWith(".PNG") || + link.endsWith(".GIF") || + link.endsWith(".JPG") || + link.endsWith(".JPEG"))) + { + insertImageDialog->show( + selectedText.size()?selectedText:QString{tr("image")}, + link); + } else { + insertLinkDialog->show( + config.getActiveRepository(), + orloj->getOutlineView()->getCurrentOutline(), + os, + ns, + selectedText, + link); + } } void MainWindowPresenter::doActionFormatLink() { - doActionFormatLink(QString{}); + doActionFormatLinkOrImage(QString{}); } void MainWindowPresenter::injectMarkdownText(const QString& text, bool newline, int offset) diff --git a/app/src/qt/main_window_presenter.h b/app/src/qt/main_window_presenter.h index fbeff829..1632f771 100644 --- a/app/src/qt/main_window_presenter.h +++ b/app/src/qt/main_window_presenter.h @@ -269,7 +269,7 @@ public slots: void doActionFormatDiagramGantt(); void doActionFormatDiagramSequence(); void doActionFormatBlockquote(); - void doActionFormatLink(QString link); + void doActionFormatLinkOrImage(QString link); void doActionFormatLink(); void handleFormatLink(); void doActionFormatImage(); From ac631f344ba1a1b26f3020609f727e49b9c54727 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 08:17:01 +0100 Subject: [PATCH 12/43] Fixing disabled menu items #1224 --- app/src/qt/look_n_feel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/qt/look_n_feel.cpp b/app/src/qt/look_n_feel.cpp index 95486927..e2f02608 100644 --- a/app/src/qt/look_n_feel.cpp +++ b/app/src/qt/look_n_feel.cpp @@ -226,7 +226,10 @@ void LookAndFeels::setBlackTheme() // IMPROVE tooltips are set in two ways mindforgerApplication->setStyleSheet("QToolTip { color: #ffffff; background-color: #000000; border: 1px solid white; }"); - menuStylesheet = QString("QMenu::separator { background: #444; height: 1px; margin-left: 10px; margin-right: 10px; }"); + menuStylesheet = QString{ + "QMenu::separator { background: #444; height: 1px; margin-left: 10px; margin-right: 10px; }" + "QMenuBar::item:disabled { color: #555; }" + "QMenu::item:disabled { color: #555; background: "}+backgroundColor+QString{"; }"}; } void LookAndFeels::setNativeTheme() From 3ce1417e42600aee93830222e049f4d2d3530886 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 08:20:08 +0100 Subject: [PATCH 13/43] Making dark theme default which resolves #1239 --- lib/src/config/configuration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/config/configuration.h b/lib/src/config/configuration.h index ed9a7a9e..11db438e 100644 --- a/lib/src/config/configuration.h +++ b/lib/src/config/configuration.h @@ -92,7 +92,7 @@ constexpr const auto UI_JS_LIB_NO = "no"; constexpr const auto UI_OS_TABLE_SORT_ORDER_ASC = "ascending"; constexpr const auto UI_OS_TABLE_SORT_ORDER_DESC = "descending"; -constexpr const auto UI_DEFAULT_THEME = UI_THEME_LIGHT; +constexpr const auto UI_DEFAULT_THEME = UI_THEME_DARK; constexpr const auto UI_DEFAULT_HTML_CSS_THEME = UI_HTML_THEME_CSS_LIGHT; constexpr const auto UI_DEFAULT_EDITOR_FONT = "Monospace,10"; constexpr const auto UI_DEFAULT_FONT_POINT_SIZE = 10; From 91de4501bcbe971f640b85c63e2f427a271e45cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Dvo=C5=99=C3=A1k?= Date: Sat, 7 Mar 2020 09:47:37 +0100 Subject: [PATCH 14/43] Fixing leave of O/N editor and N tree using Cmd-L on macOS which resolves #578 --- app/src/qt/main_menu_presenter.cpp | 1 + app/src/qt/main_window_presenter.cpp | 5 ++++ app/src/qt/main_window_presenter.h | 1 + app/src/qt/note_view.cpp | 5 ---- app/src/qt/orloj_presenter.cpp | 2 +- app/src/qt/outline_tree_view.cpp | 23 ++++++++----------- app/src/qt/widgets/edit_buttons_panel.cpp | 4 ++++ .../qt/widgets/view_to_edit_buttons_panel.cpp | 4 ++++ 8 files changed, 25 insertions(+), 20 deletions(-) diff --git a/app/src/qt/main_menu_presenter.cpp b/app/src/qt/main_menu_presenter.cpp index 0a9c748b..d202d992 100644 --- a/app/src/qt/main_menu_presenter.cpp +++ b/app/src/qt/main_menu_presenter.cpp @@ -90,6 +90,7 @@ MainMenuPresenter::MainMenuPresenter(MainWindowPresenter* mwp) // menu: Note QObject::connect(view->actionNoteNew, SIGNAL(triggered()), mwp, SLOT(doActionNoteNew())); QObject::connect(view->actionNoteEdit, SIGNAL(triggered()), mwp, SLOT(doActionNoteEdit())); + QObject::connect(view->actionNoteClose, SIGNAL(triggered()), mwp, SLOT(doActionNoteLeave())); QObject::connect(view->actionNoteForget, SIGNAL(triggered()), mwp, SLOT(doActionNoteForget())); QObject::connect(view->actionNotePromote, SIGNAL(triggered()), mwp, SLOT(doActionNotePromote())); QObject::connect(view->actionNoteDemote, SIGNAL(triggered()), mwp, SLOT(doActionNoteDemote())); diff --git a/app/src/qt/main_window_presenter.cpp b/app/src/qt/main_window_presenter.cpp index 25bd4273..252081e9 100644 --- a/app/src/qt/main_window_presenter.cpp +++ b/app/src/qt/main_window_presenter.cpp @@ -2059,6 +2059,11 @@ void MainWindowPresenter::doActionNoteHoist() } } +void MainWindowPresenter::doActionNoteLeave() +{ + orloj->slotShowOutlines(); +} + void MainWindowPresenter::doActionNoteForget() { if(orloj->isFacetActive(OrlojPresenterFacets::FACET_VIEW_OUTLINE) diff --git a/app/src/qt/main_window_presenter.h b/app/src/qt/main_window_presenter.h index 1632f771..495e22fa 100644 --- a/app/src/qt/main_window_presenter.h +++ b/app/src/qt/main_window_presenter.h @@ -304,6 +304,7 @@ public slots: void doActionNoteExtract(); void doActionRefactorNoteToOutline(); void handleRefactorNoteToOutline(); + void doActionNoteLeave(); void doActionNoteForget(); // edit void doActionEditFind(); diff --git a/app/src/qt/note_view.cpp b/app/src/qt/note_view.cpp index 8194fa29..7e889cc2 100644 --- a/app/src/qt/note_view.cpp +++ b/app/src/qt/note_view.cpp @@ -72,13 +72,8 @@ bool NoteViewerView::eventFilter(QObject* obj, QEvent *event) void NoteViewerView::keyPressEvent(QKeyEvent* event) { -#ifdef __APPLE__ - if(event->modifiers() & Qt::ControlModifier){ - if(event->key()==Qt::Key_L) { -#else if(event->modifiers() & Qt::AltModifier){ if(event->key()==Qt::Key_Left) { -#endif emit signalFromViewNoteToOutlines(); } } diff --git a/app/src/qt/orloj_presenter.cpp b/app/src/qt/orloj_presenter.cpp index e6a61ed0..61ffd8ce 100644 --- a/app/src/qt/orloj_presenter.cpp +++ b/app/src/qt/orloj_presenter.cpp @@ -69,7 +69,7 @@ OrlojPresenter::OrlojPresenter(MainWindowPresenter* mainPresenter, SIGNAL(signalFindOutlineByName()), mainPresenter, SLOT(doActionFindOutlineByName())); - // click Outline tree to view Note + // click O tree to view Note QObject::connect( view->getOutlineView()->getOutlineTree()->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), diff --git a/app/src/qt/outline_tree_view.cpp b/app/src/qt/outline_tree_view.cpp index 55d2ddc3..fce47975 100644 --- a/app/src/qt/outline_tree_view.cpp +++ b/app/src/qt/outline_tree_view.cpp @@ -42,16 +42,13 @@ OutlineTreeView::OutlineTreeView(QWidget* parent) void OutlineTreeView::keyPressEvent(QKeyEvent* event) { // leave note view navigation -#ifdef __APPLE__ - if(event->modifiers() & Qt::ControlModifier){ - if(event->key()==Qt::Key_L) { -#else - if(event->modifiers() & Qt::AltModifier){ +#ifndef __APPLE__ + if(event->modifiers() & Qt::AltModifier) s{ if(event->key()==Qt::Key_Left) { -#endif - signalFromOutlineTreeToOutlines(); + emit signalFromOutlineTreeToOutlines(); } } else { +#endif // up/down/promote/demote note tree changes if(event->modifiers() & Qt::ControlModifier){ if(event->modifiers() & Qt::ShiftModifier) { @@ -79,6 +76,9 @@ void OutlineTreeView::keyPressEvent(QKeyEvent* event) emit signalChangeDemote(); break; #else + case Qt::Key_L: + emit signalFromOutlineTreeToOutlines(); + break; case Qt::Key_D: emit signalForget(); break; @@ -86,13 +86,6 @@ void OutlineTreeView::keyPressEvent(QKeyEvent* event) case Qt::Key_E: emit signalOutlineOrNoteEdit(); break; - - //case Qt::Key_F: - // emit signalChangeFirst(); - // break; - //case Qt::Key_L: - // emit signalChangeLast(); - // break; } } } else { @@ -121,7 +114,9 @@ void OutlineTreeView::keyPressEvent(QKeyEvent* event) break; } } +#ifndef __APPLE__ } +#endif QWidget::keyPressEvent(event); } diff --git a/app/src/qt/widgets/edit_buttons_panel.cpp b/app/src/qt/widgets/edit_buttons_panel.cpp index 44f55132..00e616b9 100644 --- a/app/src/qt/widgets/edit_buttons_panel.cpp +++ b/app/src/qt/widgets/edit_buttons_panel.cpp @@ -27,7 +27,11 @@ EditButtonsPanel::EditButtonsPanel(MfWidgetMode mode, QWidget* parent) { // widgets previewButton = new QPushButton{tr("Preview"), this}; +#ifdef __APPLE__ + previewButton->setToolTip("⌘+Shift+P"); +#else previewButton->setToolTip("Ctrl+Shift+P"); +#endif moreButton = new QPushButton{tr("Properties"), this}; moreButton->setToolTip("Alt+Enter"); rememberButton = new QPushButton{tr("Remember"), this}; diff --git a/app/src/qt/widgets/view_to_edit_buttons_panel.cpp b/app/src/qt/widgets/view_to_edit_buttons_panel.cpp index a6b23e0d..47720597 100644 --- a/app/src/qt/widgets/view_to_edit_buttons_panel.cpp +++ b/app/src/qt/widgets/view_to_edit_buttons_panel.cpp @@ -27,7 +27,11 @@ ViewToEditEditButtonsPanel::ViewToEditEditButtonsPanel(MfWidgetMode mode, QWidge { // widgets editButton = new QPushButton{tr("Edit"), this}; +#ifdef __APPLE__ + editButton->setToolTip("⌘+E"); +#else editButton->setToolTip("Ctrl+E"); +#endif if(MfWidgetMode::OUTLINE_MODE == mode) { toggleFullOPreviewButton = new QPushButton{tr("Toggle Full Preview"), this}; From 8c21627ee0a7f113c5c513870ef936e8f0d16f1a Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 09:52:53 +0100 Subject: [PATCH 15/43] Making sources compilable again. --- app/src/qt/outline_tree_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/qt/outline_tree_view.cpp b/app/src/qt/outline_tree_view.cpp index fce47975..f4b115c0 100644 --- a/app/src/qt/outline_tree_view.cpp +++ b/app/src/qt/outline_tree_view.cpp @@ -43,7 +43,7 @@ void OutlineTreeView::keyPressEvent(QKeyEvent* event) { // leave note view navigation #ifndef __APPLE__ - if(event->modifiers() & Qt::AltModifier) s{ + if(event->modifiers() & Qt::AltModifier) { if(event->key()==Qt::Key_Left) { emit signalFromOutlineTreeToOutlines(); } From 07f36906bd34b330d7096b87070dcf9017554669 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 10:21:15 +0100 Subject: [PATCH 16/43] Fixing code to make tests green (\n in MD serialization). --- build/test-lib-units.sh | 6 +++--- .../markdown/markdown_outline_representation.cpp | 4 ++-- lib/test/src/config/configuration_test.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/test-lib-units.sh b/build/test-lib-units.sh index 0ba8ade2..e123467a 100755 --- a/build/test-lib-units.sh +++ b/build/test-lib-units.sh @@ -17,9 +17,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -export OPTION_RUN_ALL_TESTS=yes # comment this line to run OPTION_TEST only +#export OPTION_RUN_ALL_TESTS=yes # comment this line to run OPTION_TEST only export OPTION_RECOMPILE=yes # recompile before running test(s) (comment this line to disable) -export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to disable) +#export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to disable) #export OPTION_RUN_GDB=yes # run test(s) w/ GDB (comment this line to disable) # benchmarks @@ -96,7 +96,7 @@ export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to d #export OPTION_TEST="DateTimeGearTestCase.*" #export OPTION_TEST="DateTimeGearTestCase.Immutability" #export OPTION_TEST="ConfigurationTestCase.*" -#export OPTION_TEST="ConfigurationTestCase.SaveDefaultConfig" +export OPTION_TEST="ConfigurationTestCase.SaveDefaultConfig" #export OPTION_TEST="ConfigurationTestCase.SaveAndLoad" #export OPTION_TEST="ConfigurationTestCase.FromConstructor" #export OPTION_TEST="ConfigurationTestCase.FromEnvironment" diff --git a/lib/src/representations/markdown/markdown_outline_representation.cpp b/lib/src/representations/markdown/markdown_outline_representation.cpp index 02d6485b..0cb48f48 100644 --- a/lib/src/representations/markdown/markdown_outline_representation.cpp +++ b/lib/src/representations/markdown/markdown_outline_representation.cpp @@ -376,12 +376,12 @@ string* MarkdownOutlineRepresentation::to(const Outline* outline, string* md) { toPreamble(outline, md); toHeader(outline, md); + // no longer needed: md->append("\n"); if(outline) { const vector& notes=outline->getNotes(); if(notes.size()) { string noteMd{}; - for(Note *note:notes) { - md->append("\n"); + for(Note* note:notes) { to( note, ¬eMd, diff --git a/lib/test/src/config/configuration_test.cpp b/lib/test/src/config/configuration_test.cpp index e7fadff3..0dc76e79 100644 --- a/lib/test/src/config/configuration_test.cpp +++ b/lib/test/src/config/configuration_test.cpp @@ -101,7 +101,7 @@ TEST(ConfigurationTestCase, SaveDefaultConfig) // asserts string* asString = m8r::fileToString(file.getName()); - EXPECT_NE(std::string::npos, asString->find("Theme: light")); + EXPECT_NE(std::string::npos, asString->find("Theme: dark")); EXPECT_NE(std::string::npos, asString->find("Time scope: 0y0m0d0h0m")); EXPECT_NE(std::string::npos, asString->find("Editor syntax highlighting: yes")); EXPECT_NE(std::string::npos, asString->find("Save reads metadata: yes")); From 9672b592aa21a24c2ec967661fa8f6f88f0f55d2 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 13:54:55 +0100 Subject: [PATCH 17/43] WIP travis-ci Xenial build. --- .travis.yml | 107 +++++++++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/.travis.yml b/.travis.yml index 83f1ed4a..86d1ca1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,61 +14,72 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +# +# For more details on Travis CI check: +# +# - https://travis-ci.org +# - https://docs.travis-ci.com/user/languages/cpp/ +# +# Examples: +# +# - https://github.com/LunarG/VulkanSamples/blob/master/.travis.yml +# +# os: +# - osx +# osx_image: xcode9.4 +# eval "${MATRIX_EVAL}" +# +sudo: required os: - linux +dist: bionic -# Missing codecvt: upgrade from g++ 4.8 to 5 > MATRIX_EVAL sets CXX to g++-5 > qmake CONFIG and QMAKE_CXX sets it to build process -matrix: - include: - - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-5 - env: - - MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" # IMPROVE prepend ccache to speed up 2nd build (MF after units) - -language: cpp # see https://docs.travis-ci.com/user/languages/cpp/ +language: cpp compiler: - - gcc # Travis CI defines CXX=g++ env var -sudo: required -dist: trusty # Travis CI provides Precise and Trusty only + - gcc +cache: ccache before_install: - - sudo apt-get update -qq - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" - - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - - sudo apt-get update -qq - - eval "${MATRIX_EVAL}" + - if [[ "$TRAVIS_OS_NAME" == "linux" ]] + then + sudo apt-get update -qq + "export DISPLAY=:99.0" + "sh -e /etc/init.d/xvfb start" + sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa + sudo apt-get update -qq + fi -install: - - sudo apt-get install -qq qtbase5-dev libqt5webkit5-dev - - sudo apt-get install -qq qt5-default qttools5-dev-tools - - sudo apt-get install -qq ccache - - sudo apt-get install -qq libgtest-dev - - "export M8RHOME=`pwd`" - - cd /usr/src/gtest # I have to build Google Test Framework myself - - sudo apt-get install -qq cmake - - sudo cmake . - - sudo make - - sudo mv libg* /usr/lib/ +install: # install dependencies & build Google Test Framework + - if [[ "$TRAVIS_OS_NAME" == "linux" ]] + then + sudo apt-get install -qq qtbase5-dev libqt5webkit5-dev + sudo apt-get install -qq qt5-default qttools5-dev-tools + sudo apt-get install -qq ccache + sudo apt-get install -qq libgtest-dev + "export M8RHOME=`pwd`" + cd /usr/src/gtest # Google Test Framework + sudo apt-get install -qq cmake + sudo cmake . + sudo make + sudo mv libg* /usr/lib/ + fi script: # make lib unit tests > run lib unit tests > make MF > install MF - - cd "${M8RHOME}" - - eval "${MATRIX_EVAL}" - - cd deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . && cd ../../.. - - "cd deps/discount && ./configure.sh && make ; cd ../.." - - "echo \"M8RDEBUG: g++ compiler is set to: ${CXX}\"" - - cd lib/test # UNIT tests - - qmake -r CONFIG+=mfnocxx CONFIG+=mfunits QMAKE_CXX=${CXX} mindforger-lib-unit-tests.pro - - make - - cd src && export M8R_GIT_PATH="${M8RHOME}" && ./mindforger-lib-unit-tests > /tmp/mindforger-unit-tests.log 2>&1 # ; true - - cd ../../.. - - cat /tmp/mindforger-unit-tests.log - - qmake -r CONFIG+=mfnocxx QMAKE_CXX=${CXX} mindforger.pro - - make - - sudo make install + - if [[ "$TRAVIS_OS_NAME" == "linux" ]] + then + cd "${M8RHOME}" + cd deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . && cd ../../.. + "cd deps/discount && ./configure.sh && make ; cd ../.." + "echo \"M8RDEBUG: g++ compiler is set to: ${CXX}\"" + cd lib/test # UNIT tests + qmake -r CONFIG+=mfnocxx CONFIG+=mfunits QMAKE_CXX=${CXX} mindforger-lib-unit-tests.pro + make + cd src && export M8R_GIT_PATH="${M8RHOME}" && ./mindforger-lib-unit-tests > /tmp/mindforger-unit-tests.log 2>&1 # ; true + cd ../../.. + cat /tmp/mindforger-unit-tests.log + #qmake -r CONFIG+=mfnocxx QMAKE_CXX=${CXX} mindforger.pro + qmake -r CONFIG+=mfnocxx QMAKE_CXX=${CXX} mindforger.pro + make + sudo make install + fi From 5d8706edec7ac4bfb22e8fbd9b3badb52c1e684a Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 14:03:53 +0100 Subject: [PATCH 18/43] WIP Travis CI Xenial build. --- .travis.yml | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 86d1ca1f..14ea4e8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,10 +15,16 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -# For more details on Travis CI check: +# CI monitoring: +# +# - https://travis-ci.org/dvorka/mindforger/requests +# +# For more Travis CI details check: # # - https://travis-ci.org # - https://docs.travis-ci.com/user/languages/cpp/ +# - https://config.travis-ci.com/explore +# Travis CI YAML validation # # Examples: # @@ -30,7 +36,6 @@ # eval "${MATRIX_EVAL}" # -sudo: required os: - linux dist: bionic @@ -41,7 +46,8 @@ compiler: cache: ccache before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]] + - | + if [[ "$TRAVIS_OS_NAME" == "linux" ]] then sudo apt-get update -qq "export DISPLAY=:99.0" @@ -51,7 +57,8 @@ before_install: fi install: # install dependencies & build Google Test Framework - - if [[ "$TRAVIS_OS_NAME" == "linux" ]] + - | + if [[ "$TRAVIS_OS_NAME" == "linux" ]] then sudo apt-get install -qq qtbase5-dev libqt5webkit5-dev sudo apt-get install -qq qt5-default qttools5-dev-tools @@ -66,20 +73,22 @@ install: # install dependencies & build Google Test Framework fi script: # make lib unit tests > run lib unit tests > make MF > install MF - - if [[ "$TRAVIS_OS_NAME" == "linux" ]] + - | + if [[ "$TRAVIS_OS_NAME" == "linux" ]] then cd "${M8RHOME}" cd deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . && cd ../../.. "cd deps/discount && ./configure.sh && make ; cd ../.." "echo \"M8RDEBUG: g++ compiler is set to: ${CXX}\"" cd lib/test # UNIT tests - qmake -r CONFIG+=mfnocxx CONFIG+=mfunits QMAKE_CXX=${CXX} mindforger-lib-unit-tests.pro + #qmake -r CONFIG+=mfnocxx CONFIG+=mfunits QMAKE_CXX=${CXX} mindforger-lib-unit-tests.pro + qmake -r CONFIG+=mfunits mindforger-lib-unit-tests.pro make cd src && export M8R_GIT_PATH="${M8RHOME}" && ./mindforger-lib-unit-tests > /tmp/mindforger-unit-tests.log 2>&1 # ; true cd ../../.. cat /tmp/mindforger-unit-tests.log #qmake -r CONFIG+=mfnocxx QMAKE_CXX=${CXX} mindforger.pro - qmake -r CONFIG+=mfnocxx QMAKE_CXX=${CXX} mindforger.pro + qmake -r mindforger.pro make sudo make install fi From ef7981bc2a69ce15dc7729564b2d2a5edf1ef259 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 14:07:41 +0100 Subject: [PATCH 19/43] WIP Travis CI Xenial build. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 14ea4e8c..ac45f42c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ # CI monitoring: # # - https://travis-ci.org/dvorka/mindforger/requests +# - https://travis-ci.org/dvorka/mindforger # # For more Travis CI details check: # @@ -50,8 +51,6 @@ before_install: if [[ "$TRAVIS_OS_NAME" == "linux" ]] then sudo apt-get update -qq - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa sudo apt-get update -qq fi From 1e7fe8c2540b2862d0d9af988393c0be0933c17e Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 14:11:30 +0100 Subject: [PATCH 20/43] WIP Travis CI Xenial build. --- .travis.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index ac45f42c..3a07821f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,8 +17,9 @@ # # CI monitoring: # -# - https://travis-ci.org/dvorka/mindforger/requests # - https://travis-ci.org/dvorka/mindforger +# - https://travis-ci.org/dvorka/mindforger/builds +# - https://travis-ci.org/dvorka/mindforger/requests # # For more Travis CI details check: # @@ -46,15 +47,6 @@ compiler: - gcc cache: ccache -before_install: - - | - if [[ "$TRAVIS_OS_NAME" == "linux" ]] - then - sudo apt-get update -qq - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - sudo apt-get update -qq - fi - install: # install dependencies & build Google Test Framework - | if [[ "$TRAVIS_OS_NAME" == "linux" ]] From b18d1ee00fb233a6267a33ba3d821793c2d5ccdd Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 14:19:18 +0100 Subject: [PATCH 21/43] WIP Travis CI Xenial build. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3a07821f..0b3c5d88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,7 +47,7 @@ compiler: - gcc cache: ccache -install: # install dependencies & build Google Test Framework +before_install: # install dependencies & build Google Test Framework - | if [[ "$TRAVIS_OS_NAME" == "linux" ]] then From d42a7db355d086db064d39fc49d6a68254eb7204 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 14:24:50 +0100 Subject: [PATCH 22/43] WIP Travis CI Xenial build. --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0b3c5d88..bf8a63ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,6 +64,10 @@ before_install: # install dependencies & build Google Test Framework fi script: # make lib unit tests > run lib unit tests > make MF > install MF + - echo `pwd` + - echo `pwd` + - echo `pwd` + - ls - | if [[ "$TRAVIS_OS_NAME" == "linux" ]] then From 3d8452042aeaaae6d49e048bf0b27471185d5e9f Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 14:30:03 +0100 Subject: [PATCH 23/43] WIP Travis CI Xenial build. --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bf8a63ce..1062e786 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,10 @@ before_install: # install dependencies & build Google Test Framework sudo apt-get install -qq qt5-default qttools5-dev-tools sudo apt-get install -qq ccache sudo apt-get install -qq libgtest-dev - "export M8RHOME=`pwd`" + echo `pwd` + echo `pwd` + echo `pwd` + export M8RHOME=`pwd` cd /usr/src/gtest # Google Test Framework sudo apt-get install -qq cmake sudo cmake . @@ -64,10 +67,12 @@ before_install: # install dependencies & build Google Test Framework fi script: # make lib unit tests > run lib unit tests > make MF > install MF + - cd ~ - echo `pwd` - echo `pwd` - echo `pwd` - ls + - cd mindforger - | if [[ "$TRAVIS_OS_NAME" == "linux" ]] then From d4b6ab117bda3a2b13f6630dccfb366e78eab222 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 14:39:02 +0100 Subject: [PATCH 24/43] Travis CI rollback. --- .travis.yml | 120 ++++++++++++++++++++++------------------------------ 1 file changed, 50 insertions(+), 70 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1062e786..83f1ed4a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,81 +14,61 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# -# CI monitoring: -# -# - https://travis-ci.org/dvorka/mindforger -# - https://travis-ci.org/dvorka/mindforger/builds -# - https://travis-ci.org/dvorka/mindforger/requests -# -# For more Travis CI details check: -# -# - https://travis-ci.org -# - https://docs.travis-ci.com/user/languages/cpp/ -# - https://config.travis-ci.com/explore -# Travis CI YAML validation -# -# Examples: -# -# - https://github.com/LunarG/VulkanSamples/blob/master/.travis.yml -# -# os: -# - osx -# osx_image: xcode9.4 -# eval "${MATRIX_EVAL}" -# os: - linux -dist: bionic -language: cpp +# Missing codecvt: upgrade from g++ 4.8 to 5 > MATRIX_EVAL sets CXX to g++-5 > qmake CONFIG and QMAKE_CXX sets it to build process +matrix: + include: + - os: linux + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 + env: + - MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" # IMPROVE prepend ccache to speed up 2nd build (MF after units) + +language: cpp # see https://docs.travis-ci.com/user/languages/cpp/ compiler: - - gcc -cache: ccache + - gcc # Travis CI defines CXX=g++ env var +sudo: required +dist: trusty # Travis CI provides Precise and Trusty only + +before_install: + - sudo apt-get update -qq + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa + - sudo apt-get update -qq + - eval "${MATRIX_EVAL}" -before_install: # install dependencies & build Google Test Framework - - | - if [[ "$TRAVIS_OS_NAME" == "linux" ]] - then - sudo apt-get install -qq qtbase5-dev libqt5webkit5-dev - sudo apt-get install -qq qt5-default qttools5-dev-tools - sudo apt-get install -qq ccache - sudo apt-get install -qq libgtest-dev - echo `pwd` - echo `pwd` - echo `pwd` - export M8RHOME=`pwd` - cd /usr/src/gtest # Google Test Framework - sudo apt-get install -qq cmake - sudo cmake . - sudo make - sudo mv libg* /usr/lib/ - fi +install: + - sudo apt-get install -qq qtbase5-dev libqt5webkit5-dev + - sudo apt-get install -qq qt5-default qttools5-dev-tools + - sudo apt-get install -qq ccache + - sudo apt-get install -qq libgtest-dev + - "export M8RHOME=`pwd`" + - cd /usr/src/gtest # I have to build Google Test Framework myself + - sudo apt-get install -qq cmake + - sudo cmake . + - sudo make + - sudo mv libg* /usr/lib/ script: # make lib unit tests > run lib unit tests > make MF > install MF - - cd ~ - - echo `pwd` - - echo `pwd` - - echo `pwd` - - ls - - cd mindforger - - | - if [[ "$TRAVIS_OS_NAME" == "linux" ]] - then - cd "${M8RHOME}" - cd deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . && cd ../../.. - "cd deps/discount && ./configure.sh && make ; cd ../.." - "echo \"M8RDEBUG: g++ compiler is set to: ${CXX}\"" - cd lib/test # UNIT tests - #qmake -r CONFIG+=mfnocxx CONFIG+=mfunits QMAKE_CXX=${CXX} mindforger-lib-unit-tests.pro - qmake -r CONFIG+=mfunits mindforger-lib-unit-tests.pro - make - cd src && export M8R_GIT_PATH="${M8RHOME}" && ./mindforger-lib-unit-tests > /tmp/mindforger-unit-tests.log 2>&1 # ; true - cd ../../.. - cat /tmp/mindforger-unit-tests.log - #qmake -r CONFIG+=mfnocxx QMAKE_CXX=${CXX} mindforger.pro - qmake -r mindforger.pro - make - sudo make install - fi + - cd "${M8RHOME}" + - eval "${MATRIX_EVAL}" + - cd deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . && cd ../../.. + - "cd deps/discount && ./configure.sh && make ; cd ../.." + - "echo \"M8RDEBUG: g++ compiler is set to: ${CXX}\"" + - cd lib/test # UNIT tests + - qmake -r CONFIG+=mfnocxx CONFIG+=mfunits QMAKE_CXX=${CXX} mindforger-lib-unit-tests.pro + - make + - cd src && export M8R_GIT_PATH="${M8RHOME}" && ./mindforger-lib-unit-tests > /tmp/mindforger-unit-tests.log 2>&1 # ; true + - cd ../../.. + - cat /tmp/mindforger-unit-tests.log + - qmake -r CONFIG+=mfnocxx QMAKE_CXX=${CXX} mindforger.pro + - make + - sudo make install From 18601818d5bd3816864995fa962de4a1108435d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Dvo=C5=99=C3=A1k?= Date: Sat, 7 Mar 2020 21:03:45 +0100 Subject: [PATCH 25/43] WIP paste image to editor. --- app/src/qt/note_editor_view.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/app/src/qt/note_editor_view.cpp b/app/src/qt/note_editor_view.cpp index 764195ee..45e87338 100644 --- a/app/src/qt/note_editor_view.cpp +++ b/app/src/qt/note_editor_view.cpp @@ -237,16 +237,35 @@ QString NoteEditorView::getRelevantWords() const * Autocomplete */ -void NoteEditorView::keyPressEvent(QKeyEvent *event) +void NoteEditorView::keyPressEvent(QKeyEvent* event) { hitCounter++; + // TODO Linux paste + if(event->modifiers() & Qt::ControlModifier) { switch (event->key()) { - case Qt::Key_F: + case Qt::Key_V: { + // TODO make this private function + QClipboard* clip = QApplication::clipboard(); + const QMimeData* mime = clip->mimeData(); + if(mime->hasImage()) { + MF_DEBUG("PASTE: image - has URLs?" << mime->hasUrls() << endl); + QImage image = qvariant_cast(mime->imageData()); + // TODO signal w/ QImage to presenter + // TODO mainWindowPresenter saves image to path constructed in copyImageOrLink() + // TODO resulting path is injected to the markdown source + // TODO v this goes away + image.save("/Users/dvorka/mf-img.png"); + return; + } + break; + } + case Qt::Key_F: { findStringAgain(); return; // exit to override default key binding } + } } // IMPROVE get configuration reference and editor mode setting - this must be fast From 84f326e153c0c4ae2c9193660ddb4a6dc8cf33f6 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 21:55:39 +0100 Subject: [PATCH 26/43] Adding pasting of image data to editor which resolves #1243 --- app/src/qt/main_window_presenter.cpp | 70 ++++++++++++++++++++++------ app/src/qt/main_window_presenter.h | 2 + app/src/qt/note_editor_view.cpp | 8 +--- app/src/qt/note_editor_view.h | 1 + 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/app/src/qt/main_window_presenter.cpp b/app/src/qt/main_window_presenter.cpp index 252081e9..41641da4 100644 --- a/app/src/qt/main_window_presenter.cpp +++ b/app/src/qt/main_window_presenter.cpp @@ -102,6 +102,14 @@ MainWindowPresenter::MainWindowPresenter(MainWindowView& view) orloj->getOutlineHeaderEdit()->getView()->getHeaderEditor(), SIGNAL(signalDnDropUrl(QString)), this, SLOT(doActionFormatLinkOrImage(QString)) ); + QObject::connect( + orloj->getNoteEdit()->getView()->getNoteEditor(), SIGNAL(signalPasteImageData(QImage)), + this, SLOT(doActionEditPasteImageData(QImage)) + ); + QObject::connect( + orloj->getOutlineHeaderEdit()->getView()->getHeaderEditor(), SIGNAL(signalPasteImageData(QImage)), + this, SLOT(doActionEditPasteImageData(QImage)) + ); // wire toolbar signals QObject::connect(view.getToolBar()->actionNewOutlineOrNote, SIGNAL(triggered()), this, SLOT(doActionOutlineOrNoteNew())); QObject::connect(view.getToolBar()->actionOpenRepository, SIGNAL(triggered()), this, SLOT(doActionMindLearnRepository())); @@ -1536,7 +1544,7 @@ void MainWindowPresenter::doActionFormatLinkOrImage(QString link) // IMPROVE rebuild model ONLY if dirty i.e. an outline name was changed on save vector oss{mind->getOutlines()}; mind->remind().sortByName(oss); - vector os{oss.begin(),oss.end()}; + vector os{oss.begin(), oss.end()}; vector ns{}; mind->getAllNotes(ns); @@ -1603,7 +1611,7 @@ void MainWindowPresenter::copyLinkOrImageToRepository(const string& srcPath, QSt } else if(orloj->isFacetActive(OrlojPresenterFacets::FACET_EDIT_OUTLINE_HEADER)) { oPath = orloj->getOutlineHeaderEdit()->getCurrentOutline()->getKey(); } - if(stringEndsWith(oPath, ".md")) { + if(stringEndsWith(oPath, FILE_EXTENSION_MD_MD)) { pathPrefix = QString::fromStdString(oPath.substr(0, oPath.length()-3)); } else { pathPrefix = QString::fromStdString(oPath); @@ -1647,12 +1655,43 @@ void MainWindowPresenter::copyLinkOrImageToRepository(const string& srcPath, QSt } } +// IMPROVE optimize this function (QString, string, ...) +// IMPROVE deduplicate this method and copy image/attachment code +void MainWindowPresenter::doActionEditPasteImageData(QImage image) +{ + // save image object as file + string oPath{}; + if(orloj->isFacetActive(OrlojPresenterFacets::FACET_EDIT_NOTE)) { + oPath = orloj->getNoteEdit()->getCurrentNote()->getOutlineKey(); + } else if(orloj->isFacetActive(OrlojPresenterFacets::FACET_EDIT_OUTLINE_HEADER)) { + oPath = orloj->getOutlineHeaderEdit()->getCurrentOutline()->getKey(); + } + QString pathPrefix{}; + if(stringEndsWith(oPath, FILE_EXTENSION_MD_MD)) { + pathPrefix = QString::fromStdString(oPath.substr(0, oPath.length()-3)); + } else { + pathPrefix = QString::fromStdString(oPath); + } + pathPrefix.append("."); + QString pathSuffix{"image.png"}; + QString path = pathPrefix + pathSuffix; + while(isDirectoryOrFileExists(path.toStdString().c_str())) { + pathSuffix.prepend("_"); + path = pathPrefix + pathSuffix; + } + + statusBar->showInfo(tr("Saving pasted image data to file: '%1'").arg(path.toStdString().c_str())); + image.save(path); + + // inject link to file to O + injectImageLinkToEditor(path); +} + void MainWindowPresenter::statusInfoPreviewFlickering() { statusBar->showInfo(QString(tr("HTML Note preview flickering can be eliminated by disabling math and diagrams in Preferences menu"))); } - /* * See InsertLinkDialog for link creation hints */ @@ -1699,17 +1738,8 @@ void MainWindowPresenter::doActionFormatImage() insertImageDialog->show(); } -void MainWindowPresenter::handleFormatImage() +void MainWindowPresenter::injectImageLinkToEditor(const QString& path) { - insertImageDialog->hide(); - - QString path{}; - if(insertImageDialog->isCopyToRepo()) { - copyLinkOrImageToRepository(insertImageDialog->getPathText().toStdString(), path); - } else { - path = insertImageDialog->getPathText(); - } - QString text{"!["}; text += insertImageDialog->getAlternateText(); text += "]("; @@ -1723,6 +1753,20 @@ void MainWindowPresenter::handleFormatImage() } } +void MainWindowPresenter::handleFormatImage() +{ + insertImageDialog->hide(); + + QString path{}; + if(insertImageDialog->isCopyToRepo()) { + copyLinkOrImageToRepository(insertImageDialog->getPathText().toStdString(), path); + } else { + path = insertImageDialog->getPathText(); + } + + injectImageLinkToEditor(path); +} + void MainWindowPresenter::doActionFormatHr() { QString text{"\n---"}; diff --git a/app/src/qt/main_window_presenter.h b/app/src/qt/main_window_presenter.h index 495e22fa..a2ed1a6e 100644 --- a/app/src/qt/main_window_presenter.h +++ b/app/src/qt/main_window_presenter.h @@ -273,6 +273,7 @@ public slots: void doActionFormatLink(); void handleFormatLink(); void doActionFormatImage(); + void injectImageLinkToEditor(const QString& path); void handleFormatImage(); void doActionFormatTable(); void doActionFormatHr(); @@ -310,6 +311,7 @@ public slots: void doActionEditFind(); void doActionEditFindAgain(); void doActionEditWordWrapToggle(); + void doActionEditPasteImageData(QImage image); void doActionToggleLiveNotePreview(); void doActionNameDescFocusSwap(); // help diff --git a/app/src/qt/note_editor_view.cpp b/app/src/qt/note_editor_view.cpp index 45e87338..90ee12b5 100644 --- a/app/src/qt/note_editor_view.cpp +++ b/app/src/qt/note_editor_view.cpp @@ -250,13 +250,9 @@ void NoteEditorView::keyPressEvent(QKeyEvent* event) QClipboard* clip = QApplication::clipboard(); const QMimeData* mime = clip->mimeData(); if(mime->hasImage()) { - MF_DEBUG("PASTE: image - has URLs?" << mime->hasUrls() << endl); + MF_DEBUG("Image PASTED to editor" << endl); QImage image = qvariant_cast(mime->imageData()); - // TODO signal w/ QImage to presenter - // TODO mainWindowPresenter saves image to path constructed in copyImageOrLink() - // TODO resulting path is injected to the markdown source - // TODO v this goes away - image.save("/Users/dvorka/mf-img.png"); + emit signalPasteImageData(image); return; } break; diff --git a/app/src/qt/note_editor_view.h b/app/src/qt/note_editor_view.h index 4ad5f22b..1f90f31a 100644 --- a/app/src/qt/note_editor_view.h +++ b/app/src/qt/note_editor_view.h @@ -140,6 +140,7 @@ public slots: signals: void signalDnDropUrl(QString); + void signalPasteImageData(QImage); void signalGetLinksForPattern(const QString&); }; From e47c8d6be676f1f3da9c588c561279824b1d7676 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sat, 7 Mar 2020 22:48:15 +0100 Subject: [PATCH 27/43] Fixing broken O header live preview #1244 --- app/src/qt/main_window_presenter.cpp | 2 ++ app/src/qt/orloj_presenter.cpp | 3 +++ app/src/qt/widgets/edit_buttons_panel.cpp | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/qt/main_window_presenter.cpp b/app/src/qt/main_window_presenter.cpp index 41641da4..c513c112 100644 --- a/app/src/qt/main_window_presenter.cpp +++ b/app/src/qt/main_window_presenter.cpp @@ -550,6 +550,8 @@ void MainWindowPresenter::doActionNameDescFocusSwap() void MainWindowPresenter::doActionToggleLiveNotePreview() { + MF_DEBUG("Toggling live N preview" << endl); + // toggle config if(config.isUiLiveNotePreview()) { config.setUiLiveNotePreview(false); diff --git a/app/src/qt/orloj_presenter.cpp b/app/src/qt/orloj_presenter.cpp index 61ffd8ce..c8bccee5 100644 --- a/app/src/qt/orloj_presenter.cpp +++ b/app/src/qt/orloj_presenter.cpp @@ -120,6 +120,9 @@ OrlojPresenter::OrlojPresenter(MainWindowPresenter* mainPresenter, QObject::connect( this, SIGNAL(signalLinksForHeaderPattern(const QString&, std::vector*)), view->getOutlineHeaderEdit()->getHeaderEditor(), SLOT(slotPerformLinkCompletion(const QString&, std::vector*))); + QObject::connect( + outlineHeaderEditPresenter->getView()->getButtonsPanel(), SIGNAL(signalShowLivePreview()), + mainPresenter, SLOT(doActionToggleLiveNotePreview())); QObject::connect( noteEditPresenter->getView()->getButtonsPanel(), SIGNAL(signalShowLivePreview()), mainPresenter, SLOT(doActionToggleLiveNotePreview())); diff --git a/app/src/qt/widgets/edit_buttons_panel.cpp b/app/src/qt/widgets/edit_buttons_panel.cpp index 00e616b9..f8d39f37 100644 --- a/app/src/qt/widgets/edit_buttons_panel.cpp +++ b/app/src/qt/widgets/edit_buttons_panel.cpp @@ -28,7 +28,7 @@ EditButtonsPanel::EditButtonsPanel(MfWidgetMode mode, QWidget* parent) // widgets previewButton = new QPushButton{tr("Preview"), this}; #ifdef __APPLE__ - previewButton->setToolTip("⌘+Shift+P"); + previewButton->setToolTip("⌘+Shift+P"); #else previewButton->setToolTip("Ctrl+Shift+P"); #endif From 9afbd55abf4746494fa3933172d88945c510a5d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Dvo=C5=99=C3=A1k?= Date: Sat, 7 Mar 2020 23:45:53 +0100 Subject: [PATCH 28/43] Fixing macOS specific shortcut characters & apple symbols. --- app/src/qt/gear/apple_utils.h | 35 ++++++++++++++++++++--- app/src/qt/widgets/edit_buttons_panel.cpp | 10 +++++-- build/macos/.gitignore | 1 + build/macos/macos-build.sh | 7 ++++- 4 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 build/macos/.gitignore diff --git a/app/src/qt/gear/apple_utils.h b/app/src/qt/gear/apple_utils.h index beeedeb4..a0b29a5c 100644 --- a/app/src/qt/gear/apple_utils.h +++ b/app/src/qt/gear/apple_utils.h @@ -28,14 +28,13 @@ * - OS keyboard, naming, filesystem, process, ... conventions. * - OS specifics. * - * Keyboard modifiers: + * Keyboard modifiers (common): * * - Control (or Ctrl) ⌃ * - Option (or Alt) ⌥ * - Command (or Cmd ~ Win key) ⌘ * - Shift ⇧ * - Caps Lock ⇪ - * - Fn * * Common keyboard shortcuts: * @@ -45,8 +44,6 @@ * * - ifdef __APPLE__ / if defined(__APPLE__) * - * - * * Qt * * enum Qt::Modifier: @@ -59,6 +56,36 @@ * Qt KEY_META -> macOS control (CTRL) * Qt KEY_ALT -> macos option (OPTION) * + * Keyboard unicode & entities (all): + * + * HTML Entity GLYPH NAME + *   Apple + * ⌘ ⌘ Command, Cmd, Clover, (formerly) Apple + * ⌃ ⌃ Control, Ctl, Ctrl + * ⌥ ⌥ Option, Opt, (Windows) Alt + * ⇧ ⇧ Shift + * ⇪ ⇪ Caps lock + * ⏏ ⏏ Eject + * ↩ ↩ Return, Carriage Return + * ↵ ↵ ↵ Return, Carriage Return + * ⏎ ⏎ Return, Carriage Return + * ⌤ ⌤ Enter + * ⌫ ⌫ Delete, Backspace + * ⌦ ⌦ Forward Delete + * ⎋ ⎋ Escape, Esc + * → → → Right arrow + * ← ← ← Left arrow + * ↑ ↑ ↑ Up arrow + * ↓ ↓ ↓ Down arrow + * ⇞ ⇞ Page Up, PgUp + * ⇟ ⇟ Page Down, PgDn + * ↖ ↖ Home + * ↘ ↘ End + * ⌧ ⌧ Clear + * ⇥ ⇥ Tab, Tab Right, Horizontal Tab + * ⇤ ⇤ Shift Tab, Tab Left, Back-tab + * ␢ ␢ Space, Blank + * ␣ **␣** Space, Blank */ namespace m8r { diff --git a/app/src/qt/widgets/edit_buttons_panel.cpp b/app/src/qt/widgets/edit_buttons_panel.cpp index 00e616b9..880e7990 100644 --- a/app/src/qt/widgets/edit_buttons_panel.cpp +++ b/app/src/qt/widgets/edit_buttons_panel.cpp @@ -28,21 +28,25 @@ EditButtonsPanel::EditButtonsPanel(MfWidgetMode mode, QWidget* parent) // widgets previewButton = new QPushButton{tr("Preview"), this}; #ifdef __APPLE__ - previewButton->setToolTip("⌘+Shift+P"); + previewButton->setToolTip("⇧⌘P"); #else previewButton->setToolTip("Ctrl+Shift+P"); #endif moreButton = new QPushButton{tr("Properties"), this}; +#ifdef __APPLE__ + moreButton->setToolTip("⌥↩"); +#else moreButton->setToolTip("Alt+Enter"); +#endif rememberButton = new QPushButton{tr("Remember"), this}; #ifdef __APPLE__ - rememberButton->setToolTip("⌘+L"); + rememberButton->setToolTip("⌘L"); #else rememberButton->setToolTip("Alt+Left"); #endif cancelButton = new QPushButton{tr("Cancel"), this}; #ifdef __APPLE__ - cancelButton->setToolTip("⌘+G"); + cancelButton->setToolTip("⌘G"); #else cancelButton->setToolTip("Ctrl+G"); #endif diff --git a/build/macos/.gitignore b/build/macos/.gitignore new file mode 100644 index 00000000..c8ff0518 --- /dev/null +++ b/build/macos/.gitignore @@ -0,0 +1 @@ +mindforger.dmg \ No newline at end of file diff --git a/build/macos/macos-build.sh b/build/macos/macos-build.sh index 6f4c6d29..ec15bf7c 100755 --- a/build/macos/macos-build.sh +++ b/build/macos/macos-build.sh @@ -47,7 +47,12 @@ packageMindForger() { # main ######################################################################### # build MindForger in Qt to get qt.io kits, CLI must be configured to avoid brew Qt -#buildMindForger + +export SCRIPT_HOME=`pwd` +buildMindForger +cd ${SCRIPT_HOME} packageMindForger +cp -vf ../../app/mindforger.dmg . + # eof From 78ddc784d86f685751a47f069a97d64dbfdb914c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Dvo=C5=99=C3=A1k?= Date: Sun, 8 Mar 2020 00:02:10 +0100 Subject: [PATCH 29/43] Fixing macOS build script. --- build/macos/macos-build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build/macos/macos-build.sh b/build/macos/macos-build.sh index ec15bf7c..ebb07ebe 100755 --- a/build/macos/macos-build.sh +++ b/build/macos/macos-build.sh @@ -52,6 +52,7 @@ export SCRIPT_HOME=`pwd` buildMindForger cd ${SCRIPT_HOME} packageMindForger +cd ${SCRIPT_HOME} cp -vf ../../app/mindforger.dmg . From d630fc50b2fdc99bffb9e43c03226232072f6120 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sun, 8 Mar 2020 10:52:29 +0100 Subject: [PATCH 30/43] Fixing HTML preview base path which resolves #1242 --- app/src/qt/note_view_presenter.cpp | 24 +++++++------------ app/src/qt/note_view_presenter.h | 1 - app/src/qt/outline_header_view_presenter.cpp | 8 ++++--- lib/src/debug.h | 3 ++- .../html/html_outline_representation.cpp | 17 ++++++++----- .../markdown_outline_representation.cpp | 4 ++-- 6 files changed, 29 insertions(+), 28 deletions(-) diff --git a/app/src/qt/note_view_presenter.cpp b/app/src/qt/note_view_presenter.cpp index 1120db4d..441602f7 100644 --- a/app/src/qt/note_view_presenter.cpp +++ b/app/src/qt/note_view_presenter.cpp @@ -32,8 +32,6 @@ NoteViewPresenter::NoteViewPresenter(NoteView* view, OrlojPresenter* orloj) // IMPORTANT: pre-allocate string using reserve() to ensure good append performance html = string{}; html.reserve(10000); - qHtml = QString(); - qHtml.reserve(10000); this->view = view; this->orloj = orloj; @@ -102,10 +100,14 @@ void NoteViewPresenter::refreshLivePreview() } #endif - // refresh HTML view (autolinking intentionally disabled) - htmlRepresentation->to(&auxNote, &html, false, static_cast(yScrollPct)); - qHtml = QString::fromStdString(html); - view->setHtml(qHtml); + // refresh N HTML view (autolinking intentionally disabled) + htmlRepresentation->to( + &auxNote, + &html, + false, + static_cast(yScrollPct) + ); + view->setHtml(QString::fromStdString(html)); // IMPROVE share code between O header and N #if not defined(_WIN32) && not defined(__APPLE__) @@ -132,17 +134,9 @@ void NoteViewPresenter::refresh(Note* note) note->makeRead(); this->currentNote = note; - // autolinking debug - // MF_DEBUG("H " << htmlRepresentation << endl); - // MF_DEBUG("N " << note << endl); - // MF_DEBUG("T " << html << endl); - // MF_DEBUG("A " << Configuration::getInstance().isAutolinking() << endl); - // HTML htmlRepresentation->to(note, &html, Configuration::getInstance().isAutolinking()); - qHtml= QString::fromStdString(html); - - view->setHtml(qHtml); + view->setHtml(QString::fromStdString(html)); // leaderboard mind->associate(); diff --git a/app/src/qt/note_view_presenter.h b/app/src/qt/note_view_presenter.h index 5fb310f7..4bb2bde9 100644 --- a/app/src/qt/note_view_presenter.h +++ b/app/src/qt/note_view_presenter.h @@ -41,7 +41,6 @@ class NoteViewPresenter : public QObject private: std::string html; - QString qHtml; Configuration& config; Mind* mind; diff --git a/app/src/qt/outline_header_view_presenter.cpp b/app/src/qt/outline_header_view_presenter.cpp index a8436b20..470384d9 100644 --- a/app/src/qt/outline_header_view_presenter.cpp +++ b/app/src/qt/outline_header_view_presenter.cpp @@ -60,11 +60,13 @@ OutlineHeaderViewPresenter::OutlineHeaderViewPresenter( void OutlineHeaderViewPresenter::refreshLivePreview() { - MF_DEBUG("Refreshing O header HTML preview from editor: " << this->currentOutline->getName() << endl); + MF_DEBUG("Refreshing O header HTML preview from editor: " << currentOutline->getName() << endl); // O w/ current editor text w/o saving it Outline auxOutline{*currentOutline}; + auxOutline.setKey(currentOutline->getKey()); auxOutline.setName(orloj->getOutlineHeaderEdit()->getView()->getName().toStdString()); + QString description = orloj->getOutlineHeaderEdit()->getView()->getDescription(); string s{description.toStdString()}; vector d{}; @@ -85,8 +87,8 @@ void OutlineHeaderViewPresenter::refreshLivePreview() } } #endif - MF_DEBUG("SCROLL offset: " << yScrollPct << endl); - // refresh HTML view (autolinking intentionally disabled) + + // refresh O header HTML view (autolinking intentionally disabled) htmlRepresentation->to( &auxOutline, &html, diff --git a/lib/src/debug.h b/lib/src/debug.h index c40c8fd4..877c1425 100644 --- a/lib/src/debug.h +++ b/lib/src/debug.h @@ -32,10 +32,11 @@ #define MF_DEBUG(x) do { std::cerr << x; } while (0) // enable/disable verbose debug of particular components - //#define MF_DEBUG_HTML + #define MF_DEBUG_HTML //#define MF_DEBUG_ASYNC_TASKS //#define MF_DEBUG_QRC //#define MF_DEBUG_L10N + //#define MF_DEBUG_AUTOLINKING // show WIP features #define MF_WIP diff --git a/lib/src/representations/html/html_outline_representation.cpp b/lib/src/representations/html/html_outline_representation.cpp index a0e52a1e..9d3c047a 100644 --- a/lib/src/representations/html/html_outline_representation.cpp +++ b/lib/src/representations/html/html_outline_representation.cpp @@ -319,7 +319,6 @@ string* HtmlOutlineRepresentation::to( return toNoMeta(outline, html, standalone, yScrollTo); } - if(!config.isUiHtmlTheme()) { header(*html, nullptr, standalone, 0); string markdown{"# "}; @@ -421,14 +420,18 @@ string* HtmlOutlineRepresentation::to( string outlineMd{}; string path, file; pathToDirectoryAndFile(outline->getKey(), path, file); - // Oheader + + // O header if(autolinking) { markdownRepresentation.toDescription( - outline->getOutlineDescriptorAsNote(), - &outlineMd, - autolinking); + outline->getOutlineDescriptorAsNote(), + &outlineMd, + autolinking + ); } else { - outlineMd.append(outline->getOutlineDescriptorAsNote()->getDescriptionAsString()); + outlineMd.append( + outline->getOutlineDescriptorAsNote()->getDescriptionAsString() + ); } // Ns if(whole) { @@ -460,6 +463,8 @@ string* HtmlOutlineRepresentation::to( } #ifdef MF_DEBUG_HTML + // debug MD + MF_DEBUG("=== BEGIN HEADER MD ===" << endl << *html << endl << "=== END HEADER MD ===" << endl); // debug generated HTML MF_DEBUG("=== BEGIN HEADER HTML ===" << endl << *html << endl << "=== END HEADER HTML ===" << endl); #endif diff --git a/lib/src/representations/markdown/markdown_outline_representation.cpp b/lib/src/representations/markdown/markdown_outline_representation.cpp index 0cb48f48..3eabc256 100644 --- a/lib/src/representations/markdown/markdown_outline_representation.cpp +++ b/lib/src/representations/markdown/markdown_outline_representation.cpp @@ -499,9 +499,9 @@ string* MarkdownOutlineRepresentation::to(const Note* note, string* md, bool inc md->append("\n"); } - MF_DEBUG("BEFORE: " << md << endl); + MF_DEBUG("= BEFORE autolinking =============================" << endl << md << endl); toDescription(note, md, autolinking); - MF_DEBUG("AFTER: " << md << endl); + MF_DEBUG("= AFTER autolinking ==============================" << endl << md << endl); return md; } From c5f3f05ca88b1a851ad520cd3752c031ee54d3f5 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sun, 8 Mar 2020 11:21:29 +0100 Subject: [PATCH 31/43] Ensuring image alternate text presents on data paste which resolves #1250 --- app/src/qt/main_window_presenter.cpp | 14 ++++++++++---- app/src/qt/main_window_presenter.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/src/qt/main_window_presenter.cpp b/app/src/qt/main_window_presenter.cpp index c513c112..d0a3709c 100644 --- a/app/src/qt/main_window_presenter.cpp +++ b/app/src/qt/main_window_presenter.cpp @@ -1686,7 +1686,7 @@ void MainWindowPresenter::doActionEditPasteImageData(QImage image) image.save(path); // inject link to file to O - injectImageLinkToEditor(path); + injectImageLinkToEditor(path, QString{"image"}); } void MainWindowPresenter::statusInfoPreviewFlickering() @@ -1740,10 +1740,16 @@ void MainWindowPresenter::doActionFormatImage() insertImageDialog->show(); } -void MainWindowPresenter::injectImageLinkToEditor(const QString& path) +void MainWindowPresenter::injectImageLinkToEditor( + const QString& path, + const QString& alternateText) { QString text{"!["}; - text += insertImageDialog->getAlternateText(); + if(alternateText.size()) { + text += alternateText; + } else { + text += insertImageDialog->getAlternateText(); + } text += "]("; text += path; text += ")"; @@ -1766,7 +1772,7 @@ void MainWindowPresenter::handleFormatImage() path = insertImageDialog->getPathText(); } - injectImageLinkToEditor(path); + injectImageLinkToEditor(path, QString{}); } void MainWindowPresenter::doActionFormatHr() diff --git a/app/src/qt/main_window_presenter.h b/app/src/qt/main_window_presenter.h index a2ed1a6e..1d7e5632 100644 --- a/app/src/qt/main_window_presenter.h +++ b/app/src/qt/main_window_presenter.h @@ -273,7 +273,7 @@ public slots: void doActionFormatLink(); void handleFormatLink(); void doActionFormatImage(); - void injectImageLinkToEditor(const QString& path); + void injectImageLinkToEditor(const QString& path, const QString& alternateText); void handleFormatImage(); void doActionFormatTable(); void doActionFormatHr(); From c4908d7a3d8be753ceb2f42ca535a7828b882257 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sun, 8 Mar 2020 12:33:42 +0100 Subject: [PATCH 32/43] Removing Discount Markdown to HTML transcoder which resolves #1252 --- .gitmodules | 3 - .travis.yml | 1 - CREDITS.md | 13 +-- Changelog | 6 ++ app/app.pro | 39 ++++---- build/macos/macos-build.sh | 2 +- build/test-lib-units.sh | 5 +- build/travis-ci/.travis-trusty.yml | 73 +++++++++++++++ build/ubuntu/build-all-clean-system.sh | 10 +- deps/deps.pro | 25 ----- deps/discount | 1 - lib/lib.pro | 18 +--- lib/src/mind/mind.cpp | 2 +- .../html/html_outline_representation.cpp | 10 +- .../html/html_outline_representation.h | 4 - .../markdown/discount_markdown_transcoder.cpp | 93 ------------------- .../markdown/discount_markdown_transcoder.h | 84 ----------------- lib/test/mindforger-lib-unit-tests.pro | 4 +- .../memory/08. Attributes.md | 4 +- .../memory/09. Advanced Attributes.md | 4 +- .../memory/10. Data Structures.md | 4 +- .../memory/feature-md-2-html-extensions.md | 4 +- lib/test/resources/markdowns/autolinking.md | 4 +- lib/test/src/src.pro | 24 ++--- mindforger.pro | 6 +- 25 files changed, 141 insertions(+), 302 deletions(-) create mode 100644 build/travis-ci/.travis-trusty.yml delete mode 100644 deps/deps.pro delete mode 160000 deps/discount delete mode 100644 lib/src/representations/markdown/discount_markdown_transcoder.cpp delete mode 100644 lib/src/representations/markdown/discount_markdown_transcoder.h diff --git a/.gitmodules b/.gitmodules index 578d5a7e..5402d0a8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "doc"] path = doc url = https://github.com/dvorka/mindforger-repository.git -[submodule "deps/discount"] - path = deps/discount - url = https://github.com/dvorka/discount.git [submodule "deps/mitie"] path = deps/mitie url = https://github.com/dvorka/MITIE.git diff --git a/.travis.yml b/.travis.yml index 83f1ed4a..4bfa5bcd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,7 +61,6 @@ script: # make lib unit tests > run lib unit tests > make MF > install MF - cd "${M8RHOME}" - eval "${MATRIX_EVAL}" - cd deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . && cd ../../.. - - "cd deps/discount && ./configure.sh && make ; cd ../.." - "echo \"M8RDEBUG: g++ compiler is set to: ${CXX}\"" - cd lib/test # UNIT tests - qmake -r CONFIG+=mfnocxx CONFIG+=mfunits QMAKE_CXX=${CXX} mindforger-lib-unit-tests.pro diff --git a/CREDITS.md b/CREDITS.md index fe6bcd56..b5d45426 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -12,19 +12,19 @@ Big thanks to 3rd party FOSS content authors: * Qt Company ([Qt](https://www.qt.io/) - lib and code) * Christian Loose ([CuteMarkEd](https://cloose.github.io/CuteMarkEd/) - inspiration and code) * GitHub ([CMark GFM](https://github.com/github/cmark-gfm) - Markdown rendering - library) -* David Parsons ([Discount](http://www.pell.portland.or.us/~orc/Code/discount/) - Markdown rendering - library) * NetBSD Foundation (strptime - Windows port - lib) * Toni Ronkko (dirent - Windows port - lib) * Microsoft (getopt - Windows port - lib) * Jordan Russell ([jrsoftware.org](http://jrsoftware.org) - Windows installer framework) * Davis E. King ([MITIE](https://github.com/mit-nlp/MITIE) - AI/NLP library and tools for information extraction - library) * Jean-loup Gailly, Mark Adler ([Zlib](https://sourceforge.net/projects/gnuwin32/) - library) +* David Parsons ([Discount](http://www.pell.portland.or.us/~orc/Code/discount/) - Markdown rendering - library used in the past) * Google ([Google C++ unit testing framework](https://github.com/google/googletest)) * Knut Sveidqvist ([Mermaid.js](https://mermaidjs.github.io/) - diagrams and flowcharts rendering in HTML) * AMS and SIAM ([MathJax.js](https://www.mathjax.org/) - math rendering in HTML) * Ivan Sagalaev ([Highlight.js](https://highlightjs.org/) - source code syntax highlighting) * Danny Allen (primary [icon theme](https://store.kde.org/content/show.php?content=18317) store.kde.com - icons) -* Krita (https://github.com/KDE/krita - menu icons) +* Krita (https://github.com/KDE/krita - menu icons - remixed) * Travis CI ([travis-ci.org](https://travis-ci.org/) - continous integration tests and builds infra - Ubuntu, macOS) * AppVeyor CI ([appveyor.com](https://www.appveyor.com/) - continous integration tests and builds infra - Windows) * Raimund Hocke ([SikuliX](http://sikulix.com/)- GUI automation testing) @@ -41,13 +41,15 @@ See [licenses](./licenses) folder for 3rd party content licensing details. Acknowledgements to researchers: * Karel Moulik (long term vision and ideas, consultations) -* Gekaremi (comprehensive AI/NLP research, ideas and suggestions) * Tomas Sieger (MindForger applications ideas, consultations) +* Gekaremi (comprehensive AI/NLP research, ideas and suggestions) -Acknowledgements to reviewers and testers: +Acknowledgements to reviewers, testers and supporters: -* Tomas 'Floex' Dvorak (review, testing) +* Ivan Kudibal (review, adoption and project support) * Stefan Pacinda (review, testing) +* Petr Kozelka (MacBook borrowing, consultations) +* Tomas 'Floex' Dvorak (review, testing) * Honza Odstrcil (feedback) Special thanks to: @@ -55,4 +57,3 @@ Special thanks to: * Bjarne Stroustrup (C++ - for inspiring visions and being the authority behind C++ language) * Linus Torvalds (Linux and Git - for being inspiration and strong opinions) * Richard Stallman (GNU and GNU GPL - for passionate software freedom activism) - diff --git a/Changelog b/Changelog index 519ebfa2..87a3edca 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,9 @@ +2020-03-08 Martin Dvorak + + * Released v1.52.0 - Production quality Autolinking (cmark-gfm and Trie based), + macOS improvements (keyboard shortcuts, drag & drop, key characters, ...), + discount (MD to HTML processor) removal. + 2020-02-16 Martin Dvorak * Released v1.51.0 - Live HTML preview, (partially) fixed Mermed diagrams, diff --git a/app/app.pro b/app/app.pro index b10d8004..73622cb0 100644 --- a/app/app.pro +++ b/app/app.pro @@ -61,32 +61,29 @@ win32 { LIBS += -L$$OUT_PWD/../lib -lmindforger } -# Markdown to HTML: Discount if mfmd2htmldiscount and not Windows otherwise cmark-gfm +# Markdown to HTML: cmark-gfm (or nothing) !mfnomd2html { win32 { CONFIG(release, debug|release) { - LIBS += -L$$PWD/../deps/cmark-gfm/build/src/Release -lcmark-gfm_static - LIBS += -L$$PWD/../deps/cmark-gfm/build/extensions/Release -lcmark-gfm-extensions_static + LIBS += -L$$PWD/../deps/cmark-gfm/build/src/Release -lcmark-gfm_static + LIBS += -L$$PWD/../deps/cmark-gfm/build/extensions/Release -lcmark-gfm-extensions_static } else:CONFIG(debug, debug|release) { - LIBS += -L$$PWD/../deps/cmark-gfm/build/src/Debug -lcmark-gfm_static - LIBS += -L$$PWD/../deps/cmark-gfm/build/extensions/Debug -lcmark-gfm-extensions_static - } - } else:mfmd2htmldiscount { - # MF must link against ldiscount.a (built in ../deps/discount) - NOT lmarkdown - LIBS += -L$$OUT_PWD/../deps/discount -ldiscount - } else { - # cmark-gfm - DEFINES += MF_MD_2_HTML_CMARK - - # cmark-gfm to be built by qmake to enable clean system build for Launchpad debuild - libcmark-gfm.target = libcmark-gfm - libcmark-gfm.commands = cd -L$$PWD/../deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . - libcmark-gfm_clean.commands = cd -L$$PWD/../deps/cmark-gfm rm -rvf build - QT_EXTRA_TARGETS += libcmark-gfm - - LIBS += -L$$PWD/../deps/cmark-gfm/build/extensions -lcmark-gfm-extensions - LIBS += -L$$PWD/../deps/cmark-gfm/build/src -lcmark-gfm + LIBS += -L$$PWD/../deps/cmark-gfm/build/src/Debug -lcmark-gfm_static + LIBS += -L$$PWD/../deps/cmark-gfm/build/extensions/Debug -lcmark-gfm-extensions_static } + } else { + # cmark-gfm + DEFINES += MF_MD_2_HTML_CMARK + + # cmark-gfm to be built by qmake to enable clean system build for Launchpad debuild + libcmark-gfm.target = libcmark-gfm + libcmark-gfm.commands = cd -L$$PWD/../deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . + libcmark-gfm_clean.commands = cd -L$$PWD/../deps/cmark-gfm rm -rvf build + QT_EXTRA_TARGETS += libcmark-gfm + + LIBS += -L$$PWD/../deps/cmark-gfm/build/extensions -lcmark-gfm-extensions + LIBS += -L$$PWD/../deps/cmark-gfm/build/src -lcmark-gfm + } } # NER library diff --git a/build/macos/macos-build.sh b/build/macos/macos-build.sh index ebb07ebe..eb4b1f80 100755 --- a/build/macos/macos-build.sh +++ b/build/macos/macos-build.sh @@ -20,7 +20,7 @@ # make project w/ QtWebEngine instead QtWebKit buildMindForger() { - echo "IMPORTANT: build mindforger/deps/discount before running this script!" + echo "IMPORTANT: build MindForger deps (like cmark-gfm) before running this script!" echo "Clean..." rm -vrf ../../app/mindforger.app ../../app/mindforger.dmg diff --git a/build/test-lib-units.sh b/build/test-lib-units.sh index e123467a..ddf6b795 100755 --- a/build/test-lib-units.sh +++ b/build/test-lib-units.sh @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -#export OPTION_RUN_ALL_TESTS=yes # comment this line to run OPTION_TEST only +export OPTION_RUN_ALL_TESTS=yes # comment this line to run OPTION_TEST only export OPTION_RECOMPILE=yes # recompile before running test(s) (comment this line to disable) #export OPTION_RUN_VALGRIND=yes # run test(s) w/ Valgrind (comment this line to disable) #export OPTION_RUN_GDB=yes # run test(s) w/ GDB (comment this line to disable) @@ -154,8 +154,7 @@ export BUILD_DIR=${SCRIPT_DIR}/../lib/test if [ ${OPTION_RECOMPILE} ] then # cleanup - cd ${BUILD_DIR} && cd ../../deps && make clean && rm *.a - cd ${BUILD_DIR} && cd .. && make clean && rm *.a + cd ${BUILD_DIR} && cd ../../ && make clean && rm *.a cd ${BUILD_DIR} && cd ./src && make clean # recursive qmake and recompilation - IMPORTANT: mfunits ensures MF_DEBUG is enabled in library src cd ${BUILD_DIR} && make clean && qmake -r mindforger-lib-unit-tests.pro CONFIG+=mfunits && make -j${M8R_CPU_CORES} diff --git a/build/travis-ci/.travis-trusty.yml b/build/travis-ci/.travis-trusty.yml new file mode 100644 index 00000000..4bfa5bcd --- /dev/null +++ b/build/travis-ci/.travis-trusty.yml @@ -0,0 +1,73 @@ +# .travis.yml Travis CI configuration file for MindForger +# +# Copyright (C) 2014-2020 Martin Dvorak +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +os: + - linux + +# Missing codecvt: upgrade from g++ 4.8 to 5 > MATRIX_EVAL sets CXX to g++-5 > qmake CONFIG and QMAKE_CXX sets it to build process +matrix: + include: + - os: linux + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 + env: + - MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" # IMPROVE prepend ccache to speed up 2nd build (MF after units) + +language: cpp # see https://docs.travis-ci.com/user/languages/cpp/ +compiler: + - gcc # Travis CI defines CXX=g++ env var +sudo: required +dist: trusty # Travis CI provides Precise and Trusty only + +before_install: + - sudo apt-get update -qq + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa + - sudo apt-get update -qq + - eval "${MATRIX_EVAL}" + +install: + - sudo apt-get install -qq qtbase5-dev libqt5webkit5-dev + - sudo apt-get install -qq qt5-default qttools5-dev-tools + - sudo apt-get install -qq ccache + - sudo apt-get install -qq libgtest-dev + - "export M8RHOME=`pwd`" + - cd /usr/src/gtest # I have to build Google Test Framework myself + - sudo apt-get install -qq cmake + - sudo cmake . + - sudo make + - sudo mv libg* /usr/lib/ + +script: # make lib unit tests > run lib unit tests > make MF > install MF + - cd "${M8RHOME}" + - eval "${MATRIX_EVAL}" + - cd deps/cmark-gfm && mkdir -v build && cd build && cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. && cmake --build . && cd ../../.. + - "echo \"M8RDEBUG: g++ compiler is set to: ${CXX}\"" + - cd lib/test # UNIT tests + - qmake -r CONFIG+=mfnocxx CONFIG+=mfunits QMAKE_CXX=${CXX} mindforger-lib-unit-tests.pro + - make + - cd src && export M8R_GIT_PATH="${M8RHOME}" && ./mindforger-lib-unit-tests > /tmp/mindforger-unit-tests.log 2>&1 # ; true + - cd ../../.. + - cat /tmp/mindforger-unit-tests.log + - qmake -r CONFIG+=mfnocxx QMAKE_CXX=${CXX} mindforger.pro + - make + - sudo make install diff --git a/build/ubuntu/build-all-clean-system.sh b/build/ubuntu/build-all-clean-system.sh index 917e59ad..aa3d2176 100755 --- a/build/ubuntu/build-all-clean-system.sh +++ b/build/ubuntu/build-all-clean-system.sh @@ -32,14 +32,14 @@ git submodule update sudo apt-get install build-essential zlib1g-dev libqt5webkit5-dev qttools5-dev-tools qt5-default ccache # deps build -export MF_BUILD="/tmp" -cd deps/discount -./configure.sh -make +cd ${SCRIPT_HOME}/deps/cmark-gfm +mkdir build && cd build +cmake -DCMARK_TESTS=OFF -DCMARK_SHARED=OFF .. +cmake --build . # build cd ${SCRIPT_HOME}/../.. qmake -r mindforger.pro -make -j 8 +make -j 6 # eof diff --git a/deps/deps.pro b/deps/deps.pro deleted file mode 100644 index 33cf775f..00000000 --- a/deps/deps.pro +++ /dev/null @@ -1,25 +0,0 @@ -# mindforger-deps.pro Qt project file for MindForger -# -# Copyright (C) 2016-2020 Martin Dvorak -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -TEMPLATE = subdirs - -!win32 { - !mfnomd2html { - SUBDIRS = discount - } -} -# eof diff --git a/deps/discount b/deps/discount deleted file mode 160000 index 50ad85cd..00000000 --- a/deps/discount +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 50ad85cd324e56d003d7c870bdb250cfc860c717 diff --git a/lib/lib.pro b/lib/lib.pro index 21db1d09..57027ca5 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -28,17 +28,11 @@ CONFIG -= qt mfnomd2html { DEFINES += MF_NO_MD_2_HTML } else { - mfmd2htmldiscount { - DEFINES += MF_MD_2_HTML_DISCOUNT - INCLUDEPATH += $$PWD/../deps/discount - DEPENDPATH += $$PWD/../deps/discount - } else { - DEFINES += MF_MD_2_HTML_CMARK CMARK_GFM_STATIC_DEFINE CMARK_GFM_EXTENSIONS_STATIC_DEFINE - INCLUDEPATH += $$PWD/../deps/cmark-gfm/src - INCLUDEPATH += $$PWD/../deps/cmark-gfm/extensions - INCLUDEPATH += $$PWD/../deps/cmark-gfm/build/src - INCLUDEPATH += $$PWD/../deps/cmark-gfm/build/extensions - } + DEFINES += MF_MD_2_HTML_CMARK CMARK_GFM_STATIC_DEFINE CMARK_GFM_EXTENSIONS_STATIC_DEFINE + INCLUDEPATH += $$PWD/../deps/cmark-gfm/src + INCLUDEPATH += $$PWD/../deps/cmark-gfm/extensions + INCLUDEPATH += $$PWD/../deps/cmark-gfm/build/src + INCLUDEPATH += $$PWD/../deps/cmark-gfm/build/extensions } # Zlib on Windows @@ -140,7 +134,6 @@ SOURCES += \ src/mind/ai/autolinking_preprocessor.cpp \ src/representations/csv/csv_outline_representation.cpp \ src/mind/ai/autolinking/naive_autolinking_preprocessor.cpp \ - src/representations/markdown/discount_markdown_transcoder.cpp \ src/representations/markdown/cmark_gfm_markdown_transcoder.cpp \ src/mind/ai/autolinking/autolinking_mind.cpp \ src/mind/ai/autolinking/cmark_aho_corasick_block_autolinking_preprocessor.cpp \ @@ -259,7 +252,6 @@ HEADERS += \ src/representations/csv/csv_outline_representation.h \ src/mind/ai/autolinking/naive_autolinking_preprocessor.h \ src/representations/markdown/markdown_transcoder.h \ - src/representations/markdown/discount_markdown_transcoder.h \ src/representations/representation_type.h \ src/config/config.h \ src/representations/markdown/cmark_gfm_markdown_transcoder.h \ diff --git a/lib/src/mind/mind.cpp b/lib/src/mind/mind.cpp index 5e6133f4..8d3f11b1 100644 --- a/lib/src/mind/mind.cpp +++ b/lib/src/mind/mind.cpp @@ -21,7 +21,7 @@ #ifdef MF_MD_2_HTML_CMARK #include "ai/autolinking/autolinking_mind.h" #include "ai/autolinking/cmark_aho_corasick_block_autolinking_preprocessor.h" -# else +#else #include "ai/autolinking/naive_autolinking_preprocessor.h" #endif diff --git a/lib/src/representations/html/html_outline_representation.cpp b/lib/src/representations/html/html_outline_representation.cpp index 9d3c047a..206d0a0b 100644 --- a/lib/src/representations/html/html_outline_representation.cpp +++ b/lib/src/representations/html/html_outline_representation.cpp @@ -32,8 +32,6 @@ HtmlOutlineRepresentation::HtmlOutlineRepresentation( { #if defined MF_MD_2_HTML_CMARK markdownTranscoder = new CmarkGfmMarkdownTranscoder{}; -#elif defined MF_MD_2_HTML_DISCOUNT - markdownTranscoder = new DiscountMarkdownTranscoder{}; #else markdownTranscoder = nullptr; #endif @@ -268,17 +266,11 @@ string* HtmlOutlineRepresentation::to(const string* markdown, string* html, stri html->append(*markdown); footer(*html); } else { - // create HTML body using Discount first html->clear(); header(*html, basePath, standalone, yScrollTo); if(markdown->size() > 0) { #ifdef MF_NO_MD_2_HTML - // Discount: make sure that MD ends with new line, otherwise there would be missing characters in output HTML - //if(markdown->at(markdown->size()-1) != '\n') { - // markdown->append("\n"); - //} - html->append("
");
             html->append(*markdown);
             html->append("
"); @@ -333,7 +325,7 @@ string* HtmlOutlineRepresentation::to( // table htmlHeader = - "" // body tag is later replaced in Discount generated HTML > must be present in the header + "" // body tag is later replaced in generated HTML > must be present in the header "" "" "
" diff --git a/lib/src/representations/html/html_outline_representation.h b/lib/src/representations/html/html_outline_representation.h index 8e628385..3cbf0e11 100644 --- a/lib/src/representations/html/html_outline_representation.h +++ b/lib/src/representations/html/html_outline_representation.h @@ -27,8 +27,6 @@ #include "../markdown/markdown_transcoder.h" #if defined MF_MD_2_HTML_CMARK #include "../markdown/cmark_gfm_markdown_transcoder.h" -#else -#include "../markdown/discount_markdown_transcoder.h" #endif namespace m8r { @@ -61,8 +59,6 @@ class HtmlExportColorsRepresentation : public HtmlColorsRepresentation /** * @brief HTML Outline representation. - * - * Discount-based HTML Outline representation. */ class HtmlOutlineRepresentation { diff --git a/lib/src/representations/markdown/discount_markdown_transcoder.cpp b/lib/src/representations/markdown/discount_markdown_transcoder.cpp deleted file mode 100644 index 344ef0f3..00000000 --- a/lib/src/representations/markdown/discount_markdown_transcoder.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - discount_markdown_transcoder.cpp MindForger thinking notebook - - Copyright (C) 2016-2020 Martin Dvorak - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "discount_markdown_transcoder.h" - -#if defined MF_MD_2_HTML_DISCOUNT - extern "C" { - #include "../../../../deps/discount/mkdio.h" - } -#endif - -namespace m8r { - -using namespace std; - -DiscountMarkdownTranscoder::DiscountMarkdownTranscoder() - : config(Configuration::getInstance()) -{ - lastMfOptions = discountOptions = 0; -} - -DiscountMarkdownTranscoder::~DiscountMarkdownTranscoder() -{ -} - -std::string* DiscountMarkdownTranscoder::to(RepresentationType format, const string* markdown, string* html) -{ -#if defined MF_MD_2_HTML_DISCOUNT - if(format == RepresentationType::HTML) { - MMIOT* doc = nullptr; - - // options - unsigned int mfOptions = config.getMd2HtmlOptions(); - if(mfOptions!=lastMfOptions) { - lastMfOptions = mfOptions; - discountOptions - = MKD_TOC - | MKD_NOSTYLE - | MKD_FENCEDCODE // this enables ``` and ~~~ - | MKD_LATEX // this helps to enable mathjax - | MKD_AUTOLINK // enable making http://acme.com HTML link - | MKD_NOSUPERSCRIPT // if enabled it BREAKS MathJax - | (mfOptions&DiscountOption::NoStrikethroughOption?MKD_NOSTRIKETHROUGH:0) - | (mfOptions&DiscountOption::NoAlphaListOption?MKD_NOALPHALIST:0) - | (mfOptions&DiscountOption::NoDefinitionListOption?MKD_NODLIST:0) - | (mfOptions&DiscountOption::NoSmartypantsOption?MKD_NOPANTS:0) - | (mfOptions&DiscountOption::ExtraFootnoteOption?MKD_EXTRA_FOOTNOTE:0); - } - - // compile to AST - a tree of paragraphs - doc = mkd_string(markdown->c_str(), markdown->size(), discountOptions); - mkd_compile(doc, discountOptions); - - char* body = nullptr; - if(doc) { - // compile AST to HTML string - int bodySize = mkd_document(doc, &body); - - MF_DEBUG("Markdown by Discount " << bodySize << "B HTML" << endl); - if(bodySize && body) { - html->append(body); - // body is not memory leak - it's freed automatically - } - - mkd_cleanup(doc); - } - } else { - // fallback to identity() ~ Markdown - html->append(*markdown); - } -#else - UNUSED_ARG(format); - html->append(*markdown); -#endif //MF_NO_MD_2_HTML - return html; -} - -} // m8r namespace diff --git a/lib/src/representations/markdown/discount_markdown_transcoder.h b/lib/src/representations/markdown/discount_markdown_transcoder.h deleted file mode 100644 index 789c701c..00000000 --- a/lib/src/representations/markdown/discount_markdown_transcoder.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - discount_markdown_transcoder.h MindForger thinking notebook - - Copyright (C) 2016-2020 Martin Dvorak - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef M8R_DISCOUNT_MARKDOWN_TRANSCODER_H -#define M8R_DISCOUNT_MARKDOWN_TRANSCODER_H - -#include "markdown_transcoder.h" - -#include "../../config/configuration.h" - -namespace m8r { - -/** - * @brief Discount options. - * - * See https://www.pell.portland.or.us/~orc/Code/discount/ - */ - enum DiscountOption { - NoLinksOption = 1<<0, /* don't do link processing, block tags */ - NoImagesOption = 1<<1, /* don't do image processing, block */ - NoSmartypantsOption = 1<<2, /* don't run smartypants() */ - NoHtmlOption = 1<<3, /* don't allow raw html through AT ALL */ - NoSuperscriptOption = 1<<4, /* don't process a^2 as superscript() */ - NoTablesOption = 1<<5, /* disallow tables */ - NoStrikethroughOption = 1<<6, /* forbid ~~strikethrough~~ */ - TableOfContentsOption = 1<<7, /* do table-of-contents processing */ - AutolinkOption = 1<<8, /* make http://foo.com link even without <>s */ - NoHeaderOption = 1<<9, /* don't process header blocks */ - NoDivQuoteOption = 1<<10, /* forbid >%class% blocks */ - NoAlphaListOption = 1<<11, /* forbid alphabetic lists */ - NoDefinitionListOption = 1<<12, /* forbid definition lists */ - ExtraFootnoteOption = 1<<13, /* enable markdown extra-style footnotes */ - NoStyleOption = 1<<14, /* don't extract