Bug Summary

File:OMEdit/OMEditLIB/Modeling/DocumentationWidget.cpp
Warning:line 370, column 43
Potential leak of memory pointed to by 'pHTMLHighlighter'

Annotated Source Code

[?] Use j/k keys for keyboard navigation

1/*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
14 * ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the Open Source Modelica
17 * Consortium (OSMC) Public License (OSMC-PL) are obtained
18 * from OSMC, either from the above address,
19 * from the URLs: http://www.ida.liu.se/projects/OpenModelica or
20 * http://www.openmodelica.org, and in the OpenModelica distribution.
21 * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
22 *
23 * This program is distributed WITHOUT ANY WARRANTY; without
24 * even the implied warranty of MERCHANTABILITY or FITNESS
25 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
26 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
27 *
28 * See the full OSMC Public License conditions for more details.
29 *
30 */
31/*
32 * @author Adeel Asghar <adeel.asghar@liu.se>
33 */
34
35#include "DocumentationWidget.h"
36#include "MainWindow.h"
37#include "OMC/OMCProxy.h"
38#include "Modeling/LibraryTreeWidget.h"
39#include "Util/Helper.h"
40#include "Util/Utilities.h"
41#include "Editors/HTMLEditor.h"
42#include "Options/OptionsDialog.h"
43#include "Modeling/Commands.h"
44
45#include <QNetworkRequest>
46#include <QNetworkReply>
47#include <QMenu>
48#include <QDesktopServices>
49#include <QApplication>
50#include <QDesktopWidget>
51#include <QWebFrame>
52#include <QWidgetAction>
53#include <QButtonGroup>
54#include <QInputDialog>
55
56/*!
57 * \class DocumentationWidget
58 * \brief Displays the model documentation.
59 */
60/*!
61 * \brief DocumentationWidget::DocumentationWidget
62 * \param pParent
63 */
64DocumentationWidget::DocumentationWidget(QWidget *pParent)
65 : QWidget(pParent)
66{
67 setObjectName("DocumentationWidget");
68 mDocumentationFile.setFileName(Utilities::tempDirectory() + "/DocumentationWidget.html");
69 // documentation toolbar
70 QToolBar *pDocumentationToolBar = new QToolBar;
71 int toolbarIconSize = OptionsDialog::instance()->getGeneralSettingsPage()->getToolbarIconSizeSpinBox()->value();
72 pDocumentationToolBar->setIconSize(QSize(toolbarIconSize, toolbarIconSize));
73 // create the previous action
74 mpPreviousAction = new QAction(QIcon(":/Resources/icons/previous.svg"), tr("Previous (backspace)"), this);
75 mpPreviousAction->setStatusTip(tr("Moves to previous documentation"));
76 mpPreviousAction->setDisabled(true);
77 connect(mpPreviousAction, SIGNAL(triggered())"2""triggered()", SLOT(previousDocumentation())"1""previousDocumentation()");
78 // create the next action
79 mpNextAction = new QAction(QIcon(":/Resources/icons/next.svg"), tr("Next (shift+backspace)"), this);
80 mpNextAction->setStatusTip(tr("Moves to next documentation"));
81 mpNextAction->setDisabled(true);
82 connect(mpNextAction, SIGNAL(triggered())"2""triggered()", SLOT(nextDocumentation())"1""nextDocumentation()");
83 // create the edit info action
84 mpEditInfoAction = new QAction(QIcon(":/Resources/icons/edit-info.svg"), tr("Edit Info Documentation"), this);
85 mpEditInfoAction->setStatusTip(tr("Starts editing info documentation"));
86 mpEditInfoAction->setDisabled(true);
87 connect(mpEditInfoAction, SIGNAL(triggered())"2""triggered()", SLOT(editInfoDocumentation())"1""editInfoDocumentation()");
88 // create the edit revisions action
89 mpEditRevisionsAction = new QAction(QIcon(":/Resources/icons/edit-revisions.svg"), tr("Edit Revisions Documentation"), this);
90 mpEditRevisionsAction->setStatusTip(tr("Starts editing revisions documentation"));
91 mpEditRevisionsAction->setDisabled(true);
92 connect(mpEditRevisionsAction, SIGNAL(triggered())"2""triggered()", SLOT(editRevisionsDocumentation())"1""editRevisionsDocumentation()");
93 // create the edit infoHeader action
94 mpEditInfoHeaderAction = new QAction(QIcon(":/Resources/icons/edit-info-header.svg"), tr("Edit __OpenModelica_infoHeader Documentation"), this);
95 mpEditInfoHeaderAction->setStatusTip(tr("Starts editing __OpenModelica_infoHeader documentation"));
96 mpEditInfoHeaderAction->setDisabled(true);
97 connect(mpEditInfoHeaderAction, SIGNAL(triggered())"2""triggered()", SLOT(editInfoHeaderDocumentation())"1""editInfoHeaderDocumentation()");
98 // create the save action
99 mpSaveAction = new QAction(QIcon(":/Resources/icons/save.svg"), Helper::save, this);
100 mpSaveAction->setStatusTip(tr("Saves the edited documentation"));
101 mpSaveAction->setDisabled(true);
102 connect(mpSaveAction, SIGNAL(triggered())"2""triggered()", SLOT(saveDocumentation())"1""saveDocumentation()");
103 // create the cancel action
104 mpCancelAction = new QAction(QIcon(":/Resources/icons/delete.svg"), Helper::cancel, this);
105 mpCancelAction->setStatusTip(tr("Cancels the documentation editing"));
106 mpCancelAction->setDisabled(true);
107 connect(mpCancelAction, SIGNAL(triggered())"2""triggered()", SLOT(cancelDocumentation())"1""cancelDocumentation()");
108 // add actions to documentation toolbar
109 pDocumentationToolBar->addAction(mpPreviousAction);
110 pDocumentationToolBar->addAction(mpNextAction);
111 pDocumentationToolBar->addSeparator();
112 pDocumentationToolBar->addAction(mpEditInfoAction);
113 pDocumentationToolBar->addAction(mpEditRevisionsAction);
114 pDocumentationToolBar->addAction(mpEditInfoHeaderAction);
115 pDocumentationToolBar->addSeparator();
116 pDocumentationToolBar->addAction(mpSaveAction);
117 pDocumentationToolBar->addAction(mpCancelAction);
118 // create the documentation viewer
119 mpDocumentationViewer = new DocumentationViewer(this, false);
120 mpDocumentationViewerFrame = new QFrame;
121 mpDocumentationViewerFrame->setContentsMargins(0, 0, 0, 0);
122 mpDocumentationViewerFrame->setFrameStyle(QFrame::StyledPanel);
123 QHBoxLayout *pDocumentationViewerLayout = new QHBoxLayout;
124 pDocumentationViewerLayout->setContentsMargins(0, 0, 0, 0);
125 pDocumentationViewerLayout->addWidget(mpDocumentationViewer);
126 mpDocumentationViewerFrame->setLayout(pDocumentationViewerLayout);
127 // create the editors tab widget
128 mpEditorsWidget = new QWidget;
129 mpEditorsWidget->hide();
130 // create a tab bar
131 mpTabBar = new QTabBar;
132 mpTabBar->setContentsMargins(0, 0, 0, 0);
133 mpTabBar->addTab("");
134 mpTabBar->addTab("");
135 connect(mpTabBar, SIGNAL(currentChanged(int))"2""currentChanged(int)", SLOT(toggleEditor(int))"1""toggleEditor(int)");
136 // create the html editor widget
137 mpHTMLEditorWidget = new QWidget;
138 // editor toolbar
139 mpEditorToolBar = new QToolBar;
140 mpEditorToolBar->setIconSize(QSize(toolbarIconSize, toolbarIconSize));
141 // create the html editor viewer
142 mpHTMLEditor = new DocumentationViewer(this, true);
143 mpHTMLEditorFrame = new QFrame;
144 mpHTMLEditorFrame->setContentsMargins(0, 0, 0, 0);
145 mpHTMLEditorFrame->setFrameStyle(QFrame::StyledPanel);
146 QHBoxLayout *pHTMLEditorLayout = new QHBoxLayout;
147 pHTMLEditorLayout->setContentsMargins(0, 0, 0, 0);
148 pHTMLEditorLayout->addWidget(mpHTMLEditor);
149 mpHTMLEditorFrame->setLayout(pHTMLEditorLayout);
150 // editor actions
151 // style combobox
152 mpStyleComboBox = new QComboBox;
153 mpStyleComboBox->setMinimumHeight(toolbarIconSize);
154 mpStyleComboBox->setToolTip(tr("Style"));
155 mpStyleComboBox->setStatusTip(tr("Sets the text style"));
156 mpStyleComboBox->addItem(tr("Normal"), "p");
157 mpStyleComboBox->addItem(tr("Heading 1"), "h1");
158 mpStyleComboBox->addItem(tr("Heading 2"), "h2");
159 mpStyleComboBox->addItem(tr("Heading 3"), "h3");
160 mpStyleComboBox->addItem(tr("Heading 4"), "h4");
161 mpStyleComboBox->addItem(tr("Heading 5"), "h5");
162 mpStyleComboBox->addItem(tr("Heading 6"), "h6");
163 mpStyleComboBox->addItem(tr("Preformatted"), "pre");
164 connect(mpStyleComboBox, SIGNAL(currentIndexChanged(int))"2""currentIndexChanged(int)", SLOT(formatBlock(int))"1""formatBlock(int)");
165 // font combobox
166 mpFontComboBox = new QFontComboBox;
167 mpFontComboBox->setMinimumHeight(toolbarIconSize);
168 mpFontComboBox->setToolTip(tr("Font"));
169 mpFontComboBox->setStatusTip(tr("Sets the text font"));
170 connect(mpFontComboBox, SIGNAL(currentFontChanged(QFont))"2""currentFontChanged(QFont)", SLOT(fontName(QFont))"1""fontName(QFont)");
171 // font combobox
172 mpFontSizeSpinBox = new QSpinBox;
173 mpFontSizeSpinBox->setMinimumHeight(toolbarIconSize);
174 mpFontSizeSpinBox->setToolTip(tr("Font Size"));
175 mpFontSizeSpinBox->setStatusTip(tr("Sets the text font size"));
176 mpFontSizeSpinBox->setMinimum(1);
177 mpFontSizeSpinBox->setMaximum(7);
178// mpFontSizeSpinBox->setSpecialValueText(tr("(Default)"));
179 connect(mpFontSizeSpinBox, SIGNAL(valueChanged(int))"2""valueChanged(int)", SLOT(fontSize(int))"1""fontSize(int)");
180 // bold action
181 mpBoldAction = new QAction(QIcon(":/Resources/icons/bold-icon.svg"), Helper::bold, this);
182 mpBoldAction->setStatusTip(tr("Make your text bold"));
183 mpBoldAction->setShortcut(QKeySequence("Ctrl+b"));
184 mpBoldAction->setCheckable(true);
185 connect(mpBoldAction, SIGNAL(triggered())"2""triggered()", mpHTMLEditor->pageAction(QWebPage::ToggleBold), SLOT(trigger())"1""trigger()");
186 // italic action
187 mpItalicAction = new QAction(QIcon(":/Resources/icons/italic-icon.svg"), Helper::italic, this);
188 mpItalicAction->setStatusTip(tr("Italicize your text"));
189 mpItalicAction->setShortcut(QKeySequence("Ctrl+i"));
190 mpItalicAction->setCheckable(true);
191 connect(mpItalicAction, SIGNAL(triggered())"2""triggered()", mpHTMLEditor->pageAction(QWebPage::ToggleItalic), SLOT(trigger())"1""trigger()");
192 // underline action
193 mpUnderlineAction = new QAction(QIcon(":/Resources/icons/underline-icon.svg"), Helper::underline, this);
194 mpUnderlineAction->setStatusTip(tr("Underline your text"));
195 mpUnderlineAction->setShortcut(QKeySequence("Ctrl+u"));
196 mpUnderlineAction->setCheckable(true);
197 connect(mpUnderlineAction, SIGNAL(triggered())"2""triggered()", mpHTMLEditor->pageAction(QWebPage::ToggleUnderline), SLOT(trigger())"1""trigger()");
198 // strikethrough action
199 mpStrikethroughAction = new QAction(QIcon(":/Resources/icons/strikethrough-icon.svg"), tr("Strikethrough"), this);
200 mpStrikethroughAction->setStatusTip(tr("Cross something out by drawing a line through it"));
201 mpStrikethroughAction->setCheckable(true);
202 connect(mpStrikethroughAction, SIGNAL(triggered())"2""triggered()", mpHTMLEditor->pageAction(QWebPage::ToggleStrikethrough), SLOT(trigger())"1""trigger()");
203 // subscript superscript action group
204 QActionGroup *pSubscriptSuperscriptActionGroup = new QActionGroup(this);
205 pSubscriptSuperscriptActionGroup->setExclusive(true);
206 // subscript action
207 mpSubscriptAction = new QAction(QIcon(":/Resources/icons/subscript-icon.svg"), tr("Subscript"), pSubscriptSuperscriptActionGroup);
208 mpSubscriptAction->setStatusTip(tr("Type very small letters just below the line of text"));
209 mpSubscriptAction->setCheckable(true);
210 connect(mpSubscriptAction, SIGNAL(triggered())"2""triggered()", mpHTMLEditor->pageAction(QWebPage::ToggleSubscript), SLOT(trigger())"1""trigger()");
211 // superscript action
212 mpSuperscriptAction = new QAction(QIcon(":/Resources/icons/superscript-icon.svg"), tr("Superscript"), pSubscriptSuperscriptActionGroup);
213 mpSuperscriptAction->setStatusTip(tr("Type very small letters just above the line of text"));
214 mpSuperscriptAction->setCheckable(true);
215 connect(mpSuperscriptAction, SIGNAL(triggered())"2""triggered()", mpHTMLEditor->pageAction(QWebPage::ToggleSuperscript), SLOT(trigger())"1""trigger()");
216 // text color toobutton
217 mTextColor = Qt::black;
218 mpTextColorDialog = new QColorDialog;
219 mpTextColorDialog->setWindowFlags(Qt::Widget);
220 QMenu *pTextColorMenu = new QMenu;
221 QWidgetAction *pTextColorWidgetAction = new QWidgetAction(this);
222 pTextColorWidgetAction->setDefaultWidget(mpTextColorDialog);
223 pTextColorMenu->addAction(pTextColorWidgetAction);
224 connect(pTextColorMenu, SIGNAL(aboutToShow())"2""aboutToShow()", mpTextColorDialog, SLOT(show())"1""show()");
225 connect(pTextColorMenu, SIGNAL(aboutToHide())"2""aboutToHide()", mpTextColorDialog, SLOT(hide())"1""hide()");
226 connect(mpTextColorDialog, SIGNAL(colorSelected(QColor))"2""colorSelected(QColor)", pTextColorMenu, SLOT(hide())"1""hide()");
227 connect(mpTextColorDialog, SIGNAL(colorSelected(QColor))"2""colorSelected(QColor)", SLOT(applyTextColor(QColor))"1""applyTextColor(QColor)");
228 connect(mpTextColorDialog, SIGNAL(rejected())"2""rejected()", pTextColorMenu, SLOT(hide())"1""hide()");
229 mpTextColorToolButton = new QToolButton;
230 mpTextColorToolButton->setText(tr("Text Color"));
231 mpTextColorToolButton->setToolTip(mpTextColorToolButton->text());
232 mpTextColorToolButton->setStatusTip(tr("Change the color of your text"));
233 mpTextColorToolButton->setMenu(pTextColorMenu);
234 mpTextColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
235 mpTextColorToolButton->setIcon(createPixmapForToolButton(mTextColor, QIcon(":/Resources/icons/text-color-icon.svg")));
236 connect(mpTextColorToolButton, SIGNAL(clicked())"2""clicked()", SLOT(applyTextColor())"1""applyTextColor()");
237 // background color toolbutton
238 mBackgroundColor = Qt::white;
239 mpBackgroundColorDialog = new QColorDialog;
240 mpBackgroundColorDialog->setWindowFlags(Qt::Widget);
241 QMenu *pBackgroundColorMenu = new QMenu;
242 QWidgetAction *pBackgroundColorWidgetAction = new QWidgetAction(this);
243 pBackgroundColorWidgetAction->setDefaultWidget(mpBackgroundColorDialog);
244 pBackgroundColorMenu->addAction(pBackgroundColorWidgetAction);
245 connect(pBackgroundColorMenu, SIGNAL(aboutToShow())"2""aboutToShow()", mpBackgroundColorDialog, SLOT(show())"1""show()");
246 connect(pBackgroundColorMenu, SIGNAL(aboutToHide())"2""aboutToHide()", mpBackgroundColorDialog, SLOT(hide())"1""hide()");
247 connect(mpBackgroundColorDialog, SIGNAL(colorSelected(QColor))"2""colorSelected(QColor)", pBackgroundColorMenu, SLOT(hide())"1""hide()");
248 connect(mpBackgroundColorDialog, SIGNAL(colorSelected(QColor))"2""colorSelected(QColor)", SLOT(applyBackgroundColor(QColor))"1""applyBackgroundColor(QColor)");
249 connect(mpBackgroundColorDialog, SIGNAL(rejected())"2""rejected()", pBackgroundColorMenu, SLOT(hide())"1""hide()");
250 mpBackgroundColorToolButton = new QToolButton;
251 mpBackgroundColorToolButton->setText(tr("Background Color"));
252 mpBackgroundColorToolButton->setToolTip(mpBackgroundColorToolButton->text());
253 mpBackgroundColorToolButton->setStatusTip(tr("Change the color of your text"));
254 mpBackgroundColorToolButton->setMenu(pBackgroundColorMenu);
255 mpBackgroundColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
256 mpBackgroundColorToolButton->setIcon(createPixmapForToolButton(mBackgroundColor, QIcon(":/Resources/icons/background-color-icon.svg")));
257 connect(mpBackgroundColorToolButton, SIGNAL(clicked())"2""clicked()", SLOT(applyBackgroundColor())"1""applyBackgroundColor()");
258 // align left toolbutton
259 mpAlignLeftToolButton = new QToolButton;
260 mpAlignLeftToolButton->setText(tr("Align Left"));
261 mpAlignLeftToolButton->setToolTip(mpAlignLeftToolButton->text());
262 mpAlignLeftToolButton->setStatusTip(tr("Aligns the text to the left"));
263 mpAlignLeftToolButton->setIcon(QIcon(":/Resources/icons/align-left.svg"));
264 mpAlignLeftToolButton->setCheckable(true);
265 mpAlignLeftToolButton->setChecked(true);
266 connect(mpAlignLeftToolButton, SIGNAL(clicked())"2""clicked()", SLOT(alignLeft())"1""alignLeft()");
267 // align center toolbutton
268 mpAlignCenterToolButton = new QToolButton;
269 mpAlignCenterToolButton->setText(tr("Align Center"));
270 mpAlignCenterToolButton->setToolTip(mpAlignCenterToolButton->text());
271 mpAlignCenterToolButton->setStatusTip(tr("Aligns the text to the center"));
272 mpAlignCenterToolButton->setIcon(QIcon(":/Resources/icons/align-center.svg"));
273 mpAlignCenterToolButton->setCheckable(true);
274 connect(mpAlignCenterToolButton, SIGNAL(clicked())"2""clicked()", SLOT(alignCenter())"1""alignCenter()");
275 // align right toolbutton
276 mpAlignRightToolButton = new QToolButton;
277 mpAlignRightToolButton->setText(tr("Align Right"));
278 mpAlignRightToolButton->setToolTip(mpAlignRightToolButton->text());
279 mpAlignRightToolButton->setStatusTip(tr("Aligns the text to the right"));
280 mpAlignRightToolButton->setIcon(QIcon(":/Resources/icons/align-right.svg"));
281 mpAlignRightToolButton->setCheckable(true);
282 connect(mpAlignRightToolButton, SIGNAL(clicked())"2""clicked()", SLOT(alignRight())"1""alignRight()");
283 // justify toolbutton
284 mpJustifyToolButton = new QToolButton;
285 mpJustifyToolButton->setText(tr("Justify"));
286 mpJustifyToolButton->setToolTip(mpJustifyToolButton->text());
287 mpJustifyToolButton->setStatusTip(tr("Justifies the text evenly"));
288 mpJustifyToolButton->setIcon(QIcon(":/Resources/icons/justify.svg"));
289 mpJustifyToolButton->setCheckable(true);
290 connect(mpJustifyToolButton, SIGNAL(clicked())"2""clicked()", SLOT(justify())"1""justify()");
291 // alignment button group
292 QButtonGroup *pAlignmentButtonGroup = new QButtonGroup;
293 pAlignmentButtonGroup->setExclusive(true);
294 pAlignmentButtonGroup->addButton(mpAlignLeftToolButton);
295 pAlignmentButtonGroup->addButton(mpAlignCenterToolButton);
296 pAlignmentButtonGroup->addButton(mpAlignRightToolButton);
297 pAlignmentButtonGroup->addButton(mpJustifyToolButton);
298 // decrease indent action
299 mpDecreaseIndentAction = new QAction(QIcon(":/Resources/icons/decrease-indent.svg"), tr("Decrease Indent"), this);
300 mpDecreaseIndentAction->setStatusTip(tr("Decreases the indent by moving left"));
301 connect(mpDecreaseIndentAction, SIGNAL(triggered())"2""triggered()", mpHTMLEditor->pageAction(QWebPage::Outdent), SLOT(trigger())"1""trigger()");
302 // increase indent action
303 mpIncreaseIndentAction = new QAction(QIcon(":/Resources/icons/increase-indent.svg"), tr("Increase Indent"), this);
304 mpIncreaseIndentAction->setStatusTip(tr("Increases the indent by moving right"));
305 connect(mpIncreaseIndentAction, SIGNAL(triggered())"2""triggered()", mpHTMLEditor->pageAction(QWebPage::Indent), SLOT(trigger())"1""trigger()");
306 // bullet list action
307 mpBulletListAction = new QAction(QIcon(":/Resources/icons/bullet-list.svg"), tr("Bullet List"), this);
308 mpBulletListAction->setStatusTip(tr("Creates a bulleted list"));
309 mpBulletListAction->setCheckable(true);
310 connect(mpBulletListAction, SIGNAL(triggered())"2""triggered()", SLOT(bulletList())"1""bulletList()");
311 // numbered list action
312 mpNumberedListAction = new QAction(QIcon(":/Resources/icons/numbered-list.svg"), tr("Numbered List"), this);
313 mpNumberedListAction->setStatusTip(tr("Creates a numbered list"));
314 mpNumberedListAction->setCheckable(true);
315 connect(mpNumberedListAction, SIGNAL(triggered())"2""triggered()", SLOT(numberedList())"1""numberedList()");
316 // link action
317 mpLinkAction = new QAction(QIcon(":/Resources/icons/link.svg"), tr("Create Link"), this);
318 mpLinkAction->setStatusTip(tr("Creates a link"));
319 mpLinkAction->setEnabled(false);
320 connect(mpLinkAction, SIGNAL(triggered())"2""triggered()", SLOT(createLink())"1""createLink()");
321 // unklink action
322 mpUnLinkAction = new QAction(QIcon(":/Resources/icons/unlink.svg"), tr("Remove Link"), this);
323 mpUnLinkAction->setStatusTip(tr("Removes a link"));
324 mpUnLinkAction->setEnabled(false);
325 connect(mpUnLinkAction, SIGNAL(triggered())"2""triggered()", SLOT(removeLink())"1""removeLink()");
326 // add actions to editor toolbar
327 mpEditorToolBar->addWidget(mpStyleComboBox);
328 mpEditorToolBar->addWidget(mpFontComboBox);
329 mpEditorToolBar->addWidget(mpFontSizeSpinBox);
330 mpEditorToolBar->addAction(mpBoldAction);
331 mpEditorToolBar->addAction(mpItalicAction);
332 mpEditorToolBar->addAction(mpUnderlineAction);
333 mpEditorToolBar->addAction(mpStrikethroughAction);
334 mpEditorToolBar->addAction(mpSubscriptAction);
335 mpEditorToolBar->addAction(mpSuperscriptAction);
336 mpEditorToolBar->addSeparator();
337 mpEditorToolBar->addWidget(mpTextColorToolButton);
338 mpEditorToolBar->addWidget(mpBackgroundColorToolButton);
339 mpEditorToolBar->addSeparator();
340 mpEditorToolBar->addWidget(mpAlignLeftToolButton);
341 mpEditorToolBar->addWidget(mpAlignCenterToolButton);
342 mpEditorToolBar->addWidget(mpAlignRightToolButton);
343 mpEditorToolBar->addWidget(mpJustifyToolButton);
344 mpEditorToolBar->addSeparator();
345 mpEditorToolBar->addAction(mpDecreaseIndentAction);
346 mpEditorToolBar->addAction(mpIncreaseIndentAction);
347 mpEditorToolBar->addSeparator();
348 mpEditorToolBar->addAction(mpBulletListAction);
349 mpEditorToolBar->addAction(mpNumberedListAction);
350 mpEditorToolBar->addSeparator();
351 mpEditorToolBar->addAction(mpLinkAction);
352 mpEditorToolBar->addAction(mpUnLinkAction);
353 // update the actions whenever the selectionChanged signal is raised.
354 connect(mpHTMLEditor->page(), SIGNAL(selectionChanged())"2""selectionChanged()", SLOT(updateActions())"1""updateActions()");
355 // add a layout to html editor widget
356 QVBoxLayout *pHTMLWidgetLayout = new QVBoxLayout;
357 pHTMLWidgetLayout->setAlignment(Qt::AlignTop);
358 pHTMLWidgetLayout->setContentsMargins(0, 0, 0, 0);
359 pHTMLWidgetLayout->setSpacing(0);
360 pHTMLWidgetLayout->addWidget(mpEditorToolBar);
361 pHTMLWidgetLayout->addWidget(mpHTMLEditorFrame, 1);
362 mpHTMLEditorWidget->setLayout(pHTMLWidgetLayout);
363 // create the HTMLEditor
364 mpHTMLSourceEditor = new HTMLEditor(this);
365 mpHTMLSourceEditor->hide();
366 connect(mpHTMLEditor->page(), SIGNAL(contentsChanged())"2""contentsChanged()", SLOT(updateHTMLSourceEditor())"1""updateHTMLSourceEditor()");
367 HTMLHighlighter *pHTMLHighlighter = new HTMLHighlighter(OptionsDialog::instance()->getHTMLEditorPage(), mpHTMLSourceEditor->getPlainTextEdit());
1
Memory is allocated
368 connect(OptionsDialog::instance(), SIGNAL(HTMLEditorSettingsChanged())"2""HTMLEditorSettingsChanged()", pHTMLHighlighter, SLOT(settingsChanged())"1""settingsChanged()");
369 // eidtors widget layout
370 QVBoxLayout *pEditorsWidgetLayout = new QVBoxLayout;
2
Potential leak of memory pointed to by 'pHTMLHighlighter'
371 pEditorsWidgetLayout->setAlignment(Qt::AlignTop);
372 pEditorsWidgetLayout->setContentsMargins(0, 0, 0, 0);
373 pEditorsWidgetLayout->setSpacing(0);
374 pEditorsWidgetLayout->addWidget(mpTabBar);
375 pEditorsWidgetLayout->addWidget(mpHTMLEditorWidget);
376 pEditorsWidgetLayout->addWidget(mpHTMLSourceEditor);
377 mpEditorsWidget->setLayout(pEditorsWidgetLayout);
378 mEditType = EditType::None;
379 // navigation history list
380 mpDocumentationHistoryList = new QList<DocumentationHistory>();
381 mDocumentationHistoryPos = -1;
382 setExecutingPreviousNextButtons(false);
383 setScrollPosition(QPoint(0, 0));
384 // Documentation viewer layout
385 QGridLayout *pGridLayout = new QGridLayout;
386 pGridLayout->setContentsMargins(0, 0, 0, 0);
387 pGridLayout->addWidget(mpDocumentationViewerFrame);
388 pGridLayout->addWidget(mpEditorsWidget);
389 QVBoxLayout *pMainLayout = new QVBoxLayout;
390 pMainLayout->setContentsMargins(0, 0, 0, 0);
391 pMainLayout->setSpacing(0);
392 pMainLayout->addWidget(pDocumentationToolBar);
393 pMainLayout->addLayout(pGridLayout, 1);
394 setLayout(pMainLayout);
395}
396
397/*!
398 * \brief DocumentationWidget::~DocumentationWidget
399 */
400DocumentationWidget::~DocumentationWidget()
401{
402 mDocumentationFile.remove();
403 delete mpDocumentationHistoryList;
404}
405
406/*!
407 * \brief DocumentationWidget::showDocumentation
408 * Shows the documentaiton annotation. If we are editing a documentation then it is saved before showing the annotation.
409 * \param pLibraryTreeItem
410 */
411void DocumentationWidget::showDocumentation(LibraryTreeItem *pLibraryTreeItem)
412{
413 // We only support documentation of Modelica classes.
414 if (pLibraryTreeItem->getLibraryType() != LibraryTreeItem::Modelica) {
415 return;
416 }
417 // if documentation is proctected then do not show it.
418 if (pLibraryTreeItem->getAccess() < LibraryTreeItem::documentation) {
419 // Remove the class documentation if it is showed previously.
420 updateDocumentationHistory(pLibraryTreeItem);
421 return;
422 }
423 if (mEditType != EditType::None) {
424 saveDocumentation(pLibraryTreeItem);
425 return;
426 }
427 // write the scroll position
428 if (!isExecutingPreviousNextButtons()) {
429 saveScrollPosition();
430 }
431 // read the scroll position
432 int index = mpDocumentationHistoryList->indexOf(DocumentationHistory(pLibraryTreeItem));
433 if (index > -1 && isExecutingPreviousNextButtons()) {
434 setScrollPosition(mpDocumentationHistoryList->at(index).mScrollPosition);
435 } else {
436 setScrollPosition(QPoint(0, 0));
437 }
438 // read documentation
439 QString documentation = MainWindow::instance()->getOMCProxy()->getDocumentationAnnotation(pLibraryTreeItem);
440 writeDocumentationFile(documentation);
441 mpDocumentationViewer->setUrl(QUrl::fromLocalFile(mDocumentationFile.fileName()));
442
443 if ((mDocumentationHistoryPos >= 0) && (pLibraryTreeItem == mpDocumentationHistoryList->at(mDocumentationHistoryPos).mpLibraryTreeItem)) {
444 /* reload url */
445 } else {
446 /* new url */
447 /* remove all following urls */
448 while (mpDocumentationHistoryList->count() > (mDocumentationHistoryPos+1)) {
449 mpDocumentationHistoryList->removeLast();
450 }
451 /* append new url */
452 mpDocumentationHistoryList->append(DocumentationHistory(pLibraryTreeItem));
453 mDocumentationHistoryPos++;
454 connect(pLibraryTreeItem, SIGNAL(unLoaded())"2""unLoaded()", SLOT(updateDocumentationHistory())"1""updateDocumentationHistory()");
455 }
456
457 updatePreviousNextButtons();
458 mpEditInfoAction->setDisabled(pLibraryTreeItem->isSystemLibrary());
459 mpEditRevisionsAction->setDisabled(pLibraryTreeItem->isSystemLibrary());
460 mpEditInfoHeaderAction->setDisabled(pLibraryTreeItem->isSystemLibrary());
461 mpSaveAction->setDisabled(true);
462 mpCancelAction->setDisabled(true);
463 mpDocumentationViewerFrame->show();
464 mpEditorsWidget->hide();
465}
466
467/*!
468 * \brief DocumentationWidget::execCommand
469 * Calls the document.execCommand API.
470 * \param commandName
471 * \sa DocumentationWidget::execCommand(commandName, valueArgument)
472 */
473void DocumentationWidget::execCommand(const QString &commandName)
474{
475 QWebFrame *pWebFrame = mpHTMLEditor->page()->mainFrame();
476 QString javaScript = QString("document.execCommand(\"%1\", false, null)").arg(commandName);
477 pWebFrame->evaluateJavaScript(javaScript);
478}
479
480/*!
481 * \brief DocumentationWidget::execCommand
482 * Calls the document.execCommand API.
483 * \param command
484 * \param valueArgument
485 * \sa DocumentationWidget::execCommand(commandName)
486 */
487void DocumentationWidget::execCommand(const QString &command, const QString &valueArgument)
488{
489 QWebFrame *pWebFrame = mpHTMLEditor->page()->mainFrame();
490 QString javaScript = QString("document.execCommand(\"%1\", false, \"%2\")").arg(command).arg(valueArgument);
491 pWebFrame->evaluateJavaScript(javaScript);
492}
493
494/*!
495 * \brief DocumentationWidget::queryCommandState
496 * Calls the document.queryCommandState API.\n
497 * Returns true if the command is enabled e.g., if the text is bold then document.queryCommandState("bold", false, null) returns true.
498 * \param commandName
499 * \return
500 */
501bool DocumentationWidget::queryCommandState(const QString &commandName)
502{
503 QWebFrame *pWebFrame = mpHTMLEditor->page()->mainFrame();
504 QString javaScript = QString("document.queryCommandState(\"%1\")").arg(commandName);
505 QVariant result = pWebFrame->evaluateJavaScript(javaScript);
506 return result.toString().simplified().toLower() == "true";
507}
508
509/*!
510 * \brief DocumentationWidget::queryCommandValue
511 * Calls the document.queryCommandValue API.\n
512 * Returns the command value e.g., if the text is heading 1 then document.queryCommandValue("formatBlock", false, null) returns h1.
513 * \param commandName
514 * \return
515 */
516QString DocumentationWidget::queryCommandValue(const QString &commandName)
517{
518 QWebFrame *pWebFrame = mpHTMLEditor->page()->mainFrame();
519 QString javaScript = QString("document.queryCommandValue(\"%1\")").arg(commandName);
520 QVariant result = pWebFrame->evaluateJavaScript(javaScript);
521 return result.toString();
522}
523
524/*!
525 * \brief DocumentationWidget::saveScrollPosition
526 * Saves the scroll position of the current page.
527 */
528void DocumentationWidget::saveScrollPosition()
529{
530 if (mDocumentationHistoryPos > -1 && mpDocumentationHistoryList->size() > 0) {
531 DocumentationHistory documentationHistory = mpDocumentationHistoryList->at(mDocumentationHistoryPos);
532 documentationHistory.mScrollPosition = mpDocumentationViewer->page()->mainFrame()->scrollPosition();
533 mpDocumentationHistoryList->replace(mDocumentationHistoryPos, documentationHistory);
534 }
535}
536
537/*!
538 * \brief DocumentationWidget::createPixmapForToolButton
539 * Creates a new pixmap which contains the QIcon and the QColor in the bottom.
540 * \param color
541 * \param icon
542 * \return
543 */
544QPixmap DocumentationWidget::createPixmapForToolButton(QColor color, QIcon icon)
545{
546 QSize size = mpEditorToolBar->iconSize();
547 int height = (size.height() * 20) / 100;
548 QPixmap upperPixmap = icon.pixmap(size.width(), size.height() - height);
549 QPixmap collagePixmap(size);
550 collagePixmap.fill(Qt::transparent);
551 QPainter painter(&collagePixmap);
552 painter.drawPixmap(upperPixmap.rect(), upperPixmap);
553 QPixmap bottomPixmap(size.width(), height);
554 bottomPixmap.fill(color);
555 painter.drawPixmap(QRect(0, upperPixmap.height(), bottomPixmap.width(), bottomPixmap.height()), bottomPixmap);
556 return collagePixmap;
557}
558
559/*!
560 * \brief DocumentationWidget::updatePreviousNextButtons
561 * Updates the previous and next button.
562 */
563void DocumentationWidget::updatePreviousNextButtons()
564{
565 // update previous button
566 if (mDocumentationHistoryPos > 0) {
567 mpPreviousAction->setDisabled(false);
568 } else {
569 mpPreviousAction->setDisabled(true);
570 }
571 // update next button
572 if (mpDocumentationHistoryList->count() == (mDocumentationHistoryPos + 1)) {
573 mpNextAction->setDisabled(true);
574 } else {
575 mpNextAction->setDisabled(false);
576 }
577}
578
579/*!
580 * \brief DocumentationWidget::writeDocumentationFile
581 * \param documentation
582 */
583void DocumentationWidget::writeDocumentationFile(QString documentation)
584{
585 /* Create a local file with the html we want to view as otherwise JavaScript does not run properly. */
586 mDocumentationFile.open(QIODevice::WriteOnly);
587 QTextStream out(&mDocumentationFile);
588 out.setCodec(Helper::utf8.toUtf8().constData());
589 out << documentation;
590 mDocumentationFile.close();
591}
592
593/*!
594 * \brief DocumentationWidget::isLinkSelected
595 * Returns true if a link is selected.
596 * \return
597 */
598bool DocumentationWidget::isLinkSelected()
599{
600 QWebFrame *pWebFrame = mpHTMLEditor->page()->mainFrame();
601 QString javaScript = QString("function isLinkSelected() {"
602 " if (document.getSelection().anchorNode.parentNode.nodeName == 'A') {"
603 " return true;"
604 " } else {"
605 " return false;"
606 " }"
607 "}"
608 "isLinkSelected()");
609 QVariant result = pWebFrame->evaluateJavaScript(javaScript);
610 return result.toString().simplified().toLower() == "true";
611}
612
613/*!
614 * \brief DocumentationWidget::updateDocumentationHistory
615 * \param pLibraryTreeItem
616 * Removes the corresponding LibraryTreeItem from the DocumentationHistory.
617 */
618void DocumentationWidget::updateDocumentationHistory(LibraryTreeItem *pLibraryTreeItem)
619{
620 if (pLibraryTreeItem) {
621 int index = mpDocumentationHistoryList->indexOf(DocumentationHistory(pLibraryTreeItem));
622 if (index > -1) {
623 mpDocumentationHistoryList->removeOne(DocumentationHistory(pLibraryTreeItem));
624 if (index == mDocumentationHistoryPos) {
625 if (!(index == 0 && !mpDocumentationHistoryList->isEmpty())) {
626 mDocumentationHistoryPos--;
627 }
628 } else if (index < mDocumentationHistoryPos) {
629 mDocumentationHistoryPos--;
630 } else if (index > mDocumentationHistoryPos) {
631 // do nothing
632 }
633 updatePreviousNextButtons();
634 if (mDocumentationHistoryPos > -1) {
635 cancelDocumentation();
636 LibraryTreeModel *pLibraryTreeModel = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel();
637 pLibraryTreeModel->showModelWidget(mpDocumentationHistoryList->at(mDocumentationHistoryPos).mpLibraryTreeItem);
638 } else {
639 mpEditInfoAction->setDisabled(true);
640 mpEditRevisionsAction->setDisabled(true);
641 mpEditInfoHeaderAction->setDisabled(true);
642 mpSaveAction->setDisabled(true);
643 mpCancelAction->setDisabled(true);
644 mpDocumentationViewer->setHtml(""); // clear if we don't have any documentation to show
645 mpDocumentationViewerFrame->show();
646 mpEditorsWidget->hide();
647 mEditType = EditType::None;
648 }
649 }
650 }
651}
652
653/*!
654 * \brief DocumentationWidget::previousDocumentation
655 * Moves to the previous documentation.\n
656 * Slot activated when clicked signal of mpPreviousToolButton is raised.
657 */
658void DocumentationWidget::previousDocumentation()
659{
660 if (mDocumentationHistoryPos > 0) {
661 saveScrollPosition();
662 mDocumentationHistoryPos--;
663 setExecutingPreviousNextButtons(true);
664 LibraryTreeModel *pLibraryTreeModel = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel();
665 pLibraryTreeModel->showModelWidget(mpDocumentationHistoryList->at(mDocumentationHistoryPos).mpLibraryTreeItem);
666 setExecutingPreviousNextButtons(false);
667 }
668}
669
670/*!
671 * \brief DocumentationWidget::nextDocumentation
672 * Moves to the next documentation.\n
673 * Slot activated when clicked signal of mpNextToolButton is raised.
674 */
675void DocumentationWidget::nextDocumentation()
676{
677 if ((mDocumentationHistoryPos + 1) < mpDocumentationHistoryList->count()) {
678 saveScrollPosition();
679 mDocumentationHistoryPos++;
680 setExecutingPreviousNextButtons(true);
681 LibraryTreeModel *pLibraryTreeModel = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel();
682 pLibraryTreeModel->showModelWidget(mpDocumentationHistoryList->at(mDocumentationHistoryPos).mpLibraryTreeItem);
683 setExecutingPreviousNextButtons(false);
684 }
685}
686
687/*!
688 * \brief DocumentationWidget::editInfoDocumentation
689 * Starts editing the info section of documentation annotation.\n
690 * Slot activated when clicked signal of mpEditInfoToolButton is raised.
691 */
692void DocumentationWidget::editInfoDocumentation()
693{
694 if (mDocumentationHistoryPos >= 0) {
695 LibraryTreeItem *pLibraryTreeItem = mpDocumentationHistoryList->at(mDocumentationHistoryPos).mpLibraryTreeItem;
696 if (pLibraryTreeItem && !pLibraryTreeItem->isNonExisting()) {
697 // get the info documentation
698 QList<QString> info = MainWindow::instance()->getOMCProxy()->getDocumentationAnnotationInClass(pLibraryTreeItem);
699 writeDocumentationFile(info.at(0));
700 mpHTMLEditor->setUrl(QUrl::fromLocalFile(mDocumentationFile.fileName()));
701 // put the info documentation in the source editor
702 mpHTMLSourceEditor->getPlainTextEdit()->setPlainText(info.at(0));
703 mpTabBar->setTabText(0, tr("Info Editor"));
704 mpTabBar->setTabText(1, tr("Info Source"));
705 mEditType = EditType::Info;
706 // update the buttons
707 mpPreviousAction->setDisabled(true);
708 mpNextAction->setDisabled(true);
709 mpEditInfoAction->setDisabled(true);
710 mpEditRevisionsAction->setDisabled(true);
711 mpEditInfoHeaderAction->setDisabled(true);
712 mpSaveAction->setDisabled(false);
713 mpCancelAction->setDisabled(false);
714 mpDocumentationViewerFrame->hide();
715 mpEditorsWidget->show();
716 mpTabBar->setCurrentIndex(0);
717 mpHTMLEditor->setFocusInternal();
718 }
719 }
720}
721
722/*!
723 * \brief DocumentationWidget::editRevisionsDocumentation
724 * Starts editing the revisions section of the documentation annotation.\n
725 * Slot activated when clicked signal of mpEditRevisionsToolButton is raised.
726 */
727void DocumentationWidget::editRevisionsDocumentation()
728{
729 if (mDocumentationHistoryPos >= 0) {
730 LibraryTreeItem *pLibraryTreeItem = mpDocumentationHistoryList->at(mDocumentationHistoryPos).mpLibraryTreeItem;
731 if (pLibraryTreeItem && !pLibraryTreeItem->isNonExisting()) {
732 // get the revision documentation
733 QList<QString> revisions = MainWindow::instance()->getOMCProxy()->getDocumentationAnnotationInClass(pLibraryTreeItem);
734 writeDocumentationFile(revisions.at(1));
735 mpHTMLEditor->setUrl(QUrl::fromLocalFile(mDocumentationFile.fileName()));
736 // put the info documentation in the source editor
737 mpHTMLSourceEditor->getPlainTextEdit()->setPlainText(revisions.at(1));
738 mpTabBar->setTabText(0, tr("Revisions Editor"));
739 mpTabBar->setTabText(1, tr("Revisions Source"));
740 mEditType = EditType::Revisions;
741 // update the buttons
742 mpPreviousAction->setDisabled(true);
743 mpNextAction->setDisabled(true);
744 mpEditInfoAction->setDisabled(true);
745 mpEditRevisionsAction->setDisabled(true);
746 mpEditInfoHeaderAction->setDisabled(true);
747 mpSaveAction->setDisabled(false);
748 mpCancelAction->setDisabled(false);
749 mpDocumentationViewerFrame->hide();
750 mpEditorsWidget->show();
751 mpTabBar->setCurrentIndex(0);
752 mpHTMLEditor->setFocusInternal();
753 }
754 }
755}
756
757/*!
758 * \brief DocumentationWidget::editInfoHeaderDocumentation
759 * Starts editing the __OpenModelica_infoHeader section of the documentation annotation.\n
760 * Slot activated when clicked signal of mpEditInfoHeaderToolButton is raised.
761 */
762void DocumentationWidget::editInfoHeaderDocumentation()
763{
764 if (mDocumentationHistoryPos >= 0) {
765 LibraryTreeItem *pLibraryTreeItem = mpDocumentationHistoryList->at(mDocumentationHistoryPos).mpLibraryTreeItem;
766 if (pLibraryTreeItem && !pLibraryTreeItem->isNonExisting()) {
767 // get the __OpenModelica_infoHeader documentation annotation
768 QList<QString> infoHeader = MainWindow::instance()->getOMCProxy()->getDocumentationAnnotationInClass(pLibraryTreeItem);
769 writeDocumentationFile(infoHeader.at(2));
770 mpHTMLEditor->setUrl(QUrl::fromLocalFile(mDocumentationFile.fileName()));
771 // put the info documentation in the source editor
772 mpHTMLSourceEditor->getPlainTextEdit()->setPlainText(infoHeader.at(2));
773 mpTabBar->setTabText(0, tr("__OpenModelica_infoHeader Editor"));
774 mpTabBar->setTabText(1, tr("__OpenModelica_infoHeader Source"));
775 mEditType = EditType::InfoHeader;
776 // update the buttons
777 mpPreviousAction->setDisabled(true);
778 mpNextAction->setDisabled(true);
779 mpEditInfoAction->setDisabled(true);
780 mpEditRevisionsAction->setDisabled(true);
781 mpEditInfoHeaderAction->setDisabled(true);
782 mpSaveAction->setDisabled(false);
783 mpCancelAction->setDisabled(false);
784 mpDocumentationViewerFrame->hide();
785 mpEditorsWidget->show();
786 mpTabBar->setCurrentIndex(0);
787 mpHTMLEditor->setFocusInternal();
788 }
789 }
790}
791
792/*!
793 * \brief DocumentationWidget::saveDocumentation
794 * Saves the documentaiton annotation. If pLibraryTreeItem is 0 then the documentation of the editing class is shown after save.\n
795 * Otherwise the documentation of pLibraryTreeItem is shown.
796 * Slot activated when clicked signal of mpSaveToolButton is raised.
797 * \param pNextLibraryTreeItem
798 */
799void DocumentationWidget::saveDocumentation(LibraryTreeItem *pNextLibraryTreeItem)
800{
801 if (mDocumentationHistoryPos >= 0) {
802 LibraryTreeItem *pLibraryTreeItem = mpDocumentationHistoryList->at(mDocumentationHistoryPos).mpLibraryTreeItem;
803 if (pLibraryTreeItem && !pLibraryTreeItem->isNonExisting()) {
804 QList<QString> documentation = MainWindow::instance()->getOMCProxy()->getDocumentationAnnotationInClass(pLibraryTreeItem);
805 // old documentation annotation
806 QString oldDocAnnotationString = "annotate=Documentation(";
807 if (!documentation.at(0).isEmpty()) {
808 oldDocAnnotationString.append("info=\"").append(StringHandler::escapeStringQuotes(documentation.at(0))).append("\"");
809 }
810 if (!documentation.at(1).isEmpty()) {
811 oldDocAnnotationString.append(", revisions=\"").append(StringHandler::escapeStringQuotes(documentation.at(1))).append("\"");
812 }
813 if (!documentation.at(2).isEmpty()) {
814 oldDocAnnotationString.append(", __OpenModelica_infoHeader=\"").append(StringHandler::escapeStringQuotes(documentation.at(2))).append("\"");
815 }
816 oldDocAnnotationString.append(")");
817 // new documentation annotation
818 QString newDocAnnotationString = "annotate=Documentation(";
819 if (mEditType == EditType::Info) { // if editing the info section
820 if (!mpHTMLSourceEditor->getPlainTextEdit()->toPlainText().isEmpty()) {
821 newDocAnnotationString.append("info=\"").append(StringHandler::escapeStringQuotes(mpHTMLSourceEditor->getPlainTextEdit()->toPlainText())).append("\"");
822 }
823 if (!documentation.at(1).isEmpty()) {
824 newDocAnnotationString.append(", revisions=\"").append(StringHandler::escapeStringQuotes(documentation.at(1))).append("\"");
825 }
826 if (!documentation.at(2).isEmpty()) {
827 newDocAnnotationString.append(", __OpenModelica_infoHeader=\"").append(StringHandler::escapeStringQuotes(documentation.at(2))).append("\"");
828 }
829 } else if (mEditType == EditType::Revisions) { // if editing the revisions section
830 if (!documentation.at(0).isEmpty()) {
831 newDocAnnotationString.append("info=\"").append(StringHandler::escapeStringQuotes(documentation.at(0))).append("\"");
832 }
833 if (!mpHTMLSourceEditor->getPlainTextEdit()->toPlainText().isEmpty()) {
834 newDocAnnotationString.append(", revisions=\"").append(StringHandler::escapeStringQuotes(mpHTMLSourceEditor->getPlainTextEdit()->toPlainText())).append("\"");
835 }
836 if (!documentation.at(2).isEmpty()) {
837 newDocAnnotationString.append(", __OpenModelica_infoHeader=\"").append(StringHandler::escapeStringQuotes(documentation.at(2))).append("\"");
838 }
839 } else if (mEditType == EditType::InfoHeader) { // if editing the __OpenModelica_infoHeader section
840 if (!documentation.at(0).isEmpty()) {
841 newDocAnnotationString.append("info=\"").append(StringHandler::escapeStringQuotes(documentation.at(0))).append("\"");
842 }
843 if (!documentation.at(1).isEmpty()) {
844 newDocAnnotationString.append(", revisions=\"").append(StringHandler::escapeStringQuotes(documentation.at(1))).append("\"");
845 }
846 if (!mpHTMLSourceEditor->getPlainTextEdit()->toPlainText().isEmpty()) {
847 newDocAnnotationString.append(", __OpenModelica_infoHeader=\"").append(StringHandler::escapeStringQuotes(mpHTMLSourceEditor->getPlainTextEdit()->toPlainText())).append("\"");
848 }
849 }
850 newDocAnnotationString.append(")");
851 // if we have ModelWidget for class then put the change on undo stack.
852 if (pLibraryTreeItem->getModelWidget()) {
853 UpdateClassAnnotationCommand *pUpdateClassExperimentAnnotationCommand;
854 pUpdateClassExperimentAnnotationCommand = new UpdateClassAnnotationCommand(pLibraryTreeItem, oldDocAnnotationString,
855 newDocAnnotationString);
856 pLibraryTreeItem->getModelWidget()->getUndoStack()->push(pUpdateClassExperimentAnnotationCommand);
857 pLibraryTreeItem->getModelWidget()->updateModelText();
858 } else {
859 // send the documentation annotation to OMC
860 MainWindow::instance()->getOMCProxy()->addClassAnnotation(pLibraryTreeItem->getNameStructure(), newDocAnnotationString);
861 LibraryTreeModel *pLibraryTreeModel = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel();
862 pLibraryTreeModel->updateLibraryTreeItemClassText(pLibraryTreeItem);
863 }
864 /* ticket:5190 Save the class when documentation save button is hit. */
865 MainWindow::instance()->getLibraryWidget()->saveLibraryTreeItem(pLibraryTreeItem);
866 mEditType = EditType::None;
867 showDocumentation(pNextLibraryTreeItem ? pNextLibraryTreeItem : pLibraryTreeItem);
868 }
869 }
870}
871
872/*!
873 * \brief DocumentationWidget::cancelDocumentation
874 * Cancels the editing of documentation annotation.
875 * Slot activated when clicked signal of mpCancelToolButton is raised.
876 */
877void DocumentationWidget::cancelDocumentation()
878{
879 updatePreviousNextButtons();
880 mpEditInfoAction->setDisabled(false);
881 mpEditRevisionsAction->setDisabled(false);
882 mpEditInfoHeaderAction->setDisabled(false);
883 mpSaveAction->setDisabled(true);
884 mpCancelAction->setDisabled(true);
885 mpDocumentationViewerFrame->show();
886 mpEditorsWidget->hide();
887 mEditType = EditType::None;
888}
889
890/*!
891 * \brief DocumentationWidget::toggleEditor
892 * Slot activated when mpTabBar currentIndexChanged SIGNAL is raised.\n
893 * Switches between editor and source.
894 * \param tabIndex
895 */
896void DocumentationWidget::toggleEditor(int tabIndex)
897{
898 switch (tabIndex) {
899 case 1:
900 mpHTMLEditorWidget->hide();
901 mpHTMLSourceEditor->show();
902 mpHTMLSourceEditor->getPlainTextEdit()->setFocus(Qt::ActiveWindowFocusReason);
903 break;
904 case 0:
905 default:
906 if (mpHTMLSourceEditor->getPlainTextEdit()->document()->isModified()) {
907 writeDocumentationFile(mpHTMLSourceEditor->getPlainTextEdit()->toPlainText());
908 mpHTMLEditor->setUrl(QUrl::fromLocalFile(mDocumentationFile.fileName()));
909 }
910 mpHTMLSourceEditor->hide();
911 mpHTMLEditorWidget->show();
912 mpHTMLEditor->setFocusInternal();
913 break;
914 }
915}
916
917/*!
918 * \brief DocumentationWidget::updateActions
919 * Slot activated when QWebView::page() selecionChanged SIGNAL is raised.\n
920 * Updates the actions according to the cursor position.
921 */
922void DocumentationWidget::updateActions()
923{
924 bool state = mpStyleComboBox->blockSignals(true);
925 QString format = queryCommandValue("formatBlock");
926 int currentIndex = mpStyleComboBox->findData(format);
927 if (currentIndex > -1) {
928 mpStyleComboBox->setCurrentIndex(currentIndex);
929 } else {
930 mpStyleComboBox->setCurrentIndex(0);
931 }
932 mpStyleComboBox->blockSignals(state);
933 state = mpFontComboBox->blockSignals(true);
934 QString fontName = queryCommandValue("fontName");
935 // font name has extra single quote around it so remove it.
936 fontName = StringHandler::removeFirstLastSingleQuotes(fontName);
937 currentIndex = mpFontComboBox->findText(fontName, Qt::MatchExactly);
938 if (currentIndex > -1) {
939 mpFontComboBox->setCurrentIndex(currentIndex);
940 }
941 mpFontComboBox->blockSignals(state);
942 bool ok;
943 int fontSize = queryCommandValue("fontSize").toInt(&ok);
944 if (ok) {
945 state = mpFontSizeSpinBox->blockSignals(true);
946 mpFontSizeSpinBox->setValue(fontSize);
947 mpFontSizeSpinBox->blockSignals(state);
948 }
949 mpBoldAction->setChecked(mpHTMLEditor->pageAction(QWebPage::ToggleBold)->isChecked());
950 mpItalicAction->setChecked(mpHTMLEditor->pageAction(QWebPage::ToggleItalic)->isChecked());
951 mpUnderlineAction->setChecked(mpHTMLEditor->pageAction(QWebPage::ToggleUnderline)->isChecked());
952 mpStrikethroughAction->setChecked(mpHTMLEditor->pageAction(QWebPage::ToggleStrikethrough)->isChecked());
953 mpSubscriptAction->setChecked(mpHTMLEditor->pageAction(QWebPage::ToggleSubscript)->isChecked());
954 mpSuperscriptAction->setChecked(mpHTMLEditor->pageAction(QWebPage::ToggleSuperscript)->isChecked());
955 mpAlignLeftToolButton->setChecked(queryCommandState("justifyLeft"));
956 mpAlignCenterToolButton->setChecked(queryCommandState("justifyCenter"));
957 mpAlignRightToolButton->setChecked(queryCommandState("justifyRight"));
958 mpJustifyToolButton->setChecked(queryCommandState("justifyFull"));
959 mpBulletListAction->setChecked(queryCommandState("insertUnorderedList"));
960 mpNumberedListAction->setChecked(queryCommandState("insertOrderedList"));
961 mpLinkAction->setEnabled(!mpHTMLEditor->page()->selectedText().isEmpty());
962 mpUnLinkAction->setEnabled(!mpHTMLEditor->page()->selectedText().isEmpty() && isLinkSelected());
963}
964
965/*!
966 * \brief DocumentationWidget::formatBlock
967 * SLOT activated when style combobox is changed.
968 * \param index
969 */
970void DocumentationWidget::formatBlock(int index)
971{
972 QString format = mpStyleComboBox->itemData(index).toString();
973 execCommand("formatBlock", format);
974}
975
976/*!
977 * \brief DocumentationWidget::fontName
978 * Sets the text font name.
979 * \param font
980 */
981void DocumentationWidget::fontName(QFont font)
982{
983// execCommand("styleWithCSS", "true");
984 execCommand("fontName", font.family());
985// execCommand("styleWithCSS", "false");
986}
987
988/*!
989 * \brief DocumentationWidget::fontSize
990 * Sets the text font size.
991 * \param size
992 */
993void DocumentationWidget::fontSize(int size)
994{
995// execCommand("styleWithCSS", "true");
996 execCommand("fontSize", QString::number(size));
997// execCommand("styleWithCSS", "false");
998}
999
1000/*!
1001 * \brief DocumentationWidget::applyTextColor
1002 * SLOT activated when text color button is clicked.\n
1003 * \sa DocumentationWidget::applyTextColor(QColor color)
1004 */
1005void DocumentationWidget::applyTextColor()
1006{
1007 applyTextColor(mTextColor);
1008}
1009
1010/*!
1011 * \brief DocumentationWidget::applyTextColor
1012 * SLOT activated when user selects a text color.\n
1013 * Applies the text color by executing command foreColor.
1014 * \param color
1015 */
1016void DocumentationWidget::applyTextColor(QColor color)
1017{
1018 mTextColor = color;
1019 mpTextColorToolButton->setIcon(createPixmapForToolButton(mTextColor, QIcon(":/Resources/icons/text-color-icon.svg")));
1020 execCommand("foreColor", color.name());
1021}
1022
1023/*!
1024 * \brief DocumentationWidget::applyBackgroundColor
1025 * SLOT activated when background color button is clicked.\n
1026 * \sa DocumentationWidget::applyBackgroundColor(QColor color)
1027 */
1028void DocumentationWidget::applyBackgroundColor()
1029{
1030 applyBackgroundColor(mBackgroundColor);
1031}
1032
1033/*!
1034 * \brief DocumentationWidget::applyBackgroundColor
1035 * SLOT activated when user selects a baclground color.\n
1036 * Applies the text color by executing command hiliteColor.
1037 * \param color
1038 */
1039void DocumentationWidget::applyBackgroundColor(QColor color)
1040{
1041 mBackgroundColor = color;
1042 mpBackgroundColorToolButton->setIcon(createPixmapForToolButton(mBackgroundColor, QIcon(":/Resources/icons/background-color-icon.svg")));
1043 execCommand("hiliteColor", color.name());
1044}
1045
1046/*!
1047 * \brief DocumentationWidget::alignLeft
1048 * Aligns the text left by executing command justifyLeft.
1049 */
1050void DocumentationWidget::alignLeft()
1051{
1052 execCommand("justifyLeft");
1053}
1054
1055/*!
1056 * \brief DocumentationWidget::alignCenter
1057 * Aligns the text center by executing command justifyCenter.
1058 */
1059void DocumentationWidget::alignCenter()
1060{
1061 execCommand("justifyCenter");
1062}
1063
1064/*!
1065 * \brief DocumentationWidget::alignRight
1066 * Aligns the text right by executing command justifyRight.
1067 */
1068void DocumentationWidget::alignRight()
1069{
1070 execCommand("justifyRight");
1071}
1072
1073/*!
1074 * \brief DocumentationWidget::justify
1075 * Justifies the text by executing command justifyFull.
1076 */
1077void DocumentationWidget::justify()
1078{
1079 execCommand("justifyFull");
1080}
1081
1082/*!
1083 * \brief DocumentationWidget::bulletList
1084 * Inserts the unordered list.
1085 */
1086void DocumentationWidget::bulletList()
1087{
1088 execCommand("insertUnorderedList");
1089}
1090
1091/*!
1092 * \brief DocumentationWidget::numberedList
1093 * Inserts the ordered list.
1094 */
1095void DocumentationWidget::numberedList()
1096{
1097 execCommand("insertOrderedList");
1098}
1099
1100/*!
1101 * \brief DocumentationWidget::createLink
1102 * Creates a link.
1103 */
1104void DocumentationWidget::createLink()
1105{
1106 QWebFrame *pWebFrame = mpHTMLEditor->page()->mainFrame();
1107 QString javaScript = QString("function getLinkHref() {"
1108 " if (document.getSelection().anchorNode.parentNode.nodeName == 'A') {"
1109 " if (document.getSelection().anchorNode.parentNode.hasAttribute('href')) {"
1110 " return document.getSelection().anchorNode.parentNode.getAttribute('href');"
1111 " }"
1112 " }"
1113 " return '';"
1114 "}"
1115 "getLinkHref()");
1116 QString href = pWebFrame->evaluateJavaScript(javaScript).toString();
1117 href = QInputDialog::getText(this, tr("Create Link"), "Enter URL", QLineEdit::Normal, href);
1118 execCommand("createLink", href);
1119}
1120
1121/*!
1122 * \brief DocumentationWidget::removeLink
1123 * Removes the link.
1124 */
1125void DocumentationWidget::removeLink()
1126{
1127 execCommand("unlink");
1128}
1129
1130/*!
1131 * \brief DocumentationWidget::updateHTMLSourceEditor
1132 * Slot activated when QWebView::page() contentsChanged SIGNAL is rasied.\n
1133 * Updates the contents of the HTML source editor.
1134 */
1135void DocumentationWidget::updateHTMLSourceEditor()
1136{
1137 mpHTMLSourceEditor->getPlainTextEdit()->setPlainText(mpHTMLEditor->page()->mainFrame()->toHtml());
1138}
1139
1140/*!
1141 * \brief DocumentationWidget::updateDocumentationHistory
1142 * Slot activated when LibraryTreeItem unloaded SIGNAL is raised.
1143 */
1144void DocumentationWidget::updateDocumentationHistory()
1145{
1146 updateDocumentationHistory(qobject_cast<LibraryTreeItem*>(sender()));
1147}
1148
1149/*!
1150 * \class DocumentationViewer
1151 * \brief A webview for displaying the html documentation.
1152 */
1153/*!
1154 * \brief DocumentationViewer::DocumentationViewer
1155 * \param pDocumentationWidget
1156 * \param isContentEditable
1157 */
1158DocumentationViewer::DocumentationViewer(DocumentationWidget *pDocumentationWidget, bool isContentEditable)
1159 : QWebView(pDocumentationWidget)
1160{
1161 setContextMenuPolicy(Qt::CustomContextMenu);
1162 connect(this, SIGNAL(customContextMenuRequested(QPoint))"2""customContextMenuRequested(QPoint)", SLOT(showContextMenu(QPoint))"1""showContextMenu(QPoint)");
1163 mpDocumentationWidget = pDocumentationWidget;
1164 resetZoom();
1165 // set DocumentationViewer settings
1166 settings()->setFontFamily(QWebSettings::StandardFont, Helper::systemFontInfo.family());
1167 settings()->setFontSize(QWebSettings::DefaultFontSize, Helper::systemFontInfo.pointSize());
1168 settings()->setAttribute(QWebSettings::LocalStorageEnabled, true);
1169 settings()->setDefaultTextEncoding(Helper::utf8.toUtf8().constData());
1170 // set DocumentationViewer web page policy
1171 page()->setContentEditable(isContentEditable);
1172 page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
1173 connect(page(), SIGNAL(linkClicked(QUrl))"2""linkClicked(QUrl)", SLOT(processLinkClick(QUrl))"1""processLinkClick(QUrl)");
1174 connect(page(), SIGNAL(linkHovered(QString,QString,QString))"2""linkHovered(QString,QString,QString)", SLOT(processLinkHover(QString,QString,QString))"1""processLinkHover(QString,QString,QString)");
1175 createActions();
1176 if (!isContentEditable) {
1177 connect(this, SIGNAL(loadFinished(bool))"2""loadFinished(bool)", SLOT(pageLoaded(bool))"1""pageLoaded(bool)");
1178 }
1179}
1180
1181/*!
1182 * \brief DocumentationViewer::setFocusInternal
1183 * Sets the focus on QWebView.\n
1184 * QWebView need an initial mouse click to show the cursor.
1185 */
1186void DocumentationViewer::setFocusInternal()
1187{
1188 setFocus(Qt::ActiveWindowFocusReason);
1189 QPoint center = QPoint(0, 0);
1190 QMouseEvent *pMouseEvent1 = new QMouseEvent(QEvent::MouseButtonPress, center, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1191 QMouseEvent *pMouseEvent2 = new QMouseEvent(QEvent::MouseButtonRelease, center, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1192 QApplication::postEvent(this, pMouseEvent1);
1193 QApplication::postEvent(this, pMouseEvent2);
1194}
1195
1196/*!
1197 * \brief DocumentationViewer::createActions
1198 */
1199void DocumentationViewer::createActions()
1200{
1201 page()->action(QWebPage::SelectAll)->setShortcut(QKeySequence("Ctrl+a"));
1202 page()->action(QWebPage::Copy)->setShortcut(QKeySequence("Ctrl+c"));
1203}
1204
1205/*!
1206 * \brief DocumentationViewer::resetZoom
1207 * Resets the zoom. \n
1208 * QWebView seems to be using fixed 96 dpi so set a proper base zoomfactor for high resolution screens.
1209 */
1210void DocumentationViewer::resetZoom()
1211{
1212 QWidget *pScreenWidget = QApplication::desktop()->screen();
1213 qreal zoomFactor = pScreenWidget->logicalDpiX() / 96;
1214 setZoomFactor(zoomFactor < 1 ? 1 : zoomFactor);
1215}
1216
1217/*!
1218 * \brief DocumentationViewer::processLinkClick
1219 * \param url
1220 * Slot activated when linkClicked signal of webview is raised.
1221 * Handles the link processing. Sends all the http starting links to the QDesktopServices and process all Modelica starting links.
1222 */
1223void DocumentationViewer::processLinkClick(QUrl url)
1224{
1225 if (page()->isContentEditable()) {
1226 return;
1227 }
1228 // Send all http requests to desktop services for now.
1229 // if url contains http or mailto: send it to desktop services
1230 if ((url.toString().startsWith("http")) || (url.toString().startsWith("mailto:"))) {
1231 QDesktopServices::openUrl(url);
1232 } else if (url.scheme().compare("modelica") == 0) { // if the user has clicked on some Modelica Links like modelica://
1233 // remove modelica:/// from Qurl
1234 QString resourceLink = url.toString().mid(12);
1235 /* if the link is a resource e.g .html, .txt or .pdf */
1236 if (resourceLink.endsWith(".html") || resourceLink.endsWith(".txt") || resourceLink.endsWith(".pdf")) {
1237 QString resourceAbsoluteFileName = MainWindow::instance()->getOMCProxy()->uriToFilename("modelica://" + resourceLink);
1238 QDesktopServices::openUrl("file:///" + resourceAbsoluteFileName);
1239 } else {
1240 LibraryTreeItem *pLibraryTreeItem = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel()->findLibraryTreeItem(resourceLink);
1241 // send the new className to DocumentationWidget
1242 if (pLibraryTreeItem) {
1243 MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel()->showModelWidget(pLibraryTreeItem);
1244 }
1245 }
1246 } else { // if it is normal http request then check if its not redirected to https
1247 QNetworkAccessManager* accessManager = page()->networkAccessManager();
1248 QNetworkRequest request(url);
1249 QNetworkReply* reply = accessManager->get(request);
1250 connect(reply, SIGNAL(finished())"2""finished()", SLOT(requestFinished())"1""requestFinished()");
1251 }
1252}
1253
1254/*!
1255 * \brief DocumentationViewer::requestFinished
1256 * Slot activated when QNetworkReply finished signal is raised.\n
1257 * Handles the link redirected to https.
1258 */
1259void DocumentationViewer::requestFinished()
1260{
1261 QNetworkReply *reply = qobject_cast<QNetworkReply*>(const_cast<QObject*>(sender()));
1262 QUrl possibleRedirectedUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
1263 //if the url contains https
1264 if (possibleRedirectedUrl.toString().contains("https")) {
1265 QDesktopServices::openUrl(possibleRedirectedUrl);
1266 } else {
1267 load(reply->url());
1268 }
1269 reply->deleteLater();
1270}
1271
1272/*!
1273 * \brief DocumentationViewer::processLinkHover
1274 * Slot activated when linkHovered signal of web view is raised.\n
1275 * Writes the url to the status bar.
1276 * \param link
1277 * \param title
1278 * \param textContent
1279 */
1280void DocumentationViewer::processLinkHover(QString link, QString title, QString textContent)
1281{
1282 Q_UNUSED(title)(void)title;;
1283 Q_UNUSED(textContent)(void)textContent;;
1284 if (link.isEmpty()) {
1285 MainWindow::instance()->getStatusBar()->clearMessage();
1286 } else {
1287 MainWindow::instance()->getStatusBar()->showMessage(link);
1288 }
1289}
1290
1291/*!
1292 * \brief DocumentationViewer::showContextMenu
1293 * Shows a context menu when user right click on the Messages tree.\n
1294 * Slot activated when DocumentationViewer::customContextMenuRequested() signal is raised.
1295 * \param point
1296 */
1297void DocumentationViewer::showContextMenu(QPoint point)
1298{
1299 QMenu menu(this);
1300 // add QWebPage default actions
1301 menu.addAction(page()->action(QWebPage::SelectAll));
1302 menu.addAction(page()->action(QWebPage::Copy));
1303 menu.exec(mapToGlobal(point));
1304}
1305
1306/*!
1307 * \brief DocumentationViewer::pageLoaded
1308 * Scrolls the page after its finished loading.
1309 * \param ok
1310 */
1311void DocumentationViewer::pageLoaded(bool ok)
1312{
1313 Q_UNUSED(ok)(void)ok;;
1314 const QPoint scrollPosition = mpDocumentationWidget->getScrollPosition();
1315 page()->mainFrame()->scroll(scrollPosition.x(), scrollPosition.y());
1316}
1317
1318/*!
1319 * \brief DocumentationViewer::createWindow
1320 * \param type
1321 * \return
1322 */
1323QWebView* DocumentationViewer::createWindow(QWebPage::WebWindowType type)
1324{
1325 Q_UNUSED(type)(void)type;;
1326 QWebView *webView = new QWebView;
1327 QWebPage *newWeb = new QWebPage(webView);
1328 webView->setAttribute(Qt::WA_DeleteOnClose, true);
1329 webView->setPage(newWeb);
1330 webView->show();
1331 return webView;
1332}
1333
1334/*!
1335 * \brief DocumentationViewer::keyPressEvent
1336 * Reimplementation of keypressevent.
1337 * Defines what to do for backspace and shift+backspace buttons.
1338 * \param event
1339 */
1340void DocumentationViewer::keyPressEvent(QKeyEvent *event)
1341{
1342 bool shiftModifier = event->modifiers().testFlag(Qt::ShiftModifier);
1343 bool controlModifier = event->modifiers().testFlag(Qt::ControlModifier);
1344 // if editable QWebView
1345 if (page()->isContentEditable()) {
1346 if (!shiftModifier && (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)) {
1347// mpDocumentationWidget->execCommand("insertHTML", "<p><br></p>");
1348 QWebView::keyPressEvent(event);
1349 } else {
1350 QWebView::keyPressEvent(event);
1351 }
1352 } else { // if non-editable QWebView
1353 if (shiftModifier && !controlModifier && event->key() == Qt::Key_Backspace) {
1354 if (mpDocumentationWidget->getNextAction()->isEnabled()) {
1355 mpDocumentationWidget->nextDocumentation();
1356 }
1357 } else if (!shiftModifier && !controlModifier && event->key() == Qt::Key_Backspace) {
1358 if (mpDocumentationWidget->getPreviousAction()->isEnabled()) {
1359 mpDocumentationWidget->previousDocumentation();
1360 }
1361 } else if (controlModifier && event->key() == Qt::Key_A) {
1362 page()->triggerAction(QWebPage::SelectAll);
1363 } else {
1364 QWebView::keyPressEvent(event);
1365 }
1366 }
1367}
1368
1369/*!
1370 * \brief DocumentationViewer::wheelEvent
1371 * Reimplementation of wheelevent.
1372 * Defines what to do for control+scrolling the wheel
1373 * \param event
1374 */
1375void DocumentationViewer::wheelEvent(QWheelEvent *event)
1376{
1377 if (event->orientation() == Qt::Vertical && event->modifiers().testFlag(Qt::ControlModifier)) {
1378 qreal zf = zoomFactor();
1379 /* ticket:4349 Take smaller steps for zooming.
1380 * Also set the minimum zoom to readable size.
1381 */
1382 if (event->delta() > 0) {
1383 zf += 0.1;
1384 zf = zf > 5 ? 5 : zf;
1385 } else {
1386 zf -= 0.1;
1387 zf = zf < 0.5 ? 0.5 : zf;
1388 }
1389 setZoomFactor(zf);
1390 } else {
1391 QWebView::wheelEvent(event);
1392 }
1393}
1394
1395/*!
1396 * \brief DocumentationViewer::mouseDoubleClickEvent
1397 * Reimplementation of mousedoubleclickevent.
1398 * Defines what to do for control+doubleclick
1399 * \param event
1400 */
1401void DocumentationViewer::mouseDoubleClickEvent(QMouseEvent *event)
1402{
1403 if (event->modifiers().testFlag(Qt::ControlModifier)) {
1404 resetZoom();
1405 } else {
1406 QWebView::mouseDoubleClickEvent(event);
1407 }
1408}