Add-ons page UI improvements based on feedback
This commit is contained in:
parent
510f2de84d
commit
8a390dab2a
7 changed files with 415 additions and 379 deletions
|
@ -2,412 +2,426 @@ import QtQuick 2.4
|
||||||
import FlightGear.Launcher 1.0
|
import FlightGear.Launcher 1.0
|
||||||
import "."
|
import "."
|
||||||
|
|
||||||
Flickable {
|
Item {
|
||||||
flickableDirection: Flickable.VerticalFlick
|
Flickable {
|
||||||
contentHeight: contents.childrenRect.height
|
id: flick
|
||||||
|
height: parent.height
|
||||||
|
width: parent.width - scrollbar.width
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
contentHeight: contents.childrenRect.height
|
||||||
|
|
||||||
interactive: false
|
Component {
|
||||||
|
id: catalogDelegate
|
||||||
|
|
||||||
Component {
|
Rectangle {
|
||||||
id: catalogDelegate
|
id: delegateRoot
|
||||||
|
|
||||||
Rectangle {
|
// don't show the delegate for newly added catalogs, until the
|
||||||
id: delegateRoot
|
// adding process is complete
|
||||||
|
visible: !model.isNewlyAdded
|
||||||
|
|
||||||
// don't show the delegate for newly added catalogs, until the
|
height: catalogTextColumn.childrenRect.height + Style.margin * 2
|
||||||
// adding process is complete
|
border.width: 1
|
||||||
visible: !model.isNewlyAdded
|
border.color: Style.themeColor
|
||||||
|
width: catalogsColumn.width
|
||||||
height: catalogTextColumn.childrenRect.height + Style.margin * 2
|
|
||||||
border.width: 1
|
|
||||||
border.color: Style.themeColor
|
|
||||||
width: catalogsColumn.width
|
|
||||||
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: catalogTextColumn
|
id: catalogTextColumn
|
||||||
|
|
||||||
y: Style.margin
|
y: Style.margin
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: Style.margin
|
anchors.leftMargin: Style.margin
|
||||||
anchors.right: catalogDeleteButton.left
|
anchors.right: catalogDeleteButton.left
|
||||||
anchors.rightMargin: Style.margin
|
anchors.rightMargin: Style.margin
|
||||||
spacing: Style.margin
|
spacing: Style.margin
|
||||||
|
|
||||||
|
Text {
|
||||||
|
font.pixelSize: Style.subHeadingFontPixelSize
|
||||||
|
font.bold: true
|
||||||
|
width: parent.width
|
||||||
|
text: model.name
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
visible: model.status === CatalogListModel.Ok
|
||||||
|
width: parent.width
|
||||||
|
text: model.description
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
ClickableText {
|
||||||
|
visible: model.status !== CatalogListModel.Ok
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: qsTr("This hangar is currently disabled due to a problem. " +
|
||||||
|
"Click here to try updating the hangar information from the server. "
|
||||||
|
+ "(An Internet connection is required for this)");
|
||||||
|
onClicked: {
|
||||||
|
_addOns.catalogs.refreshCatalog(model.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
width: parent.width
|
||||||
|
text: model.url
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
|
||||||
font.pixelSize: Style.subHeadingFontPixelSize
|
|
||||||
font.bold: true
|
|
||||||
width: parent.width
|
|
||||||
text: model.name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
DeleteButton {
|
||||||
visible: model.status === CatalogListModel.Ok
|
id: catalogDeleteButton
|
||||||
width: parent.width
|
anchors.right: parent.right
|
||||||
text: model.description
|
anchors.rightMargin: Style.margin
|
||||||
wrapMode: Text.WordWrap
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
visible: delegateHover.containsMouse
|
||||||
|
|
||||||
ClickableText {
|
|
||||||
visible: model.status !== CatalogListModel.Ok
|
|
||||||
width: parent.width
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
text: qsTr("This hangar is currently disabled due to a problem. " +
|
|
||||||
"Click here to try updating the hangar information from the server. "
|
|
||||||
+ "(An Internet connection is required for this)");
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
_addOns.catalogs.refreshCatalog(model.index)
|
confirmDeleteHangar.visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: delegateHover
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
}
|
||||||
|
|
||||||
|
YesNoPanel {
|
||||||
|
id: confirmDeleteHangar
|
||||||
|
visible: false
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
yesText: qsTr("Remove")
|
||||||
|
noText: qsTr("Cancel")
|
||||||
|
yesIsDestructive: true
|
||||||
|
promptText: qsTr("Remove this hangar? (Downloaded aircraft will be deleted from your computer)");
|
||||||
|
onAccepted: {
|
||||||
|
_addOns.catalogs.removeCatalog(model.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRejected: {
|
||||||
|
confirmDeleteHangar.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: contents
|
||||||
|
width: parent.width - (Style.margin * 2)
|
||||||
|
x: Style.margin
|
||||||
|
spacing: Style.margin
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// catalogs //////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: catalogHeaderItem
|
||||||
|
width: parent.width
|
||||||
|
height: catalogHeadingText.height + catalogDescriptionText.height + Style.margin
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: catalogHeadingText
|
||||||
|
text: qsTr("Aircraft hangars")
|
||||||
|
font.pixelSize: Style.headingFontPixelSize
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: catalogDescriptionText
|
||||||
|
text: qsTr("Aircraft hangars are managed collections of aircraft, which can be " +
|
||||||
|
"downloaded, installed and updated inside FlightGear.")
|
||||||
|
anchors {
|
||||||
|
top: catalogHeadingText.bottom
|
||||||
|
topMargin: Style.margin
|
||||||
|
}
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // of catalogs header item
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: catalogsColumn.childrenRect.height + Style.margin * 2
|
||||||
|
border.width: 1
|
||||||
|
border.color: Style.frameColor
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: catalogsColumn
|
||||||
|
width: parent.width - Style.margin * 2
|
||||||
|
x: Style.margin
|
||||||
|
y: Style.margin
|
||||||
|
spacing: Style.margin
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: catalogsRepeater
|
||||||
|
model: _addOns.catalogs
|
||||||
|
delegate: catalogDelegate
|
||||||
|
}
|
||||||
|
|
||||||
|
ClickableText {
|
||||||
|
visible: !_addOns.isOfficialHangarRegistered && !addCatalogPanel.isActive
|
||||||
|
width: parent.width
|
||||||
|
text : qsTr("The official FlightGear aircraft hangar is not set up. To add it, click here.");
|
||||||
|
onClicked: {
|
||||||
|
_addOns.catalogs.installDefaultCatalog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AddCatalogPanel {
|
||||||
|
id: addCatalogPanel
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Item {
|
||||||
|
// spacing item
|
||||||
|
width: parent.width
|
||||||
|
height: Style.margin * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: aircraftHeaderItem
|
||||||
|
width: parent.width
|
||||||
|
height: aircraftHeading.height + aircraftDescriptionText.height + Style.margin
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: aircraftHeading
|
||||||
|
text: qsTr("Additional aircraft folders")
|
||||||
|
font.pixelSize: Style.headingFontPixelSize
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: addAircraftPathButton.left
|
||||||
|
rightMargin: Style.margin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
width: parent.width
|
id: aircraftDescriptionText
|
||||||
text: model.url
|
text: qsTr("To use aircraft you download yourself, FlightGear needs to " +
|
||||||
|
"know the folder(s) containing the aircraft data.")
|
||||||
|
anchors {
|
||||||
|
top: aircraftHeading.bottom
|
||||||
|
topMargin: Style.margin
|
||||||
|
left: parent.left
|
||||||
|
right: addAircraftPathButton.left
|
||||||
|
rightMargin: Style.margin
|
||||||
|
}
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddButton {
|
||||||
|
id: addAircraftPathButton
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
var newPath =_addOns.addAircraftPath();
|
||||||
|
if (newPath !== "") {
|
||||||
|
_addOns.aircraftPaths.push(newPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // of aircraft header item
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: aircraftPathsColumn.childrenRect.height + 1
|
||||||
|
border.width: 1
|
||||||
|
border.color: Style.frameColor
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: aircraftPathsColumn
|
||||||
|
width: parent.width - Style.margin * 2
|
||||||
|
x: Style.margin
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: aircraftPathsRepeater
|
||||||
|
model: _addOns.aircraftPaths
|
||||||
|
delegate: PathListDelegate {
|
||||||
|
width: aircraftPathsColumn.width
|
||||||
|
deletePromptText: qsTr("Remove the aircraft folder: '%1' from the list? (The folder contents will not be changed)").arg(modelData);
|
||||||
|
modelCount: _addOns.aircraftPaths.length
|
||||||
|
|
||||||
|
onPerformDelete: {
|
||||||
|
var modifiedPaths = _addOns.aircraftPaths.slice()
|
||||||
|
modifiedPaths.splice(model.index, 1);
|
||||||
|
_addOns.aircraftPaths = modifiedPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
onPerformMove: {
|
||||||
|
var modifiedPaths = _addOns.aircraftPaths.slice()
|
||||||
|
modifiedPaths.splice(model.index, 1);
|
||||||
|
modifiedPaths.splice(newIndex, 0, modelData)
|
||||||
|
_addOns.aircraftPaths = modifiedPaths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
visible: (aircraftPathsRepeater.count == 0)
|
||||||
|
width: parent.width
|
||||||
|
text : qsTr("No custom aircraft paths are configured.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteButton {
|
//////////////////////////////////////////////////////////////////
|
||||||
id: catalogDeleteButton
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Style.margin
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: delegateHover.containsMouse
|
|
||||||
|
|
||||||
onClicked: {
|
Item {
|
||||||
confirmDeleteHangar.visible = true;
|
// spacing item
|
||||||
|
width: parent.width
|
||||||
|
height: Style.margin * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: sceneryHeaderItem
|
||||||
|
width: parent.width
|
||||||
|
height: sceneryHeading.height + sceneryDescriptionText.height + Style.margin
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: sceneryHeading
|
||||||
|
text: qsTr("Additional scenery folders")
|
||||||
|
font.pixelSize: Style.headingFontPixelSize
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: addSceneryPathButton.left
|
||||||
|
rightMargin: Style.margin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: sceneryDescriptionText
|
||||||
|
text: qsTr("To use scenery you download yourself, FlightGear needs " +
|
||||||
|
"to know the folders containing the scenery data. " +
|
||||||
|
"Adjust the order of the list to control which scenery is used in a region.");
|
||||||
|
anchors {
|
||||||
|
top: sceneryHeading.bottom
|
||||||
|
topMargin: Style.margin
|
||||||
|
left: parent.left
|
||||||
|
right: addSceneryPathButton.left
|
||||||
|
rightMargin: Style.margin
|
||||||
|
}
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
AddButton {
|
||||||
|
id: addSceneryPathButton
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
var newPath =_addOns.addSceneryPath();
|
||||||
|
if (newPath !== "") {
|
||||||
|
_addOns.sceneryPaths.push(newPath)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // of aircraft header item
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: sceneryPathsColumn.childrenRect.height + 1
|
||||||
|
border.width: 1
|
||||||
|
border.color: Style.frameColor
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: sceneryPathsColumn
|
||||||
|
width: parent.width - Style.margin * 2
|
||||||
|
x: Style.margin
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: sceneryPathsRepeater
|
||||||
|
model: _addOns.sceneryPaths
|
||||||
|
|
||||||
|
delegate: PathListDelegate {
|
||||||
|
width: sceneryPathsColumn.width
|
||||||
|
deletePromptText: qsTr("Remove the scenery folder: '%1' from the list? (The folder contents will not be changed)").arg(modelData);
|
||||||
|
modelCount: _addOns.sceneryPaths.length
|
||||||
|
|
||||||
|
onPerformDelete: {
|
||||||
|
var modifiedPaths = _addOns.sceneryPaths.slice()
|
||||||
|
modifiedPaths.splice(model.index, 1);
|
||||||
|
_addOns.sceneryPaths = modifiedPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
onPerformMove: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
visible: (sceneryPathsRepeater.count == 0)
|
||||||
|
width: parent.width
|
||||||
|
text : qsTr("No custom scenery paths are configured.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
Item {
|
||||||
id: delegateHover
|
width: parent.width
|
||||||
anchors.fill: parent
|
height: Math.max(installTarballText.implicitHeight, installTarballButton.height)
|
||||||
hoverEnabled: true
|
Button {
|
||||||
acceptedButtons: Qt.NoButton
|
id: installTarballButton
|
||||||
}
|
text: "Install add-on scenery"
|
||||||
|
|
||||||
YesNoPanel {
|
onClicked: {
|
||||||
id: confirmDeleteHangar
|
var path = _addOns.installCustomScenery();
|
||||||
visible: false
|
if (path !== "") {
|
||||||
anchors.fill: parent
|
// insert into scenery paths if not already present
|
||||||
|
for (var p in _addOns.sceneryPaths) {
|
||||||
|
if (p === path)
|
||||||
|
return; // found, we are are done
|
||||||
|
}
|
||||||
|
|
||||||
yesText: qsTr("Remove")
|
// not found, add it
|
||||||
noText: qsTr("Cancel")
|
_addOns.sceneryPaths.push(path);
|
||||||
yesIsDestructive: true
|
}
|
||||||
promptText: qsTr("Remove this hangar? (Downloaded aircraft will be deleted from your computer)");
|
}
|
||||||
onAccepted: {
|
|
||||||
_addOns.catalogs.removeCatalog(model.index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onRejected: {
|
Text {
|
||||||
confirmDeleteHangar.visible = false
|
id: installTarballText
|
||||||
|
anchors {
|
||||||
|
left: installTarballButton.right
|
||||||
|
right: parent.right
|
||||||
|
leftMargin: Style.margin
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: qsTr("If you have downloaded scenery manually from the official FlightGear website, " +
|
||||||
|
"you can use this button to extract and install it into a suitable folder. " +
|
||||||
|
"(Scenery downloaded this way should have a file name such as 'w40n020.tar.gz')"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
} // of install-tarbal item
|
||||||
|
} // of column
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Scrollbar {
|
||||||
id: contents
|
id: scrollbar
|
||||||
width: parent.width - (Style.margin * 2)
|
anchors.right: parent.right
|
||||||
x: Style.margin
|
height: parent.height
|
||||||
spacing: Style.margin
|
flickable: flick
|
||||||
|
visible: flick.contentHeight > flick.height
|
||||||
//////////////////////////////////////////////////////////////////
|
}
|
||||||
// catalogs //////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: catalogHeaderItem
|
|
||||||
width: parent.width
|
|
||||||
height: catalogHeadingText.height + catalogDescriptionText.height + Style.margin
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: catalogHeadingText
|
|
||||||
text: qsTr("Aircraft hangars")
|
|
||||||
font.pixelSize: Style.headingFontPixelSize
|
|
||||||
width: parent.width
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: catalogDescriptionText
|
|
||||||
text: qsTr("Aircraft hangars are managed collections of aircraft, which can be " +
|
|
||||||
"downloaded, installed and updated inside FlightGear.")
|
|
||||||
anchors {
|
|
||||||
top: catalogHeadingText.bottom
|
|
||||||
topMargin: Style.margin
|
|
||||||
}
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // of catalogs header item
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: catalogsColumn.childrenRect.height + Style.margin * 2
|
|
||||||
border.width: 1
|
|
||||||
border.color: Style.frameColor
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: catalogsColumn
|
|
||||||
width: parent.width - Style.margin * 2
|
|
||||||
x: Style.margin
|
|
||||||
y: Style.margin
|
|
||||||
spacing: Style.margin
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
id: catalogsRepeater
|
|
||||||
model: _addOns.catalogs
|
|
||||||
delegate: catalogDelegate
|
|
||||||
}
|
|
||||||
|
|
||||||
ClickableText {
|
|
||||||
visible: !_addOns.isOfficialHangarRegistered && !addCatalogPanel.isActive
|
|
||||||
width: parent.width
|
|
||||||
text : qsTr("The official FlightGear aircraft hangar is not set up. To add it, click here.");
|
|
||||||
onClicked: {
|
|
||||||
_addOns.catalogs.installDefaultCatalog()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AddCatalogPanel {
|
|
||||||
id: addCatalogPanel
|
|
||||||
width: parent.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Item {
|
|
||||||
// spacing item
|
|
||||||
width: parent.width
|
|
||||||
height: Style.margin * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: aircraftHeaderItem
|
|
||||||
width: parent.width
|
|
||||||
height: aircraftHeading.height + aircraftDescriptionText.height + Style.margin
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: aircraftHeading
|
|
||||||
text: qsTr("Additional aircraft folders")
|
|
||||||
font.pixelSize: Style.headingFontPixelSize
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
right: addAircraftPathButton.left
|
|
||||||
rightMargin: Style.margin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: aircraftDescriptionText
|
|
||||||
text: qsTr("To use aircraft you download yourself, FlightGear needs to " +
|
|
||||||
"know the folder(s) containing the aircraft data.")
|
|
||||||
anchors {
|
|
||||||
top: aircraftHeading.bottom
|
|
||||||
topMargin: Style.margin
|
|
||||||
left: parent.left
|
|
||||||
right: addAircraftPathButton.left
|
|
||||||
rightMargin: Style.margin
|
|
||||||
}
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
|
||||||
|
|
||||||
AddButton {
|
|
||||||
id: addAircraftPathButton
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
onClicked: {
|
|
||||||
var newPath =_addOns.addAircraftPath();
|
|
||||||
if (newPath != "") {
|
|
||||||
_addOns.aircraftPaths.push(newPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // of aircraft header item
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: aircraftPathsColumn.childrenRect.height + 1
|
|
||||||
border.width: 1
|
|
||||||
border.color: Style.frameColor
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: aircraftPathsColumn
|
|
||||||
width: parent.width - Style.margin * 2
|
|
||||||
x: Style.margin
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
id: aircraftPathsRepeater
|
|
||||||
model: _addOns.aircraftPaths
|
|
||||||
delegate: PathListDelegate {
|
|
||||||
width: aircraftPathsColumn.width
|
|
||||||
deletePromptText: qsTr("Remove the aircraft folder: '%1' from the list? (The folder contents will not be changed)").arg(modelData);
|
|
||||||
|
|
||||||
onPerformDelete: {
|
|
||||||
var modifiedPaths = _addOns.aircraftPaths.slice()
|
|
||||||
modifiedPaths.splice(model.index, 1);
|
|
||||||
_addOns.aircraftPaths = modifiedPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
onPerformMove: {
|
|
||||||
var modifiedPaths = _addOns.aircraftPaths.slice()
|
|
||||||
modifiedPaths.splice(model.index, 1);
|
|
||||||
modifiedPaths.splice(newIndex, 0, modelData)
|
|
||||||
_addOns.aircraftPaths = modifiedPaths;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
visible: (aircraftPathsRepeater.count == 0)
|
|
||||||
width: parent.width
|
|
||||||
text : qsTr("No custom aircraft paths are configured.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Item {
|
|
||||||
// spacing item
|
|
||||||
width: parent.width
|
|
||||||
height: Style.margin * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: sceneryHeaderItem
|
|
||||||
width: parent.width
|
|
||||||
height: sceneryHeading.height + sceneryDescriptionText.height + Style.margin
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: sceneryHeading
|
|
||||||
text: qsTr("Additional scenery folders")
|
|
||||||
font.pixelSize: Style.headingFontPixelSize
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
right: addSceneryPathButton.left
|
|
||||||
rightMargin: Style.margin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: sceneryDescriptionText
|
|
||||||
text: qsTr("To use scenery you download yourself, FlightGear needs " +
|
|
||||||
"to know the folders containing the scenery data. " +
|
|
||||||
"Adjust the order of the list to control which scenery is used in a region.");
|
|
||||||
anchors {
|
|
||||||
top: sceneryHeading.bottom
|
|
||||||
topMargin: Style.margin
|
|
||||||
left: parent.left
|
|
||||||
right: addSceneryPathButton.left
|
|
||||||
rightMargin: Style.margin
|
|
||||||
}
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
|
||||||
|
|
||||||
AddButton {
|
|
||||||
id: addSceneryPathButton
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
onClicked: {
|
|
||||||
var newPath =_addOns.addSceneryPath();
|
|
||||||
if (newPath !== "") {
|
|
||||||
_addOns.sceneryPaths.push(newPath)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // of aircraft header item
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: sceneryPathsColumn.childrenRect.height + 1
|
|
||||||
border.width: 1
|
|
||||||
border.color: Style.frameColor
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: sceneryPathsColumn
|
|
||||||
width: parent.width - Style.margin * 2
|
|
||||||
x: Style.margin
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
id: sceneryPathsRepeater
|
|
||||||
model: _addOns.sceneryPaths
|
|
||||||
|
|
||||||
delegate: PathListDelegate {
|
|
||||||
width: sceneryPathsColumn.width
|
|
||||||
deletePromptText: qsTr("Remove the scenery folder: '%1' from the list? (The folder contents will not be changed)").arg(modelData);
|
|
||||||
|
|
||||||
onPerformDelete: {
|
|
||||||
var modifiedPaths = _addOns.sceneryPaths.slice()
|
|
||||||
modifiedPaths.splice(model.index, 1);
|
|
||||||
_addOns.sceneryPaths = modifiedPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
onPerformMove: {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
visible: (sceneryPathsRepeater.count == 0)
|
|
||||||
width: parent.width
|
|
||||||
text : qsTr("No custom scenery paths are configured.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: parent.width
|
|
||||||
height: Math.max(installTarballText.implicitHeight, installTarballButton.height)
|
|
||||||
Button {
|
|
||||||
id: installTarballButton
|
|
||||||
text: "Install add-on scenery"
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
var path = _addOns.installCustomScenery();
|
|
||||||
if (path != "") {
|
|
||||||
// insert into scenery paths if not already present
|
|
||||||
for (var p in _addOns.sceneryPaths) {
|
|
||||||
if (p === path)
|
|
||||||
return; // found, we are are done
|
|
||||||
}
|
|
||||||
|
|
||||||
// not found, add it
|
|
||||||
_addOns.sceneryPaths.push(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: installTarballText
|
|
||||||
anchors {
|
|
||||||
left: installTarballButton.right
|
|
||||||
right: parent.right
|
|
||||||
leftMargin: Style.margin
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
text: qsTr("If you have downloaded scenery manually from the official FlightGear website, " +
|
|
||||||
"you can use this button to extract and install it into a suitable folder. " +
|
|
||||||
"(Scenery downloaded this way should have a file name such as 'w40n020.tar.gz')"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} // of install-tarbal item
|
|
||||||
} // of column
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ Item {
|
||||||
id: icon
|
id: icon
|
||||||
x: 0
|
x: 0
|
||||||
y: 0
|
y: 0
|
||||||
source: "qrc:///cancel-icon"
|
source: "qrc:///cancel-icon-small"
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import QtQuick 2.4
|
import QtQuick 2.4
|
||||||
|
import "."
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
property bool canMoveUp: true
|
||||||
|
property bool canMoveDown: true
|
||||||
|
|
||||||
width: height
|
width: height
|
||||||
height: icon.implicitHeight + 1
|
height: icon.implicitHeight + 1
|
||||||
|
visible: canMoveDown || canMoveUp
|
||||||
|
|
||||||
signal moveUp();
|
signal moveUp();
|
||||||
signal moveDown();
|
signal moveDown();
|
||||||
|
@ -12,12 +16,14 @@ Item {
|
||||||
id: icon
|
id: icon
|
||||||
x: 0
|
x: 0
|
||||||
y: 0
|
y: 0
|
||||||
source: "qrc:///reorder-list-icon"
|
source: "qrc:///reorder-list-icon-small"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: moveUpArea
|
id: moveUpArea
|
||||||
|
enabled: parent.canMoveUp
|
||||||
|
hoverEnabled: enabled
|
||||||
height: parent.height / 2
|
height: parent.height / 2
|
||||||
width: parent.width
|
width: parent.width
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -27,6 +33,8 @@ Item {
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: moveDownArea
|
id: moveDownArea
|
||||||
|
enabled: parent.canMoveDown
|
||||||
|
hoverEnabled: enabled
|
||||||
height: parent.height / 2
|
height: parent.height / 2
|
||||||
width: parent.width
|
width: parent.width
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
@ -34,4 +42,12 @@ Item {
|
||||||
parent.moveDown();
|
parent.moveDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.left
|
||||||
|
anchors.rightMargin: Style.margin
|
||||||
|
visible: moveUpArea.containsMouse || moveDownArea.containsMouse
|
||||||
|
text: moveUpArea.containsMouse ? qsTr("Move up") : qsTr("Move down")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ Item {
|
||||||
signal performMove(var newIndex);
|
signal performMove(var newIndex);
|
||||||
|
|
||||||
property alias deletePromptText: confirmDeletePath.promptText
|
property alias deletePromptText: confirmDeletePath.promptText
|
||||||
|
property int modelCount: 0
|
||||||
|
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
|
|
||||||
|
@ -72,7 +73,10 @@ Item {
|
||||||
id: reorderButton
|
id: reorderButton
|
||||||
anchors.right: pathDeleteButton.left
|
anchors.right: pathDeleteButton.left
|
||||||
anchors.rightMargin: Style.margin
|
anchors.rightMargin: Style.margin
|
||||||
visible: pathDelegateHover.containsMouse
|
visible: pathDelegateHover.containsMouse && (canMoveDown || canMoveUp)
|
||||||
|
|
||||||
|
canMoveUp: model.index > 0
|
||||||
|
canMoveDown: model.index < (delegateRoot.modelCount - 1)
|
||||||
|
|
||||||
onMoveUp: {
|
onMoveUp: {
|
||||||
if (model.index === 0)
|
if (model.index === 0)
|
||||||
|
|
BIN
src/GUI/qml/icons8-cancel-25.png
Normal file
BIN
src/GUI/qml/icons8-cancel-25.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
src/GUI/qml/icons8-drag-reorder-filled-25.png
Normal file
BIN
src/GUI/qml/icons8-drag-reorder-filled-25.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
|
@ -78,6 +78,8 @@
|
||||||
<file>qml/AddButton.qml</file>
|
<file>qml/AddButton.qml</file>
|
||||||
<file alias="cancel-icon">qml/icons8-cancel-50.png</file>
|
<file alias="cancel-icon">qml/icons8-cancel-50.png</file>
|
||||||
<file alias="reorder-list-icon">qml/icons8-drag-reorder-filled-50.png</file>
|
<file alias="reorder-list-icon">qml/icons8-drag-reorder-filled-50.png</file>
|
||||||
|
<file alias="cancel-icon-small">qml/icons8-cancel-25.png</file>
|
||||||
|
<file alias="reorder-list-icon-small">qml/icons8-drag-reorder-filled-25.png</file>
|
||||||
<file alias="add-icon">qml/icons8-plus-26.png</file>
|
<file alias="add-icon">qml/icons8-plus-26.png</file>
|
||||||
<file>qml/DeleteButton.qml</file>
|
<file>qml/DeleteButton.qml</file>
|
||||||
<file>qml/YesNoPanel.qml</file>
|
<file>qml/YesNoPanel.qml</file>
|
||||||
|
|
Loading…
Add table
Reference in a new issue