1 /*
2  cli_n_breadcrumbs_presenter.cpp     MindForger thinking notebook
3 
4  Copyright (C) 2016-2020 Martin Dvorak <martin.dvorak@mindforger.com>
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License
8  as published by the Free Software Foundation; either version 2
9  of the License, or (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "cli_n_breadcrumbs_presenter.h"
20 
21 using namespace std;
22 
23 namespace m8r {
24 
CliAndBreadcrumbsPresenter(MainWindowPresenter * mainPresenter,CliAndBreadcrumbsView * view,Mind * mind)25 CliAndBreadcrumbsPresenter::CliAndBreadcrumbsPresenter(
26         MainWindowPresenter* mainPresenter,
27         CliAndBreadcrumbsView* view,
28         Mind* mind)
29     : mainPresenter(mainPresenter), view(view), mind(mind)
30 {
31     // widgets
32     view->setVisible(Configuration::getInstance().isUiShowBreadcrump());
33 
34     // wire signals
35     QObject::connect(
36         view->cli, SIGNAL(returnPressed()),
37         this, SLOT(executeCommand()));
38     QObject::connect(
39         view->cli, SIGNAL(textChanged(QString)),
40         this, SLOT(handleCliTextChanged(QString)));
41 }
42 
handleCliTextChanged(const QString & text)43 void CliAndBreadcrumbsPresenter::handleCliTextChanged(const QString& text)
44 {
45     // IMPROVE remove parameter text if it's not needed
46     UNUSED_ARG(text);
47 
48     QString command = view->getCommand();
49     if(command.size()) {
50         if(command.startsWith(CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME)) {
51             QString prefix(QString::fromStdString(
52                  command.toStdString().substr(CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME.size()-1)));
53             if(prefix.size()) {
54                 mainPresenter->getStatusBar()->showInfo(prefix);
55                 if(prefix.size()==1) {
56                     // switch suggestions model
57                     vector<string> outlineNames;
58                     mind->getOutlineNames(outlineNames);
59                     QStringList outlineNamesCompletion = QStringList();
60                     if(outlineNames.size()) {
61                         QString qs;
62                         for(const string s:outlineNames) {
63                             qs.clear();
64                             // TODO commands are constants
65                             qs += CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME;
66                             qs += QString::fromStdString(s);
67                             outlineNamesCompletion << qs;
68                         }
69                     }
70                     view->updateCompleterModel(&outlineNamesCompletion);
71                 } else {
72                 }
73             } else {
74                 view->updateCompleterModel();
75             }
76             return;
77         }
78     }
79 
80     // fallback
81     view->forceFtsHistoryCompletion();
82 }
83 
84 // TODO i18n
executeCommand()85 void CliAndBreadcrumbsPresenter::executeCommand()
86 {
87     QString command = view->getCommand();
88     if(command.size()) {
89         view->addCompleterItem(command);
90 
91         if(command.startsWith(CliAndBreadcrumbsView::CMD_FTS)) {
92             executeFts(command);
93             view->showBreadcrumb();
94             return;
95         }
96         if(command.startsWith(CliAndBreadcrumbsView::CMD_LIST_OUTLINES)) {
97             executeListOutlines();
98             view->showBreadcrumb();
99             return;
100         }
101         if(command.startsWith(CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME)) {
102             string name = command.toStdString().substr(
103                 CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME.size());
104             unique_ptr<vector<Outline*>> outlines = mind->findOutlineByNameFts(name);
105             if(!outlines || !outlines->size()) {
106                 // IMPROVE memory leak if outlines && !outlines->size()
107                 QString firstCompletion = view->getFirstCompletion();
108                 if(firstCompletion != QString::null) {
109                     name = view->getFirstCompletion().toStdString().substr(
110                         CliAndBreadcrumbsView::CMD_FIND_OUTLINE_BY_NAME.size());
111                     outlines = mind->findOutlineByNameFts(name);
112                 }
113             }
114             if(outlines && outlines->size()) {
115                 mainPresenter->getOrloj()->showFacetOutline(outlines->front());
116                 // TODO efficient
117                 mainPresenter->getStatusBar()->showInfo(tr("Notebook ")+QString::fromStdString(outlines->front()->getName()));
118             } else {
119                 mainPresenter->getStatusBar()->showInfo(tr("Notebook not found: ") += QString(name.c_str()));
120             }
121             view->showBreadcrumb();
122             return;
123         }
124 
125         // do FTS as fallback
126         mainPresenter->doFts(view->getCommand(), true);
127     } else {
128         mainPresenter->getStatusBar()->showError(tr("No command!"));
129     }
130 }
131 
executeFts(QString & command)132 void CliAndBreadcrumbsPresenter::executeFts(QString& command)
133 {
134     string searchedString = command.toStdString().substr(
135          CliAndBreadcrumbsView::CMD_FTS.size());
136     if(!searchedString.empty()) {
137         mainPresenter->doFts(QString::fromStdString(searchedString), true);
138     }
139 }
140 
executeListOutlines()141 void CliAndBreadcrumbsPresenter::executeListOutlines()
142 {
143     mainPresenter->getOrloj()->showFacetOutlineList(mind->getOutlines());
144 }
145 
146 // TODO call main window handler
executeListNotes()147 void CliAndBreadcrumbsPresenter::executeListNotes()
148 {
149     if(mainPresenter->getOrloj()->isFacetActive(OrlojPresenterFacets::FACET_VIEW_OUTLINE)
150          ||
151        mainPresenter->getOrloj()->isFacetActive(OrlojPresenterFacets::FACET_VIEW_OUTLINE_HEADER)
152          ||
153        mainPresenter->getOrloj()->isFacetActive(OrlojPresenterFacets::FACET_EDIT_OUTLINE_HEADER)
154          ||
155        mainPresenter->getOrloj()->isFacetActive(OrlojPresenterFacets::FACET_VIEW_NOTE)
156          ||
157        mainPresenter->getOrloj()->isFacetActive(OrlojPresenterFacets::FACET_EDIT_NOTE)
158     ) {
159         Outline* o = mainPresenter->getOrloj()->getOutlineView()->getCurrentOutline();
160         if(o) {
161             auto notes = o->getNotes();
162             // TODO push notes to CLI completer > filter > ENTER outline's note in view
163             if(!notes.empty()) {
164                 mainPresenter->getOrloj()->showFacetNoteEdit(notes.front());
165             }
166         }
167 
168         // TODO show note on enter (actions handler)
169         mainPresenter->getStatusBar()->showInfo(QString("Listing notes..."));
170         return;
171     }
172     // else show all notes in MF (scalability?)
173     mainPresenter->getStatusBar()->showInfo(QString("No notes to list!"));
174 }
175 
176 }
177