Engauge Digitizer  2
ChecklistGuideBrowser.cpp
1 /******************************************************************************************************
2  * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3  * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5  ******************************************************************************************************/
6 
7 #include "ChecklistGuideBrowser.h"
8 #include "ChecklistTemplate.h"
9 #include "CmdMediator.h"
10 #include "Document.h"
11 #include "EngaugeAssert.h"
12 #include "Logger.h"
13 #include <QDebug>
14 
15 const int MIN_WIDTH_BROWSER = 340; // Make just big enough that each "More..." appears on same line
16 
18 {
19  setOpenLinks (false); // Disable automatic link following
20  setMinimumWidth(MIN_WIDTH_BROWSER);
21 
22  connect (this, SIGNAL (anchorClicked (const QUrl &)), this, SLOT (slotAnchorClicked (const QUrl &)));
23 }
24 
25 QString ChecklistGuideBrowser::ahref (QString &html,
26  const QString &name) const
27 {
28  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::bindToDocument";
29 
30  QString expression = QString ("%1%2%3")
31  .arg (TAG_AHREF_DELIMITER_START)
32  .arg (name)
33  .arg (TAG_AHREF_DELIMITER_END);
34 
35  QString link;
36  if (name == m_anchor) {
37 
38  // Click on this hyperlink to reload the page without details under this link, since anchor is empty
39  link = QString ("<a href=""#"">Less ...</a>");
40 
41  } else {
42 
43  // Click on this hyperlink to reload the page with details under this link
44  link = QString ("<a href=""#%1"">More ...</a>")
45  .arg (name);
46 
47  }
48 
49  html.replace (expression, link);
50 
51  return html;
52 }
53 
54 void ChecklistGuideBrowser::check (QString &html,
55  const QString &anchor,
56  bool isChecked) const
57 {
58  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::check";
59 
60  QString tag = QString ("%1%2%3")
61  .arg (TAG_ANCHOR_DELIMITER_START)
62  .arg (anchor)
63  .arg (TAG_ANCHOR_DELIMITER_END);
64 
65  if (isChecked) {
66  html.replace (tag, "<img src="":/engauge/img/16-checked.png"">");
67  } else {
68  html.replace (tag, "<img src="":/engauge/img/16-unchecked.png"">");
69  }
70 }
71 
72 void ChecklistGuideBrowser::divHide (QString &html,
73  const QString &anchor) const
74 {
75  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::divHide"
76  << " anchor=" << anchor.toLatin1().data();
77 
78  // Remove everything between the start and end tags, inclusive
79  QString expression = QString ("\\%1%2\\%3.*\\%4%5\\%6")
80  .arg (TAG_DIV_DELIMITER_START)
81  .arg (anchor)
82  .arg (TAG_DIV_DELIMITER_END)
83  .arg (TAG_DIV_DELIMITER_START_SLASH)
84  .arg (anchor)
85  .arg (TAG_DIV_DELIMITER_END);
86  QRegExp regExp (expression);
87  html.replace (regExp, "");
88 }
89 
90 void ChecklistGuideBrowser::divShow (QString &html,
91  const QString &anchor) const
92 {
93  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::divShow"
94  << " anchor=" << anchor.toLatin1().data();
95 
96  if (!anchor.isEmpty ()) {
97 
98  // Remove the start and end tags, but leave the text in between
99  QString expressionStart = QString ("\\%1%2\\%3")
100  .arg (TAG_DIV_DELIMITER_START)
101  .arg (anchor)
102  .arg (TAG_DIV_DELIMITER_END);
103  QString expressionEnd = QString ("\\%1%2\\%3")
104  .arg (TAG_DIV_DELIMITER_START_SLASH)
105  .arg (anchor)
106  .arg (TAG_DIV_DELIMITER_END);
107  QRegExp regExpStart (expressionStart);
108  QRegExp regExpEnd (expressionEnd);
109  html.replace (regExpStart, "");
110  html.replace (regExpEnd, "");
111  }
112 }
113 
114 QString ChecklistGuideBrowser::processAhrefs (const QString &htmlBefore)
115 {
116  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::processAhrefs";
117 
118  QString html = htmlBefore;
119 
120  // Background
121  ahref (html, NAME_BACKGROUND);
122 
123  // Fixed axis point hrefs
124  ahref (html, NAME_AXIS1);
125  ahref (html, NAME_AXIS2);
126  ahref (html, NAME_AXIS3);
127 
128  // Curves
129  QStringList::const_iterator itr;
130  for (itr = m_curveNames.begin(); itr != m_curveNames.end(); itr++) {
131 
132  QString curveName = *itr;
133  ahref (html, curveName);
134  }
135 
136  // Export
137  ahref (html, NAME_EXPORT);
138 
139  return html;
140 }
141 
142 QString ChecklistGuideBrowser::processCheckboxes (const QString &htmlBefore)
143 {
144  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::processCheckboxes";
145 
146  QString html = htmlBefore;
147 
148  check (html, NAME_BACKGROUND, m_checkedTags.contains (NAME_BACKGROUND));
149 
150  check (html, NAME_AXIS1, m_checkedTags.contains (NAME_AXIS1));
151  check (html, NAME_AXIS2, m_checkedTags.contains (NAME_AXIS2));
152  check (html, NAME_AXIS3, m_checkedTags.contains (NAME_AXIS3));
153 
154  // Curves
155  QStringList::const_iterator itr;
156  for (itr = m_curveNames.begin(); itr != m_curveNames.end(); itr++) {
157 
158  QString curveName = *itr;
159  check (html, curveName, m_checkedTags.contains (curveName));
160  }
161 
162  check (html, NAME_EXPORT, m_checkedTags.contains (NAME_EXPORT));
163 
164  return html;
165 }
166 
167 QString ChecklistGuideBrowser::processDivs (const QString &htmlBefore)
168 {
169  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::processDivs";
170 
171  QString html = htmlBefore;
172 
173  // Show div associated with anchor. Since this removes the tags, applying divHide below
174  // will have no effect, so we apply divHide to everything
175  divShow (html, m_anchor);
176 
177  // Background
178  divHide (html, NAME_BACKGROUND);
179 
180  // Fixed axis point tags
181  divHide (html, NAME_AXIS1);
182  divHide (html, NAME_AXIS2);
183  divHide (html, NAME_AXIS3);
184 
185  // Curve name tags
186  QStringList::const_iterator itr;
187  for (itr = m_curveNames.begin(); itr != m_curveNames.end(); itr++) {
188 
189  QString curveName = *itr;
190  divHide (html, curveName);
191  }
192 
193  divHide (html, NAME_EXPORT);
194 
195  return html;
196 }
197 
198 void ChecklistGuideBrowser::refresh ()
199 {
200  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::refresh";
201 
202  QString html = m_templateHtml;
203 
204  html = processAhrefs (html);
205  html = processCheckboxes (html);
206  html = processDivs (html);
207 
208  QTextBrowser::setHtml (html);
209 }
210 
211 void ChecklistGuideBrowser::repopulateCheckedTags (const CmdMediator &cmdMediator,
212  bool documentIsExported)
213 {
214  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::repopulateCheckedTags";
215 
216  m_checkedTags.clear();
217 
218  if (cmdMediator.document().curveAxes().numPoints() > 0) {
219  m_checkedTags [NAME_AXIS1] = true;
220  }
221 
222  if (cmdMediator.document().curveAxes().numPoints() > 1) {
223  m_checkedTags [NAME_AXIS2] = true;
224  }
225 
226  if (cmdMediator.document().curveAxes().numPoints() > 2) {
227  m_checkedTags [NAME_AXIS3] = true;
228  }
229 
230  // Curves
231  QStringList::const_iterator itr;
232  for (itr = m_curveNames.begin(); itr != m_curveNames.end(); itr++) {
233 
234  QString curveName = *itr;
235  if (cmdMediator.document().curvesGraphsNumPoints (curveName) > 0) {
236  m_checkedTags [curveName] = true;
237  }
238  }
239 
240  // The export case is very tricky. The modified/dirty flag tells us when there are unsaved points,
241  // but for some reason the value returned by CmdMediator.isModified (which is QUndoStack::isClean)
242  // is often wrong at this point in execution. So we use a different trick - asking MainWindow if file has
243  // been saved
244  if (documentIsExported) {
245  m_checkedTags [NAME_EXPORT] = true;
246  }
247 }
248 
249 void ChecklistGuideBrowser::setTemplateHtml (const QString &html,
250  const QStringList &curveNames)
251 {
252  m_templateHtml = html;
253  m_curveNames = curveNames;
254 
255  refresh();
256 }
257 
258 void ChecklistGuideBrowser::slotAnchorClicked (const QUrl &url)
259 {
260  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::slotAnchorClicked";
261 
262  m_anchor = "";
263  if (url.hasFragment ()) {
264  m_anchor = url.fragment ();
265  }
266 
267  refresh();
268 }
269 
271  bool documentIsExported)
272 {
273  LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideBrowser::update";
274 
275  repopulateCheckedTags(cmdMediator,
276  documentIsExported);
277 
278  refresh();
279 }
int curvesGraphsNumPoints(const QString &curveName) const
See CurvesGraphs::curvesGraphsNumPoints.
Definition: Document.cpp:353
virtual void setTemplateHtml(const QString &html, const QStringList &curveNames)
Populate the browser with template html. The template html will be converted to real html...
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
int numPoints() const
Number of points.
Definition: Curve.cpp:432
void update(const CmdMediator &cmdMediator, bool documentIsExported)
Update using current CmdMediator/Document state.
Command queue stack.
Definition: CmdMediator.h:23
ChecklistGuideBrowser()
Single constructor.
const Curve & curveAxes() const
Get method for axis curve.
Definition: Document.cpp:318