diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ece8b9f6..34ad9178 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -149,8 +149,8 @@ class MyClass int field; // brief field description in the lower case /** - * @brief Another field. - * + * @brief Another field. + * * Field with a long description must be documented using * this style of the comment. The text of description to be * formed by sentences. Apart to that you can use any formatting diff --git a/Changelog b/Changelog index 939903af..7fbf5849 100644 --- a/Changelog +++ b/Changelog @@ -1,16 +1,28 @@ 2024-01-?? Martin Dvorak - * Released v2.0.0 - Limbo added to the application menu View/Limbo, - polished Preferences (Appearance refactored to Controls; restart requirement - highlighted), missing OOTB Eisenhower Matrix is automatically added back - to the list of Organizers, up/down button in O/N preview mode to move around - O's Ns while presenting a N. - Libraries - ability to index external PDF files and generate Notebooks - which represent them in MindForger (update and removal of the library - supported as well. New left side toolbar which runs various tools + * Released v2.0.0 - major release which removes features which are not used + in practices and brings several new features. + * Feature: Notebook Tree view brings ability to organize Notebooks to + and outline. + * Feature: Libraries bring ability to index external PDF files and generate + Notebooks which represent them in MindForger (update and removal of the + library supported as well. + * Feature: New left side toolbar which runs various tools (like Wikipedia, arXiv, StackOverflow, ...) on phrase which is the current context (Notebook or Note name, selected text or text under the cursor, ...) in order to get more information about the phrase. + * Enhancement: CLI to Wingman rewrite: help, search, knowledge recherche and + commands. + * Enhancement: Limbo added to the application menu View/Limbo. + * Enhancement: Polished Preferences - Appearance refactored to Controls, + restart requirement highlighted. + * Enhancement: Added up and down button in O/N preview mode to move around + O's Ns while presenting a N. + * Enhancement: MindForger icon changed to GenAI style. + * Enhancement: CLI rewrite towards Wingman with help, search, knowledge recherche and commands. + * Fix: Missing OOTB Eisenhower Matrix is automatically added back to + the list of Organizers. + * Fix: Conflicting menu keyboard shortcuts resolved. 2023-01-15 Martin Dvorak diff --git a/app/mf-resources.qrc b/app/mf-resources.qrc index 2358eb23..36bc6a29 100644 --- a/app/mf-resources.qrc +++ b/app/mf-resources.qrc @@ -18,15 +18,6 @@ resources/icons/flat-think.svg resources/icons/flat-adapt.svg resources/icons/flat-help.svg - resources/icons/arxiv.png - resources/icons/wikipedia.png - resources/icons/stackoverflow.png - resources/icons/duckduckgo.png - resources/icons/h2oai.png - resources/icons/github.png - resources/icons/bard.png - resources/icons/python.png - resources/icons/cpp.png resources/qt/translations/mindforger_cs.qm diff --git a/app/resources/icons/arxiv.png b/app/resources/icons/arxiv.png deleted file mode 100644 index 08e504b6..00000000 Binary files a/app/resources/icons/arxiv.png and /dev/null differ diff --git a/app/resources/icons/bard.png b/app/resources/icons/bard.png deleted file mode 100644 index e9250331..00000000 Binary files a/app/resources/icons/bard.png and /dev/null differ diff --git a/app/resources/icons/cpp.png b/app/resources/icons/cpp.png deleted file mode 100644 index d736e194..00000000 Binary files a/app/resources/icons/cpp.png and /dev/null differ diff --git a/app/resources/icons/duckduckgo.png b/app/resources/icons/duckduckgo.png deleted file mode 100644 index 66e630a6..00000000 Binary files a/app/resources/icons/duckduckgo.png and /dev/null differ diff --git a/app/resources/icons/github.png b/app/resources/icons/github.png deleted file mode 100644 index 2bfbc541..00000000 Binary files a/app/resources/icons/github.png and /dev/null differ diff --git a/app/resources/icons/h2oai.png b/app/resources/icons/h2oai.png deleted file mode 100644 index e6c21f6f..00000000 Binary files a/app/resources/icons/h2oai.png and /dev/null differ diff --git a/app/resources/icons/mindforger-bw.icns b/app/resources/icons/logo-bw/mindforger-bw.icns similarity index 100% rename from app/resources/icons/mindforger-bw.icns rename to app/resources/icons/logo-bw/mindforger-bw.icns diff --git a/app/resources/icons/mindforger-bw.ico b/app/resources/icons/logo-bw/mindforger-bw.ico similarity index 100% rename from app/resources/icons/mindforger-bw.ico rename to app/resources/icons/logo-bw/mindforger-bw.ico diff --git a/app/resources/icons/mindforger-bw.png b/app/resources/icons/logo-bw/mindforger-bw.png similarity index 100% rename from app/resources/icons/mindforger-bw.png rename to app/resources/icons/logo-bw/mindforger-bw.png diff --git a/app/resources/icons/mindforger128x128-bw.png b/app/resources/icons/logo-bw/mindforger128x128-bw.png similarity index 100% rename from app/resources/icons/mindforger128x128-bw.png rename to app/resources/icons/logo-bw/mindforger128x128-bw.png diff --git a/app/resources/icons/logo-genai/mindforger.ico b/app/resources/icons/logo-genai/mindforger.ico new file mode 100644 index 00000000..bc596811 Binary files /dev/null and b/app/resources/icons/logo-genai/mindforger.ico differ diff --git a/app/resources/icons/logo-genai/mindforger.png b/app/resources/icons/logo-genai/mindforger.png new file mode 100644 index 00000000..460d31ba Binary files /dev/null and b/app/resources/icons/logo-genai/mindforger.png differ diff --git a/app/resources/icons/logo-genai/mindforger.svg b/app/resources/icons/logo-genai/mindforger.svg new file mode 100644 index 00000000..ee9582a4 --- /dev/null +++ b/app/resources/icons/logo-genai/mindforger.svg @@ -0,0 +1,516 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/resources/icons/mindforger-uk.icns b/app/resources/icons/logo-uk/mindforger-uk.icns similarity index 100% rename from app/resources/icons/mindforger-uk.icns rename to app/resources/icons/logo-uk/mindforger-uk.icns diff --git a/app/resources/icons/mindforger-uk.ico b/app/resources/icons/logo-uk/mindforger-uk.ico similarity index 100% rename from app/resources/icons/mindforger-uk.ico rename to app/resources/icons/logo-uk/mindforger-uk.ico diff --git a/app/resources/icons/mindforger-uk.png b/app/resources/icons/logo-uk/mindforger-uk.png similarity index 100% rename from app/resources/icons/mindforger-uk.png rename to app/resources/icons/logo-uk/mindforger-uk.png diff --git a/app/resources/icons/mindforger128x128-uk.png b/app/resources/icons/logo-uk/mindforger128x128-uk.png similarity index 100% rename from app/resources/icons/mindforger128x128-uk.png rename to app/resources/icons/logo-uk/mindforger128x128-uk.png diff --git a/app/resources/icons/mindforger.ico b/app/resources/icons/mindforger.ico index b4de1d24..bc596811 100644 Binary files a/app/resources/icons/mindforger.ico and b/app/resources/icons/mindforger.ico differ diff --git a/app/resources/icons/mindforger.png b/app/resources/icons/mindforger.png index 43f7b758..460d31ba 100644 Binary files a/app/resources/icons/mindforger.png and b/app/resources/icons/mindforger.png differ diff --git a/app/resources/icons/mindforger.svg b/app/resources/icons/mindforger.svg new file mode 100644 index 00000000..ee9582a4 --- /dev/null +++ b/app/resources/icons/mindforger.svg @@ -0,0 +1,516 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/resources/icons/mindforger128x128.png b/app/resources/icons/mindforger128x128.png index 2c61a4bb..460d31ba 100644 Binary files a/app/resources/icons/mindforger128x128.png and b/app/resources/icons/mindforger128x128.png differ diff --git a/app/resources/icons/python.png b/app/resources/icons/python.png deleted file mode 100644 index c48d3af7..00000000 Binary files a/app/resources/icons/python.png and /dev/null differ diff --git a/app/resources/icons/stackoverflow.png b/app/resources/icons/stackoverflow.png deleted file mode 100644 index 78ca4ae0..00000000 Binary files a/app/resources/icons/stackoverflow.png and /dev/null differ diff --git a/app/resources/icons/wikipedia.png b/app/resources/icons/wikipedia.png deleted file mode 100644 index 5285013c..00000000 Binary files a/app/resources/icons/wikipedia.png and /dev/null differ diff --git a/app/resources/qt/images/mindforger-icon-bw.png b/app/resources/qt/images/bw/mindforger-icon-bw.png similarity index 100% rename from app/resources/qt/images/mindforger-icon-bw.png rename to app/resources/qt/images/bw/mindforger-icon-bw.png diff --git a/app/resources/qt/images/genai/mindforger-icon.png b/app/resources/qt/images/genai/mindforger-icon.png new file mode 100644 index 00000000..460d31ba Binary files /dev/null and b/app/resources/qt/images/genai/mindforger-icon.png differ diff --git a/app/resources/qt/images/mindforger-icon.png b/app/resources/qt/images/mindforger-icon.png index 43f7b758..460d31ba 100644 Binary files a/app/resources/qt/images/mindforger-icon.png and b/app/resources/qt/images/mindforger-icon.png differ diff --git a/app/resources/qt/images/mindforger-icon-uk.png b/app/resources/qt/images/uk/mindforger-icon-uk.png similarity index 100% rename from app/resources/qt/images/mindforger-icon-uk.png rename to app/resources/qt/images/uk/mindforger-icon-uk.png diff --git a/app/src/qt/cli_n_breadcrumbs_presenter.cpp b/app/src/qt/cli_n_breadcrumbs_presenter.cpp index 5a0a7703..37120189 100644 --- a/app/src/qt/cli_n_breadcrumbs_presenter.cpp +++ b/app/src/qt/cli_n_breadcrumbs_presenter.cpp @@ -31,7 +31,7 @@ CliAndBreadcrumbsPresenter::CliAndBreadcrumbsPresenter( // widgets view->setVisible(Configuration::getInstance().isUiShowBreadcrump()); - // wire signals + // wire signals (view events to presenter handlers) QObject::connect( view->cli, SIGNAL(returnPressed()), this, SLOT(executeCommand())); @@ -40,21 +40,62 @@ CliAndBreadcrumbsPresenter::CliAndBreadcrumbsPresenter( this, SLOT(handleCliTextChanged(QString))); } + void CliAndBreadcrumbsPresenter::handleCliTextChanged(const QString& text) { // IMPROVE remove parameter text if it's not needed UNUSED_ARG(text); + // TODO use status bar + QString command = view->getCommand(); + MF_DEBUG("CLI text changed to: '" << command.toStdString() << "'" << endl); if(command.size()) { - if(command.startsWith(CliAndBreadcrumbsView::CMD_TOOL)) { + MF_DEBUG(" handling:" << endl); + if(command.startsWith(CliAndBreadcrumbsView::CHAR_HELP)) { + MF_DEBUG(" HELP" << endl); + QMessageBox::information( + &mainPresenter->getView(), + tr("Wingman help"), + tr( + // IMPROVE consider prefix,
separator and colors/bold + "Use the following commands to use Wingman:\n" + "\n" + "? ... help\n" + "/ ... search\n" + "@ ... knowledge recherche\n" + "> ... run a command\n" + ": ... chat with workspace, Notebook or Note\n" + "\n" + "or type full-text search phrase\n" + ) + ); + view->setCommand(""); + mainPresenter->getStatusBar()->showInfo( + tr("Wingman: ? for help, / search, @ knowledge, > command, : chat, or type FTS phrase")); + return; + } else if(command.startsWith(CliAndBreadcrumbsView::CHAR_FIND)) { + MF_DEBUG(" / HELP find" << endl); + view->updateCompleterModel(CliAndBreadcrumbsView::HELP_FIND_CMDS); + return; + } else if(command.startsWith(CliAndBreadcrumbsView::CHAR_KNOW)) { + MF_DEBUG(" @ HELP knowledge" << endl); + view->updateCompleterModel(CliAndBreadcrumbsView::HELP_KNOW_CMDS); + return; + } else if(command.startsWith(CliAndBreadcrumbsView::CHAR_CMD)) { + MF_DEBUG(" > HELP command" << endl); + view->updateCompleterModel(CliAndBreadcrumbsView::HELP_CMD_CMDS); + return; + } else if(command.startsWith(CliAndBreadcrumbsView::CHAR_KNOW)) { + MF_DEBUG(" @ EXEC" << endl); QString prefix( QString::fromStdString( command.toStdString().substr( - CliAndBreadcrumbsView::CMD_TOOL.size()-1))); + CliAndBreadcrumbsView::CHAR_KNOW.size()-1))); QString phrase{"PHRASE"}; mainPresenter->doActionOpenRunToolDialog(phrase); view->setCommand(""); + return; } else if(command.startsWith(CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME)) { QString prefix( QString::fromStdString( @@ -77,78 +118,70 @@ void CliAndBreadcrumbsPresenter::handleCliTextChanged(const QString& text) outlineNamesCompletion << qs; } } - view->updateCompleterModel(&outlineNamesCompletion); + view->updateCompleterModel( + CliAndBreadcrumbsView::DEFAULT_CMDS, + &outlineNamesCompletion); } else { + // TODO NOT handled } } else { - view->updateCompleterModel(); + MF_DEBUG(" FALLBACK (default CMDs)" << endl); + view->updateCompleterModel( + CliAndBreadcrumbsView::DEFAULT_CMDS); } return; } + MF_DEBUG(" NO HANDLING (FTS phrase OR lost focus)" << endl); + return; + } else { // empty command + MF_DEBUG(" EMPTY command > NO handling" << endl); + return; } - - // fallback - view->forceFtsHistoryCompletion(); } // TODO i18n void CliAndBreadcrumbsPresenter::executeCommand() { QString command = view->getCommand(); + MF_DEBUG("CLI command EXEC: '" << command.toStdString() << "'" << endl); if(command.size()) { view->addCompleterItem(command); - if(command.startsWith(CliAndBreadcrumbsView::CMD_FTS)) { - executeFts(command); - view->showBreadcrumb(); - return; - } if(command.startsWith(CliAndBreadcrumbsView::CMD_LIST_OUTLINES)) { + MF_DEBUG(" executing: list outlines" << endl); executeListOutlines(); view->showBreadcrumb(); return; - } - if(command.startsWith(CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME)) { + } else if(command.startsWith(CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_TAG)) { string name = command.toStdString().substr( - CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME.size()); - unique_ptr> outlines = mind->findOutlineByNameFts(name); - if(!outlines || !outlines->size()) { - // IMPROVE memory leak if outlines && !outlines->size() - QString firstCompletion = view->getFirstCompletion(); - if(firstCompletion.size()) { - name = view->getFirstCompletion().toStdString().substr( - CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME.size() - ); - outlines = mind->findOutlineByNameFts(name); - } + CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_TAG.size()); + MF_DEBUG(" executing: find O by tag '" << name << "'" << endl); + if(name.size()) { + mainPresenter->doActionFindOutlineByTag(name); } - if(outlines && outlines->size()) { - mainPresenter->getOrloj()->showFacetOutline(outlines->front()); - // TODO efficient - mainPresenter->getStatusBar()->showInfo(tr("Notebook ")+QString::fromStdString(outlines->front()->getName())); - } else { - mainPresenter->getStatusBar()->showInfo(tr("Notebook not found: ") += QString(name.c_str())); + mainPresenter->getStatusBar()->showInfo(tr("Notebook not found - please specify tag search phrase (is empty)")); + return; + } else if(command.startsWith(CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME)) { + string name = command.toStdString().substr( + CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME.size()); + MF_DEBUG(" executing: find O by name '" << name << "'" << endl); + if(name.size()) { + mainPresenter->doActionFindOutlineByName(name); } - view->showBreadcrumb(); + mainPresenter->getStatusBar()->showInfo(tr("Notebook not found - please specify name search phrase (is empty)")); + // status handling examples: + // mainPresenter->getStatusBar()->showInfo(tr("Notebook ")+QString::fromStdString(outlines->front()->getName())); + // mainPresenter->getStatusBar()->showInfo(tr("Notebook not found: ") += QString(name.c_str())); return; + } else { + // do FTS as fallback + mainPresenter->doFts(view->getCommand(), true); } - - // do FTS as fallback - mainPresenter->doFts(view->getCommand(), true); } else { mainPresenter->getStatusBar()->showError(tr("No command!")); } } -void CliAndBreadcrumbsPresenter::executeFts(QString& command) -{ - string searchedString = command.toStdString().substr( - CliAndBreadcrumbsView::CMD_FTS.size()); - if(!searchedString.empty()) { - mainPresenter->doFts(QString::fromStdString(searchedString), true); - } -} - void CliAndBreadcrumbsPresenter::executeListOutlines() { mainPresenter->getOrloj()->showFacetOutlineList(mind->getOutlines()); diff --git a/app/src/qt/cli_n_breadcrumbs_presenter.h b/app/src/qt/cli_n_breadcrumbs_presenter.h index 82bee235..8ee47639 100644 --- a/app/src/qt/cli_n_breadcrumbs_presenter.h +++ b/app/src/qt/cli_n_breadcrumbs_presenter.h @@ -50,11 +50,13 @@ class CliAndBreadcrumbsPresenter : public QObject void executeListOutlines(); void executeListNotes(); - void executeFts(QString& command); private slots: - void executeCommand(); + /** + * @brief key pressed handler of the CLI edit line + */ void handleCliTextChanged(const QString& text); + void executeCommand(); }; } diff --git a/app/src/qt/cli_n_breadcrumbs_view.cpp b/app/src/qt/cli_n_breadcrumbs_view.cpp index 087a5c7e..3bc997e7 100644 --- a/app/src/qt/cli_n_breadcrumbs_view.cpp +++ b/app/src/qt/cli_n_breadcrumbs_view.cpp @@ -20,22 +20,37 @@ namespace m8r { +// "Enter a prompt - \"? .\" for help, \"> .\" to chat (Alt-x), \"/ .\" run command (Ctrl-/), or type a phrase to find." +constexpr const auto CLI_HELP_SHADOW_TEXT + = "Enter a prompt, command or phrase - type ? for help."; + + CliView::CliView(CliAndBreadcrumbsView* cliAndBreadcrumps, QWidget* parent) - : QLineEdit(parent) + : QLineEdit(parent), + PALETTE_DISABLED_TEXT(this->palette()), + PALETTE_ENABLED_TEXT(this->palette()), + PALETTE_ERROR_TEXT(this->palette()) { this->cliAndBreadcrumps = cliAndBreadcrumps; -#if !defined(__APPLE__) - // changing pallette @ macOS w/ dark model @ Qt 5.15.x+ causes edit line to be unreadable - // TODO leak - QPalette* palette = new QPalette(); - palette->setColor( - QPalette::Text, + PALETTE_DISABLED_TEXT.setColor( + QPalette::Text, QColor(125, 125, 125)); - // TODO LookAndFeels::getInstance().getCliTextColor()); - setPalette(*palette); + + PALETTE_ENABLED_TEXT.setColor( + QPalette::Text, + LookAndFeels::getInstance().getCliTextColor()); + + PALETTE_ERROR_TEXT.setColor( + QPalette::Text, + QColor(125, 0, 0)); + +#if !defined(__APPLE__) + // changing pallette @ macOS w/ dark model @ Qt 5.15.x+ causes edit line to be unreadable + setPalette(PALETTE_ENABLED_TEXT); #endif - setToolTip("Run a command: Alt-x to activate, type > for available commands, type search string for FTS."); + + setToolTip(CLI_HELP_SHADOW_TEXT); } void CliView::keyPressEvent(QKeyEvent* event) @@ -51,26 +66,112 @@ void CliView::keyPressEvent(QKeyEvent* event) QLineEdit::keyPressEvent(event); } +void CliView::focusOutEvent(QFocusEvent* event) +{ + MF_DEBUG("CLI: on focus lost" << std::endl); + + if(text().size() == 0) { + setText(CLI_HELP_SHADOW_TEXT); + } + + QLineEdit::focusOutEvent(event); +} + /* * CLI and breadcrumbs view. */ -const QString CliAndBreadcrumbsView::CMD_HELP +const QStringList CliAndBreadcrumbsView::EMPTY_CMDS = QStringList(); + +// help + +const QString CliAndBreadcrumbsView::CHAR_HELP = "?"; -const QString CliAndBreadcrumbsView::CMD_FTS - = "> fts "; +const QString CliAndBreadcrumbsView::CMD_HELP_HELP + = "? ... ? for help"; +const QString CliAndBreadcrumbsView::CMD_HELP_SEARCH + = "? / to search"; +const QString CliAndBreadcrumbsView::CMD_HELP_KNOWLEDGE + = "? @ for knowledge recherche"; +const QString CliAndBreadcrumbsView::CMD_HELP_CMD + = "? > to run a command"; +const QString CliAndBreadcrumbsView::CMD_HELP_CHAT + = "? : to chat with workspace, Notebook or Note"; +const QString CliAndBreadcrumbsView::CMD_HELP_FTS + = "? full-text search phrase"; + +const QStringList CliAndBreadcrumbsView::HELP_CMDS = QStringList() + << CMD_HELP_HELP + << CMD_HELP_SEARCH + // << CMD_HELP_KNOWLEDGE + << CMD_HELP_CMD + // << CMD_HELP_CHAT + // << CMD_HELP_FTS + ; + +const QString CliAndBreadcrumbsView::CHAR_FIND + = "/"; + const QString CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME - = "> find outline by name "; + = "/ find notebook by name "; +const QString CliAndBreadcrumbsView::CMD_FIND_NOTE_BY_NAME + = "/ find note by name "; +const QString CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_TAG + = "/ find notebook by tag "; +const QString CliAndBreadcrumbsView::CMD_FIND_NOTE_BY_TAG + = "/ find note by tag "; + +const QStringList CliAndBreadcrumbsView::HELP_FIND_CMDS = QStringList() + << CMD_FIND_OUTLINE_BY_NAME + << CMD_FIND_OUTLINE_BY_TAG +// << CMD_FIND_NOTE_BY_NAME +// << CMD_FIND_NOTE_BY_TAG + ; + +const QString CliAndBreadcrumbsView::CHAR_KNOW + = "@"; + +// knowledge recherche uses current context / selected entity to lookup the knowledge +const QString CliAndBreadcrumbsView::CMD_KNOW_WIKIPEDIA + = "@wikipedia"; +const QString CliAndBreadcrumbsView::CMD_KNOW_ARXIV + = "@arxiv"; +const QString CliAndBreadcrumbsView::CMD_KNOW_STACK_OVERFLOW + = "@stackoverflow"; +const QString CliAndBreadcrumbsView::CMD_KNOW_DUCK + = "@duckduckgo"; +const QString CliAndBreadcrumbsView::CMD_KNOW_GITHUB + = "@github"; +const QString CliAndBreadcrumbsView::CMD_KNOW_BARD + = "@bard"; + +const QStringList CliAndBreadcrumbsView::HELP_KNOW_CMDS = QStringList() +// << CMD_KNOW_WIKIPEDIA +// << CMD_KNOW_ARXIV + ; + +const QString CliAndBreadcrumbsView::CHAR_CMD + = ">"; + +const QString CliAndBreadcrumbsView::CMD_HOME + = "> home"; // go to home O +const QString CliAndBreadcrumbsView::CMD_TERMINAL + = "> terminal"; const QString CliAndBreadcrumbsView::CMD_LIST_OUTLINES - = "> list outlines"; + = "> list notebooks"; + +const QStringList CliAndBreadcrumbsView::HELP_CMD_CMDS = QStringList() +// << CMD_HOME +// << CMD_TERMINAL + << CMD_LIST_OUTLINES + ; -const QString CliAndBreadcrumbsView::CMD_TOOL - = "> tool"; +const QString CliAndBreadcrumbsView::CHAR_CHAT + = ":"; // TODO migrate all commands to constants const QStringList CliAndBreadcrumbsView::DEFAULT_CMDS = QStringList() - << CMD_HELP /* << CMD_EXIT // home tools @@ -100,11 +201,8 @@ const QStringList CliAndBreadcrumbsView::DEFAULT_CMDS = QStringList() // TODO new outline // TODO new note */ - << CMD_FTS << CMD_LIST_OUTLINES << CMD_FIND_OUTLINE_BY_NAME - - << CMD_TOOL ; @@ -126,34 +224,56 @@ CliAndBreadcrumbsView::CliAndBreadcrumbsView(QWidget* parent, bool zenMode) } layout->addWidget(breadcrumbsLabel); - cli = new CliView(this, parent); - cliCompleter = new QCompleter(new QStandardItemModel{}, parent); - cliCompleter->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); - cliCompleter->setCompletionMode(QCompleter::PopupCompletion); - cli->setCompleter(cliCompleter); - cli->setText("Enter a prompt - \"? .\" for help, \"/ .\" to chat (Alt-x), \"> .\" run command (Ctrl-/), or type a phrase to find."); + this->cli = new CliView(this, parent); + this->cliCompleter = new QCompleter(new QStandardItemModel{}, parent); + this->cliCompleter->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); + this->cliCompleter->setCompletionMode(QCompleter::PopupCompletion); + this->cli->setCompleter(cliCompleter); + this->cli->setText(CLI_HELP_SHADOW_TEXT); layout->addWidget(cli); showBreadcrumb(); } +void CliAndBreadcrumbsView::showCli(bool selectAll) +{ + MF_DEBUG("CLI view: SHOW (select ALL = " << std::boolalpha << selectAll << ")" << std::endl); + + // if help presents, then clear it AND change color + if(cli->text().startsWith(CLI_HELP_SHADOW_TEXT)) { + cli->clear(); + } +#if !defined(__APPLE__) + setPalette(this->cli->PALETTE_ENABLED_TEXT); +#endif + + // show + show(); + cli->setFocus(); + if(selectAll) { + cli->selectAll(); + } +} + void appendToStandardModel(const QStringList& list, QStandardItemModel* completerModel) { for(const auto& i:list) { QStandardItem* item = new QStandardItem(i); // TODO icons are not shown on certain platforms (Linux/x86) -// if(i.startsWith(".")) { -// item->setIcon(QIcon(":/menu-icons/cli.svg")); -// } else { -// item->setIcon(QIcon(":/menu-icons/find.svg")); -// } + /* + if(i.startsWith(".")) { + item->setIcon(QIcon(":/menu-icons/cli.svg")); + } else { + item->setIcon(QIcon(":/menu-icons/find.svg")); + } + */ - // IMPROVE item->setToolTip("tool tip"); + // TODO IMPROVE item->setToolTip("tool tip"); completerModel->appendRow(item); } } -void CliAndBreadcrumbsView::updateCompleterModel(const QStringList* list) +void CliAndBreadcrumbsView::updateCompleterModel(const QStringList& helpList, const QStringList* list) { QStandardItemModel* completerModel=(QStandardItemModel*)cliCompleter->model(); if(completerModel==nullptr) { @@ -173,12 +293,12 @@ void CliAndBreadcrumbsView::updateCompleterModel(const QStringList* list) if(list!=nullptr) { appendToStandardModel(*list, completerModel); } - appendToStandardModel(DEFAULT_CMDS, completerModel); + appendToStandardModel(helpList, completerModel); } void CliAndBreadcrumbsView::forceFtsHistoryCompletion() { - updateCompleterModel(); + updateCompleterModel(DEFAULT_CMDS); // ensure completion is shown despite there is NO filtering character cliCompleter->complete(); @@ -237,27 +357,4 @@ void CliAndBreadcrumbsView::showBreadcrumb() } } -void CliAndBreadcrumbsView::showCli(bool selectAll) -{ - // clear help if it presents - if(cli->text().startsWith("Use ")) { - cli->setText(""); - - // TODO leak? - QPalette* palette = new QPalette(); - palette->setColor( - QPalette::Text, - LookAndFeels::getInstance().getCliTextColor()); - setPalette(*palette); - } - - show(); - cli->setFocus(); - if(selectAll) { - cli->selectAll(); - } - updateCompleterModel(); - cliCompleter->complete(); -} - } // m8r namespace diff --git a/app/src/qt/cli_n_breadcrumbs_view.h b/app/src/qt/cli_n_breadcrumbs_view.h index 36de011e..135740e5 100644 --- a/app/src/qt/cli_n_breadcrumbs_view.h +++ b/app/src/qt/cli_n_breadcrumbs_view.h @@ -28,6 +28,9 @@ namespace m8r { class CliAndBreadcrumbsView; +/** + * @brief Custom line edit with key and color handling. + */ class CliView : public QLineEdit { Q_OBJECT @@ -35,9 +38,17 @@ class CliView : public QLineEdit private: CliAndBreadcrumbsView* cliAndBreadcrumps; +protected: + void focusOutEvent(QFocusEvent*) override; + public: + QPalette PALETTE_DISABLED_TEXT; + QPalette PALETTE_ENABLED_TEXT; + QPalette PALETTE_ERROR_TEXT; + explicit CliView(CliAndBreadcrumbsView* cliAndBreadcrumps, QWidget* parent); void keyPressEvent(QKeyEvent* event) override; + signals: void keyReleased(QKeyEvent* event); }; @@ -49,41 +60,92 @@ class CliAndBreadcrumbsView : public QWidget friend class CliAndBreadcrumbsPresenter; private: - static const QStringList DEFAULT_CMDS; - // IMPROVE horizontal container w/ buttons names and / labels to navigate easily up/down QLabel* breadcrumbsLabel; CliView* cli; QCompleter* cliCompleter; + QStringList cliCompleterHistoryList; bool zenMode; public: - static const QString CMD_HELP; + static const QStringList DEFAULT_CMDS; // TODO remove + + static const QStringList EMPTY_CMDS; + + // help + + static const QString CHAR_HELP; + + static const QString CMD_HELP_HELP; + static const QString CMD_HELP_SEARCH; + static const QString CMD_HELP_KNOWLEDGE; + static const QString CMD_HELP_CMD; + static const QString CMD_HELP_CHAT; + static const QString CMD_HELP_FTS; + + static const QStringList HELP_CMDS; + + // search + + static const QString CHAR_FIND; - static const QString CMD_FTS; static const QString CMD_FIND_OUTLINE_BY_NAME; + static const QString CMD_FIND_OUTLINE_BY_TAG; + static const QString CMD_FIND_NOTE_BY_NAME; + static const QString CMD_FIND_NOTE_BY_TAG; + + static const QStringList HELP_FIND_CMDS; + + // knowledge + + static const QString CHAR_KNOW; + + static const QString CMD_KNOW_WIKIPEDIA; + static const QString CMD_KNOW_ARXIV; + static const QString CMD_KNOW_STACK_OVERFLOW; + static const QString CMD_KNOW_DUCK; + static const QString CMD_KNOW_GITHUB; + static const QString CMD_KNOW_BARD; + + static const QStringList HELP_KNOW_CMDS; + + // command + + static const QString CHAR_CMD; + + static const QString CMD_HOME; + static const QString CMD_TERMINAL; static const QString CMD_LIST_OUTLINES; - static const QString CMD_TOOL; + static const QStringList HELP_CMD_CMDS; + + // chat + + static const QString CHAR_CHAT; public: explicit CliAndBreadcrumbsView(QWidget* parent, bool zenMode=true); + /** + * @brief Keyboard shortcut handler (Alt-x). + */ + void showCli(bool selectAll=true); + void addCompleterItem(const QString& item) { cliCompleterHistoryList.insert(0, item); } - void updateCompleterModel(const QStringList* list=nullptr); + void updateCompleterModel(const QStringList& helpList, const QStringList* list=nullptr); void forceFtsHistoryCompletion(); QString getFirstCompletion() const; void setBreadcrumbPath(const QString& path); void setCommand(const char* command); const QString getCommand() const; void show(); + void complete() { cliCompleter->complete(); } void hide(); void showBreadcrumb(); - void showCli(bool selectAll=true); }; } diff --git a/app/src/qt/dialogs/find_outline_by_tag_dialog.cpp b/app/src/qt/dialogs/find_outline_by_tag_dialog.cpp index e46be327..c489b7db 100644 --- a/app/src/qt/dialogs/find_outline_by_tag_dialog.cpp +++ b/app/src/qt/dialogs/find_outline_by_tag_dialog.cpp @@ -74,7 +74,7 @@ FindOutlineByTagDialog::FindOutlineByTagDialog(Ontology& ontology, QWidget *pare // signals QObject::connect(editTagsGroup, SIGNAL(signalTagSelectionChanged()), this, SLOT(handleTagsChanged())); - // dialog + // dialog setWindowTitle(tr("Find Notebook by Tags")); // height is set to make sure listview gets enough lines resize(fontMetrics().averageCharWidth()*55, fontMetrics().height()*30); @@ -88,7 +88,9 @@ FindOutlineByTagDialog::~FindOutlineByTagDialog() delete closeButton; } -void FindOutlineByTagDialog::show(vector& outlines, vector* tags, vector* customizedNames) +void FindOutlineByTagDialog::show( + vector& outlines, vector* tags, vector* customizedNames, const string& searchPhrase +) { choice = nullptr; // tags are changed > need to be refreshed @@ -122,7 +124,12 @@ void FindOutlineByTagDialog::show(vector& outlines, vector* editTagsGroup->slotAddTag(); } } - editTagsGroup->getLineEdit()->clear(); + + if(searchPhrase.size()) { + editTagsGroup->getLineEdit()->setText(QString::fromStdString(searchPhrase)); + } else { + editTagsGroup->getLineEdit()->clear(); + } editTagsGroup->getLineEdit()->setFocus(); QDialog::show(); } diff --git a/app/src/qt/dialogs/find_outline_by_tag_dialog.h b/app/src/qt/dialogs/find_outline_by_tag_dialog.h index b0241280..b9aa5a80 100644 --- a/app/src/qt/dialogs/find_outline_by_tag_dialog.h +++ b/app/src/qt/dialogs/find_outline_by_tag_dialog.h @@ -74,7 +74,9 @@ class FindOutlineByTagDialog : public QDialog void show( std::vector& outlines, std::vector* tags=nullptr, - std::vector* customizedNames=nullptr); + std::vector* customizedNames=nullptr, + const std::string& searchPhrase="" + ); signals: void searchFinished(); diff --git a/app/src/qt/dialogs/run_tool_dialog.cpp b/app/src/qt/dialogs/run_tool_dialog.cpp index 7d44a308..f4b6aed0 100644 --- a/app/src/qt/dialogs/run_tool_dialog.cpp +++ b/app/src/qt/dialogs/run_tool_dialog.cpp @@ -34,8 +34,6 @@ RunToolDialog::RunToolDialog(QWidget* parent) QString{TOOL_GOOGLE_SEARCH}, QString{TOOL_GH_REPOS}, QString{TOOL_GH_TOPICS}, - QString{TOOL_H2O_GPT_WEB}, - QString{TOOL_H2O_GPT_API}, QString{TOOL_WIKIPEDIA} }; @@ -113,14 +111,6 @@ QString RunToolDialog::getTemplateTextForToolName(string selectedTool) const return templateText; } else if(selectedTool == TOOL_DEEPL) { return QString{"https://www.deepl.com/en/translator"}; - } else if(selectedTool == TOOL_DOC_PYTHON) { - QString templateText{"https://docs.python.org/3.10/search.html?q="}; - templateText.append(TOOL_PHRASE); - return templateText; - } else if(selectedTool == TOOL_DOC_CPP) { - QString templateText{"https://duckduckgo.com/?sites=cppreference.com&ia=web&q="}; - templateText.append(TOOL_PHRASE); - return templateText; } else if(selectedTool == TOOL_STACK_OVERFLOW) { QString templateText{"https://stackoverflow.com/search?q="}; templateText.append(TOOL_PHRASE); @@ -147,11 +137,6 @@ QString RunToolDialog::getTemplateTextForToolName(string selectedTool) const QString temlateText{"https://www.google.com/search?q="}; temlateText.append(TOOL_PHRASE); return temlateText; - } else if(selectedTool == TOOL_H2O_GPT_API) { - // TODO: sniff HTTP traffic and use HTTP client/JSon to talk to the service - MF_DEBUG("H2O GPT API not implemented yet"); - } else if(selectedTool == TOOL_H2O_GPT_WEB) { - return QString{"https://gpt.h2o.ai/"}; } else if(selectedTool == TOOL_WIKIPEDIA) { // TODO: URL QString temlateText{"https://en.wikipedia.org/w/index.php?search="}; diff --git a/app/src/qt/left_toolbar_view.cpp b/app/src/qt/left_toolbar_view.cpp index 5f693407..b4671197 100644 --- a/app/src/qt/left_toolbar_view.cpp +++ b/app/src/qt/left_toolbar_view.cpp @@ -25,43 +25,28 @@ LeftToolbarView::LeftToolbarView(MainWindowView* mainWindowView) mainWindow{mainWindowView} { actionLeftToolbarArxiv = addAction( - QIcon(":/icons/arxiv.png"), + QIcon(":/icons/adapt.svg"), "Open arXiv and find papers related to the current context... (Alt-1)"); actionLeftToolbarWikipedia = addAction( - QIcon(":/icons/wikipedia.png"), + QIcon(":/icons/adapt.svg"), "Open Wikipedia and find entries related to the current context... (Alt-2)"); actionLeftToolbarStackOverflow = addAction( - QIcon(":/icons/stackoverflow.png"), + QIcon(":/icons/adapt.svg"), "Open StackOverflow and find entries related to the current context... (Alt-3)"); - actionLeftToolbarH2oGpt= addAction( - QIcon(":/icons/h2oai.png"), - "Open h2oGPT and chat about the current context... (Alt-4)"); - actionLeftToolbarDuckDuckGo = addAction( - QIcon(":/icons/duckduckgo.png"), + QIcon(":/icons/adapt.svg"), "Open DuckDuckGo and find entries related to the current context... (Alt-5)"); actionLeftToolbarGitHub = addAction( - QIcon(":/icons/github.png"), + QIcon(":/icons/adapt.svg"), "Open GitHub and find entries related to the current context... (Alt-6)"); actionLeftToolbarBard = addAction( - QIcon(":/icons/bard.png"), + QIcon(":/icons/adapt.svg"), "Open Bard and chat about the current context... (Alt-7)"); - - actionLeftToolbarPython = addAction( - QIcon(":/icons/python.png"), - "Open Python documentation and find entries related to the current context... (Alt-8)"); - - actionLeftToolbarCpp = addAction( - QIcon(":/icons/cpp.png"), - "Open C++ documentation and find entries related to the current context... (Alt-9)"); - - // TODO "Let chatGPT to explaine in simple terms..." - // TODO "Use Gramarly to check to grammar..." > bard/chatGPT can check grammar } LeftToolbarView::~LeftToolbarView() diff --git a/app/src/qt/left_toolbar_view.h b/app/src/qt/left_toolbar_view.h index e1d69d86..ed8688df 100644 --- a/app/src/qt/left_toolbar_view.h +++ b/app/src/qt/left_toolbar_view.h @@ -37,12 +37,9 @@ class LeftToolbarView : public QToolBar QAction* actionLeftToolbarArxiv; QAction* actionLeftToolbarWikipedia; QAction* actionLeftToolbarStackOverflow; - QAction* actionLeftToolbarH2oGpt; QAction* actionLeftToolbarDuckDuckGo; QAction* actionLeftToolbarGitHub; QAction* actionLeftToolbarBard; - QAction* actionLeftToolbarPython; - QAction* actionLeftToolbarCpp; // IMPORTANT: hide event hidden as it was causing undesired configuration // changes and toolbar hiding on Qt's spontaneous hide/show events. Citation diff --git a/app/src/qt/main_window_presenter.cpp b/app/src/qt/main_window_presenter.cpp index 3a51f8bc..812a4180 100644 --- a/app/src/qt/main_window_presenter.cpp +++ b/app/src/qt/main_window_presenter.cpp @@ -196,14 +196,6 @@ MainWindowPresenter::MainWindowPresenter(MainWindowView& view) view.getLeftToolBar()->actionLeftToolbarStackOverflow, SIGNAL(triggered()), this, SLOT(doActionStackOverflowToolbar()) ); - QObject::connect( - new QShortcut(QKeySequence("Alt+4"), view.getOrloj()), SIGNAL(activated()), - this, SLOT(doActionH2oGptToolbar()) - ); - QObject::connect( - view.getLeftToolBar()->actionLeftToolbarH2oGpt, SIGNAL(triggered()), - this, SLOT(doActionH2oGptToolbar()) - ); QObject::connect( new QShortcut(QKeySequence("Alt+5"), view.getOrloj()), SIGNAL(activated()), this, SLOT(doActionDuckDuckGoToolbar()) @@ -228,18 +220,6 @@ MainWindowPresenter::MainWindowPresenter(MainWindowView& view) view.getLeftToolBar()->actionLeftToolbarBard, SIGNAL(triggered()), this, SLOT(doActionBardToolbar()) ); - QObject::connect( - new QShortcut(QKeySequence("Alt+8"), view.getOrloj()), SIGNAL(activated()), - this, SLOT(doActionPythonToolbar()) - ); - QObject::connect( - view.getLeftToolBar()->actionLeftToolbarPython, SIGNAL(triggered()), - this, SLOT(doActionPythonToolbar()) - ); - QObject::connect( - new QShortcut(QKeySequence("Alt+9"), view.getOrloj()), SIGNAL(activated()), - this, SLOT(doActionCppToolbar()) - ); */ // wire TOP toolbar signals QObject::connect( @@ -935,7 +915,7 @@ void MainWindowPresenter::slotMainToolbarVisibilityChanged(bool visibility) mdConfigRepresentation->save(config); } -void MainWindowPresenter::doActionFindOutlineByName() +void MainWindowPresenter::doActionFindOutlineByName(const std::string& phrase) { // IMPROVE rebuild model ONLY if dirty i.e. an outline name was changed on save vector os{mind->getOutlines()}; @@ -943,6 +923,9 @@ void MainWindowPresenter::doActionFindOutlineByName() vector es{os.begin(),os.end()}; findOutlineByNameDialog->show(es); + if(phrase.size()) { + findOutlineByNameDialog->setSearchedString(QString::fromStdString(phrase)); + } } void MainWindowPresenter::handleFindOutlineByName() @@ -971,14 +954,14 @@ void MainWindowPresenter::handleFindThingByName() } } -void MainWindowPresenter::doActionFindOutlineByTag() +void MainWindowPresenter::doActionFindOutlineByTag(const string& tag) { // IMPROVE rebuild model ONLY if dirty i.e. an outline name was changed on save vector os{mind->getOutlines()}; Outline::sortByName(os); vector outlines{os.begin(),os.end()}; - findOutlineByTagDialog->show(outlines); + findOutlineByTagDialog->show(outlines, nullptr, nullptr, tag); } void MainWindowPresenter::handleFindOutlineByTag() @@ -2015,12 +1998,6 @@ void MainWindowPresenter::handleRunTool() ); // RUN tool - if(selectedTool == TOOL_H2O_GPT_API) { - // TODO: sniff HTTP traffic and use HTTP client/JSon to talk to the service - MF_DEBUG("H2O GPT API not implemented yet"); - return; - } - QDesktopServices::openUrl(QUrl{command}); } @@ -2154,11 +2131,6 @@ void MainWindowPresenter::doActionStackOverflowToolbar() handleLeftToolbarAction(TOOL_STACK_OVERFLOW); } -void MainWindowPresenter::doActionH2oGptToolbar() -{ - handleLeftToolbarAction(TOOL_H2O_GPT_WEB); -} - void MainWindowPresenter::doActionDuckDuckGoToolbar() { handleLeftToolbarAction(TOOL_DUCKDUCKGO); @@ -2174,16 +2146,6 @@ void MainWindowPresenter::doActionBardToolbar() handleLeftToolbarAction(TOOL_GOOGLE_BARD); } -void MainWindowPresenter::doActionPythonToolbar() -{ - handleLeftToolbarAction(TOOL_DOC_PYTHON); -} - -void MainWindowPresenter::doActionCppToolbar() -{ - handleLeftToolbarAction(TOOL_DOC_CPP); -} - void MainWindowPresenter::handleLeftToolbarAction(string selectedTool) { // get PHRASE from the active context: @@ -2245,12 +2207,6 @@ void MainWindowPresenter::handleLeftToolbarAction(string selectedTool) // phrase replace @ template > get command, if invalid, then fallback QString command = templateText.replace(QString{TOOL_PHRASE}, phrase); MF_DEBUG("Run tool: command '" << command.toStdString() << "'" << endl); - if(selectedTool == TOOL_H2O_GPT_API) { - // TODO: sniff HTTP traffic and use HTTP client/JSon to talk to the service - MF_DEBUG("H2O GPT API not implemented yet"); - return; - } - QDesktopServices::openUrl(QUrl{command}); } diff --git a/app/src/qt/main_window_presenter.h b/app/src/qt/main_window_presenter.h index bfad20c9..b730923d 100644 --- a/app/src/qt/main_window_presenter.h +++ b/app/src/qt/main_window_presenter.h @@ -218,12 +218,12 @@ public slots: // recall void doActionFts(); void doFts(const QString& pattern, bool doSearch=false); - void doActionFindOutlineByName(); + void doActionFindOutlineByName(const std::string& phrase=""); void handleFindOutlineByName(); void handleFindThingByName(); void doActionFindNoteByName(); void handleFindNoteByName(); - void doActionFindOutlineByTag(); + void doActionFindOutlineByTag(const std::string& tag=""); void handleFindOutlineByTag(); void doActionFindNoteByTag(); void doTriggerFindNoteByTag(const m8r::Tag* tag); @@ -311,7 +311,7 @@ public slots: void doActionFormatTocWithoutTags(); void doActionFormatTimestamp(); void doActionFormatCodeBlock(); - void doActionFormatMathBlock(); + void doActionFormatMathBlock(); void doActionFormatDiagramBlock(); void doActionFormatDiagramPie(); void doActionFormatDiagramFlow(); @@ -376,12 +376,9 @@ public slots: void doActionArxivToolbar(); void doActionWikipediaToolbar(); void doActionStackOverflowToolbar(); - void doActionH2oGptToolbar(); void doActionDuckDuckGoToolbar(); void doActionGitHubToolbar(); void doActionBardToolbar(); - void doActionPythonToolbar(); - void doActionCppToolbar(); // help void doActionHelpDocumentation(); void doActionHelpWeb(); diff --git a/app/src/qt/widgets/edit_tags_panel.h b/app/src/qt/widgets/edit_tags_panel.h index efa26b59..e2ca1236 100644 --- a/app/src/qt/widgets/edit_tags_panel.h +++ b/app/src/qt/widgets/edit_tags_panel.h @@ -74,6 +74,9 @@ class EditTagsPanel : public QGroupBox ~EditTagsPanel(); QLineEdit* getLineEdit() const { return lineEdit; } + void setTagToFind(const std::string& tagAsText) { + lineEdit->setText(QString::fromStdString(tagAsText)); + } void clearTagList(); void refreshOntologyTags(); void refresh(const std::vector* noteTags); diff --git a/build/Makefile b/build/Makefile index 5fe13bb5..a59bf6c3 100644 --- a/build/Makefile +++ b/build/Makefile @@ -18,7 +18,11 @@ .DEFAULT_GOAL := help -MINDFORGER_VERSION := 1.55.1 +# +# variables +# + +MINDFORGER_VERSION := 2.0.0 MINDFORGER_RELEASE_BASE_DIR := /home/dvorka/p/mindforger/release MINDFORGER_RELEASE_DIR := $(MINDFORGER_RELEASE_BASE_DIR)/$(MINDFORGER_VERSION)-maker @@ -31,38 +35,22 @@ MF_LANG := "en" # Ubuntu distro: trusty xenial bionic focal jammy kinetic DISTRO := "bionic" + +# +# targets +# + + .PHONY: help -help: +help: ## make targets help @echo "MindForger Swiss knife help:" - @echo "clean clean build artifacts" - @echo "build production build MindForger application binary" - @echo "build-dev development build of MindForger application binary" - @echo "build-ci CI build MindForger application binary" - @echo "run run production MindForger" - @echo "run-dev run development MindForger" - @echo "l10n update and release localization strings: MF_LANG=en" - @echo "gen-lib-class generate lib C++ class skeleton: CLASS_NAME=My_Class" - @echo "gen-ui-class generate UI C++ class skeleton: CLASS_NAME=My_Class" - @echo "test-lib compile and run lib/ unit tests" - @echo "test-app compile and run app/ integration tests" - @echo "dist-all build all distributions" - @echo "dist-tarball build tarball distribution" - @echo "dist-deb build Debian distribution" - @echo "dist-rpm build .rpm package on Fedora" - @echo "dist-dmg build macOS Disk iMaGe .dmg package" - @echo "dist-debian-ppa add .deb to aptly PPA" - @echo "dist-ubuntu-deb locally build .deb for any Ubuntu version:" - @echo "dist-snap build snap distro for snapcraft.io" - @echo " DISTRO=focal" - @echo "doc-to-wiki mindforger-documentation to mindforger.wiki" - @echo "api-reference generate Doxygen documentation" - @echo "statistic show source code statistic" - @echo "git-subs-update update git submodules" - @echo "dev-install-local compile and install binary to ~/bin as MIND" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \ + | sort \ + | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' .PHONY: clean -clean: +clean: ## clean build artifacts rm -vf ../app/mindforger rm -vf ../lib/libmindforger.a rm -vf ../lib/test/src/mindforger-lib-unit-tests @@ -70,19 +58,24 @@ clean: cd ../lib/test && make clean +.PHONY: clean-app +clean-app: + rm -vf ../app/mindforger + + .PHONY: git-subs-update -git-subs-update: +git-subs-update: ## update Git submodules cd .. && git submodule update --init --recursive .PHONY: gen-lib-class -gen-lib-class: +gen-lib-class: ## generate lib C++ class skeleton: CLASS_NAME=My_Class @echo "Generating lib C++ class for name: $(CLASS_NAME)" ./make/gen-cpp-class.py $(CLASS_NAME) .PHONY: gen-ui-class -gen-ui-class: +gen-ui-class: ## generate UI C++ class skeleton: CLASS_NAME=My_Class @echo "Generating UI C++ class for name: $(CLASS_NAME)" ./make/gen-cpp-ui-class.py $(CLASS_NAME) @@ -99,12 +92,12 @@ gen-ui-class: ls -al ../app/mindforger -build: ../app/mindforger +build: clean-app ../app/mindforger ## build production MindForger application binary ls -al ../app/mindforger .PHONY: build-dev -build-dev: +build-dev: clean-app ## build development MindForger application binary @echo "Building DEV MindForger executable..." cd .. && qmake -r mindforger.pro DEFINES+=DO_MF_DEBUG && make -j 7 ; cd .. @echo "If build succeeded, then MindForger executable can be found in:\n app/mindforger" @@ -115,7 +108,7 @@ build-dev: .PHONY: build-rc -build-rc: +build-rc: clean-app ## build RC MindForger application binary @echo "MindForger RC build..." cd .. && qmake CONFIG+=mfrc -r mindforger.pro && make -j 7 @echo "If RC build succeeded, then MindForger executable can be found in:\n app/mindforger" @@ -123,7 +116,7 @@ build-rc: .PHONY: build-ci -build-ci: +build-ci: clean-app ## build CI MindForger application binary @echo "MindForger CI build..." cd .. && qmake CONFIG+=mfci -r mindforger.pro && make -j 7 @echo "If CI build succeeded, then MindForger executable can be found in:\n app/mindforger" @@ -131,26 +124,26 @@ build-ci: # -# build +# run # -run: ../app/mindforger +run: ../app/mindforger ## run production MindForger # cd ../app && pwd && ./mindforger cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/library-trainer # cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/computer-hw.md # cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/bug-copy-image -run-rc: build-rc +run-rc: build-rc ## run MindForger RC build cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/library-trainer -run-ci: build-ci +run-ci: build-ci ## run MindForger CI build cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/library-trainer -run-dev: build-dev +run-dev: build-dev ## run MindForger development build cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/library-trainer # cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/computer-hw.md # cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/bug-copy-image @@ -160,14 +153,7 @@ run-dev: build-dev # install # - -install: clean ../app/mindforger - cp -vf ../app/mindforger ~/bin - mv -vf ~/bin/mindforger ~/bin/mind - ~/bin/mind --version - - -install-dev-local: clean build-rc +install-dev-local: clean build-rc ## install MindForger RC build to ~/bin as 'mind' executable cp -vf ../app/mindforger ~/bin mv -vf ~/bin/mindforger ~/bin/mind ~/bin/mind --version @@ -179,16 +165,16 @@ install-dev-local: clean build-rc .PHONY: l10n -l10n: +l10n: ## update and release localization strings: MF_LANG=en cd make && ./l10n-update-strings.sh && ./l10n-edit-and-release.sh $(MF_LANG) .PHONY: ver-find -ver-find: +ver-find: ## pre-version update finder cd .. && git grep "1\.55" -test-lib: clean +test-lib: clean ## compile and run lib/ unit tests cd make && ./test-lib-units.sh @@ -205,14 +191,14 @@ $(MINDFORGER_RELEASE_DIR): mkdir -v $(MINDFORGER_RELEASE_DIR) || echo "$(MINDFORGER_RELEASE_DIR) already exists" -dist-tarball: dist-work-clean $(MF_MAKER_WORKING_DIR) $(MINDFORGER_RELEASE_DIR) +dist-tarball: dist-work-clean $(MF_MAKER_WORKING_DIR) $(MINDFORGER_RELEASE_DIR) ## build tarball distribution @echo "Building TARBALL distribution..." mkdir -vp $(MF_MAKER_WORKING_DIR) cp -vf ./tarball/tarball-build.sh $(MF_MAKER_WORKING_DIR) && cd $(MF_MAKER_WORKING_DIR) && ./tarball-build.sh cp -vf $(MF_MAKER_WORKING_DIR)/`cd $(MF_MAKER_WORKING_DIR) && ls -d mindforger*`/mindforger_$(MINDFORGER_VERSION)_tarball.tgz $(MINDFORGER_RELEASE_DIR) -dist-deb: dist-work-clean $(MF_MAKER_WORKING_DIR) $(MINDFORGER_RELEASE_DIR) +dist-deb: dist-work-clean $(MF_MAKER_WORKING_DIR) $(MINDFORGER_RELEASE_DIR) ## build Debian distribution @echo "Building DEB distribution..." mkdir -vp $(MF_MAKER_WORKING_DIR) cp -vf ./debian/debian-make-deb.sh $(MF_MAKER_WORKING_DIR) && cd $(MF_MAKER_WORKING_DIR) && ./debian-make-deb.sh @@ -220,7 +206,7 @@ dist-deb: dist-work-clean $(MF_MAKER_WORKING_DIR) $(MINDFORGER_RELEASE_DIR) .PHONY: dist-rpm -dist-rpm: +dist-rpm: ## build .rpm package on Fedora @echo "IMPORTANT: this target MUST be run on Fedora!" cd fedora && ./fedora-distro-setup.sh @echo "Building .rpm package..." @@ -229,18 +215,18 @@ dist-rpm: .PHONY: dist-dmg -dist-dmg: +dist-dmg: ## build macOS Disk iMaGe .dmg package @echo "Building .dmg package..." cd macos && ./mindforger-build.sh && ./dmg-package-build.sh .PHONY: dist-debian-ppa -dist-debian-ppa: +dist-debian-ppa: ## add .deb to aptly PPA cd debian && ./debian-aptly-add-deb.sh .PHONY: dist-ubuntu-deb -dist-ubuntu-deb: +dist-ubuntu-deb: ## locally build .deb for any Ubuntu version: DISTRO=bionic @echo "Building Ubuntu $(DISTRO) .deb ..." @echo "Copying latest version of .sh script to launchpad/ ..." @echo "Running .sh script ..." @@ -249,7 +235,7 @@ dist-ubuntu-deb: .PHONY: dist-snap -dist-snap: +dist-snap: ## build snap distro for snapcraft.io @echo "Building Snap ..." cd .. && make clean && cd build cp -vf snap/snapcraft.yaml .. && cd .. && snapcraft clean && snapcraft --debug @@ -266,22 +252,22 @@ dist-all-clean: rm -rvf $(MINDFORGER_RELEASE_DIR) -dist-all: dist-all-clean $(MINDFORGER_RELEASE_DIR) dist-tarball dist-deb +dist-all: dist-all-clean $(MINDFORGER_RELEASE_DIR) dist-tarball dist-deb ## build all distributions @echo "Building all $(MINDFORGER_VERSION) distributions" .PHONY: statistic -statistic: +statistic: ## show source code statistic cd make && ./statistic.sh .PHONY: doc-to-wiki -doc-to-wiki: +doc-to-wiki: ## mindforger-documentation to mindforger.wiki cd doc && ./mf-doc-to-wiki.py .PHONY: api-reference -api-reference: +api-reference: ## generate Doxygen source code documentation cd doxygen && doxygen ./mindforger.cfg # eof diff --git a/lib/src/config/configuration.h b/lib/src/config/configuration.h index 5f847f52..3fb79e7c 100644 --- a/lib/src/config/configuration.h +++ b/lib/src/config/configuration.h @@ -111,12 +111,8 @@ constexpr const auto TOOL_GH_REPOS = "GitHub repositories"; constexpr const auto TOOL_GH_TOPICS = "GitHub topics"; constexpr const auto TOOL_GOOGLE_BARD = "Google Bard"; constexpr const auto TOOL_GOOGLE_SEARCH = "Google Search"; -constexpr const auto TOOL_H2O_GPT_WEB = "h2oGPT web"; -constexpr const auto TOOL_H2O_GPT_API = "h2oGPT API"; constexpr const auto TOOL_CHAT_GPT_WEB = "OpenAI chatGPT web"; constexpr const auto TOOL_WIKIPEDIA = "Wikipedia"; -constexpr const auto TOOL_DOC_PYTHON = "Python documentation"; -constexpr const auto TOOL_DOC_CPP = "C++ documentation"; // improve platform/language specific constexpr const auto DEFAULT_NEW_OUTLINE = "# New Markdown File\n\nThis is a new Markdown file created by MindForger.\n\n#Section 1\nThe first section.\n\n"; @@ -243,7 +239,7 @@ class Configuration { // configured Mind state where user wants Mind to be MindState desiredMindState; // current Mind state on the way to desired state - MindState mindState; + MindState mindState; // if count(N) > asyncMindTreshold then long-running mind computations should be run in async unsigned int asyncMindThreshold; @@ -477,7 +473,7 @@ class Configuration { void setUiEditorLiveSpellCheck(bool enable) { uiEditorLiveSpellCheck= enable; } std::string getUiEditorSpellCheckDefaultLanguage() const { return uiEditorSpellCheckLanguage; - } + } void setUiEditorSpellCheckDefaultLanguage(std::string lang) { uiEditorSpellCheckLanguage = lang; } diff --git a/lib/src/mind/ai/llm/wingman.h b/lib/src/mind/ai/llm/wingman.h index 74ce4b18..0d5b8c7e 100644 --- a/lib/src/mind/ai/llm/wingman.h +++ b/lib/src/mind/ai/llm/wingman.h @@ -23,6 +23,9 @@ namespace m8r { +/** + * Wingman is a class that provides a set of LLM-based use cases. +*/ class Wingman { public: @@ -48,7 +51,7 @@ class Wingman void fix_grammar(std::string grammar); void fix_spelling(std::string spelling); void fix_style(std::string style); - + void translate(std::string text); void summarize(std::string text); diff --git a/lib/src/mind/knowledge_graph.h b/lib/src/mind/knowledge_graph.h index 4edd1050..cc1686b0 100644 --- a/lib/src/mind/knowledge_graph.h +++ b/lib/src/mind/knowledge_graph.h @@ -123,11 +123,11 @@ class KnowledgeGraph public: explicit KnowledgeGraph( - Mind* mind, - long unsigned mindColor=0x008C00, - long unsigned coreColor=0x000000, - long unsigned outlinesColor=0x220000, - long unsigned notesColor=0x000022); + Mind* mind, + long unsigned mindColor=0x008C00, + long unsigned coreColor=0x000000, + long unsigned outlinesColor=0x220000, + long unsigned notesColor=0x000022); KnowledgeGraph(const KnowledgeGraph&) = delete; KnowledgeGraph(const KnowledgeGraph&&) = delete; KnowledgeGraph &operator=(const KnowledgeGraph&) = delete; diff --git a/lib/src/mind/mind.cpp b/lib/src/mind/mind.cpp index fca6e025..5098ae3c 100644 --- a/lib/src/mind/mind.cpp +++ b/lib/src/mind/mind.cpp @@ -977,8 +977,8 @@ string Mind::outlineMapKey2Relative(const string& outlineKey) const string Mind::outlineMapKey2Absolute(const string& outlineKey) const { string resolvedKey{ - config.getMemoryPath() - + FILE_PATH_SEPARATOR + config.getMemoryPath() + + FILE_PATH_SEPARATOR + outlineKey }; MF_DEBUG(" " << resolvedKey << endl); @@ -1051,7 +1051,7 @@ void Mind::outlinesMapSynchronize(Outline* outlinesMap) MF_DEBUG("DONE O links validity check" << endl); if(osToRemove.size()) { - MF_DEBUG("Removing Ns with INVALID O key:" << endl); + MF_DEBUG("Removing Ns with INVALID O key:" << endl); for(auto oToRemove:osToRemove) { MF_DEBUG(" " << oToRemove->getName() << endl); delete oToRemove; @@ -1143,7 +1143,7 @@ Outline* Mind::outlinesMapLearn(string outlineKey) } if(osToRemove.size()) { - MF_DEBUG("Removing Ns with MISSING relative O key:" << endl); + MF_DEBUG("Removing Ns with MISSING relative O key:" << endl); for(auto oToRemove:osToRemove) { MF_DEBUG(" " << oToRemove->getName() << endl); delete oToRemove; @@ -1187,6 +1187,8 @@ Outline* Mind::outlinesMapRemember() if(this->outlinesMap) { remind().getPersistence().save(this->outlinesMap); } + + return this->outlinesMap; } Note* Mind::noteNew(