1 /*
2  outline_header_view_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 "outline_header_view_presenter.h"
20 
21 #include "look_n_feel.h"
22 
23 namespace m8r {
24 
25 using namespace std;
26 
OutlineHeaderViewPresenter(OutlineHeaderView * view,OrlojPresenter * orloj)27 OutlineHeaderViewPresenter::OutlineHeaderViewPresenter(
28         OutlineHeaderView* view,
29         OrlojPresenter* orloj)
30 {
31     this->view = view;
32     this->orloj = orloj;
33 
34     this->htmlRepresentation
35         = orloj->getMainPresenter()->getHtmlRepresentation();
36 
37     // IMPORTANT: pre-allocate string using reserve() to ensure good append performance
38     html = string{};
39     html.reserve(10000);
40 
41 #ifdef MF_QT_WEB_ENGINE
42     QObject::connect(
43         view->getViever()->getPage(), SIGNAL(signalLinkClicked(QUrl)),
44         this, SLOT(slotLinkClicked(QUrl)));
45 #else
46     QObject::connect(
47         view->getViever(), SIGNAL(linkClicked(QUrl)),
48         this, SLOT(slotLinkClicked(QUrl)));
49 #endif
50     QObject::connect(
51         view->getViever(), SIGNAL(signalMouseDoubleClickEvent()),
52         this, SLOT(slotEditOutlineHeader()));
53     QObject::connect(
54         view, SIGNAL(signalOpenEditor()),
55         this, SLOT(slotEditOutlineHeader()));
56     QObject::connect(
57         view->getViever(), SIGNAL(signalFromViewOutlineHeaderToOutlines()),
58         orloj, SLOT(slotShowOutlines()));
59 }
60 
refreshLivePreview()61 void OutlineHeaderViewPresenter::refreshLivePreview()
62 {
63     MF_DEBUG("Refreshing O header HTML preview from editor: " << currentOutline->getName() << endl);
64 
65     // O w/ current editor text w/o saving it
66     Outline auxOutline{*currentOutline};
67     auxOutline.setKey(currentOutline->getKey());
68     auxOutline.setName(orloj->getOutlineHeaderEdit()->getView()->getName().toStdString());
69 
70     QString description = orloj->getOutlineHeaderEdit()->getView()->getDescription();
71     string s{description.toStdString()};
72     vector<string*> d{};
73     orloj->getMainPresenter()->getMarkdownRepresentation()->description(&s, d);
74     auxOutline.setDescription(d);
75 
76     double yScrollPct{0};
77     QScrollBar* scrollbar = orloj->getOutlineHeaderEdit()->getView()->getHeaderEditor()->verticalScrollBar();
78 #if defined(_WIN32) || defined(__DragonFly__)
79     // WebEngine: scroll to same pct view
80     if(scrollbar) {
81         if(scrollbar->maximum()) {
82             // scroll: QWebEngine API for scrolling is not available - JavaScript must be used instead (via signal)
83             yScrollPct =
84                 static_cast<double>(scrollbar->value())
85                     /
86                 (static_cast<double>(scrollbar->maximum())/100.0);
87         }
88     }
89 #endif
90 
91     // refresh O header HTML view (autolinking intentionally disabled)
92     htmlRepresentation->to(
93         &auxOutline,
94         &html,
95         false,
96         false,
97         false,
98         true,
99         static_cast<int>(yScrollPct)
100     );
101     view->setHtml(QString::fromStdString(html));
102 
103     // IMPROVE share code between O header and N
104 #if not defined(__DragonFly__) && not defined(_WIN32)
105     // WebView: scroll to same pct view
106     if(scrollbar) {
107         if(scrollbar->maximum()) {
108             yScrollPct =
109                 static_cast<double>(scrollbar->value())
110                     /
111                 (static_cast<double>(scrollbar->maximum())/100.0);
112             // scroll
113             QWebFrame* webFrame=view->getViever()->page()->mainFrame();
114             webFrame->setScrollPosition(QPoint(
115                 0,
116                 static_cast<int>((webFrame->scrollBarMaximum(Qt::Orientation::Vertical)/100.0)*yScrollPct)));
117         }
118     }
119 #endif
120 }
121 
refresh(Outline * outline)122 void OutlineHeaderViewPresenter::refresh(Outline* outline)
123 {
124     currentOutline = outline;
125 
126     // IMPROVE consider TOC injection
127     htmlRepresentation->to(
128         outline,
129         &html,
130         false,
131         Configuration::getInstance().isAutolinking(),
132         Configuration::getInstance().isUiFullOPreview(),
133         true
134     );
135 
136     view->setHtml(QString::fromStdString(html));
137 
138     // leaderboard
139     orloj->getMind()->associate();
140 }
141 
slotLinkClicked(const QUrl & url)142 void OutlineHeaderViewPresenter::slotLinkClicked(const QUrl& url)
143 {
144     orloj->getMainPresenter()->handleNoteViewLinkClicked(url);
145 }
146 
slotEditOutlineHeader()147 void OutlineHeaderViewPresenter::slotEditOutlineHeader()
148 {
149     orloj->showFacetOutlineHeaderEdit(currentOutline);
150 }
151 
slotRefreshHeaderLeaderboardByValue(AssociatedNotes * associations)152 void OutlineHeaderViewPresenter::slotRefreshHeaderLeaderboardByValue(AssociatedNotes* associations)
153 {
154     if(orloj->isFacetActive(OrlojPresenterFacets::FACET_VIEW_OUTLINE_HEADER)
155          ||
156        orloj->isFacetActive(OrlojPresenterFacets::FACET_VIEW_OUTLINE)
157          ||
158        orloj->isFacetActive(OrlojPresenterFacets::FACET_EDIT_OUTLINE_HEADER)) // leaderboard for edit @ view
159     {
160         orloj->getOutlineView()->getAssocLeaderboard()->refresh(associations);
161         delete associations;
162     }
163 }
164 
165 } // m8r namespace
166