mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-07-17 08:37:17 +02:00
Merge pull request #2599 from alicevision/dev/qt6.6
Qt6.6.3 / PySide6.6.3.1 upgrade
This commit is contained in:
commit
66e3dd409d
145 changed files with 2346 additions and 1702 deletions
|
@ -1,3 +1,5 @@
|
|||
# [qt6][qml] Clean-up code and harmonize comments
|
||||
5a0b1c0c9547b0d00f3f10fae6994d6d8ea0b45e
|
||||
# [nodes] Linting: Clean-up files
|
||||
4c0409f573c2694325b104c2686a1532f95cb9bc
|
||||
# Linting: Clean-up files
|
||||
|
|
|
@ -15,7 +15,7 @@ Meshroom is licensed under the [MPL2 license](LICENSE-MPL2.md).
|
|||
Copyright (c) 2001-2018 Python Software Foundation.
|
||||
Distributed under the [PSFL V2 license](https://www.python.org/download/releases/2.7/license/).
|
||||
|
||||
* __Qt/PySide2__
|
||||
* __Qt/PySide6__
|
||||
[https://www.qt.io](https://www.qt.io)
|
||||
Copyright (C) 2018 The Qt Company Ltd and other contributors.
|
||||
Distributed under the [LGPL V3 license](https://opensource.org/licenses/LGPL-3.0).
|
||||
|
|
|
@ -157,3 +157,4 @@ def setupEnvironment(backend=Backend.STANDALONE):
|
|||
os.environ["QML_XHR_ALLOW_FILE_READ"] = '1'
|
||||
os.environ["QML_XHR_ALLOW_FILE_WRITE"] = '1'
|
||||
os.environ["PYSEQ_STRICT_PAD"] = '1'
|
||||
os.environ["QSG_RHI_BACKEND"] = "opengl"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from PySide2 import QtCore, QtQml
|
||||
import shiboken2
|
||||
from PySide6 import QtCore, QtQml
|
||||
import shiboken6
|
||||
|
||||
|
||||
class QObjectListModel(QtCore.QAbstractListModel):
|
||||
|
@ -285,7 +285,7 @@ class QObjectListModel(QtCore.QAbstractListModel):
|
|||
|
||||
def _dereferenceItem(self, item):
|
||||
# Ask for object deletion if parented to the model
|
||||
if shiboken2.isValid(item) and item.parent() == self:
|
||||
if shiboken6.isValid(item) and item.parent() == self:
|
||||
# delay deletion until the next event loop
|
||||
# This avoids warnings when the QML engine tries to evaluate (but should not)
|
||||
# an object that has already been deleted
|
||||
|
|
|
@ -116,8 +116,11 @@ class StatusData(BaseObject):
|
|||
|
||||
def toDict(self):
|
||||
d = self.__dict__.copy()
|
||||
d.pop('destroyed', None) # skip non data attributes from BaseObject
|
||||
d["elapsedTimeStr"] = self.elapsedTimeStr
|
||||
|
||||
# Skip non data attributes from BaseObject
|
||||
d.pop("destroyed", None)
|
||||
d.pop("objectNameChanged", None)
|
||||
return d
|
||||
|
||||
def fromDict(self, d):
|
||||
|
|
|
@ -39,7 +39,7 @@ class SimpleFarmSubmitter(BaseSubmitter):
|
|||
# logging.info('REZ: {}'.format(str(r)))
|
||||
v = r.split('-')
|
||||
# logging.info(' v: {}'.format(str(v)))
|
||||
if len(v) == 2:
|
||||
if len(v) >= 2:
|
||||
resolvedVersions[v[0]] = v[1]
|
||||
for p in packages:
|
||||
if p.startswith('~'):
|
||||
|
|
|
@ -10,4 +10,4 @@ import meshroom.ui
|
|||
import meshroom.ui.app
|
||||
|
||||
meshroom.ui.uiInstance = meshroom.ui.app.MeshroomApp(sys.argv)
|
||||
meshroom.ui.uiInstance.exec_()
|
||||
meshroom.ui.uiInstance.exec()
|
||||
|
|
|
@ -4,10 +4,11 @@ import re
|
|||
import argparse
|
||||
import json
|
||||
|
||||
from PySide2 import QtCore
|
||||
from PySide2.QtCore import Qt, QUrl, QJsonValue, qInstallMessageHandler, QtMsgType, QSettings
|
||||
from PySide2.QtGui import QIcon
|
||||
from PySide2.QtWidgets import QApplication
|
||||
from PySide6 import __version__ as PySideVersion
|
||||
from PySide6 import QtCore
|
||||
from PySide6.QtCore import Qt, QUrl, QJsonValue, qInstallMessageHandler, QtMsgType, QSettings
|
||||
from PySide6.QtGui import QIcon
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
import meshroom
|
||||
from meshroom.core import nodesDesc
|
||||
|
@ -188,7 +189,7 @@ class MeshroomApp(QApplication):
|
|||
def __init__(self, args):
|
||||
meshroom.core.initPipelines()
|
||||
|
||||
QtArgs = [args[0], '-style', 'fusion'] + args[1:] # force Fusion style by default
|
||||
QtArgs = [args[0], '-style', 'Fusion'] + args[1:] # force Fusion style by default
|
||||
|
||||
args = createMeshroomParser(args)
|
||||
|
||||
|
@ -202,8 +203,6 @@ class MeshroomApp(QApplication):
|
|||
}
|
||||
logging.getLogger().setLevel(logStringToPython[args.verbose])
|
||||
|
||||
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
||||
|
||||
super(MeshroomApp, self).__init__(QtArgs)
|
||||
|
||||
self.setOrganizationName('AliceVision')
|
||||
|
@ -355,6 +354,7 @@ class MeshroomApp(QApplication):
|
|||
p = {"path": p, "thumbnail": thumbnail}
|
||||
projects.append(p)
|
||||
settings.endArray()
|
||||
settings.endGroup()
|
||||
return projects
|
||||
|
||||
@Slot(str)
|
||||
|
@ -394,6 +394,7 @@ class MeshroomApp(QApplication):
|
|||
settings.setArrayIndex(i)
|
||||
settings.setValue("filepath", p)
|
||||
settings.endArray()
|
||||
settings.endGroup()
|
||||
settings.sync()
|
||||
|
||||
self.recentProjectFilesChanged.emit()
|
||||
|
@ -539,7 +540,8 @@ class MeshroomApp(QApplication):
|
|||
import sys
|
||||
return {
|
||||
'platform': '{} {}'.format(platform.system(), platform.release()),
|
||||
'python': 'Python {}'.format(sys.version.split(" ")[0])
|
||||
'python': 'Python {}'.format(sys.version.split(" ")[0]),
|
||||
'pyside': 'PySide6 {}'.format(PySideVersion)
|
||||
}
|
||||
|
||||
systemInfo = Property(QJsonValue, _systemInfo, constant=True)
|
||||
|
|
|
@ -2,8 +2,8 @@ import logging
|
|||
import traceback
|
||||
from contextlib import contextmanager
|
||||
|
||||
from PySide2.QtWidgets import QUndoCommand, QUndoStack
|
||||
from PySide2.QtCore import Property, Signal
|
||||
from PySide6.QtGui import QUndoCommand, QUndoStack
|
||||
from PySide6.QtCore import Property, Signal
|
||||
|
||||
from meshroom.core.attribute import ListAttribute, Attribute
|
||||
from meshroom.core.graph import GraphModification
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
def registerTypes():
|
||||
from PySide2.QtQml import qmlRegisterType
|
||||
from PySide6.QtQml import qmlRegisterType
|
||||
from meshroom.ui.components.clipboard import ClipboardHelper
|
||||
from meshroom.ui.components.edge import EdgeMouseArea
|
||||
from meshroom.ui.components.filepath import FilepathHelper
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from PySide2.QtCore import Slot, QObject
|
||||
from PySide2.QtGui import QClipboard
|
||||
from PySide6.QtCore import Slot, QObject
|
||||
from PySide6.QtGui import QClipboard
|
||||
|
||||
|
||||
class ClipboardHelper(QObject):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from meshroom.common.qt import QObjectListModel
|
||||
|
||||
from PySide2.QtCore import QObject, Slot, Signal, Property
|
||||
from PySide2.QtCharts import QtCharts
|
||||
from PySide6.QtCore import QObject, Slot, Signal, Property
|
||||
from PySide6 import QtCharts
|
||||
|
||||
import csv
|
||||
import os
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from PySide2.QtCore import Signal, Property, QPointF, Qt, QObject
|
||||
from PySide2.QtGui import QPainterPath, QVector2D
|
||||
from PySide2.QtQuick import QQuickItem
|
||||
from PySide6.QtCore import Signal, Property, QPointF, Qt, QObject
|
||||
from PySide6.QtGui import QPainterPath, QVector2D
|
||||
from PySide6.QtQuick import QQuickItem
|
||||
|
||||
|
||||
class MouseEvent(QObject):
|
||||
|
@ -9,8 +9,8 @@ class MouseEvent(QObject):
|
|||
"""
|
||||
def __init__(self, evt):
|
||||
super(MouseEvent, self).__init__()
|
||||
self._x = evt.x()
|
||||
self._y = evt.y()
|
||||
self._x = evt.position().x()
|
||||
self._y = evt.position().y()
|
||||
self._button = evt.button()
|
||||
self._modifiers = evt.modifiers()
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# coding:utf-8
|
||||
from PySide2.QtCore import QUrl, QFileInfo
|
||||
from PySide2.QtCore import QObject, Slot
|
||||
from PySide6.QtCore import QUrl, QFileInfo
|
||||
from PySide6.QtCore import QObject, Slot
|
||||
|
||||
import os
|
||||
import glob
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from math import acos, pi, sqrt, atan2, cos, sin, asin
|
||||
|
||||
from PySide2.QtCore import QObject, Slot, QSize, Signal, QPointF
|
||||
from PySide2.Qt3DCore import Qt3DCore
|
||||
from PySide2.Qt3DRender import Qt3DRender
|
||||
from PySide2.QtGui import QVector3D, QQuaternion, QVector2D, QVector4D, QMatrix4x4
|
||||
from PySide6.QtCore import QObject, Slot, QSize, Signal, QPointF
|
||||
from PySide6.Qt3DCore import Qt3DCore
|
||||
from PySide6.Qt3DRender import Qt3DRender
|
||||
from PySide6.QtGui import QVector3D, QQuaternion, QVector2D, QVector4D, QMatrix4x4
|
||||
|
||||
from meshroom.ui.utils import makeProperty
|
||||
|
||||
|
@ -41,14 +41,14 @@ class Scene3DHelper(QObject):
|
|||
def faceCount(self, entity):
|
||||
""" Returns face count based on children QGeometry buffers size."""
|
||||
count = 0
|
||||
for geo in entity.findChildren(Qt3DRender.QGeometry):
|
||||
for geo in entity.findChildren(Qt3DCore.QGeometry):
|
||||
count += sum([attr.count() for attr in geo.attributes() if attr.name() == "vertexPosition"])
|
||||
return count / 3
|
||||
|
||||
@Slot(Qt3DCore.QEntity, result=int)
|
||||
def vertexColorCount(self, entity):
|
||||
count = 0
|
||||
for geo in entity.findChildren(Qt3DRender.QGeometry):
|
||||
for geo in entity.findChildren(Qt3DCore.QGeometry):
|
||||
count += sum([attr.count() for attr in geo.attributes() if attr.name() == "vertexColor"])
|
||||
return count
|
||||
|
||||
|
@ -59,10 +59,12 @@ class TrackballController(QObject):
|
|||
Based on the C++ version from https://github.com/cjmdaixi/Qt3DTrackball
|
||||
"""
|
||||
|
||||
_windowSize = QSize()
|
||||
_camera = None
|
||||
_trackballSize = 1.0
|
||||
_rotationSpeed = 5.0
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._windowSize = QSize()
|
||||
self._camera = None
|
||||
self._trackballSize = 1.0
|
||||
self._rotationSpeed = 5.0
|
||||
|
||||
def projectToTrackball(self, screenCoords):
|
||||
sx = screenCoords.x()
|
||||
|
@ -98,7 +100,7 @@ class TrackballController(QObject):
|
|||
windowSizeChanged = Signal()
|
||||
windowSize = makeProperty(QSize, '_windowSize', windowSizeChanged)
|
||||
cameraChanged = Signal()
|
||||
camera = makeProperty(Qt3DRender.QCamera, '_camera', cameraChanged)
|
||||
camera = makeProperty(QObject, '_camera', cameraChanged)
|
||||
trackballSizeChanged = Signal()
|
||||
trackballSize = makeProperty(float, '_trackballSize', trackballSizeChanged)
|
||||
rotationSpeedChanged = Signal()
|
||||
|
@ -353,6 +355,22 @@ class Transformations3DHelper(QObject):
|
|||
|
||||
return U.toEulerAngles()
|
||||
|
||||
@Slot(QVector3D, QVector3D, float, float, result=QVector3D)
|
||||
def getRotatedCameraViewVector(self, camereViewVector, cameraUpVector, pitch, yaw):
|
||||
""" Compute the rotated camera view vector with given pitch and yaw (in degrees).
|
||||
Args:
|
||||
camereViewVector (QVector3D): Camera view vector, the displacement from the camera position to its target
|
||||
cameraUpVector (QVector3D): Camera up vector, the direction the top of the camera is facing
|
||||
pitch (float): Rotation pitch (in degrees)
|
||||
yaw (float): Rotation yaw (in degrees)
|
||||
Returns:
|
||||
QVector3D: rotated camera view vector
|
||||
"""
|
||||
cameraSideVector = QVector3D.crossProduct(camereViewVector, cameraUpVector)
|
||||
yawRot = QQuaternion.fromAxisAndAngle(cameraUpVector, yaw)
|
||||
pitchRot = QQuaternion.fromAxisAndAngle(cameraSideVector, pitch)
|
||||
return (yawRot * pitchRot).rotatedVector(camereViewVector)
|
||||
|
||||
@Slot(QVector3D, QMatrix4x4, Qt3DRender.QCamera, QSize, result=float)
|
||||
def computeScaleUnitFromModelMatrix(self, axis, modelMat, camera, windowSize):
|
||||
""" Compute the length of the screen projected vector axis unit transformed by the model matrix.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from PySide2.QtCore import QObject, Slot
|
||||
from PySide6.QtCore import QObject, Slot
|
||||
|
||||
from io import StringIO
|
||||
from contextlib import redirect_stdout
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from meshroom.common import Signal
|
||||
|
||||
from PySide2.QtCore import QObject, Slot, QSize, QUrl, Qt, QStandardPaths
|
||||
from PySide2.QtGui import QImageReader, QImageWriter
|
||||
from PySide6.QtCore import QObject, Slot, QSize, QUrl, Qt, QStandardPaths
|
||||
from PySide6.QtGui import QImageReader, QImageWriter
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
|
|
@ -8,7 +8,7 @@ from enum import Enum
|
|||
from threading import Thread, Event, Lock
|
||||
from multiprocessing.pool import ThreadPool
|
||||
|
||||
from PySide2.QtCore import Slot, QJsonValue, QObject, QUrl, Property, Signal, QPoint
|
||||
from PySide6.QtCore import Slot, QJsonValue, QObject, QUrl, Property, Signal, QPoint
|
||||
|
||||
from meshroom.core import sessionUid
|
||||
from meshroom.common.qt import QObjectListModel
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from PySide2.QtCore import QObject, Qt, Slot, Property, Signal
|
||||
from PySide2.QtGui import QPalette, QColor
|
||||
from PySide2.QtWidgets import QApplication
|
||||
from PySide6.QtCore import QObject, Qt, Slot, Property, Signal
|
||||
from PySide6.QtGui import QPalette, QColor
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
|
||||
class PaletteManager(QObject):
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Utils 1.0
|
||||
import MaterialIcons 2.2
|
||||
|
||||
|
||||
/// Meshroom "About" window
|
||||
/**
|
||||
* Meshroom "About" window
|
||||
*/
|
||||
|
||||
Dialog {
|
||||
id: root
|
||||
|
||||
|
@ -24,7 +27,7 @@ Dialog {
|
|||
modal: true
|
||||
closePolicy: Dialog.CloseOnEscape | Dialog.CloseOnPressOutside
|
||||
padding: 30
|
||||
topPadding: 0 // header provides top padding
|
||||
topPadding: 0 // Header provides top padding
|
||||
|
||||
header: Pane {
|
||||
background: Item {}
|
||||
|
@ -56,7 +59,8 @@ Dialog {
|
|||
selectByMouse: true
|
||||
text: "Version " + Qt.application.version + "\n"
|
||||
+ MeshroomApp.systemInfo["platform"] + " \n"
|
||||
+ MeshroomApp.systemInfo["python"]
|
||||
+ MeshroomApp.systemInfo["python"] + "\n"
|
||||
+ MeshroomApp.systemInfo["pyside"]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,16 +178,16 @@ Dialog {
|
|||
sourceComponent: ScrollView {
|
||||
|
||||
Component.onCompleted: {
|
||||
// try to load the local file
|
||||
// Try to load the local file
|
||||
var url = Filepath.stringToUrl(modelData.localUrl)
|
||||
// fallback to the online url if file is not found
|
||||
// Fallback to the online url if file is not found
|
||||
if (!Filepath.exists(url))
|
||||
url = modelData.onlineUrl
|
||||
Request.get(url,
|
||||
function(xhr) {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE)
|
||||
{
|
||||
// status is OK
|
||||
// Status is OK
|
||||
if (xhr.status === 200)
|
||||
textArea.text = MeshroomApp.markdownToHtml(xhr.responseText)
|
||||
else
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick.Window 2.15
|
||||
import QtQml.Models 2.15
|
||||
import QtCore
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQml.Models
|
||||
|
||||
import Qt.labs.platform 1.0 as Platform
|
||||
import QtQuick.Dialogs 1.3
|
||||
import QtQuick.Dialogs
|
||||
|
||||
import Qt.labs.settings 1.0
|
||||
import GraphEditor 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
@ -22,7 +22,7 @@ Page {
|
|||
|
||||
Settings {
|
||||
id: settingsUILayout
|
||||
category: 'UILayout'
|
||||
category: "UILayout"
|
||||
property alias showLiveReconstruction: liveSfMVisibilityCB.checked
|
||||
property alias showGraphEditor: graphEditorVisibilityCB.checked
|
||||
property alias showImageViewer: imageViewerVisibilityCB.checked
|
||||
|
@ -521,8 +521,8 @@ Page {
|
|||
text: "Load Template"
|
||||
onTriggered: {
|
||||
ensureSaved(function() {
|
||||
initFileDialogFolder(loadTemplateDialog);
|
||||
loadTemplateDialog.open();
|
||||
initFileDialogFolder(loadTemplateDialog)
|
||||
loadTemplateDialog.open()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1158,15 +1158,15 @@ Page {
|
|||
uigraph: _reconstruction
|
||||
nodeTypesModel: _nodeTypes
|
||||
|
||||
onNodeDoubleClicked: {
|
||||
onNodeDoubleClicked: function(mouse, node) {
|
||||
_reconstruction.setActiveNode(node);
|
||||
workspaceView.viewNode(node, mouse);
|
||||
}
|
||||
onComputeRequest: {
|
||||
onComputeRequest: function(nodes) {
|
||||
_reconstruction.forceNodesStatusUpdate();
|
||||
computeManager.compute(nodes)
|
||||
}
|
||||
onSubmitRequest: {
|
||||
onSubmitRequest: function(nodes) {
|
||||
_reconstruction.forceNodesStatusUpdate();
|
||||
computeManager.submit(nodes)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
/**
|
||||
* A custom CheckBox designed to be used in ChartView's legend.
|
||||
*/
|
||||
|
||||
CheckBox {
|
||||
id: root
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtCharts 2.15
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtCharts
|
||||
|
||||
/**
|
||||
* ChartViewLegend is an interactive legend component for ChartViews.
|
||||
* It provides a CheckBox for each series that can control its visibility,
|
||||
* and highlight on hovering.
|
||||
*/
|
||||
|
||||
Flow {
|
||||
id: root
|
||||
|
||||
|
@ -49,7 +49,6 @@ Flow {
|
|||
}
|
||||
|
||||
Repeater {
|
||||
|
||||
// ChartView series can't be accessed directly as a model.
|
||||
// Use an intermediate ListModel populated with those series.
|
||||
model: ListModel {
|
||||
|
@ -70,7 +69,7 @@ Flow {
|
|||
root.hoveredSeries = null
|
||||
}
|
||||
|
||||
// hovered serie properties override
|
||||
// Hovered serie properties override
|
||||
states: [
|
||||
State {
|
||||
when: series && root.hoveredSeries === series
|
||||
|
@ -84,7 +83,7 @@ Flow {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
onClicked: function(mouse) {
|
||||
if (mouse.modifiers & Qt.ControlModifier)
|
||||
root.soloSeries(index)
|
||||
else
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtPositioning 5.15
|
||||
import QtLocation 5.15
|
||||
|
||||
import QtCharts 2.15
|
||||
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtCharts
|
||||
|
||||
ChartView {
|
||||
id: root
|
||||
|
@ -26,32 +17,11 @@ ChartView {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
property double degreeToScale: 1.0 / 120.0 // default mouse scroll is 15 degree
|
||||
property double degreeToScale: 1.0 / 120.0 // Default mouse scroll is 15 degree
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
// onWheel: {
|
||||
// console.warn("root.plotArea before: " + root.plotArea)
|
||||
// var zoomFactor = wheel.angleDelta.y > 0 ? 1.0 / (1.0 + wheel.angleDelta.y * degreeToScale) : (1.0 + Math.abs(wheel.angleDelta.y) * degreeToScale)
|
||||
|
||||
// // var mouse_screen = Qt.point(wheel.x, wheel.y)
|
||||
// var mouse_screen = mapToItem(root, wheel.x, wheel.y)
|
||||
// var mouse_normalized = Qt.point(mouse_screen.x / plotZone.width, mouse_screen.y / plotZone.height)
|
||||
// var mouse_plot = Qt.point(mouse_normalized.x * plotZone.width, mouse_normalized.y * plotZone.height)
|
||||
|
||||
// // var p = mapToValue(mouse_screen, root.series(0))
|
||||
// // var pMin = mapToValue(mouse_screen, Qt.point(root.axisX().min, root.axisY().min))
|
||||
// // var pMax = mapToValue(mouse_screen, Qt.point(root.axisX().max, root.axisY().max))
|
||||
// // console.warn("p: " + p)
|
||||
|
||||
// // Qt.rect()
|
||||
// var r = Qt.rect(mouse_plot.x, mouse_plot.y, plotZone.width * zoomFactor, plotZone.height * zoomFactor)
|
||||
// //var r = Qt.rect(pMin.x, pMin.y, (pMax.x-pMin.x) / 2, (pMax.y-pMin.y) / 2)
|
||||
// root.zoomIn(r)
|
||||
// }
|
||||
onClicked: {
|
||||
root.zoomReset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
import Utils 1.0
|
||||
|
||||
|
@ -7,6 +7,7 @@ import Utils 1.0
|
|||
* ColorChart is a color picker based on a set of predefined colors.
|
||||
* It takes the form of a ToolButton that pops-up its palette when pressed.
|
||||
*/
|
||||
|
||||
ToolButton {
|
||||
id: root
|
||||
|
||||
|
@ -28,10 +29,10 @@ ToolButton {
|
|||
id: palettePopup
|
||||
|
||||
padding: 4
|
||||
// content width is missing side padding (hence the + padding*2)
|
||||
// Content width is missing side padding (hence the + padding*2)
|
||||
implicitWidth: colorChart.contentItem.width + padding * 2
|
||||
|
||||
// center the current color
|
||||
// Center the current color
|
||||
y: -(root.height - padding) / 2
|
||||
x: -colorChart.currentItem.x - padding
|
||||
|
||||
|
@ -44,14 +45,14 @@ ToolButton {
|
|||
spacing: 2
|
||||
currentIndex: root.currentIndex
|
||||
model: root.colors
|
||||
// display each color as a ToolButton with a custom background
|
||||
// Display each color as a ToolButton with a custom background
|
||||
delegate: ToolButton {
|
||||
padding: 0
|
||||
width: root.width
|
||||
height: root.height
|
||||
background: Rectangle {
|
||||
color: modelData
|
||||
// display border of current/selected item
|
||||
// Display border of current/selected item
|
||||
border.width: hovered || index === colorChart.currentIndex ? 1 : 0
|
||||
border.color: Colors.sysPalette.midlight
|
||||
}
|
||||
|
|
261
meshroom/ui/qml/Controls/DirectionalLightPane.qml
Normal file
261
meshroom/ui/qml/Controls/DirectionalLightPane.qml
Normal file
|
@ -0,0 +1,261 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects // for OpacityMask & Glow
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* Directional Light Pane
|
||||
*
|
||||
* @biref A small pane to control a directional light with a 2d ball controller.
|
||||
*
|
||||
* @param lightYawValue - directional light yaw (degrees)
|
||||
* @param lightPitchValue - directional light pitch (degrees)
|
||||
*/
|
||||
|
||||
FloatingPane {
|
||||
id: root
|
||||
|
||||
// yaw and pitch properties
|
||||
property double lightYawValue: 0
|
||||
property double lightPitchValue: 0
|
||||
|
||||
// 2d controller display size properties
|
||||
readonly property real controllerSize: 80
|
||||
readonly property real controllerRadius: controllerSize * 0.5
|
||||
|
||||
function reset() {
|
||||
lightYawValue = 0;
|
||||
lightPitchValue = 0;
|
||||
}
|
||||
|
||||
// update 2d controller if yaw value changed
|
||||
onLightYawValueChanged: { lightBallController.update() }
|
||||
|
||||
// update 2d controller if pitch value changed
|
||||
onLightPitchValueChanged: { lightBallController.update() }
|
||||
|
||||
anchors.margins: 0
|
||||
padding: 5
|
||||
radius: 0
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
// header
|
||||
RowLayout {
|
||||
// pane title
|
||||
Label {
|
||||
text: "Directional Light"
|
||||
font.bold: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// minimize or maximize button
|
||||
MaterialToolButton {
|
||||
id: bodyButton
|
||||
text: lightPaneBody.visible ? MaterialIcons.arrow_drop_down : MaterialIcons.arrow_drop_up
|
||||
font.pointSize: 10
|
||||
ToolTip.text: lightPaneBody.visible ? "Minimize" : "Maximize"
|
||||
onClicked: { lightPaneBody.visible = !lightPaneBody.visible }
|
||||
}
|
||||
|
||||
// reset button
|
||||
MaterialToolButton {
|
||||
id: resetButton
|
||||
text: MaterialIcons.refresh
|
||||
font.pointSize: 10
|
||||
ToolTip.text: "Reset"
|
||||
onClicked: reset()
|
||||
}
|
||||
}
|
||||
|
||||
// body
|
||||
RowLayout {
|
||||
id: lightPaneBody
|
||||
spacing: 10
|
||||
|
||||
// light parameters
|
||||
GridLayout {
|
||||
columns: 3
|
||||
rowSpacing: 2
|
||||
columnSpacing: 8
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
|
||||
// light yaw
|
||||
Label {
|
||||
text: "Yaw"
|
||||
}
|
||||
TextField {
|
||||
id: lightYawTF
|
||||
text: lightYawValue.toFixed(2)
|
||||
selectByMouse: true
|
||||
horizontalAlignment: TextInput.AlignRight
|
||||
validator: doubleDegreeValidator
|
||||
onEditingFinished: { lightYawValue = lightYawTF.text }
|
||||
ToolTip.text: "Light yaw (degrees)."
|
||||
ToolTip.visible: hovered
|
||||
Layout.preferredWidth: textMetricsDegreeValue.width
|
||||
}
|
||||
Label {
|
||||
text: "°"
|
||||
}
|
||||
|
||||
// light pitch
|
||||
Label {
|
||||
text: "Pitch"
|
||||
}
|
||||
TextField {
|
||||
id: lightPitchTF
|
||||
text: lightPitchValue.toFixed(2)
|
||||
selectByMouse: true
|
||||
horizontalAlignment: TextInput.AlignRight
|
||||
validator: doubleDegreeValidator
|
||||
onEditingFinished: { lightPitchValue = lightPitchTF.text }
|
||||
ToolTip.text: "Light pitch (degrees)."
|
||||
ToolTip.visible: hovered
|
||||
Layout.preferredWidth: textMetricsDegreeValue.width
|
||||
}
|
||||
Label {
|
||||
text: "°"
|
||||
}
|
||||
}
|
||||
|
||||
// directional light ball controller
|
||||
Rectangle {
|
||||
id: lightBallController
|
||||
anchors.margins: 0
|
||||
width: controllerSize
|
||||
height: controllerSize
|
||||
radius: 180 // circle
|
||||
color: "#FF000000"
|
||||
Layout.rightMargin: 5
|
||||
Layout.leftMargin: 5
|
||||
Layout.bottomMargin: 5
|
||||
|
||||
function update() {
|
||||
// get point from light yaw and pitch
|
||||
var y = (lightPitchValue / 90 * controllerRadius)
|
||||
var xMax = Math.sqrt(controllerRadius * controllerRadius - y * y) // get sphere maximum x coordinate
|
||||
var x = (lightYawValue / 90 * xMax)
|
||||
|
||||
// get angle and distance
|
||||
var angleRad = Math.atan2(y, x)
|
||||
var distance = Math.sqrt(x * x + y * y)
|
||||
|
||||
// avoid controller overflow
|
||||
if(distance > controllerRadius)
|
||||
{
|
||||
x = controllerRadius * Math.cos(angleRad)
|
||||
y = controllerRadius * Math.sin(angleRad)
|
||||
}
|
||||
|
||||
// compute distance function for light gradient emulation
|
||||
var distanceRatio = Math.min(distance, controllerRadius) / controllerRadius
|
||||
var distanceFunct = distanceRatio * distanceRatio * 0.3
|
||||
|
||||
// update light point
|
||||
lightPoint.x = lightPoint.startOffset + x
|
||||
lightPoint.y = lightPoint.startOffset + y
|
||||
|
||||
// update light gradient
|
||||
lightGradient.angle = angleRad * (180 / Math.PI) // radians to degrees
|
||||
lightGradient.horizontalRadius = controllerSize * (1 - distanceFunct)
|
||||
lightGradient.verticalRadius = controllerSize * (1 + distanceFunct)
|
||||
lightGradient.horizontalOffset = x * (1 - distanceFunct)
|
||||
lightGradient.verticalOffset = y * (1 - distanceFunct)
|
||||
}
|
||||
|
||||
RadialGradient {
|
||||
id: lightGradient
|
||||
anchors.centerIn: parent
|
||||
width: controllerSize
|
||||
height: width
|
||||
horizontalRadius: controllerSize
|
||||
verticalRadius: controllerSize
|
||||
angle: 0
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.00; color: "#FFFFFFFF" }
|
||||
GradientStop { position: 0.10; color: "#FFAAAAAA" }
|
||||
GradientStop { position: 0.50; color: "#FF0C0C0C" }
|
||||
}
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
id: mask
|
||||
maskSource: Rectangle {
|
||||
height: lightGradient.height
|
||||
width: lightGradient.width
|
||||
radius: 180 // circle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: lightPoint
|
||||
|
||||
property double startOffset : (parent.width - width) * 0.5
|
||||
|
||||
x: startOffset
|
||||
y: startOffset
|
||||
width: controllerRadius / 6
|
||||
height: width
|
||||
radius: 180 // circle
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Glow {
|
||||
anchors.fill: lightPoint
|
||||
radius: controllerRadius / 5
|
||||
samples: 17
|
||||
color: "white"
|
||||
source: lightPoint
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: lightMouseArea
|
||||
anchors.centerIn: parent
|
||||
anchors.fill: parent
|
||||
|
||||
onPositionChanged: {
|
||||
// get coordinates from center
|
||||
var x = mouseX - controllerRadius
|
||||
var y = mouseY - controllerRadius
|
||||
|
||||
// get distance to center
|
||||
var distance = Math.sqrt(x * x + y * y)
|
||||
|
||||
// avoid controller overflow
|
||||
if(distance > controllerRadius)
|
||||
{
|
||||
var angleRad = Math.atan2(y, x)
|
||||
x = controllerRadius * Math.cos(angleRad)
|
||||
y = controllerRadius * Math.sin(angleRad)
|
||||
}
|
||||
|
||||
// get sphere maximum x coordinate
|
||||
var xMax = Math.sqrt(controllerRadius * controllerRadius - y * y)
|
||||
|
||||
// update light yaw and pitch
|
||||
lightYawValue = (xMax > 0) ? ((x / xMax) * 90) : 0 // between -90 and 90 degrees
|
||||
lightPitchValue = (y / controllerRadius) * 90 // between -90 and 90 degrees
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoubleValidator {
|
||||
id: doubleDegreeValidator
|
||||
locale: 'C' // use '.' decimal separator disregarding of the system locale
|
||||
bottom: -90.0
|
||||
top: 90.0
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: textMetricsDegreeValue
|
||||
font: lightYawTF.font
|
||||
text: "12.3456"
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.11
|
||||
import QtQuick
|
||||
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
/**
|
||||
* FloatingPane provides a Pane with a slightly transparent default background
|
||||
* using palette.base as color. Useful to create floating toolbar/overlays.
|
||||
*/
|
||||
|
||||
Pane {
|
||||
id: root
|
||||
|
||||
|
@ -14,5 +15,9 @@ Pane {
|
|||
|
||||
padding: 6
|
||||
anchors.margins: 2
|
||||
background: Rectangle { color: root.palette.base; opacity: opaque ? 1.0 : 0.7; radius: root.radius }
|
||||
background: Rectangle {
|
||||
color: root.palette.base
|
||||
opacity: opaque ? 1.0 : 0.7
|
||||
radius: root.radius
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
/**
|
||||
* A custom GroupBox with predefined header.
|
||||
*/
|
||||
|
||||
GroupBox {
|
||||
id: root
|
||||
|
||||
|
@ -21,13 +21,14 @@ GroupBox {
|
|||
background: Item {}
|
||||
|
||||
label: Pane {
|
||||
padding: 2
|
||||
width: root.width
|
||||
background: Rectangle {
|
||||
id: labelBg
|
||||
color: palette.base
|
||||
opacity: 0.8
|
||||
}
|
||||
padding: 2
|
||||
width: root.width
|
||||
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
Label {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
|
||||
/*
|
||||
* IntSelector with arrows and a text input to select a number
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
/**
|
||||
* KeyValue allows to create a list of key/value, like a table.
|
||||
*/
|
||||
|
||||
Rectangle {
|
||||
property alias key: keyLabel.text
|
||||
property alias value: valueText.text
|
||||
|
@ -20,7 +20,6 @@ Rectangle {
|
|||
Rectangle {
|
||||
anchors.margins: 2
|
||||
color: Qt.darker(activePalette.window, 1.1)
|
||||
// Layout.preferredWidth: sizeHandle.x
|
||||
Layout.minimumWidth: 10.0 * Qt.application.font.pixelSize
|
||||
Layout.maximumWidth: 15.0 * Qt.application.font.pixelSize
|
||||
Layout.fillWidth: false
|
||||
|
@ -46,7 +45,10 @@ Rectangle {
|
|||
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
background: Rectangle { anchors.fill: parent; color: Qt.darker(activePalette.window, 1.05) }
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Qt.darker(activePalette.window, 1.05)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
/**
|
||||
* MScrollBar is a custom scrollbar implementation.
|
||||
* It is a vertical scrollbar that can be used to scroll a ListView.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
SplitView {
|
||||
id: splitView
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
|
||||
Dialog {
|
||||
|
@ -15,7 +16,7 @@ Dialog {
|
|||
|
||||
default property alias children: layout.children
|
||||
|
||||
// the content of this MessageDialog as a string
|
||||
// The content of this MessageDialog as a string
|
||||
readonly property string asString: titleLabel.text + "\n\n" + text + "\n" + detailedText + "\n" + helperText + "\n"
|
||||
|
||||
/// Return the text content of this dialog as a simple string.
|
||||
|
@ -39,7 +40,7 @@ Dialog {
|
|||
rightPadding: leftPadding
|
||||
|
||||
background: Item {
|
||||
// hidden text edit to perform copy in clipboard
|
||||
// Hidden text edit to perform copy in clipboard
|
||||
TextEdit {
|
||||
id: textContent
|
||||
visible: false
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
/**
|
||||
* Panel is a container control with preconfigured header/footer.
|
||||
|
@ -12,6 +11,7 @@ import QtQuick.Layouts 1.11
|
|||
*
|
||||
* The footer is empty (and not visible) by default. It does not provided any layout.
|
||||
*/
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
|
||||
/**
|
||||
* Basic SearchBar component with an appropriate icon and a TextField.
|
||||
*/
|
||||
|
||||
FocusScope {
|
||||
property alias textField: field
|
||||
property alias text: field.text
|
||||
|
@ -35,7 +36,7 @@ FocusScope {
|
|||
Layout.fillWidth: true
|
||||
selectByMouse: true
|
||||
|
||||
// ensure the field has focus when the text is modified
|
||||
// Ensure the field has focus when the text is modified
|
||||
onTextChanged: {
|
||||
forceActiveFocus()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
@ -47,16 +47,16 @@ Page {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
property bool commonBorder : false
|
||||
property bool commonBorder: false
|
||||
|
||||
property int lBorderwidth : index === mainTabBar.currentIndex ? 2 : 1
|
||||
property int rBorderwidth : index === mainTabBar.currentIndex ? 2 : 1
|
||||
property int tBorderwidth : index === mainTabBar.currentIndex ? 2 : 1
|
||||
property int bBorderwidth : 0
|
||||
property int lBorderwidth: index === mainTabBar.currentIndex ? 2 : 1
|
||||
property int rBorderwidth: index === mainTabBar.currentIndex ? 2 : 1
|
||||
property int tBorderwidth: index === mainTabBar.currentIndex ? 2 : 1
|
||||
property int bBorderwidth: 0
|
||||
|
||||
property int commonBorderWidth : 1
|
||||
property int commonBorderWidth: 1
|
||||
|
||||
z : -1
|
||||
z: -1
|
||||
|
||||
color: Qt.darker(root.palette.window, 1.50)
|
||||
|
||||
|
@ -66,10 +66,10 @@ Page {
|
|||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
|
||||
topMargin : commonBorder ? -commonBorderWidth : -tBorderwidth
|
||||
bottomMargin : commonBorder ? -commonBorderWidth : -bBorderwidth
|
||||
leftMargin : commonBorder ? -commonBorderWidth : -lBorderwidth
|
||||
rightMargin : commonBorder ? -commonBorderWidth : -rBorderwidth
|
||||
topMargin: commonBorder ? -commonBorderWidth : -tBorderwidth
|
||||
bottomMargin: commonBorder ? -commonBorderWidth : -bBorderwidth
|
||||
leftMargin: commonBorder ? -commonBorderWidth : -lBorderwidth
|
||||
rightMargin: commonBorder ? -commonBorderWidth : -rBorderwidth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* Text file viewer with auto-reload feature.
|
||||
* Uses a ListView with one delegate by line instead of a TextArea for performance reasons.
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
|
@ -115,7 +116,7 @@ Item {
|
|||
clip: true
|
||||
focus: true
|
||||
|
||||
// custom key navigation handling
|
||||
// Custom key navigation handling
|
||||
keyNavigationEnabled: false
|
||||
highlightFollowsCurrentItem: true
|
||||
highlightMoveDuration: 0
|
||||
|
@ -145,14 +146,14 @@ Item {
|
|||
}
|
||||
|
||||
function setText(value) {
|
||||
// store current first index
|
||||
// Store current first index
|
||||
var topIndex = firstVisibleIndex()
|
||||
// store whether autoscroll to bottom is active
|
||||
// Store whether autoscroll to bottom is active
|
||||
var scrollToBottom = atYEnd && autoscroll.checked
|
||||
// replace text
|
||||
// Replace text
|
||||
text = value
|
||||
|
||||
// restore content position by either:
|
||||
// Restore content position by either:
|
||||
// - autoscrolling to bottom
|
||||
if (scrollToBottom)
|
||||
positionViewAtEnd()
|
||||
|
@ -183,7 +184,7 @@ Item {
|
|||
// TextMetrics for textual progress bar
|
||||
TextMetrics {
|
||||
id: progressMetrics
|
||||
// total number of character in textual progress bar
|
||||
// Total number of character in textual progress bar
|
||||
property int count: 51
|
||||
property string character: '*'
|
||||
text: character.repeat(count)
|
||||
|
@ -230,15 +231,15 @@ Item {
|
|||
Loader {
|
||||
id: delegateLoader
|
||||
Layout.fillWidth: true
|
||||
// default line delegate
|
||||
// Default line delegate
|
||||
sourceComponent: line_component
|
||||
|
||||
// line delegate selector based on content
|
||||
// Line delegate selector based on content
|
||||
StateGroup {
|
||||
states: [
|
||||
State {
|
||||
name: "progressBar"
|
||||
// detect textual progressbar (non empty line with only progressbar character)
|
||||
// Detect textual progressbar (non-empty line with only progressbar character)
|
||||
when: logLine.line.trim().length
|
||||
&& logLine.line.split(progressMetrics.character).length - 1 === logLine.line.trim().length
|
||||
PropertyChanges {
|
||||
|
@ -281,7 +282,7 @@ Item {
|
|||
Keys.forwardTo: [textView]
|
||||
|
||||
color: {
|
||||
// color line according to log level
|
||||
// Color line according to log level
|
||||
if (text.indexOf("[warning]") >= 0)
|
||||
return Colors.orange
|
||||
else if(text.indexOf("[error]") >= 0)
|
||||
|
@ -350,7 +351,7 @@ Item {
|
|||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
textView.setText(xhr.status === 200 ? xhr.responseText : "")
|
||||
loading = false
|
||||
// re-trigger reload source file
|
||||
// Re-trigger reload source file
|
||||
if (autoReload)
|
||||
reloadTimer.restart()
|
||||
}
|
||||
|
|
|
@ -15,3 +15,4 @@ FilterComboBox 1.0 FilterComboBox.qml
|
|||
IntSelector 1.0 IntSelector.qml
|
||||
MScrollBar 1.0 MScrollBar.qml
|
||||
MSplitView 1.0 MSplitView.qml
|
||||
DirectionalLightPane 1.0 DirectionalLightPane.qml
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import QtQuick 2.15
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import Controls 1.0
|
||||
|
||||
/**
|
||||
* DialogsFactory is utility object to instantiate generic purpose Dialogs.
|
||||
*/
|
||||
|
||||
QtObject {
|
||||
|
||||
readonly property string defaultErrorText: "An unexpected error has occurred"
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick.Controls 2.15
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
import Controls 1.0
|
||||
|
||||
/**
|
||||
|
@ -42,7 +40,9 @@ ListView {
|
|||
filterText: root.filterText
|
||||
objectsHideable: root.objectsHideable
|
||||
attribute: object
|
||||
onDoubleClicked: root.attributeDoubleClicked(mouse, attr)
|
||||
onDoubleClicked: function(mouse, attr) {
|
||||
root.attributeDoubleClicked(mouse, attr)
|
||||
}
|
||||
}
|
||||
|
||||
onActiveChanged: height = active ? item.implicitHeight : -spacing
|
||||
|
@ -56,12 +56,10 @@ ListView {
|
|||
}
|
||||
}
|
||||
|
||||
// Helper MouseArea to lose edit/activeFocus
|
||||
// when clicking on the background
|
||||
// Helper MouseArea to lose edit/activeFocus when clicking on the background
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: forceActiveFocus()
|
||||
z: -1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Dialogs 1.3
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Dialogs
|
||||
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
import Controls 1.0
|
||||
|
||||
/**
|
||||
Instantiate a control to visualize and edit an Attribute based on its type.
|
||||
*/
|
||||
* Instantiate a control to visualize and edit an Attribute based on its type.
|
||||
*/
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
property variant attribute: null
|
||||
property bool readOnly: false // whether the attribute's value can be modified
|
||||
property bool readOnly: false // Whether the attribute's value can be modified
|
||||
property bool objectsHideable: true
|
||||
property string filterText: ""
|
||||
|
||||
property alias label: parameterLabel // accessor to the internal Label (attribute's name)
|
||||
property int labelWidth // shortcut to set the fixed size of the Label
|
||||
property alias label: parameterLabel // Accessor to the internal Label (attribute's name)
|
||||
property int labelWidth // Shortcut to set the fixed size of the Label
|
||||
|
||||
readonly property bool editable: !attribute.isOutput && !attribute.isLink && !readOnly
|
||||
|
||||
|
@ -42,7 +44,7 @@ RowLayout {
|
|||
Pane {
|
||||
background: Rectangle {
|
||||
id: background
|
||||
color: object.validValue ? Qt.darker(parent.palette.window, 1.1) : Qt.darker(Colors.red, 1.5)
|
||||
color: object != undefined && object.validValue ? Qt.darker(parent.palette.window, 1.1) : Qt.darker(Colors.red, 1.5)
|
||||
}
|
||||
padding: 0
|
||||
Layout.preferredWidth: labelWidth || implicitWidth
|
||||
|
@ -66,8 +68,10 @@ RowLayout {
|
|||
text: object.label
|
||||
|
||||
color: {
|
||||
if ((object.hasOutputConnections || object.isLink) && !object.enabled) return Colors.lightgrey
|
||||
else return palette.text
|
||||
if (object != undefined && (object.hasOutputConnections || object.isLink) && !object.enabled)
|
||||
return Colors.lightgrey
|
||||
else
|
||||
return palette.text
|
||||
}
|
||||
|
||||
// Tooltip hint with attribute's description
|
||||
|
@ -88,10 +92,10 @@ RowLayout {
|
|||
delay: 800
|
||||
}
|
||||
|
||||
// make label bold if attribute's value is not the default one
|
||||
// Make label bold if attribute's value is not the default one
|
||||
font.bold: !object.isOutput && !object.isDefault
|
||||
|
||||
// make label italic if attribute is a link
|
||||
// Make label italic if attribute is a link
|
||||
font.italic: object.isLink
|
||||
|
||||
MouseArea {
|
||||
|
@ -152,7 +156,7 @@ RowLayout {
|
|||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
onClicked: function(mouse) {
|
||||
forceActiveFocus()
|
||||
if (mouse.button == Qt.RightButton) {
|
||||
var menu = menuComp.createObject(parameterLabel)
|
||||
|
@ -198,37 +202,37 @@ RowLayout {
|
|||
sourceComponent: {
|
||||
// PushButtonParam always has value == undefined, so it needs to be excluded from this check
|
||||
if (attribute.type != "PushButtonParam" && attribute.value === undefined) {
|
||||
return notComputed_component
|
||||
return notComputedComponent
|
||||
}
|
||||
switch (attribute.type) {
|
||||
case "PushButtonParam":
|
||||
return pushButton_component
|
||||
return pushButtonComponent
|
||||
case "ChoiceParam":
|
||||
return attribute.desc.exclusive ? comboBox_component : multiChoice_component
|
||||
case "IntParam": return slider_component
|
||||
return attribute.desc.exclusive ? comboBoxComponent : multiChoiceComponent
|
||||
case "IntParam": return sliderComponent
|
||||
case "FloatParam":
|
||||
if (attribute.desc.semantic === 'color/hue')
|
||||
return color_hue_component
|
||||
return slider_component
|
||||
return colorHueComponent
|
||||
return sliderComponent
|
||||
case "BoolParam":
|
||||
return checkbox_component
|
||||
return checkboxComponent
|
||||
case "ListAttribute":
|
||||
return listAttribute_component
|
||||
return listAttributeComponent
|
||||
case "GroupAttribute":
|
||||
return groupAttribute_component
|
||||
return groupAttributeComponent
|
||||
case "StringParam":
|
||||
if (attribute.desc.semantic.includes('multiline'))
|
||||
return textArea_component
|
||||
return textField_component
|
||||
return textAreaComponent
|
||||
return textFieldComponent
|
||||
case "ColorParam":
|
||||
return color_component
|
||||
return colorComponent
|
||||
default:
|
||||
return textField_component
|
||||
return textFieldComponent
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: notComputed_component
|
||||
id: notComputedComponent
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
text: MaterialIcons.do_not_disturb_alt
|
||||
|
@ -244,7 +248,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: pushButton_component
|
||||
id: pushButtonComponent
|
||||
Button {
|
||||
text: attribute.label
|
||||
enabled: root.editable
|
||||
|
@ -255,7 +259,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: textField_component
|
||||
id: textFieldComponent
|
||||
TextField {
|
||||
id: textField
|
||||
readOnly: !root.editable
|
||||
|
@ -268,7 +272,7 @@ RowLayout {
|
|||
setTextFieldAttribute(text)
|
||||
parameterLabel.forceActiveFocus()
|
||||
}
|
||||
Keys.onPressed: (event)=> {
|
||||
Keys.onPressed: function(event) {
|
||||
if ((event.key == Qt.Key_Escape)) {
|
||||
event.accepted = true
|
||||
parameterLabel.forceActiveFocus()
|
||||
|
@ -281,7 +285,7 @@ RowLayout {
|
|||
DropArea {
|
||||
enabled: root.editable
|
||||
anchors.fill: parent
|
||||
onDropped: {
|
||||
onDropped: function(drop) {
|
||||
if (drop.hasUrls)
|
||||
setTextFieldAttribute(Filepath.urlToString(drop.urls[0]))
|
||||
else if (drop.hasText && drop.text != '')
|
||||
|
@ -291,8 +295,8 @@ RowLayout {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: (mouse)=> {
|
||||
// Do not loose the selection during the right click
|
||||
onClicked: function(mouse) {
|
||||
// Do not lose the selection during the right click
|
||||
textField.persistentSelection = true
|
||||
// We store the status of the activeFocus before opening the popup
|
||||
textField.memoryActiveFocus = textField.activeFocus
|
||||
|
@ -318,7 +322,7 @@ RowLayout {
|
|||
Clipboard.clear()
|
||||
Clipboard.setText(attribute.value)
|
||||
} else {
|
||||
// copy selection only
|
||||
// Copy selection only
|
||||
textField.copy()
|
||||
}
|
||||
}
|
||||
|
@ -328,12 +332,12 @@ RowLayout {
|
|||
enabled: Clipboard.getText() != "" && !readOnly
|
||||
onTriggered: {
|
||||
if (textField.memoryActiveFocus) {
|
||||
// replace the selected text with the clipboard
|
||||
// Replace the selected text with the clipboard
|
||||
// or if there is no selection insert at the cursor position
|
||||
var before = textField.text.substr(0, textField.selectionStart)
|
||||
var after = textField.text.substr(textField.selectionEnd, textField.text.length)
|
||||
setTextFieldAttribute(before + Clipboard.getText() + after)
|
||||
// set the cursor at the end of the added text
|
||||
// Set the cursor at the end of the added text
|
||||
textField.cursorPosition = before.length + Clipboard.getText().length
|
||||
} else {
|
||||
setTextFieldAttribute(Clipboard.getText())
|
||||
|
@ -346,7 +350,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: textArea_component
|
||||
id: textAreaComponent
|
||||
|
||||
Rectangle {
|
||||
// Fixed background for the flickable object
|
||||
|
@ -395,17 +399,20 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: color_component
|
||||
id: colorComponent
|
||||
RowLayout {
|
||||
CheckBox {
|
||||
id: color_checkbox
|
||||
id: colorCheckbox
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
checked: node && node.color === "" ? false : true
|
||||
checkable: root.editable
|
||||
text: "Custom Color"
|
||||
onClicked: {
|
||||
if (checked) {
|
||||
_reconstruction.setAttribute(attribute, "#0000FF")
|
||||
if (colorText.text == "")
|
||||
_reconstruction.setAttribute(attribute, "#0000FF")
|
||||
else
|
||||
_reconstruction.setAttribute(attribute, colorText.text)
|
||||
} else {
|
||||
_reconstruction.setAttribute(attribute, "")
|
||||
}
|
||||
|
@ -415,9 +422,9 @@ RowLayout {
|
|||
id: colorText
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
implicitWidth: 100
|
||||
enabled: color_checkbox.checked && root.editable
|
||||
visible: color_checkbox.checked
|
||||
text: color_checkbox.checked ? attribute.value : ""
|
||||
enabled: colorCheckbox.checked && root.editable
|
||||
visible: colorCheckbox.checked
|
||||
text: colorCheckbox.checked ? attribute.value : ""
|
||||
selectByMouse: true
|
||||
onEditingFinished: setTextFieldAttribute(text)
|
||||
onAccepted: setTextFieldAttribute(text)
|
||||
|
@ -431,8 +438,8 @@ RowLayout {
|
|||
height: colorText.height
|
||||
width: colorText.width / 2
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
visible: color_checkbox.checked
|
||||
color: color_checkbox.checked ? attribute.value : ""
|
||||
visible: colorCheckbox.checked
|
||||
color: colorCheckbox.checked ? colorDialog.selectedColor : ""
|
||||
|
||||
MouseArea {
|
||||
enabled: root.editable
|
||||
|
@ -444,9 +451,9 @@ RowLayout {
|
|||
ColorDialog {
|
||||
id: colorDialog
|
||||
title: "Please choose a color"
|
||||
color: attribute.value
|
||||
selectedColor: colorText.text
|
||||
onAccepted: {
|
||||
colorText.text = color
|
||||
colorText.text = colorDialog.selectedColor
|
||||
// Artificially trigger change of attribute value
|
||||
colorText.editingFinished()
|
||||
close()
|
||||
|
@ -461,13 +468,13 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: comboBox_component
|
||||
id: comboBoxComponent
|
||||
|
||||
FilterComboBox {
|
||||
inputModel: attribute.values
|
||||
|
||||
Component.onCompleted: {
|
||||
// if value not in list, override the text and precise it is not valid
|
||||
// If value not in list, override the text and precise it is not valid
|
||||
var idx = find(attribute.value)
|
||||
if (idx === -1) {
|
||||
displayText = attribute.value
|
||||
|
@ -484,10 +491,10 @@ RowLayout {
|
|||
Connections {
|
||||
target: attribute
|
||||
function onValueChanged() {
|
||||
// when reset, clear and find the current index
|
||||
// When reset, clear and find the current index
|
||||
// but if only reopen the combo box, keep the current value
|
||||
|
||||
//convert all values of desc values as string
|
||||
// Convert all values of desc values as string
|
||||
var valuesAsString = attribute.values.map(function(value) {
|
||||
return value.toString()
|
||||
})
|
||||
|
@ -503,10 +510,10 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: multiChoice_component
|
||||
id: multiChoiceComponent
|
||||
Flow {
|
||||
Repeater {
|
||||
id: checkbox_repeater
|
||||
id: checkboxRepeater
|
||||
model: attribute.values
|
||||
delegate: CheckBox {
|
||||
enabled: root.editable
|
||||
|
@ -515,9 +522,9 @@ RowLayout {
|
|||
onToggled: {
|
||||
var t = attribute.value
|
||||
if (!checked) {
|
||||
t.splice(t.indexOf(modelData), 1) // remove element
|
||||
t.splice(t.indexOf(modelData), 1) // Remove element
|
||||
} else {
|
||||
t.push(modelData) // add element
|
||||
t.push(modelData) // Add element
|
||||
}
|
||||
_reconstruction.setAttribute(attribute, t)
|
||||
}
|
||||
|
@ -527,7 +534,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: slider_component
|
||||
id: sliderComponent
|
||||
RowLayout {
|
||||
TextField {
|
||||
IntValidator {
|
||||
|
@ -535,12 +542,12 @@ RowLayout {
|
|||
}
|
||||
DoubleValidator {
|
||||
id: doubleValidator
|
||||
locale: 'C' // use '.' decimal separator disregarding the system locale
|
||||
locale: 'C' // Use '.' decimal separator disregarding the system locale
|
||||
}
|
||||
implicitWidth: 100
|
||||
Layout.fillWidth: !slider.active
|
||||
enabled: root.editable
|
||||
// cast value to string to avoid intrusive scientific notations on numbers
|
||||
// Cast value to string to avoid intrusive scientific notations on numbers
|
||||
property string displayValue: String(slider.active && slider.item.pressed ? slider.item.formattedValue : attribute.value)
|
||||
text: displayValue
|
||||
selectByMouse: true
|
||||
|
@ -594,7 +601,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: checkbox_component
|
||||
id: checkboxComponent
|
||||
Row {
|
||||
CheckBox {
|
||||
enabled: root.editable
|
||||
|
@ -605,17 +612,17 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: listAttribute_component
|
||||
id: listAttributeComponent
|
||||
ColumnLayout {
|
||||
id: listAttribute_layout
|
||||
id: listAttributeLayout
|
||||
width: parent.width
|
||||
property bool expanded: false
|
||||
RowLayout {
|
||||
spacing: 4
|
||||
ToolButton {
|
||||
text: listAttribute_layout.expanded ? MaterialIcons.keyboard_arrow_down : MaterialIcons.keyboard_arrow_right
|
||||
text: listAttributeLayout.expanded ? MaterialIcons.keyboard_arrow_down : MaterialIcons.keyboard_arrow_right
|
||||
font.family: MaterialIcons.fontFamily
|
||||
onClicked: listAttribute_layout.expanded = !listAttribute_layout.expanded
|
||||
onClicked: listAttributeLayout.expanded = !listAttributeLayout.expanded
|
||||
}
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
@ -632,7 +639,7 @@ RowLayout {
|
|||
}
|
||||
ListView {
|
||||
id: lv
|
||||
model: listAttribute_layout.expanded ? attribute.value : undefined
|
||||
model: listAttributeLayout.expanded ? attribute.value : undefined
|
||||
visible: model !== undefined && count > 0
|
||||
implicitHeight: Math.min(contentHeight, 300)
|
||||
Layout.fillWidth: true
|
||||
|
@ -683,7 +690,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: groupAttribute_component
|
||||
id: groupAttributeComponent
|
||||
ColumnLayout {
|
||||
id: groupItem
|
||||
Component.onCompleted: {
|
||||
|
@ -692,7 +699,7 @@ RowLayout {
|
|||
{
|
||||
'model': Qt.binding(function() { return attribute.value }),
|
||||
'readOnly': Qt.binding(function() { return root.readOnly }),
|
||||
'labelWidth': 100, // reduce label width for children (space gain)
|
||||
'labelWidth': 100, // Reduce label width for children (space gain)
|
||||
'objectsHideable': Qt.binding(function() { return root.objectsHideable }),
|
||||
'filterText': Qt.binding(function() { return root.filterText }),
|
||||
})
|
||||
|
@ -703,17 +710,17 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: color_hue_component
|
||||
id: colorHueComponent
|
||||
RowLayout {
|
||||
TextField {
|
||||
implicitWidth: 100
|
||||
enabled: root.editable
|
||||
// cast value to string to avoid intrusive scientific notations on numbers
|
||||
// Cast value to string to avoid intrusive scientific notations on numbers
|
||||
property string displayValue: String(slider.pressed ? slider.formattedValue : attribute.value)
|
||||
text: displayValue
|
||||
selectByMouse: true
|
||||
validator: DoubleValidator {
|
||||
locale: 'C' // use '.' decimal separator disregarding the system locale
|
||||
locale: 'C' // Use '.' decimal separator disregarding the system locale
|
||||
}
|
||||
onEditingFinished: setTextFieldAttribute(text)
|
||||
onAccepted: setTextFieldAttribute(text)
|
||||
|
@ -748,16 +755,7 @@ RowLayout {
|
|||
width: control.availableWidth
|
||||
height: control.availableHeight
|
||||
blending: false
|
||||
fragmentShader: "
|
||||
varying mediump vec2 qt_TexCoord0;
|
||||
vec3 hsv2rgb(vec3 c) {
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
void main() {
|
||||
gl_FragColor = vec4(hsv2rgb(vec3(qt_TexCoord0.x, 1.0, 1.0)), 1.0);
|
||||
}"
|
||||
fragmentShader: "qrc:/shaders/AttributeItemDelegate.frag.qsb"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
The representation of an Attribute on a Node.
|
||||
*/
|
||||
* The representation of an Attribute on a Node.
|
||||
*/
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
|
@ -43,24 +44,23 @@ RowLayout {
|
|||
x: nameLabel.x
|
||||
}
|
||||
|
||||
function updatePin(isSrc, isVisible)
|
||||
{
|
||||
function updatePin(isSrc, isVisible) {
|
||||
if (isSrc) {
|
||||
innerOutputAnchor.linkEnabled = isVisible
|
||||
} else {
|
||||
innerInputAnchor.linkEnabled = isVisible
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Instantiate empty Items for each child attribute
|
||||
Repeater {
|
||||
id: childrenRepeater
|
||||
model: isList && !attribute.isLink ? attribute.value : 0
|
||||
onItemAdded: childPinCreated(item.childAttribute, item)
|
||||
onItemRemoved: childPinDeleted(item.childAttribute, item)
|
||||
onItemAdded: function(index, item) { childPinCreated(item.childAttribute, root) }
|
||||
onItemRemoved: function(index, item) { childPinDeleted(item.childAttribute, root) }
|
||||
delegate: Item {
|
||||
property var childAttribute: object
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,38 +95,39 @@ RowLayout {
|
|||
|
||||
property bool acceptableDrop: false
|
||||
|
||||
// add negative margins for DropArea to make the connection zone easier to reach
|
||||
// Add negative margins for DropArea to make the connection zone easier to reach
|
||||
anchors.fill: parent
|
||||
anchors.margins: -2
|
||||
// add horizontal negative margins according to the current layout
|
||||
// Add horizontal negative margins according to the current layout
|
||||
anchors.rightMargin: -root.width * 0.3
|
||||
|
||||
keys: [inputDragTarget.objectName]
|
||||
onEntered: {
|
||||
onEntered: function(drag) {
|
||||
// Check if attributes are compatible to create a valid connection
|
||||
if (root.readOnly // cannot connect on a read-only attribute
|
||||
|| drag.source.objectName != inputDragTarget.objectName // not an edge connector
|
||||
|| drag.source.baseType !== inputDragTarget.baseType // not the same base type
|
||||
|| drag.source.nodeItem === inputDragTarget.nodeItem // connection between attributes of the same node
|
||||
|| (drag.source.isList && childrenRepeater.count) // source/target are lists but target already has children
|
||||
|| drag.source.connectorType === "input" // refuse to connect an "input pin" on another one (input attr can be connected to input attr, but not the graphical pin)
|
||||
if (root.readOnly // Cannot connect on a read-only attribute
|
||||
|| drag.source.objectName != inputDragTarget.objectName // Not an edge connector
|
||||
|| drag.source.baseType !== inputDragTarget.baseType // Not the same base type
|
||||
|| drag.source.nodeItem === inputDragTarget.nodeItem // Connection between attributes of the same node
|
||||
|| (drag.source.isList && childrenRepeater.count) // Source/target are lists but target already has children
|
||||
|| drag.source.connectorType === "input" // Refuse to connect an "input pin" on another one (input attr can be connected to input attr, but not the graphical pin)
|
||||
) {
|
||||
// Refuse attributes connection
|
||||
drag.accepted = false
|
||||
} else if (inputDragTarget.attribute.isLink) { // already connected attribute
|
||||
} else if (inputDragTarget.attribute.isLink) { // Already connected attribute
|
||||
root.edgeAboutToBeRemoved(inputDragTarget.attribute)
|
||||
}
|
||||
inputDropArea.acceptableDrop = drag.accepted
|
||||
}
|
||||
|
||||
onExited: {
|
||||
if (inputDragTarget.attribute.isLink) { // already connected attribute
|
||||
if (inputDragTarget.attribute.isLink) { // Already connected attribute
|
||||
root.edgeAboutToBeRemoved(undefined)
|
||||
}
|
||||
acceptableDrop = false
|
||||
drag.source.dropAccepted = false
|
||||
}
|
||||
|
||||
onDropped: {
|
||||
onDropped: function(drop) {
|
||||
root.edgeAboutToBeRemoved(undefined)
|
||||
_reconstruction.addEdge(drag.source.attribute, inputDragTarget.attribute)
|
||||
}
|
||||
|
@ -160,11 +161,11 @@ RowLayout {
|
|||
drag.smoothed: false
|
||||
enabled: !root.readOnly
|
||||
anchors.fill: parent
|
||||
// use the same negative margins as DropArea to ease pin selection
|
||||
// Use the same negative margins as DropArea to ease pin selection
|
||||
anchors.margins: inputDropArea.anchors.margins
|
||||
anchors.leftMargin: inputDropArea.anchors.leftMargin
|
||||
anchors.rightMargin: inputDropArea.anchors.rightMargin
|
||||
onPressed: {
|
||||
onPressed: function(mouse) {
|
||||
root.pressed(mouse)
|
||||
}
|
||||
onReleased: {
|
||||
|
@ -185,14 +186,11 @@ RowLayout {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Attribute name
|
||||
Item {
|
||||
id: nameContainer
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: childrenRect.height
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
Label {
|
||||
|
@ -208,13 +206,13 @@ RowLayout {
|
|||
anchors.right: attribute && attribute.isOutput ? parent.right : undefined
|
||||
rightPadding: 0
|
||||
color: {
|
||||
if ((object.hasOutputConnections || object.isLink) && !object.enabled) return Colors.lightgrey
|
||||
if ((object.hasOutputConnections || object.isLink) && !object.enabled)
|
||||
return Colors.lightgrey
|
||||
return hovered ? palette.highlight : palette.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: outputAnchor
|
||||
|
||||
|
@ -248,25 +246,25 @@ RowLayout {
|
|||
|
||||
property bool acceptableDrop: false
|
||||
|
||||
// add negative margins for DropArea to make the connection zone easier to reach
|
||||
// Add negative margins for DropArea to make the connection zone easier to reach
|
||||
anchors.fill: parent
|
||||
anchors.margins: -2
|
||||
// add horizontal negative margins according to the current layout
|
||||
// Add horizontal negative margins according to the current layout
|
||||
anchors.leftMargin: -root.width * 0.2
|
||||
|
||||
keys: [outputDragTarget.objectName]
|
||||
onEntered: {
|
||||
onEntered: function(drag) {
|
||||
// Check if attributes are compatible to create a valid connection
|
||||
if (drag.source.objectName != outputDragTarget.objectName // not an edge connector
|
||||
|| drag.source.baseType !== outputDragTarget.baseType // not the same base type
|
||||
|| drag.source.nodeItem === outputDragTarget.nodeItem // connection between attributes of the same node
|
||||
|| (!drag.source.isList && outputDragTarget.isList) // connection between a list and a simple attribute
|
||||
|| (drag.source.isList && childrenRepeater.count) // source/target are lists but target already has children
|
||||
|| drag.source.connectorType === "output" // refuse to connect an output pin on another one
|
||||
if (drag.source.objectName != outputDragTarget.objectName // Not an edge connector
|
||||
|| drag.source.baseType !== outputDragTarget.baseType // Not the same base type
|
||||
|| drag.source.nodeItem === outputDragTarget.nodeItem // Connection between attributes of the same node
|
||||
|| (!drag.source.isList && outputDragTarget.isList) // Connection between a list and a simple attribute
|
||||
|| (drag.source.isList && childrenRepeater.count) // Source/target are lists but target already has children
|
||||
|| drag.source.connectorType === "output" // Refuse to connect an output pin on another one
|
||||
) {
|
||||
// Refuse attributes connection
|
||||
drag.accepted = false
|
||||
} else if (drag.source.attribute.isLink) { // already connected attribute
|
||||
} else if (drag.source.attribute.isLink) { // Already connected attribute
|
||||
root.edgeAboutToBeRemoved(drag.source.attribute)
|
||||
}
|
||||
outputDropArea.acceptableDrop = drag.accepted
|
||||
|
@ -276,7 +274,7 @@ RowLayout {
|
|||
acceptableDrop = false
|
||||
}
|
||||
|
||||
onDropped: {
|
||||
onDropped: function(drop) {
|
||||
root.edgeAboutToBeRemoved(undefined)
|
||||
_reconstruction.addEdge(outputDragTarget.attribute, drag.source.attribute)
|
||||
}
|
||||
|
@ -309,12 +307,12 @@ RowLayout {
|
|||
// Move the edge's tip straight to the the current mouse position instead of waiting after the drag operation has started
|
||||
drag.smoothed: false
|
||||
anchors.fill: parent
|
||||
// use the same negative margins as DropArea to ease pin selection
|
||||
// Use the same negative margins as DropArea to ease pin selection
|
||||
anchors.margins: outputDropArea.anchors.margins
|
||||
anchors.leftMargin: outputDropArea.anchors.leftMargin
|
||||
anchors.rightMargin: outputDropArea.anchors.rightMargin
|
||||
|
||||
onPressed: root.pressed(mouse)
|
||||
onPressed: function(mouse) { root.pressed(mouse) }
|
||||
onReleased: outputDragTarget.Drag.drop()
|
||||
|
||||
hoverEnabled: true
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import "common.js" as Common
|
||||
|
||||
/**
|
||||
* ChunkListView
|
||||
*/
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
property variant chunks
|
||||
|
@ -78,7 +77,7 @@ ColumnLayout {
|
|||
id: chunkDelegate
|
||||
property var chunk: object
|
||||
text: index
|
||||
width: parent ? parent.width : 0
|
||||
width: ListView.view.width
|
||||
leftPadding: 8
|
||||
onClicked: {
|
||||
chunksLV.forceActiveFocus()
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
|
||||
|
||||
/** Node Badge to inform about compatibility issues
|
||||
/**
|
||||
* Node Badge to inform about compatibility issues
|
||||
* Provides 2 delegates (can be set using sourceComponent property):
|
||||
* - iconDelegate (default): icon + tooltip with information about the issue
|
||||
* - bannerDelegate: banner with issue info + upgrade request button
|
||||
*/
|
||||
*/
|
||||
|
||||
Loader {
|
||||
id: root
|
||||
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* CompatibilityManager summarizes and allows to resolve compatibility issues.
|
||||
*/
|
||||
*/
|
||||
|
||||
MessageDialog {
|
||||
id: root
|
||||
|
||||
// the UIGraph instance
|
||||
// The UIGraph instance
|
||||
property var uigraph
|
||||
// alias to underlying compatibilityNodes model
|
||||
// Alias to underlying compatibilityNodes model
|
||||
readonly property var nodesModel: uigraph ? uigraph.graph.compatibilityNodes : undefined
|
||||
// the total number of compatibility issues
|
||||
// The total number of compatibility issues
|
||||
readonly property int issueCount: (nodesModel !== undefined && nodesModel !== null) ? nodesModel.count : 0
|
||||
// the number of CompatibilityNodes that can be upgraded
|
||||
// The number of CompatibilityNodes that can be upgraded
|
||||
readonly property int upgradableCount: {
|
||||
var count = 0
|
||||
for (var i = 0; i < issueCount; ++i) {
|
||||
|
@ -27,7 +29,7 @@ MessageDialog {
|
|||
return count
|
||||
}
|
||||
|
||||
// override MessageDialog.getAsString to add compatibility report
|
||||
// Override MessageDialog.getAsString to add compatibility report
|
||||
function getAsString() {
|
||||
var t = asString + "\n"
|
||||
t += '-------------------------\n'
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Shapes 1.6
|
||||
|
||||
import GraphEditor 1.0
|
||||
import QtQuick.Shapes 1.15
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
/**
|
||||
A cubic spline representing an edge, going from point1 to point2, providing mouse interaction.
|
||||
*/
|
||||
* A cubic spline representing an edge, going from point1 to point2, providing mouse interaction.
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
|
@ -40,7 +42,7 @@ Item {
|
|||
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
// cause rendering artifacts when enabled (and don't support hot reload really well)
|
||||
// Cause rendering artifacts when enabled (and don't support hot reload really well)
|
||||
vendorExtensionsEnabled: false
|
||||
opacity: 0.7
|
||||
|
||||
|
@ -53,7 +55,7 @@ Item {
|
|||
strokeColor: "#3E3E3E"
|
||||
strokeStyle: edge !== undefined && ((edge.src !== undefined && edge.src.isOutput) || edge.dst === undefined) ? ShapePath.SolidLine : ShapePath.DashLine
|
||||
strokeWidth: 1
|
||||
// final visual width of this path (never below 1)
|
||||
// Final visual width of this path (never below 1)
|
||||
readonly property real visualWidth: Math.max(strokeWidth, 1)
|
||||
dashPattern: [6 / visualWidth, 4 / visualWidth]
|
||||
capStyle: ShapePath.RoundCap
|
||||
|
@ -68,7 +70,6 @@ Item {
|
|||
control2X: x - ctrlPtDist
|
||||
control2Y: y
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
|
@ -80,7 +81,7 @@ Item {
|
|||
strokeColor: root.isForLoop ? root.color : "transparent"
|
||||
strokeStyle: edge !== undefined && ((edge.src !== undefined && edge.src.isOutput) || edge.dst === undefined) ? ShapePath.SolidLine : ShapePath.DashLine
|
||||
strokeWidth: root.thickness
|
||||
// final visual width of this path (never below 1)
|
||||
// Final visual width of this path (never below 1)
|
||||
readonly property real visualWidth: Math.max(strokeWidth, 1)
|
||||
dashPattern: [6 / visualWidth, 4 / visualWidth]
|
||||
capStyle: ShapePath.RoundCap
|
||||
|
@ -97,11 +98,13 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
// place the label at the middle of the edge
|
||||
// Place the label at the middle of the edge
|
||||
x: (root.startX + root.endX) / 2
|
||||
y: (root.startY + root.endY) / 2
|
||||
visible: root.isForLoop
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
property int margin: 2
|
||||
|
@ -109,6 +112,7 @@ Item {
|
|||
height: icon.height + 2 * margin
|
||||
radius: width
|
||||
color: path.strokeColor
|
||||
|
||||
MaterialToolLabel {
|
||||
id: icon
|
||||
anchors.centerIn: parent
|
||||
|
@ -119,6 +123,7 @@ Item {
|
|||
color: palette.base
|
||||
ToolTip.text: "Foreach Loop"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: loopArea
|
||||
anchors.fill: parent
|
||||
|
@ -126,16 +131,25 @@ Item {
|
|||
onClicked: root.pressed(arguments[0])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EdgeMouseArea {
|
||||
id: edgeArea
|
||||
anchors.fill: parent
|
||||
curveScale: cubic.ctrlPtDist / root.width // normalize by width
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
thickness: root.thickness + 4
|
||||
onPressed: root.pressed(arguments[0]) // can't get named args, use arguments array
|
||||
onReleased: root.released(arguments[0])
|
||||
onPressed: function(event) {
|
||||
root.pressed(event)
|
||||
}
|
||||
onReleased: function(event) {
|
||||
root.released(event)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
/* The curve scale must be set only once the component has been fully created, so
|
||||
* that all the events following the update of the curve scale can be taken into
|
||||
* account */
|
||||
curveScale = cubic.ctrlPtDist / root.width // Normalize by width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
A component displaying a Graph (nodes, attributes and edges).
|
||||
*/
|
||||
* A component displaying a Graph (nodes, attributes and edges).
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property variant uigraph: null /// Meshroom ui graph (UIGraph)
|
||||
readonly property variant graph: uigraph ? uigraph.graph : null /// core graph contained in ui graph
|
||||
property variant nodeTypesModel: null /// the list of node types that can be instantiated
|
||||
property variant uigraph: null /// Meshroom UI graph (UIGraph)
|
||||
readonly property variant graph: uigraph ? uigraph.graph : null /// Core graph contained in the UI graph
|
||||
property variant nodeTypesModel: null /// The list of node types that can be instantiated
|
||||
property real maxZoom: 2.0
|
||||
property real minZoom: 0.1
|
||||
|
||||
|
@ -21,7 +23,7 @@ Item {
|
|||
|
||||
property var _attributeToDelegate: ({})
|
||||
|
||||
// signals
|
||||
// Signals
|
||||
signal workspaceMoved()
|
||||
signal workspaceClicked()
|
||||
|
||||
|
@ -33,10 +35,9 @@ Item {
|
|||
|
||||
property int nbMeshroomScenes: 0
|
||||
property int nbDraggedFiles: 0
|
||||
// Files have been dropped
|
||||
signal filesDropped(var drop, var mousePosition)
|
||||
signal filesDropped(var drop, var mousePosition) // Files have been dropped
|
||||
|
||||
// trigger initial fit() after initialization
|
||||
// Trigger initial fit() after initialization
|
||||
// (ensure GraphEditor has its final size)
|
||||
Component.onCompleted: firstFitTimer.start()
|
||||
|
||||
|
@ -132,7 +133,7 @@ Item {
|
|||
return mapToItem(draggable, mouseArea.width / 2, mouseArea.height / 2)
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_F) {
|
||||
fit()
|
||||
} else if (event.key === Qt.Key_Delete) {
|
||||
|
@ -172,7 +173,7 @@ Item {
|
|||
drag.threshold: 0
|
||||
cursorShape: drag.target == draggable ? Qt.ClosedHandCursor : Qt.ArrowCursor
|
||||
|
||||
onWheel: {
|
||||
onWheel: function(wheel) {
|
||||
var zoomFactor = wheel.angleDelta.y > 0 ? factor : 1 / factor
|
||||
var scale = draggable.scale * zoomFactor
|
||||
scale = Math.min(Math.max(minZoom, scale), maxZoom)
|
||||
|
@ -185,7 +186,7 @@ Item {
|
|||
workspaceMoved()
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
onPressed: function(mouse) {
|
||||
if (mouse.button != Qt.MiddleButton && mouse.modifiers == Qt.NoModifier) {
|
||||
uigraph.clearNodeSelection()
|
||||
}
|
||||
|
@ -200,19 +201,21 @@ Item {
|
|||
drag.target = draggable // start drag
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
drag.target = undefined // stop drag
|
||||
root.forceActiveFocus()
|
||||
workspaceClicked()
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
if (drag.active)
|
||||
workspaceMoved()
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
onClicked: function(mouse) {
|
||||
if (mouse.button == Qt.RightButton) {
|
||||
// store mouse click position in 'draggable' coordinates as new node spawn position
|
||||
// Store mouse click position in 'draggable' coordinates as new node spawn position
|
||||
newNodeMenu.spawnPosition = mouseArea.mapToItem(draggable, mouse.x, mouse.y)
|
||||
newNodeMenu.popup()
|
||||
}
|
||||
|
@ -271,7 +274,7 @@ Item {
|
|||
onVisibleChanged: {
|
||||
searchBar.clear()
|
||||
if (visible) {
|
||||
// when menu is shown, give focus to the TextField filter
|
||||
// When menu is shown, give focus to the TextField filter
|
||||
searchBar.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
@ -295,12 +298,12 @@ Item {
|
|||
// Forward key events to the search bar to continue typing seamlessly
|
||||
// even if this delegate took the activeFocus due to mouse hovering
|
||||
Keys.forwardTo: [searchBar.textField]
|
||||
Keys.onPressed: {
|
||||
Keys.onPressed: function(event) {
|
||||
event.accepted = false;
|
||||
switch (event.key) {
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
// create node on validation (Enter/Return keys)
|
||||
// Create node on validation (Enter/Return keys)
|
||||
newNodeMenu.createNode(modelData)
|
||||
event.accepted = true
|
||||
break
|
||||
|
@ -308,7 +311,7 @@ Item {
|
|||
case Qt.Key_Down:
|
||||
case Qt.Key_Left:
|
||||
case Qt.Key_Right:
|
||||
break // ignore if arrow key was pressed to let the menu be controlled
|
||||
break // Ignore if arrow key was pressed to let the menu be controlled
|
||||
default:
|
||||
searchBar.forceActiveFocus()
|
||||
}
|
||||
|
@ -323,8 +326,8 @@ Item {
|
|||
name: "invisible"
|
||||
PropertyChanges {
|
||||
target: menuItemDelegate
|
||||
height: 0 // make sure the item is no visible by setting height to 0
|
||||
focusPolicy: Qt.NoFocus // don't grab focus when not visible
|
||||
height: 0 // Make sure the item is no visible by setting height to 0
|
||||
focusPolicy: Qt.NoFocus // Don't grab focus when not visible
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -335,7 +338,7 @@ Item {
|
|||
id: nodeMenuRepeater
|
||||
model: searchBar.text !== "" ? Object.values(newNodeMenu.menuKeys) : undefined
|
||||
|
||||
// create Menu items from available items
|
||||
// Create Menu items from available items
|
||||
delegate: menuItemDelegateComponent
|
||||
}
|
||||
|
||||
|
@ -343,8 +346,13 @@ Item {
|
|||
Instantiator {
|
||||
id: instantiator
|
||||
model: (searchBar.text === "") ? Object.keys(newNodeMenu.parseCategories()).sort() : undefined
|
||||
onObjectAdded: newNodeMenu.insertMenu(index + 1, object ) // add sub-menu under the search bar
|
||||
onObjectRemoved: newNodeMenu.removeMenu(object)
|
||||
onObjectAdded: function(index, object) {
|
||||
// Add sub-menu under the search bar
|
||||
newNodeMenu.insertMenu(index + 1, object)
|
||||
}
|
||||
onObjectRemoved: function(index, object) {
|
||||
newNodeMenu.removeMenu(object)
|
||||
}
|
||||
|
||||
delegate: Menu {
|
||||
title: modelData
|
||||
|
@ -352,8 +360,12 @@ Item {
|
|||
|
||||
Instantiator {
|
||||
model: newNodeMenu.visible ? newNodeMenu.parseCategories()[modelData] : undefined
|
||||
onObjectAdded: newNodeSubMenu.insertItem(index, object)
|
||||
onObjectRemoved: newNodeSubMenu.removeItem(object)
|
||||
onObjectAdded: function(index, object) {
|
||||
newNodeSubMenu.insertItem(index, object)
|
||||
}
|
||||
onObjectRemoved: function(index, object) {
|
||||
newNodeSubMenu.removeItem(object)
|
||||
}
|
||||
delegate: menuItemDelegateComponent
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +429,7 @@ Item {
|
|||
const newSrcAttr = listAttr.value.at(value - 1)
|
||||
const dst = edgeMenu.currentEdge.dst
|
||||
|
||||
// if the edge exists do not replace it
|
||||
// If the edge exists, do not replace it
|
||||
if (newSrcAttr === edgeMenu.currentEdge.src && dst === edgeMenu.currentEdge.dst) {
|
||||
return
|
||||
}
|
||||
|
@ -476,7 +488,7 @@ Item {
|
|||
Repeater {
|
||||
id: edgesRepeater
|
||||
|
||||
// delay edges loading after nodes (edges needs attribute pins to be created)
|
||||
// Delay edges loading after nodes (edges needs attribute pins to be created)
|
||||
model: nodeRepeater.loaded && root.graph ? root.graph.edges : undefined
|
||||
|
||||
delegate: Edge {
|
||||
|
@ -500,12 +512,11 @@ Item {
|
|||
}
|
||||
return (inFocus) ? 2 : 1
|
||||
}
|
||||
|
||||
point1x: isValidEdge ? src.globalX + src.outputAnchorPos.x : 0
|
||||
point1y: isValidEdge ? src.globalY + src.outputAnchorPos.y : 0
|
||||
point2x: isValidEdge ? dst.globalX + dst.inputAnchorPos.x : 0
|
||||
point2y: isValidEdge ? dst.globalY + dst.inputAnchorPos.y : 0
|
||||
onPressed: {
|
||||
onPressed: function(event) {
|
||||
const canEdit = !edge.dst.node.locked
|
||||
|
||||
if (event.button) {
|
||||
|
@ -540,7 +551,7 @@ Item {
|
|||
id: nodeMenu
|
||||
property var currentNode: null
|
||||
property bool canComputeNode: currentNode != null && uigraph.graph.canComputeTopologically(currentNode)
|
||||
//canSubmitOrCompute: return int n : 0 >= n <= 3 | n=0 cannot submit or compute | n=1 can compute | n=2 can submit | n=3 can compute & submit
|
||||
// canSubmitOrCompute: return int n : 0 >= n <= 3 | n=0 cannot submit or compute | n=1 can compute | n=2 can submit | n=3 can compute & submit
|
||||
property int canSubmitOrCompute: currentNode != null && uigraph.graph.canSubmitOrCompute(currentNode)
|
||||
property bool isComputed: {
|
||||
var count = 0
|
||||
|
@ -589,7 +600,7 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
return canCompute //canSubmit if canSubmitOrCompute == 1(can compute) or 3(can compute & submit)
|
||||
return canCompute // canSubmit if canSubmitOrCompute == 1(can compute) or 3(can compute & submit)
|
||||
}
|
||||
|
||||
onTriggered: {
|
||||
|
@ -823,14 +834,14 @@ Item {
|
|||
selected: uigraph.selectedNodes.contains(node)
|
||||
hovered: uigraph.hoveredNode === node
|
||||
|
||||
onAttributePinCreated: registerAttributePin(attribute, pin)
|
||||
onAttributePinDeleted: unregisterAttributePin(attribute, pin)
|
||||
onAttributePinCreated: function(attribute, pin) { registerAttributePin(attribute, pin) }
|
||||
onAttributePinDeleted: function(attribute, pin) { unregisterAttributePin(attribute, pin) }
|
||||
|
||||
onPressed: {
|
||||
onPressed: function(mouse) {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
if (mouse.modifiers & Qt.ControlModifier && !(mouse.modifiers & Qt.AltModifier)) {
|
||||
if (mainSelected && selected) {
|
||||
// left clicking a selected node twice with control will deselect it
|
||||
// Left clicking a selected node twice with control will deselect it
|
||||
uigraph.selectedNodes.remove(node)
|
||||
uigraph.selectedNodesChanged()
|
||||
selectNode(null)
|
||||
|
@ -854,21 +865,19 @@ Item {
|
|||
selectNode(node)
|
||||
}
|
||||
|
||||
onDoubleClicked: root.nodeDoubleClicked(mouse, node)
|
||||
onDoubleClicked: function(mouse) { root.nodeDoubleClicked(mouse, node) }
|
||||
|
||||
onMoved: uigraph.moveNode(node, position, uigraph.selectedNodes)
|
||||
onMoved: function(position) { uigraph.moveNode(node, position, uigraph.selectedNodes) }
|
||||
|
||||
onEntered: uigraph.hoveredNode = node
|
||||
onExited: uigraph.hoveredNode = null
|
||||
|
||||
onEdgeAboutToBeRemoved: {
|
||||
onEdgeAboutToBeRemoved: function(input) {
|
||||
/*
|
||||
Sometimes the signals are not in the right order
|
||||
because of weird Qt/QML update order (next DropArea
|
||||
entered signal before previous DropArea exited signal)
|
||||
so edgeAboutToBeRemoved must be set to undefined before
|
||||
it can be set to another attribute object.
|
||||
*/
|
||||
* Sometimes the signals are not in the right order because of weird Qt/QML update order
|
||||
* (next DropArea entered signal before previous DropArea exited signal) so edgeAboutToBeRemoved
|
||||
* must be set to undefined before it can be set to another attribute object.
|
||||
*/
|
||||
if (input === undefined) {
|
||||
if (nodeRepeater.temporaryEdgeAboutToBeRemoved === undefined) {
|
||||
root.edgeAboutToBeRemoved = input
|
||||
|
@ -887,7 +896,7 @@ Item {
|
|||
|
||||
onPositionChanged: {
|
||||
if (dragging && uigraph.selectedNodes.contains(node)) {
|
||||
// update all selected nodes positions with this node that is being dragged
|
||||
// Update all selected nodes positions with this node that is being dragged
|
||||
for (var i = 0; i < nodeRepeater.count; i++) {
|
||||
var otherNode = nodeRepeater.itemAt(i)
|
||||
if (uigraph.selectedNodes.contains(otherNode.node) && otherNode.node !== node) {
|
||||
|
@ -898,10 +907,10 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
// allow all nodes to know if they are being dragged
|
||||
// Allow all nodes to know if they are being dragged
|
||||
onDraggingChanged: nodeRepeater.dragging = dragging
|
||||
|
||||
// must not be enabled during drag because the other nodes will be slow to match the movement of the node being dragged
|
||||
// Must not be enabled during drag because the other nodes will be slow to match the movement of the node being dragged
|
||||
Behavior on x {
|
||||
enabled: !nodeRepeater.dragging
|
||||
NumberAnimation { duration: 100 }
|
||||
|
@ -956,12 +965,12 @@ Item {
|
|||
})
|
||||
}
|
||||
|
||||
onDropped: {
|
||||
onDropped: function(drop) {
|
||||
if (nbMeshroomScenes == nbDraggedFiles || nbMeshroomScenes == 0) {
|
||||
// retrieve mouse position and convert coordinate system
|
||||
// Retrieve mouse position and convert coordinate system
|
||||
// from pixel values to graph reference system
|
||||
var mousePosition = mapToItem(draggable, drag.x, drag.y)
|
||||
// send the list of files,
|
||||
// Send the list of files,
|
||||
// to create the corresponding nodes or open another scene
|
||||
filesDropped(drop, mousePosition)
|
||||
} else {
|
||||
|
@ -1110,12 +1119,12 @@ Item {
|
|||
}
|
||||
|
||||
function nextItem() {
|
||||
// compute bounding box
|
||||
// Compute bounding box
|
||||
var node = nodeRepeater.itemAt(filteredNodes.itemAt(navigation.currentIndex).index_)
|
||||
var bbox = Qt.rect(node.x, node.y, node.width, node.height)
|
||||
// rescale to fit the bounding box in the view, zoom is limited to prevent huge text
|
||||
// Rescale to fit the bounding box in the view, zoom is limited to prevent huge text
|
||||
draggable.scale = Math.min(Math.min(root.width / bbox.width, root.height / bbox.height),maxZoom)
|
||||
// recenter
|
||||
// Recenter
|
||||
draggable.x = bbox.x*draggable.scale * -1 + (root.width - bbox.width * draggable.scale) * 0.5
|
||||
draggable.y = bbox.y*draggable.scale * -1 + (root.height - bbox.height * draggable.scale) * 0.5
|
||||
}
|
||||
|
@ -1124,6 +1133,7 @@ Item {
|
|||
function registerAttributePin(attribute, pin) {
|
||||
root._attributeToDelegate[attribute] = pin
|
||||
}
|
||||
|
||||
function unregisterAttributePin(attribute, pin) {
|
||||
delete root._attributeToDelegate[attribute]
|
||||
}
|
||||
|
@ -1148,11 +1158,11 @@ Item {
|
|||
|
||||
// Fit graph to fill root
|
||||
function fit() {
|
||||
// compute bounding box
|
||||
// Compute bounding box
|
||||
var bbox = boundingBox()
|
||||
// rescale to fit the bounding box in the view, zoom is limited to prevent huge text
|
||||
// Rescale to fit the bounding box in the view, zoom is limited to prevent huge text
|
||||
draggable.scale = Math.min(Math.min(root.width / bbox.width, root.height / bbox.height), maxZoom)
|
||||
// recenter
|
||||
// Recenter
|
||||
draggable.x = bbox.x * draggable.scale * -1 + (root.width - bbox.width * draggable.scale) * 0.5
|
||||
draggable.y = bbox.y * draggable.scale * -1 + (root.height - bbox.height * draggable.scale) * 0.5
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
pragma Singleton
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import QtCore
|
||||
|
||||
/**
|
||||
* Persistent Settings related to the GraphEditor module.
|
||||
*/
|
||||
|
||||
Settings {
|
||||
category: 'GraphEditor'
|
||||
property bool showAdvancedAttributes: false
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtGraphicalEffects 1.12
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Utils 1.0
|
||||
import MaterialIcons 2.2
|
||||
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* Visual representation of a Graph Node.
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
|
@ -121,12 +121,12 @@ Item {
|
|||
width: parent.width
|
||||
height: body.height
|
||||
drag.target: root
|
||||
// small drag threshold to avoid moving the node by mistake
|
||||
// Small drag threshold to avoid moving the node by mistake
|
||||
drag.threshold: 2
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onPressed: root.pressed(mouse)
|
||||
onDoubleClicked: root.doubleClicked(mouse)
|
||||
onPressed: function(mouse) { root.pressed(mouse) }
|
||||
onDoubleClicked: function(mouse) { root.doubleClicked(mouse) }
|
||||
onEntered: root.entered()
|
||||
onExited: root.exited()
|
||||
drag.onActiveChanged: {
|
||||
|
@ -412,8 +412,8 @@ Item {
|
|||
property real globalX: root.x + nodeAttributes.x + outputs.x + outputLoader.x + outPin.x
|
||||
property real globalY: root.y + nodeAttributes.y + outputs.y + outputLoader.y + outPin.y
|
||||
|
||||
onPressed: root.pressed(mouse)
|
||||
onEdgeAboutToBeRemoved: root.edgeAboutToBeRemoved(input)
|
||||
onPressed: function(mouse) { root.pressed(mouse) }
|
||||
onEdgeAboutToBeRemoved: function(input) { root.edgeAboutToBeRemoved(input) }
|
||||
|
||||
Component.onCompleted: attributePinCreated(attribute, outPin)
|
||||
onChildPinCreated: attributePinCreated(childAttribute, outPin)
|
||||
|
@ -446,13 +446,13 @@ Item {
|
|||
property real globalX: root.x + nodeAttributes.x + inputs.x + inputLoader.x + inPin.x
|
||||
property real globalY: root.y + nodeAttributes.y + inputs.y + inputLoader.y + inPin.y
|
||||
|
||||
readOnly: root.readOnly || object.isReadOnly
|
||||
readOnly: Boolean(root.readOnly || object.isReadOnly)
|
||||
Component.onCompleted: attributePinCreated(attribute, inPin)
|
||||
Component.onDestruction: attributePinDeleted(attribute, inPin)
|
||||
onPressed: root.pressed(mouse)
|
||||
onEdgeAboutToBeRemoved: root.edgeAboutToBeRemoved(input)
|
||||
onChildPinCreated: attributePinCreated(childAttribute, inPin)
|
||||
onChildPinDeleted: attributePinDeleted(childAttribute, inPin)
|
||||
onPressed: function(mouse) { root.pressed(mouse) }
|
||||
onEdgeAboutToBeRemoved: function(input) { root.edgeAboutToBeRemoved(input) }
|
||||
onChildPinCreated: function(childAttribute, inPin) { attributePinCreated(childAttribute, inPin) }
|
||||
onChildPinDeleted: function(childAttribute, inPin) { attributePinDeleted(childAttribute, inPin) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -512,10 +512,10 @@ Item {
|
|||
readOnly: Boolean(root.readOnly || object.isReadOnly)
|
||||
Component.onCompleted: attributePinCreated(attribute, inParamsPin)
|
||||
Component.onDestruction: attributePinDeleted(attribute, inParamsPin)
|
||||
onPressed: root.pressed(mouse)
|
||||
onEdgeAboutToBeRemoved: root.edgeAboutToBeRemoved(input)
|
||||
onChildPinCreated: attributePinCreated(childAttribute, inParamsPin)
|
||||
onChildPinDeleted: attributePinDeleted(childAttribute, inParamsPin)
|
||||
onPressed: function(mouse) { root.pressed(mouse) }
|
||||
onEdgeAboutToBeRemoved: function(input) { root.edgeAboutToBeRemoved(input) }
|
||||
onChildPinCreated: function(childAttribute, inParamsPin) { attributePinCreated(childAttribute, inParamsPin) }
|
||||
onChildPinDeleted: function(childAttribute, inParamsPin) { attributePinDeleted(childAttribute, inParamsPin) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import Utils 1.0
|
||||
import QtQuick
|
||||
|
||||
//import "common.js" as Common
|
||||
import Utils 1.0
|
||||
|
||||
ListView {
|
||||
id: root
|
||||
|
@ -14,7 +13,7 @@ ListView {
|
|||
property real chunkHeight: height
|
||||
property bool modelIsBig: (3 * model.count >= width)
|
||||
property real chunkWidth: {
|
||||
if(!model || model.count == 0)
|
||||
if (!model || model.count == 0)
|
||||
return 0
|
||||
return (width / model.count) - spacing
|
||||
}
|
||||
|
@ -29,13 +28,12 @@ ListView {
|
|||
width: root.chunkWidth
|
||||
property var chunkColor: Colors.getChunkColor(object, { "NONE": root.defaultColor })
|
||||
color: {
|
||||
if(!highlightChunks || model.count == 1)
|
||||
if (!highlightChunks || model.count == 1)
|
||||
return chunkColor
|
||||
if(index % 2 == 0)
|
||||
if (index % 2 == 0)
|
||||
return Qt.lighter(chunkColor, 1.1)
|
||||
else
|
||||
return Qt.darker(chunkColor, 1.1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
|
||||
import "common.js" as Common
|
||||
|
@ -8,6 +9,7 @@ import "common.js" as Common
|
|||
/**
|
||||
* Displays Node documentation
|
||||
*/
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* NodeEditor allows to visualize and edit the parameters of a Node.
|
||||
* It mainly provides an attribute editor and a log inspector.
|
||||
*/
|
||||
|
||||
Panel {
|
||||
id: root
|
||||
|
||||
|
@ -35,7 +36,7 @@ Panel {
|
|||
if (node !== null && (node.isFinishedOrRunning() || globalStatus == "ERROR")) {
|
||||
computationInfo.text = Format.sec2timeStr(node.elapsedTime)
|
||||
}
|
||||
else{
|
||||
else {
|
||||
computationInfo.text = ""
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +118,7 @@ Panel {
|
|||
Menu {
|
||||
id: settingsMenu
|
||||
y: parent.height
|
||||
|
||||
Menu {
|
||||
id: filterAttributesMenu
|
||||
title: "Filter Attributes"
|
||||
|
@ -138,7 +140,9 @@ Panel {
|
|||
enabled: tabBar.currentIndex === 0
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
RowLayout {
|
||||
CheckBox {
|
||||
id: defaultToggle
|
||||
|
@ -157,7 +161,9 @@ Panel {
|
|||
enabled: tabBar.currentIndex === 0
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
RowLayout {
|
||||
CheckBox {
|
||||
id: linkToggle
|
||||
|
@ -176,7 +182,9 @@ Panel {
|
|||
enabled: tabBar.currentIndex === 0
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
CheckBox {
|
||||
id: advancedToggle
|
||||
text: "Advanced"
|
||||
|
@ -196,7 +204,9 @@ Panel {
|
|||
enabled: root.node !== null
|
||||
onClicked: Qt.openUrlExternally(Filepath.stringToUrl(root.node.internalFolder))
|
||||
}
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem {
|
||||
enabled: root.node !== null
|
||||
text: "Clear Pending Status"
|
||||
|
@ -208,6 +218,7 @@ Panel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
|
@ -215,7 +226,7 @@ Panel {
|
|||
Loader {
|
||||
active: root.isCompatibilityNode
|
||||
Layout.fillWidth: true
|
||||
visible: active // for layout update
|
||||
visible: active // For layout update
|
||||
|
||||
sourceComponent: CompatibilityBadge {
|
||||
canUpgrade: root.node.canUpgrade
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
|
||||
import "common.js" as Common
|
||||
|
||||
/**
|
||||
* NodeLog displays log and statistics data of Node's chunks (NodeChunks)
|
||||
* NodeLog displays the log file of Node's chunks (NodeChunks).
|
||||
*
|
||||
* To ease monitoring, it provides periodic auto-reload of the opened file
|
||||
* if the related NodeChunk is being computed.
|
||||
*/
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
property variant node
|
||||
|
@ -29,7 +28,7 @@ FocusScope {
|
|||
anchors.fill: parent
|
||||
|
||||
property string currentFile: (root.currentChunkIndex >= 0 && root.currentChunk) ? root.currentChunk["logFile"] : ""
|
||||
property url source: Filepath.stringToUrl(currentFile)
|
||||
property url sourceFile: Filepath.stringToUrl(currentFile)
|
||||
|
||||
sourceComponent: textFileViewerComponent
|
||||
}
|
||||
|
@ -40,9 +39,8 @@ FocusScope {
|
|||
TextFileViewer {
|
||||
id: textFileViewer
|
||||
anchors.fill: parent
|
||||
source: componentLoader.source
|
||||
source: componentLoader.sourceFile
|
||||
autoReload: root.currentChunk !== undefined && root.currentChunk.statusName === "RUNNING"
|
||||
// source is set in fileSelector
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import "common.js" as Common
|
||||
import Controls 1.0
|
||||
|
||||
/**
|
||||
* NodeLog displays log and statistics data of Node's chunks (NodeChunks)
|
||||
* NodeStatistics displays statistics data of Node's chunks (NodeChunks).
|
||||
*
|
||||
* To ease monitoring, it provides periodic auto-reload of the opened file
|
||||
* if the related NodeChunk is being computed.
|
||||
*/
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
|
||||
|
@ -27,7 +25,7 @@ FocusScope {
|
|||
clip: true
|
||||
anchors.fill: parent
|
||||
property string currentFile: currentChunk ? currentChunk["statisticsFile"] : ""
|
||||
property url source: Filepath.stringToUrl(currentFile)
|
||||
property url sourceFile: Filepath.stringToUrl(currentFile)
|
||||
|
||||
sourceComponent: chunksLV.chunksSummary ? statViewerComponent : chunkStatViewerComponent
|
||||
}
|
||||
|
@ -37,7 +35,7 @@ FocusScope {
|
|||
StatViewer {
|
||||
id: statViewer
|
||||
anchors.fill: parent
|
||||
source: componentLoader.source
|
||||
source: componentLoader.sourceFile
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
|
||||
import "common.js" as Common
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
/**
|
||||
* NodeLog displays log and statistics data of Node's chunks (NodeChunks)
|
||||
* NodeStatus displays the status-related information of Node's chunks (NodeChunks)
|
||||
*
|
||||
* To ease monitoring, it provides periodic auto-reload of the opened file
|
||||
* if the related NodeChunk is being computed.
|
||||
*/
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
property variant node
|
||||
|
@ -26,7 +23,7 @@ FocusScope {
|
|||
anchors.fill: parent
|
||||
|
||||
property string currentFile: (root.currentChunkIndex >= 0) ? root.currentChunk["statusFile"] : ""
|
||||
property url source: Filepath.stringToUrl(currentFile)
|
||||
property url sourceFile: Filepath.stringToUrl(currentFile)
|
||||
|
||||
sourceComponent: statViewerComponent
|
||||
}
|
||||
|
@ -35,7 +32,7 @@ FocusScope {
|
|||
id: statViewerComponent
|
||||
Item {
|
||||
id: statusViewer
|
||||
property url source: componentLoader.source
|
||||
property url source: componentLoader.sourceFile
|
||||
property var lastModified: undefined
|
||||
|
||||
onSourceChanged: {
|
||||
|
@ -46,7 +43,7 @@ FocusScope {
|
|||
id: statusListModel
|
||||
|
||||
function readSourceFile() {
|
||||
// make sure we are trying to load a statistics file
|
||||
// Make sure we are trying to load a statistics file
|
||||
if (!Filepath.urlToString(source).endsWith("status"))
|
||||
return
|
||||
|
||||
|
@ -55,31 +52,28 @@ FocusScope {
|
|||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
|
||||
// console.warn("StatusListModel: read valid file")
|
||||
if (lastModified === undefined || lastModified !== xhr.getResponseHeader('Last-Modified')) {
|
||||
lastModified = xhr.getResponseHeader('Last-Modified')
|
||||
try {
|
||||
var jsonObject = JSON.parse(xhr.responseText)
|
||||
|
||||
var entries = []
|
||||
// prepare data to populate the ListModel from the input json object
|
||||
// Prepare data to populate the ListModel from the input json object
|
||||
for (var key in jsonObject) {
|
||||
var entry = {}
|
||||
entry["key"] = key
|
||||
entry["value"] = String(jsonObject[key])
|
||||
entries.push(entry)
|
||||
}
|
||||
// reset the model with prepared data (limit to one update event)
|
||||
// Reset the model with prepared data (limit to one update event)
|
||||
statusListModel.clear()
|
||||
statusListModel.append(entries)
|
||||
} catch(exc) {
|
||||
// console.warn("StatusListModel: failed to read file")
|
||||
lastModified = undefined
|
||||
statusListModel.clear()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// console.warn("StatusListModel: invalid file")
|
||||
lastModified = undefined
|
||||
statusListModel.clear()
|
||||
}
|
||||
|
@ -103,7 +97,6 @@ FocusScope {
|
|||
Rectangle {
|
||||
id: statusKey
|
||||
anchors.margins: 2
|
||||
// height: statusValue.height
|
||||
color: Qt.darker(activePalette.window, 1.1)
|
||||
Layout.preferredWidth: sizeHandle.x
|
||||
Layout.minimumWidth: 10.0 * Qt.application.font.pixelSize
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
import Qt.labs.platform 1.0 as Platform
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtCharts 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import Utils 1.0
|
||||
import QtCharts
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Charts 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
|
||||
Item {
|
||||
|
@ -36,8 +37,7 @@ Item {
|
|||
|
||||
property color textColor: Colors.sysPalette.text
|
||||
|
||||
|
||||
readonly property var colors: [
|
||||
readonly property var colors: [
|
||||
"#f44336",
|
||||
"#e91e63",
|
||||
"#9c27b0",
|
||||
|
@ -93,7 +93,7 @@ Item {
|
|||
}
|
||||
|
||||
function readSourceFile() {
|
||||
// make sure we are trying to load a statistics file
|
||||
// Make sure we are trying to load a statistics file
|
||||
if (!Filepath.urlToString(source).endsWith("statistics"))
|
||||
return
|
||||
|
||||
|
@ -102,7 +102,7 @@ Item {
|
|||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status == 200) {
|
||||
if (sourceModified === undefined || sourceModified < xhr.getResponseHeader('Last-Modified')) {
|
||||
if (sourceModified === undefined || sourceModified < xhr.getResponseHeader("Last-Modified")) {
|
||||
try {
|
||||
root.jsonObject = JSON.parse(xhr.responseText)
|
||||
} catch(exc) {
|
||||
|
@ -111,7 +111,7 @@ Item {
|
|||
return
|
||||
}
|
||||
resetCharts()
|
||||
sourceModified = xhr.getResponseHeader('Last-Modified')
|
||||
sourceModified = xhr.getResponseHeader("Last-Modified")
|
||||
root.createCharts()
|
||||
reloadTimer.restart()
|
||||
}
|
||||
|
@ -129,8 +129,8 @@ Item {
|
|||
}
|
||||
|
||||
function createCharts() {
|
||||
root.deltaTime = getPropertyWithDefault(jsonObject, 'interval', 30) / 60.0;
|
||||
root.fileVersion = getPropertyWithDefault(jsonObject, 'fileVersion', 0.0)
|
||||
root.deltaTime = getPropertyWithDefault(jsonObject, "interval", 30) / 60.0;
|
||||
root.fileVersion = getPropertyWithDefault(jsonObject, "fileVersion", 0.0)
|
||||
initCpuChart()
|
||||
initRamChart()
|
||||
initGpuChart()
|
||||
|
@ -157,7 +157,7 @@ Item {
|
|||
var nbCores = categories.length
|
||||
root.nbCores = nbCores
|
||||
|
||||
root.cpuFrequency = getPropertyWithDefault(jsonObject.computer, 'cpuFreq', -1)
|
||||
root.cpuFrequency = getPropertyWithDefault(jsonObject.computer, "cpuFreq", -1)
|
||||
|
||||
root.nbReads = categories[0].length-1
|
||||
|
||||
|
@ -218,9 +218,9 @@ Item {
|
|||
|
||||
function initRamChart() {
|
||||
|
||||
var ram = getPropertyWithDefault(jsonObject.computer.curves, 'ramUsage', -1)
|
||||
var ram = getPropertyWithDefault(jsonObject.computer.curves, "ramUsage", -1)
|
||||
|
||||
root.ramTotal = getPropertyWithDefault(jsonObject.computer, 'ramTotal', -1)
|
||||
root.ramTotal = getPropertyWithDefault(jsonObject.computer, "ramTotal", -1)
|
||||
root.ramLabel = "RAM: "
|
||||
if (root.ramTotal <= 0) {
|
||||
var maxRamPeak = 0
|
||||
|
@ -248,17 +248,18 @@ Item {
|
|||
ramSerie.color = colors[10]
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
*** GPU ***
|
||||
**************************/
|
||||
|
||||
function initGpuChart() {
|
||||
root.gpuTotalMemory = getPropertyWithDefault(jsonObject.computer, 'gpuMemoryTotal', 0)
|
||||
root.gpuName = getPropertyWithDefault(jsonObject.computer, 'gpuName', '')
|
||||
root.gpuTotalMemory = getPropertyWithDefault(jsonObject.computer, "gpuMemoryTotal", 0)
|
||||
root.gpuName = getPropertyWithDefault(jsonObject.computer, "gpuName", "")
|
||||
|
||||
var gpuUsedMemory = getPropertyWithDefault(jsonObject.computer.curves, 'gpuMemoryUsed', 0)
|
||||
var gpuUsed = getPropertyWithDefault(jsonObject.computer.curves, 'gpuUsed', 0)
|
||||
var gpuTemperature = getPropertyWithDefault(jsonObject.computer.curves, 'gpuTemperature', 0)
|
||||
var gpuUsedMemory = getPropertyWithDefault(jsonObject.computer.curves, "gpuMemoryUsed", 0)
|
||||
var gpuUsed = getPropertyWithDefault(jsonObject.computer.curves, "gpuUsed", 0)
|
||||
var gpuTemperature = getPropertyWithDefault(jsonObject.computer.curves, "gpuTemperature", 0)
|
||||
|
||||
var gpuUsedSerie = gpuChart.createSeries(ChartView.SeriesTypeLine, "GPU", valueGpuX, valueGpuY)
|
||||
var gpuUsedMemorySerie = gpuChart.createSeries(ChartView.SeriesTypeLine, "Memory", valueGpuX, valueGpuY)
|
||||
|
@ -389,7 +390,7 @@ Item {
|
|||
plotAreaColor: "transparent"
|
||||
titleColor: textColor
|
||||
|
||||
visible: (root.fileVersion > 0.0) // only visible if we have valid information
|
||||
visible: (root.fileVersion > 0.0) // Only visible if we have valid information
|
||||
title: "CPU: " + root.nbCores + " cores, " + root.cpuFrequency + "MHz"
|
||||
|
||||
ValueAxis {
|
||||
|
@ -421,7 +422,6 @@ Item {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**************************
|
||||
*** RAM UI ***
|
||||
**************************/
|
||||
|
@ -443,7 +443,7 @@ Item {
|
|||
plotAreaColor: "transparent"
|
||||
titleColor: textColor
|
||||
|
||||
visible: (root.fileVersion > 0.0) // only visible if we have valid information
|
||||
visible: (root.fileVersion > 0.0) // Only visible if we have valid information
|
||||
title: root.ramLabel + root.ramTotal + "GB"
|
||||
|
||||
ValueAxis {
|
||||
|
@ -475,7 +475,6 @@ Item {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**************************
|
||||
*** GPU UI ***
|
||||
**************************/
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
import MaterialIcons 2.2
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -133,7 +133,7 @@ Item {
|
|||
}
|
||||
|
||||
delegate: RowLayout {
|
||||
width: parent != null ? parent.width : undefined
|
||||
width: ListView.view.width
|
||||
height: 18
|
||||
spacing: 3
|
||||
|
||||
|
@ -261,7 +261,6 @@ Item {
|
|||
radius: 3
|
||||
border.width: 2
|
||||
border.color: chunkList.node === uigraph.selectedNode ? Colors.sysPalette.text : Colors.getChunkColor(object, {"NONE": bgColor})
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
var statusColors = {
|
||||
"NONE": "transparent",
|
||||
"SUBMITTED": "#009688",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Utils 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
|
@ -21,7 +22,6 @@ Page {
|
|||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
|
||||
SplitView.minimumWidth: 250
|
||||
SplitView.preferredWidth: 330
|
||||
SplitView.maximumWidth: 500
|
||||
|
@ -372,10 +372,10 @@ Page {
|
|||
Connections {
|
||||
target: projectDelegate
|
||||
function onClicked() {
|
||||
if (!modelData["path"]){
|
||||
if (!modelData["path"]) {
|
||||
initFileDialogFolder(openFileDialog)
|
||||
openFileDialog.open()
|
||||
} else{
|
||||
} else {
|
||||
// Open project
|
||||
mainStack.push("Application.qml")
|
||||
if (_reconstruction.loadUrl(modelData["path"])) {
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
|
||||
/**
|
||||
* ImageBadge is a preset MaterialLabel to display an icon bagdge on an image.
|
||||
*/
|
||||
|
||||
MaterialLabel {
|
||||
id: root
|
||||
|
||||
font.pointSize: 10
|
||||
padding: 2
|
||||
background: Rectangle { color: Colors.sysPalette.window; opacity: 0.6 }
|
||||
background: Rectangle {
|
||||
color: Colors.sysPalette.window
|
||||
opacity: 0.6
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import Utils 1.0
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* ImageDelegate for a Viewpoint object.
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
|
@ -24,7 +25,7 @@ Item {
|
|||
|
||||
default property alias children: imageMA.children
|
||||
|
||||
// retrieve viewpoints inner data
|
||||
// Retrieve viewpoints inner data
|
||||
QtObject {
|
||||
id: _viewpoint
|
||||
property url source: viewpoint ? Filepath.stringToUrl(viewpoint.get("path").value) : ''
|
||||
|
@ -33,8 +34,8 @@ Item {
|
|||
property var metadata: metadataStr ? JSON.parse(viewpoint.get("metadata").value) : {}
|
||||
}
|
||||
|
||||
// update thumbnail location
|
||||
// can be called from the GridView when a new thumbnail has been written on disk
|
||||
// Update thumbnail location
|
||||
// Can be called from the GridView when a new thumbnail has been written on disk
|
||||
function updateThumbnail() {
|
||||
thumbnail.source = ThumbnailCache.thumbnail(root.source, root.cellID)
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ Item {
|
|||
anchors.margins: 6
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onPressed: {
|
||||
onPressed: function(mouse) {
|
||||
if (mouse.button == Qt.RightButton)
|
||||
imageMenu.popup()
|
||||
root.pressed(mouse)
|
||||
|
@ -135,6 +136,7 @@ Item {
|
|||
running: thumbnail.status != Image.Ready
|
||||
}
|
||||
}
|
||||
|
||||
// Image basename
|
||||
Label {
|
||||
id: imageLabel
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQml.Models 2.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQml.Models
|
||||
import Qt.labs.qmlmodels 1.0
|
||||
|
||||
import Controls 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* ImageGallery displays as a grid of Images a model containing Viewpoints objects.
|
||||
* It manages a model of multiple CameraInit nodes as individual groups.
|
||||
*/
|
||||
|
||||
Panel {
|
||||
id: root
|
||||
|
||||
|
@ -28,7 +29,7 @@ Panel {
|
|||
property int defaultCellSize: 160
|
||||
property bool readOnly: false
|
||||
|
||||
property var filesByType: {}
|
||||
property var filesByType: ({})
|
||||
property int nbMeshroomScenes: 0
|
||||
property int nbDraggedFiles: 0
|
||||
|
||||
|
@ -98,7 +99,7 @@ Panel {
|
|||
intrinsic[currentAttribute.name + "." + currentAttribute.value.at(k).name] = currentAttribute.value.at(k)
|
||||
}
|
||||
} else if (currentAttribute.type === "ListAttribute") {
|
||||
// not needed for now
|
||||
// Not needed for now
|
||||
} else {
|
||||
intrinsic[currentAttribute.name] = currentAttribute
|
||||
}
|
||||
|
@ -217,12 +218,12 @@ Panel {
|
|||
Connections {
|
||||
target: ThumbnailCache
|
||||
function onThumbnailCreated(imgSource, callerID) {
|
||||
let item = grid.itemAtIndex(callerID); // item is an ImageDelegate
|
||||
let item = grid.itemAtIndex(callerID); // "item" is an ImageDelegate
|
||||
if (item && item.source === imgSource) {
|
||||
item.updateThumbnail()
|
||||
return
|
||||
}
|
||||
// fallback in case the ImageDelegate cellID changed
|
||||
// Fallback in case the ImageDelegate cellID changed
|
||||
for (let idx = 0; idx < grid.count; idx++) {
|
||||
item = grid.itemAtIndex(idx)
|
||||
if (item && item.source === imgSource) {
|
||||
|
@ -250,7 +251,7 @@ Panel {
|
|||
]
|
||||
property var reconstructionFilter: undefined
|
||||
|
||||
// override modelData to return basename of viewpoint's path for sorting
|
||||
// Override modelData to return basename of viewpoint's path for sorting
|
||||
function modelData(item, roleName_) {
|
||||
var roleNameAndCmd = roleName_.split(".")
|
||||
var roleName = roleName_
|
||||
|
@ -305,7 +306,7 @@ Panel {
|
|||
}
|
||||
|
||||
onRemoveRequest: sendRemoveRequest()
|
||||
Keys.onPressed: (event) => {
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_Delete && event.modifiers === Qt.ShiftModifier) {
|
||||
removeAllImages()
|
||||
} else if (event.key === Qt.Key_Delete) {
|
||||
|
@ -375,7 +376,7 @@ Panel {
|
|||
|
||||
// Keyboard shortcut to change current image group
|
||||
Keys.priority: Keys.BeforeItem
|
||||
Keys.onPressed: {
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.modifiers & Qt.AltModifier) {
|
||||
if (event.key === Qt.Key_Right) {
|
||||
_reconstruction.cameraInitIndex = Math.min(root.cameraInits.count - 1, root.cameraInitIndex + 1)
|
||||
|
@ -442,12 +443,12 @@ Panel {
|
|||
anchors.fill: parent
|
||||
enabled: !m.readOnly && !intrinsicsFilterButton.checked
|
||||
keys: ["text/uri-list"]
|
||||
onEntered: {
|
||||
onEntered: function(drag) {
|
||||
nbDraggedFiles = drag.urls.length
|
||||
filesByType = _reconstruction.getFilesByTypeFromDrop(drag.urls)
|
||||
nbMeshroomScenes = filesByType["meshroomScenes"].length
|
||||
}
|
||||
onDropped: {
|
||||
onDropped: function(drop) {
|
||||
var augmentSfm = augmentArea.hovered
|
||||
if (nbMeshroomScenes == nbDraggedFiles || nbMeshroomScenes == 0) {
|
||||
root.filesDropped(filesByType, augmentSfm)
|
||||
|
@ -529,7 +530,7 @@ Panel {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onPressed: {
|
||||
onPressed: function(mouse) {
|
||||
if (mouse.button == Qt.LeftButton)
|
||||
grid.forceActiveFocus()
|
||||
mouse.accepted = false
|
||||
|
@ -831,8 +832,7 @@ Panel {
|
|||
}
|
||||
}
|
||||
onEnabledChanged: {
|
||||
// Reset the toggle to avoid getting stuck
|
||||
// with the HDR node checked but disabled.
|
||||
// Reset the toggle to avoid getting stuck with the HDR node checked but disabled
|
||||
if (checked) {
|
||||
checked = false
|
||||
close()
|
||||
|
@ -875,8 +875,7 @@ Panel {
|
|||
}
|
||||
}
|
||||
onEnabledChanged: {
|
||||
// Reset the toggle to avoid getting stuck
|
||||
// with the HDR node checked but disabled.
|
||||
// Reset the toggle to avoid getting stuck with the HDR node checked but disabled
|
||||
if (checked) {
|
||||
checked = false
|
||||
close()
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick.Controls 2.15
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
@ -49,11 +47,12 @@ RowLayout {
|
|||
if (!attribute)
|
||||
return undefined
|
||||
switch (attribute.type) {
|
||||
case "ChoiceParam": return choice_component
|
||||
case "IntParam": return int_component
|
||||
case "FloatParam": return float_component
|
||||
case "BoolParam": return bool_component
|
||||
case "StringParam": return textField_component
|
||||
case "ChoiceParam": return choiceComponent
|
||||
case "IntParam": return intComponent
|
||||
case "FloatParam": return floatComponent
|
||||
case "BoolParam": return boolComponent
|
||||
case "StringParam": return textFieldComponent
|
||||
case "File": return textFieldComponent
|
||||
default: return undefined
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +61,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: textField_component
|
||||
id: textFieldComponent
|
||||
TextInput {
|
||||
text: attribute.value
|
||||
width: intrinsicModel.columnWidths[columnIndex]
|
||||
|
@ -81,14 +80,14 @@ RowLayout {
|
|||
_reconstruction.setAttribute(attribute, text)
|
||||
}
|
||||
Component.onDestruction: {
|
||||
if(activeFocus)
|
||||
if (activeFocus)
|
||||
_reconstruction.setAttribute(attribute, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: int_component
|
||||
id: intComponent
|
||||
|
||||
TextInput {
|
||||
text: model.display.value
|
||||
|
@ -121,7 +120,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: choice_component
|
||||
id: choiceComponent
|
||||
ComboBox {
|
||||
id: combo
|
||||
model: attribute.desc !== undefined ? attribute.desc.values : undefined
|
||||
|
@ -146,7 +145,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: bool_component
|
||||
id: boolComponent
|
||||
CheckBox {
|
||||
checked: attribute ? attribute.value : false
|
||||
padding: 12
|
||||
|
@ -156,7 +155,7 @@ RowLayout {
|
|||
}
|
||||
|
||||
Component {
|
||||
id: float_component
|
||||
id: floatComponent
|
||||
TextInput {
|
||||
readonly property real formattedValue: attribute.value.toFixed(2)
|
||||
property string displayValue: String(formattedValue)
|
||||
|
@ -179,9 +178,9 @@ RowLayout {
|
|||
|
||||
autoScroll: activeFocus
|
||||
|
||||
//Use this function to ensure the left part is visible
|
||||
//while keeping the trick for formatting the text
|
||||
//Timing issues otherwise
|
||||
// Use this function to ensure the left part is visible
|
||||
// while keeping the trick for formatting the text
|
||||
// Timing issues otherwise
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus)
|
||||
text = String(attribute.value)
|
||||
|
@ -192,7 +191,7 @@ RowLayout {
|
|||
|
||||
DoubleValidator {
|
||||
id: doubleValidator
|
||||
locale: 'C' // use '.' decimal separator disregarding the system locale
|
||||
locale: 'C' // Use '.' decimal separator disregarding the system locale
|
||||
}
|
||||
|
||||
validator: doubleValidator
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
|
||||
/**
|
||||
* Display camera initialization status and the value of metadata
|
||||
* that take part in this process.
|
||||
*/
|
||||
|
||||
ImageBadge {
|
||||
id: root
|
||||
|
||||
|
@ -27,7 +28,8 @@ ImageBadge {
|
|||
}
|
||||
return ""
|
||||
}
|
||||
// access useful metadata
|
||||
|
||||
// Access useful metadata
|
||||
readonly property var make: findMetadata("Make")
|
||||
readonly property var model: findMetadata("Model")
|
||||
readonly property var focalLength: findMetadata("FocalLength")
|
||||
|
@ -103,13 +105,12 @@ ImageBadge {
|
|||
}
|
||||
},
|
||||
State {
|
||||
// fallback status when initialization mode is unset
|
||||
// Fallback status when initialization mode is unset
|
||||
name: "none"
|
||||
PropertyChanges {
|
||||
target: root
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
|
||||
|
||||
MessageDialog {
|
||||
id: root
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import MaterialIcons 2.2
|
||||
import Qt.labs.platform 1.0 as Platform // for FileDialog
|
||||
import Qt.labs.platform 1.0 as Platform
|
||||
|
||||
import Controls 1.0
|
||||
|
||||
/**
|
||||
* LiveSfMView provides controls for setting up and starting a live reconstruction.
|
||||
*/
|
||||
|
||||
Panel {
|
||||
id: root
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
/**
|
||||
* MLabel is a standard Label.
|
||||
* If ToolTip.text is set, it shows up a tooltip when hovered.
|
||||
*/
|
||||
|
||||
Label {
|
||||
padding: 4
|
||||
MouseArea {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pragma Singleton
|
||||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
|
||||
QtObject {
|
||||
property FontLoader fl: FontLoader {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
/**
|
||||
* MaterialLabel is a standard Label using MaterialIcons font.
|
||||
* If ToolTip.text is set, it also shows up a tooltip when hovered.
|
||||
*/
|
||||
|
||||
Label {
|
||||
font.family: MaterialIcons.fontFamily
|
||||
font.pointSize: 10
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
/**
|
||||
* MaterialToolButton is a standard ToolButton using MaterialIcons font.
|
||||
* It also shows up its tooltip when hovered.
|
||||
*/
|
||||
|
||||
ToolButton {
|
||||
id: control
|
||||
font.family: MaterialIcons.fontFamily
|
||||
|
@ -19,7 +19,7 @@ ToolButton {
|
|||
}
|
||||
background: Rectangle {
|
||||
color: {
|
||||
if (pressed || checked || hovered) {
|
||||
if (enabled && (pressed || checked || hovered)) {
|
||||
if (pressed || checked)
|
||||
return Qt.darker(parent.palette.base, 1.3)
|
||||
if (hovered)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
/**
|
||||
* MaterialToolLabel is a Label with an icon (using MaterialIcons).
|
||||
* It shows up its tooltip when hovered.
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: control
|
||||
property alias iconText: iconItem.text
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
/**
|
||||
* MaterialToolButton is a standard ToolButton using MaterialIcons font.
|
||||
* It also shows up its tooltip when hovered.
|
||||
*/
|
||||
|
||||
ToolButton {
|
||||
id: control
|
||||
property alias iconText: icon.text
|
||||
|
@ -41,7 +41,7 @@ ToolButton {
|
|||
}
|
||||
background: Rectangle {
|
||||
color: {
|
||||
if (pressed || checked || hovered) {
|
||||
if (enabled && (pressed || checked || hovered)) {
|
||||
if (pressed || checked)
|
||||
return Qt.darker(parent.palette.base, 1.3)
|
||||
if (hovered)
|
||||
|
|
|
@ -4,6 +4,7 @@ import Meshroom.Helpers 1.0
|
|||
/**
|
||||
* Clipboard singleton object to copy values to paste buffer.
|
||||
*/
|
||||
|
||||
ClipboardHelper {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
pragma Singleton
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
/**
|
||||
* Singleton that gathers useful colors, shades and system palettes.
|
||||
*/
|
||||
|
||||
QtObject {
|
||||
property SystemPalette sysPalette: SystemPalette {}
|
||||
property SystemPalette disabledSysPalette: SystemPalette { colorGroup: SystemPalette.Disabled }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pragma Singleton
|
||||
import QtQuick 2.11
|
||||
import QtQuick
|
||||
|
||||
/**
|
||||
* Singleton that defines utility functions for supporting exif orientation tags.
|
||||
|
|
|
@ -2,5 +2,4 @@ pragma Singleton
|
|||
import Meshroom.Helpers 1.0
|
||||
|
||||
Scene3DHelper {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQml.Models 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick
|
||||
import QtQml.Models
|
||||
import QtQuick.Controls
|
||||
|
||||
/**
|
||||
* SortFilderDelegateModel adds sorting and filtering capabilities on a source model.
|
||||
|
@ -17,21 +17,21 @@ import QtQuick.Controls 2.15
|
|||
*
|
||||
* Based on http://doc.qt.io/qt-5/qtquick-tutorials-dynamicview-dynamicview4-example.html
|
||||
*/
|
||||
|
||||
DelegateModel {
|
||||
id: sortFilterModel
|
||||
|
||||
property string sortRole: "" /// the role to use for sorting
|
||||
property int sortOrder: Qt.AscendingOrder /// the sorting order
|
||||
property var filters: [] /// filter format: {role: "roleName", value: "filteringValue"}
|
||||
property string sortRole: "" /// The role to use for sorting
|
||||
property int sortOrder: Qt.AscendingOrder /// The sorting order
|
||||
property var filters: [] /// Filter format: {role: "roleName", value: "filteringValue"}
|
||||
|
||||
onSortRoleChanged: invalidateSort()
|
||||
onSortOrderChanged: invalidateSort()
|
||||
onFiltersChanged: invalidateFilters()
|
||||
|
||||
// display "filtered" group
|
||||
// Display "filtered" group
|
||||
filterOnGroup: "filtered"
|
||||
// don't include elements in "items" group by default
|
||||
// as they must fall in the "unsorted" group
|
||||
// Don't include elements in "items" group by default as they must fall in the "unsorted" group
|
||||
items.includeByDefault: false
|
||||
|
||||
groups: [
|
||||
|
@ -41,15 +41,15 @@ DelegateModel {
|
|||
|
||||
name: "unsorted"
|
||||
includeByDefault: true
|
||||
// if the source model changes, perform sorting and filtering
|
||||
// If the source model changes, perform sorting and filtering
|
||||
onChanged: {
|
||||
// no sorting: move everything from unsorted to sorted group
|
||||
// No sorting: move everything from unsorted to sorted group
|
||||
if(sortRole == "") {
|
||||
unsortedItems.setGroups(0, unsortedItems.count, ["items"])
|
||||
} else {
|
||||
sort()
|
||||
}
|
||||
// perform filter invalidation in both cases
|
||||
// Perform filter invalidation in both cases
|
||||
invalidateFilters()
|
||||
}
|
||||
},
|
||||
|
@ -87,8 +87,7 @@ DelegateModel {
|
|||
if (filter === undefined) {
|
||||
return true;
|
||||
}
|
||||
switch (value.constructor.name)
|
||||
{
|
||||
switch (value.constructor.name) {
|
||||
case "String":
|
||||
return value.toLowerCase().indexOf(filter.toLowerCase()) > -1
|
||||
default:
|
||||
|
@ -98,8 +97,8 @@ DelegateModel {
|
|||
|
||||
/// Apply respectFilter mapping and logical AND/OR reduction on filters
|
||||
function respectFilters(item) {
|
||||
let cond = (filter => respectFilter(modelData(item, filter.role), filter.value));
|
||||
return filters.every(x => Array.isArray(x) ? x.some(cond) : cond(x));
|
||||
let cond = (filter => respectFilter(modelData(item, filter.role), filter.value))
|
||||
return filters.every(x => Array.isArray(x) ? x.some(cond) : cond(x))
|
||||
}
|
||||
|
||||
/// Reverse sort order (toggle between Qt.AscendingOrder / Qt.DescendingOrder)
|
||||
|
@ -108,40 +107,42 @@ DelegateModel {
|
|||
}
|
||||
|
||||
property var lessThan: [
|
||||
function(left, right) { return modelData(left, sortRole) < modelData(right, sortRole) }
|
||||
function(left, right) {
|
||||
return modelData(left, sortRole) < modelData(right, sortRole)
|
||||
}
|
||||
]
|
||||
|
||||
function invalidateSort() {
|
||||
if (!sortFilterModel.model || !sortFilterModel.model.count)
|
||||
return;
|
||||
|
||||
// move everything from "items" to "unsorted
|
||||
// will trigger "unsorted" DelegateModelGroup 'changed' signal
|
||||
// Move everything from "items" to "unsorted", will trigger "unsorted" DelegateModelGroup 'changed' signal
|
||||
items.setGroups(0, items.count, ["unsorted"])
|
||||
}
|
||||
|
||||
/// Invalidate filtering
|
||||
function invalidateFilters() {
|
||||
for (var i = 0; i < items.count; ++i) {
|
||||
// if the property value contains filterText, add it to the filtered group
|
||||
// If the property value contains filterText, add it to the filtered group
|
||||
if (respectFilters(items.get(i))) {
|
||||
items.addGroups(items.get(i), 1, "filtered")
|
||||
} else { // otherwise, remove it from the filtered group
|
||||
} else { // Otherwise, remove it from the filtered group
|
||||
items.removeGroups(items.get(i), 1, "filtered")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute insert position of 'item' based on the value
|
||||
/// of its sortProperty
|
||||
/// Compute insert position of 'item' based on the value of its sortProperty
|
||||
function insertPosition(lessThan, item) {
|
||||
var lower = 0
|
||||
var upper = items.count
|
||||
while (lower < upper) {
|
||||
var middle = Math.floor(lower + (upper - lower) / 2)
|
||||
var result = lessThan(item, items.get(middle))
|
||||
if (sortOrder == Qt.DescendingOrder)
|
||||
if (sortOrder == Qt.DescendingOrder) {
|
||||
result = !result
|
||||
}
|
||||
|
||||
if (result) {
|
||||
upper = middle
|
||||
} else {
|
||||
|
@ -159,7 +160,7 @@ DelegateModel {
|
|||
item.groups = ["items"]
|
||||
items.move(item.itemsIndex, index)
|
||||
}
|
||||
// if some items were actually sorted, filter will be correctly invalidated
|
||||
// If some items were actually sorted, filter will be correctly invalidated
|
||||
// as unsortedGroup 'changed' signal will be triggered
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,5 +2,4 @@ pragma Singleton
|
|||
import Meshroom.Helpers 1.0
|
||||
|
||||
Transformations3DHelper {
|
||||
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
.pragma library
|
||||
|
||||
|
||||
function intToString(v) {
|
||||
// use EN locale to get comma separated thousands
|
||||
// Use EN locale to get comma separated thousands
|
||||
// + remove automatically added trailing decimals
|
||||
// (this 'toLocaleString' does not take any option)
|
||||
return v.toLocaleString(Qt.locale('en-US')).split('.')[0]
|
||||
|
@ -10,8 +9,8 @@ function intToString(v) {
|
|||
|
||||
// Convert a plain text to an html escaped string.
|
||||
function plainToHtml(t) {
|
||||
var escaped = t.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') // escape text
|
||||
return escaped.replace(/\n/g, '<br>') // replace line breaks
|
||||
var escaped = t.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') // Escape text
|
||||
return escaped.replace(/\n/g, '<br>') // Replace line breaks
|
||||
}
|
||||
|
||||
function divmod(x, y) {
|
||||
|
@ -41,8 +40,7 @@ function sec2timecode(timeSeconds) {
|
|||
}
|
||||
|
||||
function sec2timeStr(timeSeconds) {
|
||||
// Need to decide the rounding precision first
|
||||
// to propagate the right values
|
||||
// Need to decide the rounding precision first to propagate the right values
|
||||
if (timeSeconds >= 60.0) {
|
||||
timeSeconds = Math.round(timeSeconds)
|
||||
} else {
|
||||
|
@ -57,7 +55,7 @@ function sec2timeStr(timeSeconds) {
|
|||
timeStr += timeObj.minutes + "m"
|
||||
}
|
||||
if (timeObj.hours === 0) {
|
||||
// seconds only matter if the elapsed time is less than 1 hour
|
||||
// Seconds only matter if the elapsed time is less than 1 hour
|
||||
if (timeObj.minutes === 0) {
|
||||
// If less than a minute, keep millisecond precision
|
||||
timeStr += timeObj.seconds.toFixed(2) + "s"
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtPositioning 5.15
|
||||
import QtLocation 5.15
|
||||
import QtCharts 2.15
|
||||
import Charts 1.0
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import QtCharts
|
||||
|
||||
import Charts 1.0
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
import DataObjects 1.0
|
||||
|
||||
FloatingPane {
|
||||
|
@ -34,7 +31,7 @@ FloatingPane {
|
|||
onWheel: {}
|
||||
}
|
||||
|
||||
// note: We need to use csvData.getNbColumns() slot instead of the csvData.nbColumns property to avoid a crash on linux.
|
||||
// Note: We need to use csvData.getNbColumns() slot instead of the csvData.nbColumns property to avoid a crash on linux.
|
||||
property bool crfReady: csvData && csvData.ready && (csvData.getNbColumns() >= 4)
|
||||
onCrfReadyChanged: {
|
||||
if (crfReady) {
|
||||
|
@ -80,24 +77,24 @@ FloatingPane {
|
|||
}
|
||||
|
||||
// We cannot use a Repeater with these Components so we need to instantiate them one by one
|
||||
// Red curve
|
||||
LineSeries {
|
||||
// Red curve
|
||||
id: redCurve
|
||||
axisX: valueAxisX
|
||||
axisY: valueAxisY
|
||||
name: crfReady ? csvData.getColumn(1).title : ""
|
||||
color: name.toLowerCase()
|
||||
}
|
||||
// Green curve
|
||||
LineSeries {
|
||||
// Green curve
|
||||
id: greenCurve
|
||||
axisX: valueAxisX
|
||||
axisY: valueAxisY
|
||||
name: crfReady ? csvData.getColumn(2).title : ""
|
||||
color: name.toLowerCase()
|
||||
}
|
||||
// Blue curve
|
||||
LineSeries {
|
||||
// Blue curve
|
||||
id: blueCurve
|
||||
axisX: valueAxisX
|
||||
axisY: valueAxisY
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -49,7 +49,7 @@ Item {
|
|||
propagateComposedEvents: true
|
||||
|
||||
property bool controlModifierEnabled: false
|
||||
onPositionChanged: {
|
||||
onPositionChanged: function(mouse) {
|
||||
mArea.controlModifierEnabled = (mouse.modifiers & Qt.ControlModifier)
|
||||
mouse.accepted = false
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ Item {
|
|||
onPressed: {
|
||||
forceActiveFocus()
|
||||
}
|
||||
onWheel: {
|
||||
onWheel: function(wheel) {
|
||||
mArea.controlModifierEnabled = (wheel.modifiers & Qt.ControlModifier)
|
||||
if (wheel.modifiers & Qt.ControlModifier) {
|
||||
root.incrementRadius(wheel.angleDelta.y / 120.0)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// required for perspective transform
|
||||
property real sizeX: 1675.0 // might be overridden in ColorCheckerViewer
|
||||
property real sizeY: 1125.0 // might be overridden in ColorCheckerViewer
|
||||
// Required for perspective transform
|
||||
property real sizeX: 1675.0 // Might be overridden in ColorCheckerViewer
|
||||
property real sizeY: 1125.0 // Might be overridden in ColorCheckerViewer
|
||||
|
||||
property var colors: null
|
||||
property var window: null
|
||||
|
@ -27,10 +27,8 @@ Item {
|
|||
id: transformation
|
||||
matrix: Qt.matrix4x4()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function applyTransform(m) {
|
||||
transformation.matrix = Qt.matrix4x4(
|
||||
m[0][0], m[0][1], 0, m[0][2],
|
||||
|
@ -38,5 +36,4 @@ Item {
|
|||
0, 0, 1, 0,
|
||||
m[2][0], m[2][1], 0, m[2][2])
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
|
||||
|
@ -12,7 +12,6 @@ FloatingPane {
|
|||
padding: 4
|
||||
anchors.rightMargin: 0
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
|
@ -34,9 +33,7 @@ FloatingPane {
|
|||
height: root.height / grid.rows - grid.spacing * (grid.rows + 1) / grid.rows
|
||||
color: Qt.rgba(modelData.r, modelData.g, modelData.b, 1.0)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -8,9 +8,9 @@ Item {
|
|||
property var viewpoint: null
|
||||
property real zoom: 1.0
|
||||
|
||||
// required for perspective transform
|
||||
// Required for perspective transform
|
||||
// Match theoretical values in AliceVision
|
||||
// see https://github.com/alicevision/AliceVision/blob/68ab70bcbc3eb01b73dc8dea78c78d8b4778461c/src/software/utils/main_colorCheckerDetection.cpp#L47
|
||||
// See https://github.com/alicevision/AliceVision/blob/68ab70bcbc3eb01b73dc8dea78c78d8b4778461c/src/software/utils/main_colorCheckerDetection.cpp#L47
|
||||
readonly property real ccheckerSizeX: 1675.0
|
||||
readonly property real ccheckerSizeY: 1125.0
|
||||
|
||||
|
@ -34,16 +34,13 @@ Item {
|
|||
|
||||
function readSourceFile() {
|
||||
var xhr = new XMLHttpRequest
|
||||
// console.warn("readSourceFile: " + root.source)
|
||||
xhr.open("GET", root.source)
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status == 200) {
|
||||
try {
|
||||
root.json = null
|
||||
// console.warn("readSourceFile: update json from " + root.source)
|
||||
root.json = JSON.parse(xhr.responseText)
|
||||
// console.warn("readSourceFile: root.json.checkers.length=" + root.json.checkers.length)
|
||||
} catch(exc) {
|
||||
console.warn("Failed to parse ColorCheckerDetection JSON file: " + source)
|
||||
return
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Utils 1.0
|
||||
import Controls 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* FeaturesInfoOverlay is an overlay that displays info and
|
||||
* provides controls over a FeaturesViewer component.
|
||||
*/
|
||||
|
||||
FloatingPane {
|
||||
id: root
|
||||
|
||||
|
@ -65,7 +66,10 @@ FloatingPane {
|
|||
ComboBox {
|
||||
id: featureDisplayModeCB
|
||||
flat: true
|
||||
ToolTip.text: "Feature Display Mode:\n* Points: Simple points.\n* Square: Scaled filled squares.\n* Oriented Square: Scaled and oriented squares."
|
||||
ToolTip.text: "Feature Display Mode:\n" +
|
||||
"* Points: Simple points.\n" +
|
||||
"* Square: Scaled filled squares.\n" +
|
||||
"* Oriented Square: Scaled and oriented squares."
|
||||
ToolTip.visible: hovered
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignRight
|
||||
|
@ -81,7 +85,10 @@ FloatingPane {
|
|||
ComboBox {
|
||||
id: trackDisplayModeCB
|
||||
flat: true
|
||||
ToolTip.text: "Track Display Mode:\n* Lines Only: Only track lines.\n* Current Matches: Track lines with current matches / landmarks.\n* All Matches: Track lines with all matches / landmarks."
|
||||
ToolTip.text: "Track Display Mode:\n" +
|
||||
"* Lines Only: Only track lines.\n" +
|
||||
"* Current Matches: Track lines with current matches/landmarks.\n" +
|
||||
"* All Matches: Track lines with all matches / landmarks."
|
||||
ToolTip.visible: hovered
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignRight
|
||||
|
@ -152,7 +159,8 @@ FloatingPane {
|
|||
}
|
||||
SpinBox {
|
||||
id: timeWindowSB
|
||||
ToolTip.text: "Time Window: The number of frames to consider for tracks display.\ne.g. With time window set at x, tracks will start at current frame - x and they will end at current frame + x."
|
||||
ToolTip.text: "Time Window: The number of frames to consider for tracks display.\n" +
|
||||
"e.g. With time window set at x, tracks will start at current frame - x and they will end at current frame + x."
|
||||
ToolTip.visible: hovered
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignRight
|
||||
|
@ -261,7 +269,9 @@ FloatingPane {
|
|||
colors: root.featuresViewer.colors
|
||||
currentIndex: featureType.viewer.colorIndex
|
||||
// offset featuresViewer color set when changing the color of one feature type
|
||||
onColorPicked: featureType.viewer.colorOffset = colorIndex - index
|
||||
onColorPicked: function(colorIndex) {
|
||||
featureType.viewer.colorOffset = colorIndex - index
|
||||
}
|
||||
}
|
||||
// Feature type name
|
||||
Label {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import AliceVision 1.0 as AliceVision
|
||||
import QtQuick
|
||||
|
||||
import AliceVision 1.0 as AliceVision
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* FeaturesViewer displays the extracted feature points of a View.
|
||||
* Requires QtAliceVision plugin.
|
||||
*/
|
||||
|
||||
Repeater {
|
||||
id: root
|
||||
|
||||
|
@ -60,7 +61,7 @@ Repeater {
|
|||
|
||||
model: root.describerTypes
|
||||
|
||||
// instantiate one FeaturesViewer by describer type
|
||||
// Instantiate one FeaturesViewer by describer type
|
||||
delegate: AliceVision.FeaturesViewer {
|
||||
readonly property int colorIndex: (index + colorOffset) % root.colors.length
|
||||
property int colorOffset: 0
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import QtQuick 2.15
|
||||
import Utils 1.0
|
||||
import QtQuick
|
||||
|
||||
import AliceVision 1.0 as AliceVision
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* FloatImage displays an Image with gamma / offset / channel controls
|
||||
|
@ -96,7 +96,6 @@ AliceVision.FloatImageViewer {
|
|||
if (!isHighlightable) root.surface.mouseOver = false
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Principal Point
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
|
||||
FloatingPane {
|
||||
|
@ -30,19 +30,18 @@ FloatingPane {
|
|||
|
||||
DoubleValidator {
|
||||
id: doubleValidator
|
||||
locale: 'C' // use '.' decimal separator disregarding of the system locale
|
||||
locale: 'C' // Use '.' decimal separator disregarding of the system locale
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: toolLayout
|
||||
// anchors.verticalCenter: parent
|
||||
anchors.fill: parent
|
||||
|
||||
// channel mode
|
||||
// Channel mode
|
||||
ComboBox {
|
||||
id: channelsCtrl
|
||||
|
||||
// set min size to 4 characters + one margin for the combobox
|
||||
// Set min size to 4 characters + one margin for the combobox
|
||||
Layout.minimumWidth: 5.0 * Qt.application.font.pixelSize
|
||||
Layout.preferredWidth: Layout.minimumWidth
|
||||
flat: true
|
||||
|
@ -57,7 +56,7 @@ FloatingPane {
|
|||
model: channels
|
||||
}
|
||||
|
||||
// gain slider
|
||||
// Gain slider
|
||||
RowLayout {
|
||||
spacing: 5
|
||||
|
||||
|
@ -97,7 +96,7 @@ FloatingPane {
|
|||
}
|
||||
}
|
||||
|
||||
// gamma slider
|
||||
// Gamma slider
|
||||
RowLayout {
|
||||
spacing: 5
|
||||
|
||||
|
@ -242,7 +241,7 @@ FloatingPane {
|
|||
TextMetrics {
|
||||
id: textMetrics_colorValue
|
||||
font: red.font
|
||||
text: "1.2345" // use one more than expected to get the correct value (probably needed due to TextField margin)
|
||||
text: "1.2345" // Use one more than expected to get the correct value (probably needed due to TextField margin)
|
||||
}
|
||||
TextMetrics {
|
||||
id: textMetrics_gainValue
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtPositioning 5.15
|
||||
import QtLocation 5.15
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import QtPositioning 6.6
|
||||
import QtLocation 6.6
|
||||
|
||||
import Controls 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* ImageMetadataView displays a JSON model representing an image's metadata as a ListView.
|
||||
*/
|
||||
|
||||
FloatingPane {
|
||||
id: root
|
||||
|
||||
|
@ -31,11 +33,11 @@ FloatingPane {
|
|||
var values = value.split(",")
|
||||
var result = 0
|
||||
for (var i = 0; i < values.length; ++i) {
|
||||
// divide each component by the corresponding power of 60
|
||||
// Divide each component by the corresponding power of 60
|
||||
// 1 for degree, 60 for minutes, 3600 for seconds
|
||||
result += Number(values[i]) / Math.pow(60, i)
|
||||
}
|
||||
// handle opposite reference: South (latitude) or West (longitude)
|
||||
// Handle opposite reference: South (latitude) or West (longitude)
|
||||
return (ref === "S" || ref === "W") ? -result : result
|
||||
}
|
||||
|
||||
|
@ -62,14 +64,14 @@ FloatingPane {
|
|||
id: metadataModel
|
||||
property var metadata: ({})
|
||||
|
||||
// reset model when metadata changes
|
||||
// Reset model when metadata changes
|
||||
onMetadataChanged: {
|
||||
metadataModel.clear()
|
||||
var entries = []
|
||||
// prepare data to populate the model from the input metadata object
|
||||
// Prepare data to populate the model from the input metadata object
|
||||
for (var key in metadata) {
|
||||
var entry = {}
|
||||
// split on ":" to get group and key
|
||||
// Split on ":" to get group and key
|
||||
var i = key.lastIndexOf(":")
|
||||
if (i === -1) {
|
||||
i = key.lastIndexOf("/")
|
||||
|
@ -79,7 +81,7 @@ FloatingPane {
|
|||
entry["group"] = key.substr(0, i)
|
||||
entry["key"] = key.substr(i+1)
|
||||
} else {
|
||||
// set default group to something convenient for sorting
|
||||
// Set default group to something convenient for sorting
|
||||
entry["group"] = "-"
|
||||
entry["key"] = key
|
||||
}
|
||||
|
@ -93,7 +95,7 @@ FloatingPane {
|
|||
entry["raw"] = entry["group"] + ":" + entry["key"] + "=" + entry["value"]
|
||||
entries.push(entry)
|
||||
}
|
||||
// reset the model with prepared data (limit to one update event)
|
||||
// Reset the model with prepared data (limit to one update event)
|
||||
metadataModel.append(entries)
|
||||
coordinates = getGPSCoordinates(metadata)
|
||||
}
|
||||
|
@ -103,7 +105,7 @@ FloatingPane {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.MiddleButton
|
||||
onWheel: wheel.accepted = true
|
||||
onWheel: function(wheel) { wheel.accepted = true }
|
||||
}
|
||||
|
||||
// Main Layout
|
||||
|
@ -174,7 +176,7 @@ FloatingPane {
|
|||
sortRole: "raw"
|
||||
filters: [{role: "raw", value: searchBar.text}]
|
||||
delegate: RowLayout {
|
||||
width: parent ? parent.width : 0
|
||||
width: ListView.view.width
|
||||
Label {
|
||||
text: key
|
||||
leftPadding: 6
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
FloatingPane {
|
||||
|
@ -30,7 +31,7 @@ FloatingPane {
|
|||
|
||||
DoubleValidator {
|
||||
id: doubleValidator
|
||||
locale: 'C' // use '.' decimal separator disregarding of the system locale
|
||||
locale: 'C' // Use '.' decimal separator disregarding of the system locale
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -62,7 +63,7 @@ FloatingPane {
|
|||
padding : 10
|
||||
colors: root.colors
|
||||
currentIndex: root.colorIndex
|
||||
onColorPicked: root.colorOffset = colorIndex
|
||||
onColorPicked: function(colorIndex) { root.colorOffset = colorIndex }
|
||||
}
|
||||
|
||||
// Grid opacity slider
|
||||
|
@ -147,12 +148,11 @@ FloatingPane {
|
|||
}
|
||||
}
|
||||
|
||||
//Fill rectangle to have a better UI
|
||||
// Fill rectangle to have a better UI
|
||||
Rectangle {
|
||||
color: root.palette.window
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
|
||||
import AliceVision 1.0 as AliceVision
|
||||
|
||||
// Data from the View / Features.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
|
||||
import AliceVision 1.0 as AliceVision
|
||||
|
||||
// Data from the SfM
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick
|
||||
|
||||
import AliceVision 1.0 as AliceVision
|
||||
|
||||
AliceVision.MTracks {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.11
|
||||
import MaterialIcons 2.2
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Controls 1.0
|
||||
import MaterialIcons 2.2
|
||||
import Utils 1.0
|
||||
|
||||
FloatingPane {
|
||||
|
@ -31,7 +32,7 @@ FloatingPane {
|
|||
|
||||
DoubleValidator {
|
||||
id: doubleValidator
|
||||
locale: 'C' // use '.' decimal separator disregarding of the system locale
|
||||
locale: 'C' // Use '.' decimal separator disregarding of the system locale
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -131,7 +132,6 @@ FloatingPane {
|
|||
Layout.fillWidth: false
|
||||
Layout.maximumWidth: 50
|
||||
|
||||
|
||||
validator: DoubleValidator {
|
||||
bottom: Math.min(speedSpinBox.from, speedSpinBox.to)
|
||||
top: Math.max(speedSpinBox.from, speedSpinBox.to)
|
||||
|
@ -164,7 +164,6 @@ FloatingPane {
|
|||
Layout.fillWidth: false
|
||||
Layout.maximumWidth: 50
|
||||
|
||||
|
||||
validator: DoubleValidator {
|
||||
bottom: Math.min(downscaleSpinBox.from, downscaleSpinBox.to)
|
||||
top: Math.max(downscaleSpinBox.from, downscaleSpinBox.to)
|
||||
|
@ -179,8 +178,8 @@ FloatingPane {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: textMetrics_subdivisionsValue
|
||||
font: subdivisionsLabel.font
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import QtQuick 2.15
|
||||
import Utils 1.0
|
||||
import QtQuick
|
||||
|
||||
import AliceVision 1.0 as AliceVision
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* PanoramaViwer displays a list of Float Images
|
||||
|
@ -73,7 +73,7 @@ AliceVision.PanoramaViewer {
|
|||
property double pitchNode: activeNode ? activeNode.attribute("manualTransform.manualRotation.x").value : 0
|
||||
property double rollNode: activeNode ? activeNode.attribute("manualTransform.manualRotation.z").value : 0
|
||||
|
||||
//Convert angle functions
|
||||
// Convert angle functions
|
||||
function toDegrees(radians) {
|
||||
return radians * (180 / Math.PI)
|
||||
}
|
||||
|
@ -82,12 +82,16 @@ AliceVision.PanoramaViewer {
|
|||
return degrees * (Math.PI / 180)
|
||||
}
|
||||
|
||||
function fmod(a,b) { return Number((a - (Math.floor(a / b) * b)).toPrecision(8)) }
|
||||
function fmod(a,b) {
|
||||
return Number((a - (Math.floor(a / b) * b)).toPrecision(8))
|
||||
}
|
||||
|
||||
// Limit angle between -180 and 180
|
||||
function limitAngle(angle) {
|
||||
if (angle > 180) angle = -180.0 + (angle - 180.0)
|
||||
if (angle < -180) angle = 180.0 - (Math.abs(angle) - 180)
|
||||
if (angle > 180)
|
||||
angle = -180.0 + (angle - 180.0)
|
||||
if (angle < -180)
|
||||
angle = 180.0 - (Math.abs(angle) - 180)
|
||||
return angle
|
||||
}
|
||||
|
||||
|
@ -121,7 +125,7 @@ AliceVision.PanoramaViewer {
|
|||
if (isEditable)
|
||||
isRotating ? Qt.ClosedHandCursor : Qt.OpenHandCursor
|
||||
}
|
||||
onPositionChanged: {
|
||||
onPositionChanged: function(mouse) {
|
||||
// Send Mouse Coordinates to Float Images Viewers
|
||||
idSelected = -1
|
||||
for (var i = 0; i < repeater.model && isHighlightable; ++i) {
|
||||
|
@ -171,7 +175,7 @@ AliceVision.PanoramaViewer {
|
|||
}
|
||||
}
|
||||
|
||||
onPressed:{
|
||||
onPressed: function(mouse) {
|
||||
_reconstruction.beginModification("Panorama Manual Rotation")
|
||||
isRotating = true
|
||||
lastX = mouse.x
|
||||
|
@ -185,7 +189,7 @@ AliceVision.PanoramaViewer {
|
|||
previous_roll = roll
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
onReleased: function(mouse) {
|
||||
_reconstruction.endModification()
|
||||
isRotating = false
|
||||
lastX = 0
|
||||
|
@ -273,33 +277,31 @@ AliceVision.PanoramaViewer {
|
|||
var sourceItem = Filepath.stringToUrl(msfmData.getUrlFromViewId(idViewItem))
|
||||
|
||||
setSource("FloatImage.qml", {
|
||||
'surface.viewerType': AliceVision.Surface.EViewerType.PANORAMA,
|
||||
'viewerTypeString': 'panorama',
|
||||
'surface.subdivisions': Qt.binding(function() { return subdivisionsPano }),
|
||||
'cropFisheye' : Qt.binding(function(){ return cropFisheyePano }),
|
||||
'surface.pitch': Qt.binding(function() { return root.pitch }),
|
||||
'surface.yaw': Qt.binding(function() { return root.yaw }),
|
||||
'surface.roll': Qt.binding(function() { return root.roll }),
|
||||
'idView': Qt.binding(function() { return idViewItem }),
|
||||
'gamma': Qt.binding(function() { return hdrImageToolbar.gammaValue }),
|
||||
'gain': Qt.binding(function() { return hdrImageToolbar.gainValue }),
|
||||
'channelModeString': Qt.binding(function() { return hdrImageToolbar.channelModeValue }),
|
||||
'downscaleLevel' : Qt.binding(function() { return downscale }),
|
||||
'source': Qt.binding(function() { return sourceItem }),
|
||||
'surface.msfmData': Qt.binding(function() { return root.msfmData }),
|
||||
'canBeHovered': true,
|
||||
'useSequence': false
|
||||
"surface.viewerType": AliceVision.Surface.EViewerType.PANORAMA,
|
||||
"viewerTypeString": "panorama",
|
||||
"surface.subdivisions": Qt.binding(function() { return subdivisionsPano }),
|
||||
"cropFisheye" : Qt.binding(function(){ return cropFisheyePano }),
|
||||
"surface.pitch": Qt.binding(function() { return root.pitch }),
|
||||
"surface.yaw": Qt.binding(function() { return root.yaw }),
|
||||
"surface.roll": Qt.binding(function() { return root.roll }),
|
||||
"idView": Qt.binding(function() { return idViewItem }),
|
||||
"gamma": Qt.binding(function() { return hdrImageToolbar.gammaValue }),
|
||||
"gain": Qt.binding(function() { return hdrImageToolbar.gainValue }),
|
||||
"channelModeString": Qt.binding(function() { return hdrImageToolbar.channelModeValue }),
|
||||
"downscaleLevel": Qt.binding(function() { return downscale }),
|
||||
"source": Qt.binding(function() { return sourceItem }),
|
||||
"surface.msfmData": Qt.binding(function() { return root.msfmData }),
|
||||
"canBeHovered": true,
|
||||
"useSequence": false
|
||||
})
|
||||
imageLoaded = Qt.binding(function() { return repeater.itemAt(index).item.imageStatus === Image.Ready ? true : false })
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: 0
|
||||
delegate: imgPano
|
||||
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
|
@ -309,7 +311,7 @@ AliceVision.PanoramaViewer {
|
|||
// Retrieve downscale value from C++
|
||||
panoramaViewerToolbar.updateDownscaleValue(root.downscale)
|
||||
|
||||
//Changing the repeater model (number of elements)
|
||||
// Changing the repeater model (number of elements)
|
||||
panoImages.updateRepeater()
|
||||
|
||||
root.readyToLoad = Image.Ready
|
||||
|
|
48
meshroom/ui/qml/Viewer/PhongImageViewer.qml
Normal file
48
meshroom/ui/qml/Viewer/PhongImageViewer.qml
Normal file
|
@ -0,0 +1,48 @@
|
|||
import QtQuick
|
||||
import Utils 1.0
|
||||
|
||||
import AliceVision 1.0 as AliceVision
|
||||
|
||||
/**
|
||||
* PhongImageViewer displays an Image (albedo + normal) with a given light direction.
|
||||
* Shading is done using Blinn-Phong reflection model, material and light direction parameters available.
|
||||
* Accept HdrImageToolbar controls (gamma / offset / channel).
|
||||
*
|
||||
* <!> Requires QtAliceVision plugin.
|
||||
*/
|
||||
|
||||
AliceVision.PhongImageViewer {
|
||||
id: root
|
||||
|
||||
width: sourceSize.width
|
||||
height: sourceSize.height
|
||||
visible: true
|
||||
|
||||
// paintedWidth / paintedHeight / imageStatus for compatibility with standard Image
|
||||
property int paintedWidth: sourceSize.width
|
||||
property int paintedHeight: sourceSize.height
|
||||
property var imageStatus: {
|
||||
if (root.status === AliceVision.PhongImageViewer.EStatus.LOADING) {
|
||||
return Image.Loading
|
||||
} else if (root.status === AliceVision.PhongImageViewer.EStatus.LOADING_ERROR ||
|
||||
root.status === AliceVision.PhongImageViewer.EStatus.MISSING_FILE) {
|
||||
return Image.Error
|
||||
} else if ((root.sourcePath === "") || (root.sourceSize.height <= 0) || (root.sourceSize.width <= 0)) {
|
||||
return Image.Null
|
||||
}
|
||||
|
||||
return Image.Ready
|
||||
}
|
||||
|
||||
property string channelModeString : "rgba"
|
||||
channelMode: {
|
||||
switch (channelModeString) {
|
||||
case "rgb": return AliceVision.PhongImageViewer.EChannelMode.RGB
|
||||
case "r": return AliceVision.PhongImageViewer.EChannelMode.R
|
||||
case "g": return AliceVision.PhongImageViewer.EChannelMode.G
|
||||
case "b": return AliceVision.PhongImageViewer.EChannelMode.B
|
||||
case "a": return AliceVision.PhongImageViewer.EChannelMode.A
|
||||
default: return AliceVision.PhongImageViewer.EChannelMode.RGBA
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue