Scale all QML elements according to the current display size
This commit is contained in:
parent
9e7a55fc20
commit
bcdf3d94f2
15 changed files with 278 additions and 109 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -1,6 +1,4 @@
|
|||
*.autosave
|
||||
build-LenaPi-Desktop-Debug
|
||||
build-LenaPi-RasPi-Debug
|
||||
build-LenaPi-RasPi-Release
|
||||
build-LenaPi*
|
||||
LenaPi/LenaPi.pro.user.4.8-pre1
|
||||
musik
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ LIBS +=
|
|||
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-files
|
||||
SOURCES += main.cpp \
|
||||
controllers/MusicPlayer.cpp \
|
||||
controllers/StyleController.cpp \
|
||||
models/NavigationListModel.cpp \
|
||||
models/NavigationItemModel.cpp \
|
||||
controllers/NavigationController.cpp \
|
||||
|
|
@ -41,6 +42,7 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
|
|||
|
||||
HEADERS += \
|
||||
controllers/MusicPlayer.h \
|
||||
controllers/StyleController.h \
|
||||
models/MusicPlayer.h \
|
||||
models/NavigationListModel.h \
|
||||
models/NavigationItemModel.h \
|
||||
|
|
|
|||
|
|
@ -1,51 +1,52 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
Item {
|
||||
ColumnLayout {
|
||||
id: container
|
||||
property var model
|
||||
|
||||
// manually set height
|
||||
Component.onCompleted: height = childrenRect.height
|
||||
spacing: StyleSpacings.tinySpacing
|
||||
|
||||
RowLayout{
|
||||
Label{
|
||||
anchors.left: progress.left
|
||||
anchors.bottom: progress.top
|
||||
font.pointSize: 9
|
||||
color: "grey"
|
||||
text: model.pMediaTitle
|
||||
}
|
||||
Item{
|
||||
// spacer
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label{
|
||||
anchors.right: progress.right
|
||||
anchors.bottom: progress.top
|
||||
font.pointSize: 9
|
||||
color: "grey"
|
||||
text: model.pTime + " / " + model.pMediaLength
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar{
|
||||
id: progress
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
Layout.fillWidth: true
|
||||
|
||||
value: model.pProgress
|
||||
|
||||
style:ProgressBarStyle {
|
||||
background: Rectangle {
|
||||
radius: 5
|
||||
radius: StyleSizes.progressBackgroundRadius
|
||||
color: "white"
|
||||
border.color: "grey"
|
||||
border.width: 1
|
||||
border.width: StyleSizes.progressBackgroundBorderWidth
|
||||
implicitWidth: container.width
|
||||
implicitHeight: 10
|
||||
implicitHeight: StyleSizes.progressBackgroundDefaultHeight
|
||||
}
|
||||
progress: Rectangle {
|
||||
color: "blue"
|
||||
border.color: "blue"
|
||||
radius: 5
|
||||
implicitHeight: 8
|
||||
radius: StyleSizes.progressBackgroundRadius
|
||||
implicitHeight: StyleSizes.progressBarDefaultHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import QtGraphicalEffects 1.0
|
|||
Item{
|
||||
id: container
|
||||
|
||||
property int margins: 20
|
||||
property int margins: StyleMargins.defaultMargin
|
||||
|
||||
RoundImageButton{
|
||||
id: backNavigation
|
||||
|
|
@ -43,7 +43,7 @@ Item{
|
|||
Image{
|
||||
id: cover
|
||||
anchors.centerIn: parent
|
||||
height: parent.height-10
|
||||
height: parent.height-StyleMargins.smallMargin
|
||||
width: height
|
||||
source: musicModel.pCoverImageSource
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
|
|
|
|||
|
|
@ -6,24 +6,24 @@ ScrollView{
|
|||
style: ScrollViewStyle{
|
||||
transientScrollBars: true
|
||||
handle: Item {
|
||||
implicitWidth: 16
|
||||
implicitHeight: 8
|
||||
implicitWidth: StyleSizes.scrollHandleWidth
|
||||
implicitHeight: StyleSizes.scrollHandleHeight
|
||||
Rectangle {
|
||||
color: "blue"
|
||||
border.color: "black"
|
||||
radius: height/2
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 1
|
||||
anchors.leftMargin: 1
|
||||
anchors.rightMargin: 1
|
||||
anchors.bottomMargin: 1
|
||||
anchors.topMargin: StyleMargins.scrollHandleMargin
|
||||
anchors.leftMargin: StyleMargins.scrollHandleMargin
|
||||
anchors.rightMargin: StyleMargins.scrollHandleMargin
|
||||
anchors.bottomMargin: StyleMargins.scrollHandleMargin
|
||||
}
|
||||
}
|
||||
scrollBarBackground: Rectangle{
|
||||
color: "transparent"
|
||||
border.color: "grey"
|
||||
border.width: 1
|
||||
height: 8
|
||||
border.width: StyleSizes.scrollHandleBorderWidth
|
||||
height: StyleSizes.scrollHandleHeight
|
||||
radius: height/2
|
||||
}
|
||||
decrementControl: Item{}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import QtQuick.Controls 2.4
|
|||
*/
|
||||
Item {
|
||||
id: container
|
||||
property int margins: 20
|
||||
property int margins: StyleMargins.defaultMargin
|
||||
RoundImageButton{
|
||||
id: back
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ Item {
|
|||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
height: 210
|
||||
height: StyleSizes.navigationListHeight
|
||||
|
||||
color: "#99ffffff"
|
||||
|
||||
|
|
@ -51,12 +51,12 @@ Item {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: 20
|
||||
anchors.margins: StyleMargins.defaultMargin
|
||||
|
||||
height: parent.height - 40
|
||||
height: parent.height - 2*StyleMargins.defaultMargin
|
||||
|
||||
model: navigationList.pModelItems
|
||||
spacing: 20
|
||||
spacing: StyleSpacings.defaultSpacing
|
||||
orientation: ListView.Horizontal
|
||||
delegate: NavigationListDelegate{
|
||||
id: delegate
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ ItemDelegate{
|
|||
property alias imageSource: contentImage.source
|
||||
|
||||
|
||||
padding: 5
|
||||
padding: StylePaddings.defaultPadding
|
||||
|
||||
background: Rectangle{
|
||||
id: background
|
||||
implicitWidth: 150
|
||||
implicitWidth: StyleSizes.navigationDelegateDefaultSize
|
||||
implicitHeight: implicitWidth
|
||||
radius: container.isCircleDelegate ? height/2 : 0
|
||||
color: "blue"
|
||||
|
|
@ -26,7 +26,7 @@ ItemDelegate{
|
|||
id: contentImage
|
||||
source: "qrc:/default_image"
|
||||
anchors.fill: parent
|
||||
anchors.margins: 5
|
||||
anchors.margins: StyleMargins.tinyMargin
|
||||
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
layer.enabled: true
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
Item {
|
||||
RowLayout{
|
||||
id: container
|
||||
property var model
|
||||
property var spacing: 20
|
||||
Row{
|
||||
id: buttons
|
||||
anchors.centerIn: parent
|
||||
spacing: container.spacing
|
||||
property var spacing: StyleSpacings.defaultSpacing
|
||||
|
||||
RoundImageButton{
|
||||
id: previous
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
diameter: 60
|
||||
diameter: StyleSizes.smallPlayerButtonSize //60
|
||||
imageSource: "qrc:/icon_previous"
|
||||
|
||||
enabled: model.pHasPrevious
|
||||
|
|
@ -24,8 +21,8 @@ Item {
|
|||
}
|
||||
RoundImageButton{
|
||||
id: playPause
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
diameter: 80
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
diameter: StyleSizes.largePlayerButtonSize
|
||||
imageSource: model.pIsPlaying ? "qrc:/icon_pause" : "qrc:/icon_play"
|
||||
|
||||
onClicked:{
|
||||
|
|
@ -34,9 +31,9 @@ Item {
|
|||
}
|
||||
RoundImageButton{
|
||||
id: stop
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
diameter: 60
|
||||
diameter: StyleSizes.smallPlayerButtonSize
|
||||
imageSource: "qrc:/icon_stop"
|
||||
|
||||
enabled: model.pIsPlaying
|
||||
|
|
@ -47,9 +44,9 @@ Item {
|
|||
}
|
||||
RoundImageButton{
|
||||
id: next
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
diameter: 60
|
||||
diameter: StyleSizes.smallPlayerButtonSize
|
||||
imageSource: "qrc:/icon_next"
|
||||
|
||||
enabled: model.pHasNext
|
||||
|
|
@ -58,5 +55,4 @@ Item {
|
|||
model.playNext();
|
||||
}
|
||||
}
|
||||
} //Row
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
Rectangle {
|
||||
id: container
|
||||
|
|
@ -6,28 +7,29 @@ Rectangle {
|
|||
property int margins
|
||||
|
||||
color: "#99ffffff"
|
||||
height: 140
|
||||
height: content.height + 2* margins //StyleSizes.playerControlPanelHeight
|
||||
|
||||
|
||||
ColumnLayout{
|
||||
id: content
|
||||
spacing: StyleSpacings.smallSpacing
|
||||
anchors.margins: container.margins
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
MediaProgress{
|
||||
id: progress
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: container.margins
|
||||
|
||||
model: container.model
|
||||
// might require height for labels to be shown on RasPi (Qt 5.10)
|
||||
//2019-04-04: defined in MediaProgress.qml -> test on rasPi
|
||||
}
|
||||
|
||||
PlayerButtons{
|
||||
id: buttons
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: progress.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: container.model
|
||||
spacing: 20
|
||||
spacing: StyleSpacings.defaultSpacing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Button {
|
|||
id: container
|
||||
property alias imageSource: image.source
|
||||
// default button diameter -> default width, readonly
|
||||
readonly property int defaultDiameter: 65
|
||||
readonly property int defaultDiameter: StyleSizes.roundButtonDefaultSize
|
||||
// button diameter -> width
|
||||
property int diameter: defaultDiameter
|
||||
// diameter of content image -> width
|
||||
|
|
@ -16,7 +16,7 @@ Button {
|
|||
|
||||
background: Rectangle{
|
||||
|
||||
border.width: 2
|
||||
border.width: StyleSizes.roundButtonBorderWidth
|
||||
border.color: "grey"
|
||||
|
||||
color: "white"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ ColumnLayout {
|
|||
property alias to: slider.to
|
||||
property alias stepSize: slider.stepSize
|
||||
property alias value: slider.value
|
||||
spacing: 5
|
||||
spacing: StyleSpacings.tinySpacing
|
||||
RoundImageButton{
|
||||
id: increaseButton
|
||||
imageSource: "qrc:///icon_increase_volume"
|
||||
|
|
|
|||
88
LenaPi/controllers/StyleController.cpp
Normal file
88
LenaPi/controllers/StyleController.cpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#include "StyleController.h"
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
|
||||
StyleController::StyleController(QObject *parent)
|
||||
: QObject{parent}, mStyleSizes(new QQmlPropertyMap(this)),
|
||||
mMargins(new QQmlPropertyMap(this)), mSpacings(new QQmlPropertyMap(this)), mPaddings(new QQmlPropertyMap(this))
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
void StyleController::calculateAndSetRatio()
|
||||
{
|
||||
qreal refHeight = 480;
|
||||
qreal refWidth = 800;
|
||||
// Scales to fullscreen. No rescaling when changing window size
|
||||
QRect rect = QGuiApplication::primaryScreen()->geometry();
|
||||
qreal height = qMax(rect.width(),rect.height());
|
||||
qreal width = qMin(rect.width(), rect.height());
|
||||
|
||||
mRatio = qMin(height/refHeight, width/refWidth);
|
||||
}
|
||||
|
||||
void StyleController::initStyleSizes()
|
||||
{
|
||||
scaleAndInsert(mStyleSizes, "roundButtonDefaultSize", 65);
|
||||
scaleAndInsert(mStyleSizes, "roundButtonBorderWidth", 2);
|
||||
scaleAndInsert(mStyleSizes, "smallPlayerButtonSize", 60);
|
||||
scaleAndInsert(mStyleSizes, "largePlayerButtonSize", 80);
|
||||
|
||||
scaleAndInsert(mStyleSizes, "scrollHandleWidth", 16);
|
||||
scaleAndInsert(mStyleSizes, "scrollHandleHeight", 8);
|
||||
scaleAndInsert(mStyleSizes, "scrollHandleBorderWidth", 1);
|
||||
|
||||
int progressBackgroundDefaultHeight = 10;
|
||||
scaleAndInsert(mStyleSizes, "progressBackgroundDefaultHeight", progressBackgroundDefaultHeight);
|
||||
scaleAndInsert(mStyleSizes, "progressBackgroundRadius", progressBackgroundDefaultHeight/2);
|
||||
scaleAndInsert(mStyleSizes, "progressBarDefaultHeight", 8);
|
||||
scaleAndInsert(mStyleSizes, "progressBackgroundBorderWidth", 1);
|
||||
|
||||
scaleAndInsert(mStyleSizes, "navigationListHeight", 210);
|
||||
scaleAndInsert(mStyleSizes, "navigationDelegateDefaultSize", 150);
|
||||
|
||||
}
|
||||
|
||||
void StyleController::initSpacings()
|
||||
{
|
||||
scaleAndInsert(mSpacings, "defaultSpacing", 20);
|
||||
scaleAndInsert(mSpacings, "smallSpacing", 10);
|
||||
scaleAndInsert(mSpacings, "tinySpacing", 5);
|
||||
}
|
||||
|
||||
void StyleController::initMargins()
|
||||
{
|
||||
scaleAndInsert(mMargins, "defaultMargin", 20);
|
||||
scaleAndInsert(mMargins, "smallMargin", 10);
|
||||
scaleAndInsert(mMargins, "tinyMargin", 5);
|
||||
scaleAndInsert(mMargins, "scrollHandleMargins", 1);
|
||||
}
|
||||
|
||||
void StyleController::initPaddings()
|
||||
{
|
||||
scaleAndInsert(mPaddings, "defaultPadding", 5);
|
||||
}
|
||||
|
||||
void StyleController::scaleAndInsert(QQmlPropertyMap *map, const QString &key, int value)
|
||||
{
|
||||
map->insert(key, applyRatio(value));
|
||||
}
|
||||
|
||||
int StyleController::applyRatio(int size) const
|
||||
{
|
||||
return size*mRatio;
|
||||
}
|
||||
|
||||
void StyleController::init(QQmlContext *context)
|
||||
{
|
||||
calculateAndSetRatio();
|
||||
initStyleSizes();
|
||||
initMargins();
|
||||
initSpacings();
|
||||
initPaddings();
|
||||
|
||||
context->setContextProperty("StyleSizes", mStyleSizes);
|
||||
context->setContextProperty("StyleSpacings", mSpacings);
|
||||
context->setContextProperty("StyleMargins", mMargins);
|
||||
context->setContextProperty("StylePaddings", mPaddings);
|
||||
}
|
||||
78
LenaPi/controllers/StyleController.h
Normal file
78
LenaPi/controllers/StyleController.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef STYLECONTROLLER_H
|
||||
#define STYLECONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlContext>
|
||||
#include <QQmlPropertyMap>
|
||||
|
||||
/**
|
||||
* @brief Contains all style sizes, margins and paddings used throughout the application
|
||||
*
|
||||
* Based on a reference screen size, maps for scaled margins, paddings and spacings are created and
|
||||
* registered in the QML context. The values stored in the maps can then be used from QML.
|
||||
* Map names: StyleSizes, StylePaddings, StyleSpacings, StyleMargins
|
||||
*
|
||||
* Always use values from these maps in QML! Never use magic numbers! They will NOT scale when
|
||||
* the application is run on a different screen.
|
||||
*
|
||||
* See https://doc.qt.io/qt-5/scalability.html
|
||||
*/
|
||||
class StyleController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit StyleController(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Calculates ratio, initializes all maps and registers them in QML context
|
||||
* @param context Context to register Maps in
|
||||
*/
|
||||
void init(QQmlContext* context);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Calculates ratio from reference screen size and size of the current primary screen and inits member mRatio
|
||||
*/
|
||||
void calculateAndSetRatio();
|
||||
/**
|
||||
* @brief Initializes map containing all sizes (e.g., button or delegate sizes)
|
||||
*/
|
||||
void initStyleSizes();
|
||||
/**
|
||||
* @brief Initializes map containing all spacings
|
||||
*/
|
||||
void initSpacings();
|
||||
/**
|
||||
* @brief Initializes map containing all margins
|
||||
*/
|
||||
void initMargins();
|
||||
/**
|
||||
* @brief Initializes map containing all paddings
|
||||
*/
|
||||
void initPaddings();
|
||||
/**
|
||||
* @brief Scales the value with calculated ratio and inserts it into the given map under the given key
|
||||
* @param map Map to insert key-value pair into
|
||||
* @param key Key used in the map. This is the name used to retrieve the value in QML
|
||||
* @param value Unscaled value
|
||||
* @see mRatio
|
||||
*
|
||||
* In QML the value with the key "defaulSpacing" in the Map "StyleSpacings" is accessed by StyleSpacings.defaultSpacing
|
||||
*/
|
||||
void scaleAndInsert(QQmlPropertyMap* map, const QString& key, int value);
|
||||
/**
|
||||
* @brief Applys ratio to given size
|
||||
* @param size Size to be scaled
|
||||
* @return scaled size
|
||||
* @see mRatio
|
||||
*/
|
||||
int applyRatio(int size) const;
|
||||
|
||||
qreal mRatio = 1.0;
|
||||
QQmlPropertyMap* mStyleSizes = nullptr;
|
||||
QQmlPropertyMap* mMargins = nullptr;
|
||||
QQmlPropertyMap* mSpacings = nullptr;
|
||||
QQmlPropertyMap* mPaddings = nullptr;
|
||||
};
|
||||
|
||||
#endif // STYLECONTROLLER_H
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include <QCommandLineParser>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
#include <controllers/StyleController.h>
|
||||
#include "controllers/NavigationController.h"
|
||||
#include "MouseEventSpy.h"
|
||||
#include "EnergySaver.h"
|
||||
|
|
@ -42,6 +43,9 @@ int main(int argc, char *argv[])
|
|||
const auto settingsHandler = SettingsHandler::createSettingsHandlerAndFillWithDefaultsIfMissing(settings);
|
||||
|
||||
|
||||
// init style
|
||||
StyleController styleController;
|
||||
styleController.init(engine.rootContext());
|
||||
// init main app
|
||||
NavigationController navController;
|
||||
navController.setContext(engine.rootContext());
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import QtQuick.Controls 2.4
|
|||
|
||||
Window {
|
||||
visible: true
|
||||
width: 800
|
||||
height: 480
|
||||
// width: 800
|
||||
//height: 480
|
||||
title: "LenaPi 1.2"
|
||||
|
||||
Component.onCompleted: showMaximized();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue