From f5771d01ebaaa5bad0ab08a15fd7ce072daa4e71 Mon Sep 17 00:00:00 2001
From: SeeLook <945374+SeeLook@users.noreply.github.com>
Date: Sun, 4 Dec 2016 18:10:07 +0100
Subject: [PATCH] Fixed positioning of tips with question content depending on
 question-answer type. Tcanvas::determineTipPos is clear and easy readable
 instead of missed up free-something variables in TquestionTip. Added html
 file with table describing all possibilities.

---
 src/plugins/exam/tcanvas.cpp        | 192 ++++++++++++++++------------
 src/plugins/exam/tcanvas.h          |  41 ++++--
 src/plugins/exam/tip positions.ods  | Bin 0 -> 11982 bytes
 src/plugins/exam/tip_positions.html | 126 ++++++++++++++++++
 src/plugins/exam/tquestiontip.cpp   |  24 +---
 src/plugins/exam/tquestiontip.h     |  89 +++++++------
 6 files changed, 310 insertions(+), 162 deletions(-)
 create mode 100644 src/plugins/exam/tip positions.ods
 create mode 100644 src/plugins/exam/tip_positions.html

diff --git a/src/plugins/exam/tcanvas.cpp b/src/plugins/exam/tcanvas.cpp
index 5535ec470..301507250 100644
--- a/src/plugins/exam/tcanvas.cpp
+++ b/src/plugins/exam/tcanvas.cpp
@@ -67,7 +67,7 @@ QFont smalTipFont(QWidget* w) {
 
 /** Multiplexer of question tip scale factor to make it big enough on hi dpi tablet screens */
 inline qreal multiScale() {
-  return qreal(Tmtr::shortScreenSide() / Tmtr::fingerPixels()) / 5.0;
+  return (static_cast<qreal>(Tmtr::shortScreenSide()) / Tmtr::fingerPixels()) / 5.0;
 }
 
 #endif
@@ -82,7 +82,8 @@ Tcanvas::Tcanvas(QGraphicsView* view, Texam* exam) :
   m_exam(exam),
   m_timerToConfirm(new QTimer(this)),
   m_flyEllipse(nullptr),
-  m_minimizedQuestion(false), m_melodyCorrectMessage(false)
+  m_minimizedQuestion(false), m_melodyCorrectMessage(false),
+  m_tipPos(e_bottomRight)
 {
   m_scene = m_view->scene();
 	m_newSize = m_scene->sceneRect().size().toSize();
@@ -305,13 +306,11 @@ void Tcanvas::whatNextTip(bool isCorrect, bool toCorrection) {
 	}
 	whatNextText += br + TexamHelp::toStopExamTxt(QLatin1String("<a href=\"stopExam\">") + pixToHtml(Tpath::img("stopExam"), m_iconSize) + a);
   m_whatTip = new TgraphicsTextTip(whatNextText, m_view->palette().highlight().color());
-// 	if (m_guitarFree) // tip is wide there, otherwise text is word-wrapped and is narrowest but higher
-// 			m_whatTip->setTextWidth(m_maxTipWidth);
   m_scene->addItem(m_whatTip);
   m_whatTip->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
   m_whatTip->setTipMovable(true);
   connect(m_whatTip, SIGNAL(linkActivated(QString)), this, SLOT(linkActivatedSlot(QString)));
-  connect(m_whatTip, SIGNAL(moved()), this, SLOT(tipMoved()));
+  connect(m_whatTip, &TgraphicsTextTip::moved, this, &Tcanvas::tipMoved);
 #endif
   setWhatNextPos();
 }
@@ -371,21 +370,10 @@ void Tcanvas::questionTip() {
 	delete m_outTuneTip;
   clearWhatNextTip();
   clearMelodyCorrectMessage();
-	createQuestionTip();
-	m_guitarFree = m_questionTip->freeGuitar() && GUITAR->isVisible();
-	m_nameFree = m_questionTip->freeName() && SCORE->insertMode() == TmultiScore::e_single;
-	m_scoreFree = m_questionTip->freeScore();
-  if (!m_guitarFree && !m_nameFree && !m_scoreFree) // workaround when only score is visible
-    m_scoreFree = true;
-	m_tipPos = e_scoreOver; // score is visible always
-	if (m_nameFree && SCORE->insertMode() == TmultiScore::e_single)
-		m_tipPos = e_nameOver;
-	else if (m_scoreFree)
-		m_tipPos = e_scoreOver;
-	else if (m_guitarFree && GUITAR->isVisible())
-		m_tipPos = e_guitarOver;
-	m_questionTip->setMinimized(m_minimizedQuestion);
-	setQuestionPos();
+  createQuestionTip();
+  m_tipPos = determineTipPos();
+  m_questionTip->setMinimized(m_minimizedQuestion);
+  setQuestionPos();
 }
 
 
@@ -569,10 +557,6 @@ void Tcanvas::clearMelodyCorrectMessage() {
 }
 
 
-void Tcanvas::markAnswer(TQAtype::Etype qType, TQAtype::Etype aType) {
-}
-
-
 const QRect& Tcanvas::getRect(TQAtype::Etype kindOf) {
   switch (kindOf) {
     case TQAtype::e_asNote:
@@ -592,12 +576,12 @@ const QRect& Tcanvas::getRect(TQAtype::Etype kindOf) {
 
 void Tcanvas::sizeChangedDelayed(const QRectF& newRect) {
 	QSizeF factor(newRect.width() / m_prevSize.width(), newRect.height() / m_prevSize.height());
-	for (int i = 0; i < 3; ++i) {
-		if (!m_posOfQuestTips[i].isNull())
-			m_posOfQuestTips[i] = QPointF(m_posOfQuestTips[i].x() * factor.width(), m_posOfQuestTips[i].y() * factor.height());
-		if (!m_posOfWhatTips[i].isNull())
-			m_posOfWhatTips[i] = QPointF(m_posOfWhatTips[i].x() * factor.width(), m_posOfWhatTips[i].y() * factor.height());
-	}
+  for (int i = 0; i < TIP_POS_NUM; ++i) {
+    if (!m_posOfQuestTips[i].isNull())
+      m_posOfQuestTips[i] = QPointF(m_posOfQuestTips[i].x() * factor.width(), m_posOfQuestTips[i].y() * factor.height());
+    if (!m_posOfWhatTips[i].isNull())
+      m_posOfWhatTips[i] = QPointF(m_posOfWhatTips[i].x() * factor.width(), m_posOfWhatTips[i].y() * factor.height());
+  }
 	if (!m_posOfConfirm.isNull())
 			m_posOfConfirm = QPointF(m_posOfConfirm.x() * factor.width(), m_posOfConfirm.y() * factor.height());
 	m_prevSize = newRect.size();
@@ -641,8 +625,6 @@ void Tcanvas::sizeChanged() {
   if (m_confirmTip) {
     clearConfirmTip(); // To re-create confirm tip works better than re-scaling
     showConfirmTip();
-//     m_confirmTip->setScale(m_scale * 1.2);
-//     setConfirmPos();
   }
   if (m_certifyTip) {
     clearCertificate();
@@ -706,30 +688,27 @@ bool Tcanvas::eventFilter(QObject* obj, QEvent* event) {
 //##################################################################################################
 
 int Tcanvas::getMaxTipHeight() {
-	if (m_nameFree || m_scoreFree)
-		return SCORE->height() * 0.6;
-	else
-		return GUITAR->height() * 1.1;
+  if (m_tipPos == e_nameOver || m_tipPos == e_scoreOver)
+    return SCORE->height() * 0.6;
+  else
+    return GUITAR->height() * 1.1;
 }
 
 
 void Tcanvas::setPosOfTip(TgraphicsTextTip* tip) {
-	QRect geoRect;
-	if (m_nameFree) { // middle of the noteName
-			geoRect = NOTENAME->geometry();
-	} else if (m_scoreFree) {// on the score at its center
-			geoRect = SCORE->geometry();
-			fixWidthOverScore(tip);
-      if (SCORE->insertMode() != TmultiScore::e_single && !GUITAR->isVisible()) // only score - place it bottom right
-        geoRect = QRect(m_view->width() - tip->realW(), m_view->height() - tip->realH(), tip->realW(), tip->realH());
-	} else { // middle of the guitar
-			geoRect = GUITAR->geometry();
-      if (m_exam && !m_exam->melodies()) // in single mode put a tip on the right guitar side, below note name
-        geoRect.setRect(NOTENAME->x(), GUITAR->y(), NOTENAME->width(), GUITAR->height());
-  }
-	tip->setPos(qMin(geoRect.x() + (geoRect.width() - tip->realW()) / 2, m_view->width() - tip->realW() - 5.0),
-							qMin(geoRect.y() + (geoRect.height() - tip->realH()) / 2, m_view->height() - tip->realH() - 5.0));
-	// qMin guards a tip position in scene boundaries 
+  QRect geoRect;
+  if (m_tipPos == e_nameOver) { // middle of the noteName
+      geoRect.setRect(SCORE->x() + SCORE->width(), SCORE->y() + NOTENAME->y(), NOTENAME->width(), NOTENAME->height());
+  } else if (m_tipPos == e_scoreOver) {// on the score at its center
+      geoRect = SCORE->geometry();
+      fixWidthOverScore(tip);
+  } else if (m_tipPos == e_guitarOver) // middle of the guitar
+      geoRect = GUITAR->geometry();
+  else // bottom-right corner
+      geoRect = QRect(m_view->width() - tip->realW(), m_view->height() - tip->realH(), tip->realW(), tip->realH());
+  tip->setPos(qMin(geoRect.x() + (geoRect.width() - tip->realW()) / 2, m_view->width() - tip->realW() - 5.0),
+              qMin(geoRect.y() + (geoRect.height() - tip->realH()) / 2, m_view->height() - tip->realH() - 5.0));
+  // qMin guards a tip position in scene boundaries
 }
 
 
@@ -778,19 +757,20 @@ void Tcanvas::setWhatNextPos() {
   }
 #else
 	int maxTipHeight = getMaxTipHeight();
-  if (!m_nameFree && m_whatTip->realH() != maxTipHeight)
-			m_whatTip->setScale((qreal)maxTipHeight / m_whatTip->realH());
-	if (m_tipPos == e_nameOver) {
-		if (m_whatTip->realW() != m_view->width() * 0.45)
-			m_whatTip->setScale((m_view->width() * 0.45) / m_whatTip->realW());
-		if (m_whatTip->realH() > SCORE->height())
-			m_whatTip->setScale((qreal)(SCORE->height()) / m_whatTip->realH());
-	} else
-			fixWidthOverScore(m_whatTip);
-	if (m_posOfWhatTips[(int)m_tipPos].isNull()) // calculate tip position only when user doesn't change it
-		setPosOfTip(m_whatTip);
-	else
-		m_whatTip->setFixPos(m_posOfWhatTips[(int)m_tipPos]);
+  if (m_tipPos != e_nameOver && m_whatTip->realH() != maxTipHeight)
+    m_whatTip->setScale(maxTipHeight / m_whatTip->realH());
+
+  if (m_tipPos == e_nameOver) {
+      if (m_whatTip->realW() != m_view->width() * 0.45)
+        m_whatTip->setScale((m_view->width() * 0.45) / m_whatTip->realW());
+      if (m_whatTip->realH() > SCORE->height())
+        m_whatTip->setScale(SCORE->height() / m_whatTip->realH());
+  } else
+        fixWidthOverScore(m_whatTip);
+  if (m_posOfWhatTips[static_cast<int>(m_tipPos)].isNull()) // calculate tip position only when user doesn't change it
+    setPosOfTip(m_whatTip);
+  else
+    m_whatTip->setFixPos(m_posOfWhatTips[static_cast<int>(m_tipPos)]);
 #endif
 }
 
@@ -828,8 +808,8 @@ void Tcanvas::createQuestionTip() {
 
 
 void Tcanvas::setQuestionPos() {
-	int maxTipHeight = getMaxTipHeight() * 1.1;
-	qreal fineScale;
+  int maxTipHeight = qRound(getMaxTipHeight() * 1.1);
+  qreal fineScale;
 	if (m_questionTip->boundingRect().height() > maxTipHeight) { // check is scaling needed
 			fineScale = (qreal)maxTipHeight / m_questionTip->boundingRect().height();
 #if defined (Q_OS_ANDROID)
@@ -845,13 +825,13 @@ void Tcanvas::setQuestionPos() {
 					scaleStep += 0.1;
 			}
 	}
-	if (m_posOfQuestTips[(int)m_tipPos].isNull()) // calculate tip position only when user doesn't change it
-			setPosOfTip(m_questionTip);
-	else {
-		fixWidthOverScore(m_questionTip);
-		m_questionTip->setFixPos(m_posOfQuestTips[(int)m_tipPos]);
-	}
-	m_questionTip->show();
+  if (m_posOfQuestTips[static_cast<int>(m_tipPos)].isNull()) // calculate tip position only when user doesn't change it
+      setPosOfTip(m_questionTip);
+  else {
+      fixWidthOverScore(m_questionTip);
+      m_questionTip->setFixPos(m_posOfQuestTips[static_cast<int>(m_tipPos)]);
+  }
+  m_questionTip->show();
 }
 
 
@@ -873,19 +853,19 @@ void Tcanvas::updateRelatedPoint() {
 
 
 void Tcanvas::fixWidthOverScore ( TgraphicsTextTip* tip ) {
-	if (m_tipPos == e_scoreOver && tip->realW() > SCORE->width())
-    tip->setScale((qMax((qreal)SCORE->width() * 0.9, m_view->width() / 3.0) / (tip->boundingRect().width())));
+  if (m_tipPos == e_scoreOver && tip->realW() > SCORE->width())
+    tip->setScale((qMax(SCORE->width() * 0.9, m_view->width() / 3.0) / (tip->boundingRect().width())));
 }
 
 
 
 void Tcanvas::tipMoved() {
-	if (sender() == m_questionTip)
-		m_posOfQuestTips[(int)m_tipPos] = m_questionTip->pos();
-	else if (sender() == m_whatTip)
-		m_posOfWhatTips[(int)m_tipPos] = m_whatTip->pos();
-	else if (sender() == m_confirmTip)
-		m_posOfConfirm = m_confirmTip->pos();
+  if (sender() == m_questionTip)
+    m_posOfQuestTips[static_cast<int>(m_tipPos)] = m_questionTip->pos();
+  else if (sender() == m_whatTip)
+    m_posOfWhatTips[static_cast<int>(m_tipPos)] = m_whatTip->pos();
+  else if (sender() == m_confirmTip)
+    m_posOfConfirm = m_confirmTip->pos();
 }
 
 
@@ -895,6 +875,54 @@ void Tcanvas::tipStateChanged() {
 }
 
 
+/**
+ * For details, see table in tip_positions.html file
+ */
+Tcanvas::EtipPos Tcanvas::determineTipPos() {
+  EtipPos tipPos;
+  switch (m_exam->curQ()->questionAs) {
+    /** Question is note on the score, so place a tip over name if not used or over guitar if visible but if not - in bottom-right corner. */
+    case TQAtype::e_asNote : {
+      if (SCORE->insertMode() == TmainScore::e_single) {
+          if (m_exam->curQ()->answerAs == TQAtype::e_asName) {
+              tipPos = GUITAR->isVisible() ? e_guitarOver : e_bottomRight;
+          } else
+              tipPos = e_nameOver;
+      } else { // melody, so answer is sound (only supported case)
+          tipPos = GUITAR->isVisible() ? e_guitarOver : e_bottomRight;
+      }
+      break;
+    }
+    /** Question is note name, so place a tip over score if not used, or over guitar. */
+    case TQAtype::e_asName : { // single note mode only
+      if (m_exam->curQ()->answerAs == TQAtype::e_asNote)
+        tipPos = GUITAR->isVisible() ? e_guitarOver : e_bottomRight;
+      else
+        tipPos = e_scoreOver;
+      break;
+    }
+    case TQAtype::e_asFretPos : { // single note mode only
+      if (m_exam->curQ()->answerAs == TQAtype::e_asNote)
+        tipPos = e_nameOver;
+      else
+        tipPos = e_scoreOver;
+      break;
+    }
+    case TQAtype::e_asSound : {
+      if (SCORE->insertMode() == TmainScore::e_single) {
+          if (m_exam->curQ()->answerAs == TQAtype::e_asNote)
+          tipPos = e_nameOver;
+        else
+          tipPos = e_scoreOver;
+      } else {
+          tipPos = GUITAR->isVisible() ? e_guitarOver : e_bottomRight;
+      }
+      break;
+    }
+  }
+  return tipPos;
+}
+
 
 
 
diff --git a/src/plugins/exam/tcanvas.h b/src/plugins/exam/tcanvas.h
index d4773a8f3..366dbbbcb 100644
--- a/src/plugins/exam/tcanvas.h
+++ b/src/plugins/exam/tcanvas.h
@@ -27,6 +27,8 @@
 #include <tfingerpos.h>
 
 
+#define TIP_POS_NUM (4) /**< Number of possible tip positions depends on question/answer combination */
+
 class Tnote;
 class TnoteName;
 class TcombinedAnim;
@@ -56,16 +58,25 @@ class Tcanvas : public QObject
 
 public:
 
-	enum EtipPos {
-		e_guitarOver = 0, e_scoreOver = 1, e_nameOver = 2
-	}; /**< Describes a kind of tip position depended on q/a type - over what widget tip is placed */
+      /**
+       * Describes a kind of tip position depended on q/a type - over what widget tip is placed.
+       * Number of enumerators has to correspond with @p TIP_POS_NUM definition
+       */
+  enum EtipPos {
+    e_guitarOver = 0, e_scoreOver = 1, e_nameOver = 2, e_bottomRight
+  };
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
+  Q_ENUM(EtipPos)
+#endif
 
 	Tcanvas(QGraphicsView* view, Texam* exam);
 	virtual ~Tcanvas();
 
-    /** Cross platform status message:
-     * - status bar on desktops (@class TstatusLabel)
-     * - pop up message on screen bottom for mobile (@class TtouchMessage) */
+    /**
+     * Cross platform status message:
+     * - status bar on desktops (@p TstatusLabel)
+     * - pop up message on screen bottom for mobile (@p TtouchMessage) 
+     */
   void setStatusMessage(const QString& text, int duration = 0);
 
   void changeExam(Texam* newExam); /**< Replaces exam pointer given in constructor to the new one. */
@@ -74,11 +85,15 @@ public:
 	void resultTip(TQAunit *answer, int time = 0); /**< show was question correct text, hides after given time */
 	void startTip(); /**< Text with help on an exam start */
 
-		/** Text with what to click after an answer.
+    /**
+     * Text with what to click after an answer.
      * @p isCorrect - was the question correct
-     * @p toCorrection - text how to see corrected answer will be shown. */
-	void whatNextTip(bool isCorrect, bool toCorrection = false);
-	void questionTip(); /**< Text with question context */
+     * @p toCorrection - text how to see corrected answer will be shown.
+     */
+  void whatNextTip(bool isCorrect, bool toCorrection = false);
+
+      /** Text with question context */
+  void questionTip();
 	void tryAgainTip(int time); /**< "Try again" text" */
 	void confirmTip(int time = 0); /**< tip about confirm an answer appears after given time */
   void melodyCorrectMessage(); /**< Status message about how to correct a melody notes. */
@@ -99,8 +114,6 @@ public:
 	QFont tipFont(qreal factor = 1);
 	QString startTipText();
 
-			/** Paints animated exclamation mark over answering widget. */
-	void markAnswer(TQAtype::Etype qType, TQAtype::Etype aType);
 
 			/** Paints rectangle around given type of widget to mark where is answer. */
 	const QRect& getRect(TQAtype::Etype kindOf);
@@ -165,7 +178,6 @@ private:
 	QPointer<TcombinedAnim>				 m_correctAnim;
 	QTimer 												*m_timerToConfirm;
 	int 													 m_maxTipWidth;
-	bool 													 m_guitarFree, m_nameFree, m_scoreFree;
 	QSizeF												 m_prevSize;
 	QSize 												 m_newSize;
 	QGraphicsEllipseItem					*m_flyEllipse;
@@ -173,7 +185,7 @@ private:
 	QColor												 m_correctColor;
 	TnoteName											*m_noteName;
 	QPoint												 m_relPoint;
-	QPointF												 m_posOfQuestTips[3], m_posOfWhatTips[3], m_posOfConfirm;
+	QPointF												 m_posOfQuestTips[TIP_POS_NUM], m_posOfWhatTips[TIP_POS_NUM], m_posOfConfirm;
 	bool													 m_minimizedQuestion, m_melodyCorrectMessage;
 	EtipPos												 m_tipPos; /**< Kind of tip position */
 	int                            m_iconSize; /**< Icon image size on tips calculated from actual font metrics. */
@@ -191,6 +203,7 @@ private:
 	void updateRelatedPoint();
 	void createQuestionTip(); /**< Be sure that @p m_exam has already pointed current exam */
 	void fixWidthOverScore(TgraphicsTextTip* tip); /**< Scales tip if its width is bigger than score widget */
+  EtipPos determineTipPos();
 
 };
 
diff --git a/src/plugins/exam/tip positions.ods b/src/plugins/exam/tip positions.ods
new file mode 100644
index 0000000000000000000000000000000000000000..f3b5b1b521b80f98faf2a77fdc2ddcec7ae9c043
GIT binary patch
literal 11982
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

literal 0
HcmV?d00001

diff --git a/src/plugins/exam/tip_positions.html b/src/plugins/exam/tip_positions.html
new file mode 100644
index 000000000..7578581bf
--- /dev/null
+++ b/src/plugins/exam/tip_positions.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	
+	<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+	<title></title>
+	<meta name="generator" content="LibreOffice 5.2.3.3 (Linux)"/>
+	<meta name="created" content="2016-12-04T12:40:04.099779111"/>
+	<meta name="changed" content="2016-12-04T15:03:39.802531112"/>
+	
+	<style type="text/css">
+		body,div,table,thead,tbody,tfoot,tr,th,td,p { font-family:"Arial"; font-size:x-small }
+		a.comment-indicator:hover + comment { background:#ffd; position:absolute; display:block; border:1px solid black; padding:0.5em;  } 
+		a.comment-indicator { background:red; display:inline-block; border:1px solid black; width:0.5em; height:0.5em;  } 
+		comment { display:none;  } 
+	</style>
+	
+</head>
+
+<body>
+<table cellspacing="0" border="0">
+	<colgroup width="85"></colgroup>
+	<colgroup width="102"></colgroup>
+	<colgroup width="121"></colgroup>
+	<colgroup width="85"></colgroup>
+	<colgroup width="134"></colgroup>
+	<tr>
+		<td height="17" align="center" valign=middle>q/a</td>
+		<td align="center" valign=middle>score</td>
+		<td align="center" valign=middle>name</td>
+		<td align="center" valign=middle>guitar</td>
+		<td align="center" valign=middle>sound</td>
+	</tr>
+	<tr>
+		<td height="33" align="center" valign=middle>score</td>
+		<td align="center" valign=middle>------------</td>
+		<td align="center" valign=middle>------------</td>
+		<td align="center" valign=middle>------------</td>
+		<td align="center" valign=middle>over guitar<br>Or bottom-right</td>
+	</tr>
+	<tr>
+		<td height="33" align="center" valign=middle>score single</td>
+		<td align="center" valign=middle>over name</td>
+		<td align="center" valign=middle>over guitar <br>or bottom-right</td>
+		<td align="center" valign=middle>over name</td>
+		<td align="center" valign=middle>over name</td>
+	</tr>
+	<tr>
+		<td height="33" align="center" valign=middle>name single</td>
+		<td align="center" valign=middle>over guitar<br>Or bottom-right</td>
+		<td align="center" valign=middle>over score</td>
+		<td align="center" valign=middle>over score</td>
+		<td align="center" valign=middle>over score</td>
+	</tr>
+	<tr>
+		<td height="17" align="center" valign=middle>guitar single</td>
+		<td align="center" valign=middle>over name</td>
+		<td align="center" valign=middle>over score</td>
+		<td align="center" valign=middle>over score</td>
+		<td align="center" valign=middle>over score</td>
+	</tr>
+	<tr>
+		<td height="33" align="center" valign=middle>sound</td>
+		<td align="center" valign=middle>over guitar <br>or bottom-right</td>
+		<td align="center" valign=middle>------------</td>
+		<td align="center" valign=middle>------------</td>
+		<td align="center" valign=middle>------------</td>
+	</tr>
+	<tr>
+		<td height="17" align="center" valign=middle>sound single</td>
+		<td align="center" valign=middle>over name</td>
+		<td align="center" valign=middle>over score</td>
+		<td align="center" valign=middle>over score</td>
+		<td align="center" valign=middle>over score</td>
+	</tr>
+	<tr>
+		<td height="17" align="center" valign=middle><br></td>
+		<td align="center" valign=middle><br></td>
+		<td align="center" valign=middle><br></td>
+		<td align="center" valign=middle><br></td>
+		<td align="center" valign=middle><br></td>
+	</tr>
+	<tr>
+		<td height="17" align="center" valign=middle><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+	</tr>
+	<tr>
+		<td height="17" align="center" valign=middle><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+	</tr>
+	<tr>
+		<td height="17" align="center" valign=middle><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+	</tr>
+	<tr>
+		<td height="17" align="center" valign=middle><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+	</tr>
+	<tr>
+		<td height="17" align="center" valign=middle><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+		<td align="left"><br></td>
+	</tr>
+	<tr>
+		<td colspan=5 rowspan=4 height="68" align="center" valign=middle>This table describes all possible positions of tip (question or what next)<br>Available for melodies and single note questions/answers</td>
+		</tr>
+</table>
+<!-- ************************************************************************** -->
+</body>
+
+</html>
diff --git a/src/plugins/exam/tquestiontip.cpp b/src/plugins/exam/tquestiontip.cpp
index cdbaa679a..35a6f8e9b 100644
--- a/src/plugins/exam/tquestiontip.cpp
+++ b/src/plugins/exam/tquestiontip.cpp
@@ -109,9 +109,6 @@ QString TquestionTip::getNiceNoteName(Tnote& note, Tnote::EnameStyle style) {
 QString TquestionTip::getQuestion(TQAunit* question, int questNr, Tlevel* level, double scale) {
   QString br = QStringLiteral("<br>");
   QString sp = QStringLiteral(" ");
-  m_scoreFree = true;
-  m_nameFree = !(bool)question->melody(); // no name widget when level uses melodies
-  m_guitarFree = true;
   m_questText.clear();
   double sc = 4.0;
   if (scale) {
@@ -126,7 +123,6 @@ QString TquestionTip::getQuestion(TQAunit* question, int questNr, Tlevel* level,
   QString noteStr;
   switch (question->questionAs) {
       case TQAtype::e_asNote: {
-        m_scoreFree = false;
         if (question->answerAsNote()) {
             if (question->qa.note.alter != question->qa_2.note.alter)
                 m_questText += tr("Change enharmonically and show on the staff");
@@ -136,10 +132,8 @@ QString TquestionTip::getQuestion(TQAunit* question, int questNr, Tlevel* level,
 								apendix = tr("<br><b>in %1 key.</b>", "in key signature").arg(question->key.getName());
 						      m_questText += getTextHowAccid((Tnote::Ealter)question->qa_2.note.alter);
         } else if (question->answerAsName()) {
-            m_nameFree = false;
             m_questText += tr("Give name of");
 				} else if (question->answerAsFret()) {
-              m_guitarFree = false;
               m_questText += tr("Show on the guitar");
 				} else if (question->answerAsSound()) {
 									if (question->melody())
@@ -164,27 +158,23 @@ QString TquestionTip::getQuestion(TQAunit* question, int questNr, Tlevel* level,
 			}
 
       case TQAtype::e_asName:
-        m_nameFree = false;
         noteStr = br + getNiceNoteName(question->qa.note, question->styleOfQuestion());
         if (question->answerAsNote()) {
-						m_scoreFree = false;
 						      m_questText += tr("Show on the staff") + noteStr;
 						if (level->useKeySign && level->manualKey) {
 							         m_questText += tr("<br><b>in %1 key.</b>", "in key signature").arg(question->key.getName());
 						}
         } else if (question->answerAsName()) {
-            m_nameFree = false;
             noteStr = br + getNiceNoteName(question->qa.note, question->styleOfQuestion());
             if (question->qa.note.alter != question->qa_2.note.alter) {
                 m_questText += tr("Change enharmonically and give name of");
                 m_questText += noteStr + getTextHowAccid((Tnote::Ealter)question->qa_2.note.alter);
             } else
                 m_questText += tr("Use another style to give name of") + noteStr;
-				} else if (question->answerAsFret()) {
-						m_guitarFree = false;
-						      m_questText += tr("Show on the guitar") + noteStr;
-				} else if (question->answerAsSound()) {
-						      m_questText += playOrSing(int(level->instrument)) + noteStr;
+        } else if (question->answerAsFret()) {
+            m_questText += tr("Show on the guitar") + noteStr;
+        } else if (question->answerAsSound()) {
+            m_questText += playOrSing(int(level->instrument)) + noteStr;
 				}
 				if (question->answerAsFret() || question->answerAsSound()) {
 						if (level->instrument != e_noInstrument && level->showStrNr && !level->onlyLowPos)
@@ -193,15 +183,12 @@ QString TquestionTip::getQuestion(TQAunit* question, int questNr, Tlevel* level,
 			break;
 
       case TQAtype::e_asFretPos:
-        m_guitarFree = false;
         if (question->answerAsNote()) {
-						m_scoreFree = false;
 						      m_questText += tr("Show on the staff note played on");
 						if (level->useKeySign && level->manualKey) {
 							apendix = tr("<b>in %1 key.</b>", "in key signature").arg(question->key.getName());
 						}
         } else if (question->answerAsName()) {
-            m_nameFree = false;
             m_questText += tr("Give name of");
 				} else if (question->answerAsFret()) {
               m_questText += tr("Show sound from position:", "... and string + fret numbers folowing");
@@ -220,7 +207,6 @@ QString TquestionTip::getQuestion(TQAunit* question, int questNr, Tlevel* level,
 
       case TQAtype::e_asSound:
         if (question->answerAsNote()) {
-						m_scoreFree = false;
 						if (question->melody()) {
 								        m_questText += TexTrans::writeDescTxt();
 								if (level->useKeySign && level->manualKey && level->onlyCurrKey)
@@ -233,12 +219,10 @@ QString TquestionTip::getQuestion(TQAunit* question, int questNr, Tlevel* level,
 									           m_questText += getTextHowAccid((Tnote::Ealter)question->qa.note.alter);
 						}
         } else if (question->answerAsName()) {
-            m_nameFree = false;
             m_questText += tr("Give name of listened sound");
             if (level->forceAccids)
                 m_questText += getTextHowAccid((Tnote::Ealter)question->qa.note.alter);
 				} else if (question->answerAsFret()) {
-              m_guitarFree = false;
               m_questText += tr("Listened sound show on the guitar");
               if (level->showStrNr)
                 m_questText += br + sp + onStringTxt(question->qa.pos.str());
diff --git a/src/plugins/exam/tquestiontip.h b/src/plugins/exam/tquestiontip.h
index 8701c476a..47c032920 100644
--- a/src/plugins/exam/tquestiontip.h
+++ b/src/plugins/exam/tquestiontip.h
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2012-2014 by Tomasz Bojczuk                             *
+ *   Copyright (C) 2012-2016 by Tomasz Bojczuk                             *
  *   seelook@gmail.com                                                     *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -15,19 +15,22 @@
  *  You should have received a copy of the GNU General Public License      *
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
  ***************************************************************************/
- 
+
 #ifndef TQUESTIONTIP_H
 #define TQUESTIONTIP_H
 
+
 #include <graphics/tgraphicstexttip.h>
 #include <music/tnote.h>
-#include <QLinearGradient>
+#include <QtGui/qbrush.h>
+
 
 class TfadeAnim;
 class Texam;
 class Tlevel;
 class TQAunit;
 
+
 /**
  * This is graphics tip (rectangle) representing a question context
  * It can be minimized with mouse.
@@ -35,53 +38,47 @@ class TQAunit;
 class TquestionTip : public TgraphicsTextTip
 {
    Q_OBJECT
-   
+
 public:
-			/** Constructs tip with question content. */
-	TquestionTip(Texam *exam, double scale = 0);
-	~TquestionTip();
-	
-	static QString getTextHowAccid(Tnote::Ealter accid);
-	static QString onStringTxt(quint8 strNr); /** Returns translated text on (strNr) string in Nootka font. */
-	
-			/** Depend on @p instrument it returns text:
-				* 'Play or sing' (other instrument)
-				* 'Play' (guitars) */
-	static QString playOrSing(int instr);
-	
-	static QString& text() { return m_questText; } /** Returns a reference to question HTML string. */
-	
-	bool freeScore() { return m_scoreFree; } /** true when question is not on score */
-	bool freeName() { return m_nameFree; } /** true when question is not on note name */
-	bool freeGuitar() { return m_guitarFree; } /** true when question is not on guitar */
-	
-	bool isMinimized() { return m_minimized; } /** True when tip is minimized */
-	void setMinimized(bool min); /** Minimizes of maximizes a tip */
-
-	virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
-	virtual QRectF boundingRect() const;
-	
-	virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
-	virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* event);
-	virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
-		
+      /** Constructs tip with question content. */
+  TquestionTip(Texam *exam, double scale = 0);
+  ~TquestionTip();
+
+  static QString getTextHowAccid(Tnote::Ealter accid);
+  static QString onStringTxt(quint8 strNr); /** Returns translated text on (strNr) string in Nootka font. */
+
+      /** Depend on @p instrument it returns text:
+        * 'Play or sing' (other instrument)
+        * 'Play' (guitars) */
+  static QString playOrSing(int instr);
+
+  static QString& text() { return m_questText; } /**< Returns a reference to question HTML string. */
+
+  bool isMinimized() { return m_minimized; } /**< True when tip is minimized */
+  void setMinimized(bool min); /**< Minimizes of maximizes a tip */
+
+  virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
+  virtual QRectF boundingRect() const;
+
+  virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
+  virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* event);
+  virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
+
 signals:
-	void minimizeChanged(); /** Emitted when tips gets minimized or restored to normal state */
-    
+	void minimizeChanged(); /**< Emitted when tips gets minimized or restored to normal state */
+
 protected:    
-        /** Returns html-formatted question text. */
-    QString getQuestion(TQAunit* question, int questNr, Tlevel* level, double scale = 0);
-    QString getNiceNoteName(Tnote& note, Tnote::EnameStyle style);
-        
-    
+      /** Returns html-formatted question text. */
+  QString getQuestion(TQAunit* question, int questNr, Tlevel* level, double scale = 0);
+  QString getNiceNoteName(Tnote& note, Tnote::EnameStyle style);
+
 private:
-    bool                m_scoreFree, m_nameFree, m_guitarFree; /** Indicate where a tip has to be placed. */
-    Tnote::Ealter       m_forcedAccid; /** When different than Tnote::e_Natural text is shown */
-    TfadeAnim          *m_fadeInAnim;
-		bool								m_markCorner, m_minimized;
-		static QString			m_questText;
-		QLinearGradient			m_staffGradient;
+  Tnote::Ealter       m_forcedAccid; /**< When different than Tnote::e_Natural text is shown */
+  TfadeAnim          *m_fadeInAnim;
+  bool								m_markCorner, m_minimized;
+  static QString			m_questText;
+  QLinearGradient			m_staffGradient;
 };
 
 
-#endif // TQUESTIONTIP_H
\ No newline at end of file
+#endif // TQUESTIONTIP_H
-- 
GitLab