ui: Show title bar at top and scroll bar at bottom in code view snippet list if necessary (issues #432, #479)

* Show title bar at top of snippet list if first file is cut off
* Show scrollbar at bottom of snippet list if last snippet if cut off and horizontally scrollable
* Extended scrollRequest API to different ScrollTarget modes
* Fixed snippet extension broken if maximized first
* Split off title bar functionality to separate class QtCodeFileTitleBar
This commit is contained in:
Eberhard Graether
2017-12-17 13:25:11 +01:00
parent c91f5282f5
commit 8672d14319
17 changed files with 736 additions and 289 deletions
+84 -47
View File
@@ -11,7 +11,7 @@ QtCodeNavigateable::~QtCodeNavigateable()
}
void QtCodeNavigateable::ensureWidgetVisibleAnimated(
QWidget* parentWidget, QWidget *childWidget, QRectF rect, bool animated, bool onTop)
const QWidget* parentWidget, const QWidget *childWidget, QRectF rect, bool animated, ScrollTarget target)
{
QAbstractScrollArea* area = getScrollArea();
if (!area || !parentWidget->isAncestorOf(childWidget))
@@ -19,11 +19,7 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated(
return;
}
const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
const QRect defaultMicroFocus = childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect();
QRect focusRect = (microFocus != defaultMicroFocus)
? QRect(childWidget->mapTo(parentWidget, microFocus.topLeft()), microFocus.size())
: QRect(childWidget->mapTo(parentWidget, QPoint(0, 0)), childWidget->size());
QRect focusRect = getFocusRectForWidget(childWidget, parentWidget);
const QRect visibleRect(-parentWidget->pos(), area->viewport()->size());
if (rect.height() > 0)
@@ -36,15 +32,42 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated(
}
}
QScrollBar* scrollBar = area->verticalScrollBar();
int value = focusRect.center().y() - visibleRect.center().y();
if (onTop || focusRect.height() > visibleRect.height())
// scroll to top if widget is bigger than view
if (focusRect.height() > visibleRect.height())
{
value = focusRect.top() - visibleRect.top() - 20;
target = SCROLL_TOP;
}
if (scrollBar && (value > 50 || value < -50))
int value = 0;
switch (target)
{
case SCROLL_VISIBLE:
if (focusRect.top() < visibleRect.top())
{
value = focusRect.top() - visibleRect.top() - 20;
}
else if (focusRect.bottom() > visibleRect.bottom())
{
value = focusRect.bottom() - visibleRect.bottom() + 20;
}
break;
case SCROLL_CENTER:
value = focusRect.center().y() - visibleRect.center().y();
if (abs(value) < 50)
{
value = 0;
}
break;
case SCROLL_TOP:
value = focusRect.top() - visibleRect.top() - 50;
break;
}
QScrollBar* scrollBar = area->verticalScrollBar();
if (scrollBar && value)
{
if (animated && ApplicationSettings::getInstance()->getUseAnimations())
{
@@ -62,7 +85,7 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated(
}
}
void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, bool onTop)
void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, ScrollTarget target)
{
QAbstractScrollArea* area = getScrollArea();
if (!area)
@@ -78,45 +101,43 @@ void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double pe
return;
}
int scrollHeight = totalHeight * percentA;
if (!onTop)
{
if (percentB)
{
int scrollHeightB = totalHeight * percentB;
int rectHeight = scrollHeightB - scrollHeight;
if (rectHeight < visibleHeight)
{
if (rectHeight < visibleHeight / 2)
{
scrollHeight -= visibleHeight / 4;
}
else
{
scrollHeight += rectHeight / 2 - visibleHeight / 2;
}
}
else
{
scrollHeight -= 20;
}
}
else
{
scrollHeight -= visibleHeight / 4;
}
}
else
{
scrollHeight -= 20;
}
QScrollBar* scrollBar = area->verticalScrollBar();
double scrollFactor = double(scrollBar->maximum()) / scrollableHeight;
int value = scrollHeight * scrollFactor;
int visibleY = double(scrollBar->value()) / scrollFactor;
int scrollY = totalHeight * percentA;
int rectHeight = percentB ? (totalHeight * percentB) - scrollY : 0;
if (rectHeight > visibleHeight)
{
target = SCROLL_TOP;
}
switch (target)
{
case SCROLL_VISIBLE:
if (scrollY > visibleY && scrollY + rectHeight < visibleY + scrollableHeight)
{
return;
}
case SCROLL_CENTER:
if (rectHeight < visibleHeight / 2)
{
scrollY -= visibleHeight / 4;
}
else
{
scrollY += rectHeight / 2 - visibleHeight / 2;
}
break;
case SCROLL_TOP:
scrollY -= 20;
break;
}
int value = scrollY * scrollFactor;
int diff = value - scrollBar->value();
if (diff > 5 || diff < -5)
{
@@ -135,3 +156,19 @@ void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double pe
}
}
}
QRect QtCodeNavigateable::getFocusRectForWidget(const QWidget* childWidget, const QWidget* parentWidget) const
{
const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
const QRect defaultMicroFocus = childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect();
if (microFocus != defaultMicroFocus)
{
return QRect(childWidget->mapTo(parentWidget, microFocus.topLeft()), microFocus.size());
}
else
{
return QRect(childWidget->mapTo(parentWidget, QPoint(0, 0)), childWidget->size());
}
}