Codebase list engauge-digitizer / 09a4a24
Imported Upstream version 9.0 Tobias Winchen 7 years ago
225 changed file(s) with 8055 addition(s) and 1793 deletion(s). Raw diff Collapse all Expand all
0 # Example script for using ParseDig class to extract curves and their points from Engauge DIG file, and apply
1 # curve fitting
2 #
3 # Requirements:
4 # 1) python3 (versus python2)
5 # 2) numpy
6 # 3) DefaultListOrderedDict.py from the Engauge scripts directory
7 # 4) ParseDig.py from the Engauge scripts directory
8
9 from ParseDig import ParseDig
10 from numpy import poly1d
11 from numpy import polyfit
12
13 import sys
14
15 defaultHighestOrder = 3
16 if len(sys.argv) < 2:
17 print ("Usage: python3 CurveFitting.py <dig file> [<highest order>]")
18 print ("where:")
19 print (" <dig file> Version 6 or newer DIG file")
20 print (" <highest order> Highest order of polynomial to be fit to the data. Default is " + defaultHighestOrder)
21 print ("Example: python3 CurveFitting.py samples/CurveFitting.dig")
22 else:
23 parseDig = ParseDig (sys.argv [1])
24 highestOrderUser = defaultHighestOrder
25 if len(sys.argv) == 3:
26 highestOrderUser = int (sys.argv [2])
27 curveNames = parseDig.curveNames()
28 for curveName in curveNames:
29
30 print ()
31
32 # Show (x,y) points as Nx2 matrix
33 curve = parseDig.curve (curveName)
34
35 # Show (x,y) points as 2 vectors
36 xVector = [row [0] for row in curve]
37 yVector = [row [1] for row in curve]
38
39 # Fit linear and higher order polynomials. Highest order is less than number of points to prevent overfitting
40 highestOrderNoOverfit = len (xVector) - 1
41 for order in range (0, 1 + min (highestOrderUser, highestOrderNoOverfit)):
42 z = polyfit (xVector, yVector, order)
43 p = poly1d (z)
44 rmsError = 0
45 for i in range (0, len (xVector)):
46 x = xVector [i]
47 y = yVector [i]
48 rmsError += (p (x) - y) * (p (x) - y)
49 print ("Curve '" + curveName + "' with polynomial fit to order " + str (order) + " has rms error " + str (rmsError))
50
1717 curveNames = parseDig.curveNames()
1818 print ("Curve names = ", curveNames, "\n")
1919 for curveName in curveNames:
20
21 # Show (x,y) points as Nx2 matrix
2022 curve = parseDig.curve (curveName)
2123 print ("Curve ", "'" + curveName + "'", " = ", curve, "\n");
24
25 # Show (x,y) points as 2 vectors
26 x = [row [0] for row in curve]
27 y = [row [1] for row in curve]
28 print ("x=", x, "y=", y)
29
30
0 #!/usr/bin/python
1 #
2 # Usage - python insert_derived_column.py <csv file>
3 # Purpose - This script reads in a table of (longitude,latitude) data points, and then
4 # outputs a set of evenly spaced waypoints through those points assuming a constant
5 # velocity (variable velocityMps)
6 # Installation requirements - 1) sudo apt-get install python
7 # 2) sudo apt-get install python-dev (or python-devel)
8 # 3) sudo pip install numpy
9
10 from datetime import datetime, timedelta
11 import fileinput
12 import math
13 import numpy as np
14
15 def is_number(s):
16 try:
17 float(s)
18 return True
19 except ValueError:
20 return False
21
22 try:
23 import unicodedata
24 unicodedata.numeric(s)
25 return True
26 except (TypeError, ValueError):
27 return False
28
29 def readFieldsWithCommas(line):
30 return line.replace ("\n", "").split (",")
31
32 def xyzFromLatLonAlt (latLonAlt):
33 rearth = 6378160
34 pi = 3.1415926535
35 radians2degrees = pi / 180.0
36 lat = latLonAlt [0] * radians2degrees
37 lon = latLonAlt [1] * radians2degrees
38 radius = rearth + latLonAlt [2]
39 x = radius * math.cos (lat) * math.cos (lon)
40 y = radius * math.cos (lat) * math.sin (lon)
41 z = radius * math.sin (lat)
42 return np.array ([x, y, z])
43
44 # User inputs
45 altitudeM = 5000
46 velocityMps = 69 # 69 m/s = 250 km/hr
47 curDateTime = datetime (2015, 1, 1, 0, 0, 0)
48
49 # Loop through input file lines
50 isFirst = True
51 xyzLast = np.array ([0, 0, 0])
52 for line in fileinput.input():
53 fields = readFieldsWithCommas (line)
54
55 # Skip header which does not have numeric fields
56 if is_number (fields [0]) and is_number (fields [1]):
57
58 # Convert latitude and longitude to cartesian x,y,z coordinates
59 lat = float (fields [1])
60 lon = float (fields [0])
61
62 latLonAlt = np.array ([lat,
63 lon,
64 altitudeM])
65 xyz = xyzFromLatLonAlt (latLonAlt)
66 xyzDeltaMag = 0
67 if isFirst:
68 isFirst = False
69 else:
70 xyzDelta = np.subtract (xyz, xyzLast)
71 xyzDeltaMag = np.linalg.norm (xyzDelta)
72
73 # Output
74 timestamp = curDateTime.strftime ('"%j %Y %H:%M:%S.%f"')
75 fields.insert (0, timestamp)
76
77 # Use one of the following lines. The first is for python2, and the second is for python3
78 print ', '.join (str (x) for x in fields)
79 #print (', '.join (str (x) for x in fields))
80
81 # Update for next iteration
82 timeTraveledS = xyzDeltaMag / velocityMps
83 curDateTime = curDateTime + timedelta(seconds = timeTraveledS)
84 xyzLast = xyz
85
0 CurveFitting.py Python script that reads in a DIG file and performs polynomial curve fitting
01 ExampleParseDig.py Python script that shows how to use ParseDig.py. This script dumps the DIG file specified in
12 the command line. This code can serve as a starting point for other scripts that can process
23 the information into other output formats - like SQL tables and NETCDF.
3 insert_derived_column.py Python script that reads in (longitude,latitude) points and output those points with a timestamp
4 InsertDerivedColumn.py Python script that reads in (longitude,latitude) points and output those points with a timestamp
45 at each point that is computed assuming a constant speed through the points
56 ParseDig.py Python class that reads Engauge Digitizer DIG files, and provides that information through a
67 very simplie application programming interface (API)
+0
-86
contrib/python/insert_derived_column.py less more
0 #!/usr/bin/python
1 #
2 # Usage - python insert_derived_column.py <csv file>
3 # Purpose - This script reads in a table of (longitude,latitude) data points, and then
4 # outputs a set of evenly spaced waypoints through those points assuming a constant
5 # velocity (variable velocityMps)
6 # Installation requirements - 1) sudo apt-get install python
7 # 2) sudo apt-get install python-dev (or python-devel)
8 # 3) sudo pip install numpy
9
10 from datetime import datetime, timedelta
11 import fileinput
12 import math
13 import numpy as np
14
15 def is_number(s):
16 try:
17 float(s)
18 return True
19 except ValueError:
20 return False
21
22 try:
23 import unicodedata
24 unicodedata.numeric(s)
25 return True
26 except (TypeError, ValueError):
27 return False
28
29 def readFieldsWithCommas(line):
30 return line.replace ("\n", "").split (",")
31
32 def xyzFromLatLonAlt (latLonAlt):
33 rearth = 6378160
34 pi = 3.1415926535
35 radians2degrees = pi / 180.0
36 lat = latLonAlt [0] * radians2degrees
37 lon = latLonAlt [1] * radians2degrees
38 radius = rearth + latLonAlt [2]
39 x = radius * math.cos (lat) * math.cos (lon)
40 y = radius * math.cos (lat) * math.sin (lon)
41 z = radius * math.sin (lat)
42 return np.array ([x, y, z])
43
44 # User inputs
45 altitudeM = 5000
46 velocityMps = 69 # 69 m/s = 250 km/hr
47 curDateTime = datetime (2015, 1, 1, 0, 0, 0)
48
49 # Loop through input file lines
50 isFirst = True
51 xyzLast = np.array ([0, 0, 0])
52 for line in fileinput.input():
53 fields = readFieldsWithCommas (line)
54
55 # Skip header which does not have numeric fields
56 if is_number (fields [0]) and is_number (fields [1]):
57
58 # Convert latitude and longitude to cartesian x,y,z coordinates
59 lat = float (fields [1])
60 lon = float (fields [0])
61
62 latLonAlt = np.array ([lat,
63 lon,
64 altitudeM])
65 xyz = xyzFromLatLonAlt (latLonAlt)
66 xyzDeltaMag = 0
67 if isFirst:
68 isFirst = False
69 else:
70 xyzDelta = np.subtract (xyz, xyzLast)
71 xyzDeltaMag = np.linalg.norm (xyzDelta)
72
73 # Output
74 timestamp = curDateTime.strftime ('"%j %Y %H:%M:%S.%f"')
75 fields.insert (0, timestamp)
76
77 # Use one of the following lines. The first is for python2, and the second is for python3
78 print ', '.join (str (x) for x in fields)
79 #print (', '.join (str (x) for x in fields))
80
81 # Update for next iteration
82 timeTraveledS = xyzDeltaMag / velocityMps
83 curDateTime = curDateTime + timedelta(seconds = timeTraveledS)
84 xyzLast = xyz
85
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!DOCTYPE engauge>
2 <Document VersionNumber="9.0" AxesPointsRequired="0">
3 <Image Width="1028" Height="593"><![CDATA[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]]></Image>
4 <CoordSystem>
5 <General CursorSize="3" ExtraPrecision="1"/>
6 <Coords Type="0" TypeString="Cartesian" Coords="0" ScaleXTheta="0" ScaleXThetaString="Linear" ScaleYRadius="0" ScaleYRadiusString="Linear" UnitsX="0" UnitsXString="Number" UnitsY="0" UnitsYString="Number" UnitsTheta="0" UnitsThetaString="Degrees (DDD.DDDDD)" UnitsRadius="0" UnitsRadiusString="Number" UnitsDate="3" UnitsDateString="YYYY/MM/DD" UnitsTime="2" UnitsTimeString="HH:MM:SS"/>
7 <DigitizeCurve CursorInnerRadius="5" CursorLineWidth="2" CursorSize="1" CursorStandardCross="True"/>
8 <Export PointsSelectionFunctions="0" PointsSelectionFunctionsString="InterpolateAllCurves" PointsIntervalFunctions="10" PointsIntervalUnitsFunctions="1" PointsSelectionRelations="0" PointsSelectionRelationsString="Interpolate" PointsIntervalUnitsRelations="1" PointsIntervalRelations="10" LayoutFunctions="0" LayoutFunctionsString="AllPerLine" Delimiter="0" OverrideCsvTsv="True" DelimiterString="Commas" Header="1" HeaderString="Simple" XLabel="x">
9 <CurveNamesNotExported/>
10 </Export>
11 <AxesChecker Mode="1" Seconds="3" LineColor="6"/>
12 <GridDisplay Stable="True" DisableX="0" CountX="7" StartX="0" StepX="1" StopX="6" DisableY="0" CountY="4" StartY="0" StepY="5" StopY="15" Color="0" ColorString="Black"/>
13 <GridRemoval Stable="False" DefinedGridLines="False" CloseDistance="10" CoordDisableX="0" CoordDisableXString="Count" CountX="26" StartX="0.184793" StepX="0.110612" StopX="2.95008" CoordDisableY="0" CoordDisableYString="Count" CountY="6" StartY="-10.0584" StepY="2.82517" StopY="4.06742"/>
14 <PointMatch PointSize="48" ColorAccepted="4" ColorAcceptedString="Green" ColorCandidate="7" ColorCandidateString="Yellow" ColorRejected="6" ColorRejectedString="Red"/>
15 <Segments PointSeparation="25" MinLength="2" FillCorners="False" LineWidth="4" LineColor="4" LineColorString="Green"/>
16 <Curve CurveName="Axes">
17 <ColorFilter CurveName="Axes" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
18 <CurveStyle CurveName="Axes">
19 <LineStyle Width="0" Color="8" ColorString="Transparent" ConnectAs="4" ConnectAsString="ConnectSkipForAxisCurve"/>
20 <PointStyle Radius="10" LineWidth="1" Color="6" ColorString="Red" Shape="1" ShapeString="Cross"/>
21 </CurveStyle>
22 <CurvePoints>
23 <Point Identifier="Axes&#9;point&#9;1" Ordinal="1" IsAxisPoint="True" IsXOnly="False" Index="18">
24 <PositionScreen X="61.5043" Y="350.18"/>
25 <PositionGraph X="0.5" Y="0"/>
26 </Point>
27 <Point Identifier="Axes&#9;point&#9;3" Ordinal="2" IsAxisPoint="True" IsXOnly="False" Index="18">
28 <PositionScreen X="830.707" Y="350.9"/>
29 <PositionGraph X="5.5" Y="0"/>
30 </Point>
31 <Point Identifier="Axes&#9;point&#9;5" Ordinal="3" IsAxisPoint="True" IsXOnly="False" Index="18">
32 <PositionScreen X="61.5043" Y="21.616"/>
33 <PositionGraph X="0.5" Y="15"/>
34 </Point>
35 </CurvePoints>
36 </Curve>
37 <CurvesGraphs>
38 <Curve CurveName="linear">
39 <ColorFilter CurveName="linear" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
40 <CurveStyle CurveName="linear">
41 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
42 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="1" ShapeString="Cross"/>
43 </CurveStyle>
44 <CurvePoints>
45 <Point Identifier="linear&#9;point&#9;6" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="18">
46 <PositionScreen X="137.386" Y="347.298"/>
47 </Point>
48 <Point Identifier="linear&#9;point&#9;7" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="18">
49 <PositionScreen X="290.747" Y="325.682"/>
50 </Point>
51 <Point Identifier="linear&#9;point&#9;8" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="18">
52 <PositionScreen X="446.505" Y="305.507"/>
53 </Point>
54 </CurvePoints>
55 </Curve>
56 <Curve CurveName="quadratic">
57 <ColorFilter CurveName="quadratic" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
58 <CurveStyle CurveName="quadratic">
59 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
60 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="5" ShapeString="X"/>
61 </CurveStyle>
62 <CurvePoints>
63 <Point Identifier="quadratic&#9;point&#9;9" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="18">
64 <PositionScreen X="138.185" Y="175.81"/>
65 </Point>
66 <Point Identifier="quadratic&#9;point&#9;10" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="18">
67 <PositionScreen X="292.345" Y="244.261"/>
68 </Point>
69 <Point Identifier="quadratic&#9;point&#9;11" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="18">
70 <PositionScreen X="444.908" Y="282.45"/>
71 </Point>
72 <Point Identifier="quadratic&#9;point&#9;12" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="18">
73 <PositionScreen X="599.068" Y="244.261"/>
74 </Point>
75 </CurvePoints>
76 </Curve>
77 <Curve CurveName="cubic">
78 <ColorFilter CurveName="cubic" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
79 <CurveStyle CurveName="cubic">
80 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
81 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="2" ShapeString="Diamond"/>
82 </CurveStyle>
83 <CurvePoints>
84 <Point Identifier="cubic&#9;point&#9;13" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="18">
85 <PositionScreen X="139.782" Y="425.836"/>
86 </Point>
87 <Point Identifier="cubic&#9;point&#9;14" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="18">
88 <PositionScreen X="291.546" Y="472.671"/>
89 </Point>
90 <Point Identifier="cubic&#9;point&#9;15" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="18">
91 <PositionScreen X="446.505" Y="443.849"/>
92 </Point>
93 <Point Identifier="cubic&#9;point&#9;16" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="18">
94 <PositionScreen X="599.068" Y="311.991"/>
95 </Point>
96 <Point Identifier="cubic&#9;point&#9;17" Ordinal="4" IsAxisPoint="False" IsXOnly="False" Index="18">
97 <PositionScreen X="753.228" Y="48.9964"/>
98 </Point>
99 </CurvePoints>
100 </Curve>
101 </CurvesGraphs>
102 </CoordSystem>
103 </Document>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!DOCTYPE engauge>
2 <Document VersionNumber="9.0" AxesPointsRequired="0">
3 <Image Width="1028" Height="593"><![CDATA[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]]></Image>
4 <CoordSystem>
5 <General CursorSize="3" ExtraPrecision="1"/>
6 <Coords Type="0" TypeString="Cartesian" Coords="0" ScaleXTheta="0" ScaleXThetaString="Linear" ScaleYRadius="0" ScaleYRadiusString="Linear" UnitsX="0" UnitsXString="Number" UnitsY="0" UnitsYString="Number" UnitsTheta="0" UnitsThetaString="Degrees (DDD.DDDDD)" UnitsRadius="0" UnitsRadiusString="Number" UnitsDate="3" UnitsDateString="YYYY/MM/DD" UnitsTime="2" UnitsTimeString="HH:MM:SS"/>
7 <DigitizeCurve CursorInnerRadius="5" CursorLineWidth="2" CursorSize="1" CursorStandardCross="True"/>
8 <Export PointsSelectionFunctions="0" PointsSelectionFunctionsString="InterpolateAllCurves" PointsIntervalFunctions="10" PointsIntervalUnitsFunctions="1" PointsSelectionRelations="0" PointsSelectionRelationsString="Interpolate" PointsIntervalUnitsRelations="1" PointsIntervalRelations="10" LayoutFunctions="0" LayoutFunctionsString="AllPerLine" Delimiter="0" OverrideCsvTsv="True" DelimiterString="Commas" Header="1" HeaderString="Simple" XLabel="x">
9 <CurveNamesNotExported/>
10 </Export>
11 <AxesChecker Mode="1" Seconds="3" LineColor="6"/>
12 <GridDisplay Stable="True" DisableX="0" CountX="7" StartX="0" StepX="1" StopX="6" DisableY="0" CountY="4" StartY="0" StepY="5" StopY="15" Color="0" ColorString="Black"/>
13 <GridRemoval Stable="False" DefinedGridLines="False" CloseDistance="10" CoordDisableX="0" CoordDisableXString="Count" CountX="26" StartX="0.184793" StepX="0.110612" StopX="2.95008" CoordDisableY="0" CoordDisableYString="Count" CountY="6" StartY="-10.0584" StepY="2.82516" StopY="4.06741"/>
14 <PointMatch PointSize="48" ColorAccepted="4" ColorAcceptedString="Green" ColorCandidate="7" ColorCandidateString="Yellow" ColorRejected="6" ColorRejectedString="Red"/>
15 <Segments PointSeparation="25" MinLength="2" FillCorners="False" LineWidth="4" LineColor="4" LineColorString="Green"/>
16 <Curve CurveName="Axes">
17 <ColorFilter CurveName="Axes" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
18 <CurveStyle CurveName="Axes">
19 <LineStyle Width="0" Color="8" ColorString="Transparent" ConnectAs="4" ConnectAsString="ConnectSkipForAxisCurve"/>
20 <PointStyle Radius="10" LineWidth="1" Color="6" ColorString="Red" Shape="1" ShapeString="Cross"/>
21 </CurveStyle>
22 <CurvePoints>
23 <Point Identifier="Axes&#9;point&#9;1" Ordinal="1" IsAxisPoint="True" IsXOnly="False" Index="40">
24 <PositionScreen X="61.5043" Y="350.18"/>
25 <PositionGraph X="0.5" Y="0"/>
26 </Point>
27 <Point Identifier="Axes&#9;point&#9;3" Ordinal="2" IsAxisPoint="True" IsXOnly="False" Index="40">
28 <PositionScreen X="830.707" Y="350.9"/>
29 <PositionGraph X="5.5" Y="0"/>
30 </Point>
31 <Point Identifier="Axes&#9;point&#9;5" Ordinal="3" IsAxisPoint="True" IsXOnly="False" Index="40">
32 <PositionScreen X="61.5043" Y="21.616"/>
33 <PositionGraph X="0.5" Y="15"/>
34 </Point>
35 </CurvePoints>
36 </Curve>
37 <CurvesGraphs>
38 <Curve CurveName="linear">
39 <ColorFilter CurveName="linear" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
40 <CurveStyle CurveName="linear">
41 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
42 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="1" ShapeString="Cross"/>
43 </CurveStyle>
44 <CurvePoints>
45 <Point Identifier="linear&#9;point&#9;6" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="40">
46 <PositionScreen X="137.386" Y="347.298"/>
47 </Point>
48 <Point Identifier="linear&#9;point&#9;18" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="40">
49 <PositionScreen X="178.123" Y="341.533"/>
50 </Point>
51 <Point Identifier="linear&#9;point&#9;19" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="40">
52 <PositionScreen X="235.633" Y="334.328"/>
53 </Point>
54 <Point Identifier="linear&#9;point&#9;7" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="40">
55 <PositionScreen X="290.747" Y="325.682"/>
56 </Point>
57 <Point Identifier="linear&#9;point&#9;20" Ordinal="4" IsAxisPoint="False" IsXOnly="False" Index="40">
58 <PositionScreen X="330.685" Y="320.638"/>
59 </Point>
60 <Point Identifier="linear&#9;point&#9;21" Ordinal="5" IsAxisPoint="False" IsXOnly="False" Index="40">
61 <PositionScreen X="399.378" Y="311.271"/>
62 </Point>
63 <Point Identifier="linear&#9;point&#9;8" Ordinal="6" IsAxisPoint="False" IsXOnly="False" Index="40">
64 <PositionScreen X="446.505" Y="305.507"/>
65 </Point>
66 </CurvePoints>
67 </Curve>
68 <Curve CurveName="quadratic">
69 <ColorFilter CurveName="quadratic" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
70 <CurveStyle CurveName="quadratic">
71 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
72 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="5" ShapeString="X"/>
73 </CurveStyle>
74 <CurvePoints>
75 <Point Identifier="quadratic&#9;point&#9;9" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="40">
76 <PositionScreen X="138.185" Y="175.81"/>
77 </Point>
78 <Point Identifier="quadratic&#9;point&#9;22" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="40">
79 <PositionScreen X="169.336" Y="189.501"/>
80 </Point>
81 <Point Identifier="quadratic&#9;point&#9;23" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="40">
82 <PositionScreen X="234.036" Y="219.043"/>
83 </Point>
84 <Point Identifier="quadratic&#9;point&#9;10" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="40">
85 <PositionScreen X="292.345" Y="244.261"/>
86 </Point>
87 <Point Identifier="quadratic&#9;point&#9;24" Ordinal="4" IsAxisPoint="False" IsXOnly="False" Index="40">
88 <PositionScreen X="331.484" Y="258.672"/>
89 </Point>
90 <Point Identifier="quadratic&#9;point&#9;11" Ordinal="5" IsAxisPoint="False" IsXOnly="False" Index="40">
91 <PositionScreen X="444.908" Y="282.45"/>
92 </Point>
93 <Point Identifier="quadratic&#9;point&#9;12" Ordinal="6" IsAxisPoint="False" IsXOnly="False" Index="40">
94 <PositionScreen X="599.068" Y="244.261"/>
95 </Point>
96 </CurvePoints>
97 </Curve>
98 <Curve CurveName="cubic">
99 <ColorFilter CurveName="cubic" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
100 <CurveStyle CurveName="cubic">
101 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
102 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="2" ShapeString="Diamond"/>
103 </CurveStyle>
104 <CurvePoints>
105 <Point Identifier="cubic&#9;point&#9;13" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="40">
106 <PositionScreen X="139.782" Y="425.836"/>
107 </Point>
108 <Point Identifier="cubic&#9;point&#9;14" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="40">
109 <PositionScreen X="291.546" Y="472.671"/>
110 </Point>
111 <Point Identifier="cubic&#9;point&#9;15" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="40">
112 <PositionScreen X="446.505" Y="443.849"/>
113 </Point>
114 <Point Identifier="cubic&#9;point&#9;16" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="40">
115 <PositionScreen X="599.068" Y="311.991"/>
116 </Point>
117 <Point Identifier="cubic&#9;point&#9;26" Ordinal="4" IsAxisPoint="False" IsXOnly="False" Index="40">
118 <PositionScreen X="673.352" Y="195.985"/>
119 </Point>
120 <Point Identifier="cubic&#9;point&#9;25" Ordinal="5" IsAxisPoint="False" IsXOnly="False" Index="40">
121 <PositionScreen X="715.686" Y="118.888"/>
122 </Point>
123 <Point Identifier="cubic&#9;point&#9;17" Ordinal="6" IsAxisPoint="False" IsXOnly="False" Index="40">
124 <PositionScreen X="753.228" Y="48.9964"/>
125 </Point>
126 </CurvePoints>
127 </Curve>
128 <Curve CurveName="linear-3-points">
129 <ColorFilter CurveName="linear-3-points" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
130 <CurveStyle CurveName="linear-3-points">
131 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
132 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="3" ShapeString="Square"/>
133 </CurveStyle>
134 <CurvePoints>
135 <Point Identifier="linear-3-points&#9;point&#9;27" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="40">
136 <PositionScreen X="137.386" Y="346.577"/>
137 </Point>
138 <Point Identifier="linear-3-points&#9;point&#9;28" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="40">
139 <PositionScreen X="291.546" Y="325.682"/>
140 </Point>
141 <Point Identifier="linear-3-points&#9;point&#9;29" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="40">
142 <PositionScreen X="445.706" Y="304.066"/>
143 </Point>
144 </CurvePoints>
145 </Curve>
146 <Curve CurveName="quadratic-4-points">
147 <ColorFilter CurveName="quadratic-4-points" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
148 <CurveStyle CurveName="quadratic-4-points">
149 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
150 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="1" ShapeString="Cross"/>
151 </CurveStyle>
152 <CurvePoints>
153 <Point Identifier="quadratic-4-points&#9;point&#9;30" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="40">
154 <PositionScreen X="138.185" Y="176.531"/>
155 </Point>
156 <Point Identifier="quadratic-4-points&#9;point&#9;31" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="40">
157 <PositionScreen X="292.345" Y="241.379"/>
158 </Point>
159 <Point Identifier="quadratic-4-points&#9;point&#9;32" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="40">
160 <PositionScreen X="444.908" Y="281.009"/>
161 </Point>
162 <Point Identifier="quadratic-4-points&#9;point&#9;33" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="40">
163 <PositionScreen X="598.269" Y="244.261"/>
164 </Point>
165 </CurvePoints>
166 </Curve>
167 <Curve CurveName="cubic-5-points">
168 <ColorFilter CurveName="cubic-5-points" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
169 <CurveStyle CurveName="cubic-5-points">
170 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
171 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="5" ShapeString="X"/>
172 </CurveStyle>
173 <CurvePoints>
174 <Point Identifier="cubic-5-points&#9;point&#9;34" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="40">
175 <PositionScreen X="138.984" Y="424.395"/>
176 </Point>
177 <Point Identifier="cubic-5-points&#9;point&#9;35" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="40">
178 <PositionScreen X="290.747" Y="473.391"/>
179 </Point>
180 <Point Identifier="cubic-5-points&#9;point&#9;36" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="40">
181 <PositionScreen X="446.505" Y="444.57"/>
182 </Point>
183 <Point Identifier="cubic-5-points&#9;point&#9;37" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="40">
184 <PositionScreen X="599.068" Y="311.271"/>
185 </Point>
186 <Point Identifier="cubic-5-points&#9;point&#9;38" Ordinal="4" IsAxisPoint="False" IsXOnly="False" Index="40">
187 <PositionScreen X="673.352" Y="193.824"/>
188 </Point>
189 <Point Identifier="cubic-5-points&#9;point&#9;39" Ordinal="5" IsAxisPoint="False" IsXOnly="False" Index="40">
190 <PositionScreen X="754.825" Y="48.2758"/>
191 </Point>
192 </CurvePoints>
193 </Curve>
194 </CurvesGraphs>
195 </CoordSystem>
196 </Document>
00 <?xml version="1.0" encoding="UTF-8"?>
11 <!DOCTYPE QtCreatorProject>
2 <!-- Written by QtCreator 3.0.1, 2016-07-06T22:13:50. -->
2 <!-- Written by QtCreator 3.0.1, 2016-07-17T17:20:43. -->
33 <qtcreator>
44 <data>
55 <variable>ProjectExplorer.Project.ActiveTarget</variable>
1212 <key>CFBundleExecutable</key>
1313 <string>Engauge Digitizer</string>
1414 <key>CFBundleVersion</key>
15 <string>8.3</string>
15 <string>9.0</string>
1616 <key>CFBundleShortVersionString</key>
17 <string>8.3</string>
17 <string>9.0</string>
1818 <key>LSApplicationCategoryType</key>
1919 <string>public.app-category.utilities</string>
2020 <key>CFBundleIdentifier</key>
0 rem Usage: build_msi_and_zip.bat <norelease>
1
2 set ARG1=%1
3
04 call C:\"Program Files (x86)"\"Microsoft Visual Studio 12.0"\VC\vcvarsall.bat x86
15
26 set QTDIRS=bearer iconengines imageformats platforms printsupport sqldrivers
48
59 set ENGAUGE_CONFIG='pdf'
610 set QTLIBEXT='.lib'
7 set LOG4CPPDLLINK='https://dl.dropboxusercontent.com/u/1147076/log4cpp-1.1.1.zip'
11 set LOG4CPPDLLINK="https://dl.dropboxusercontent.com/s/gyqcfg2xpm4jjby/log4cpp_null.zip"
12 set FFTWLINK="ftp://ftp.fftw.org/pub/fftw/fftw-3.3.4-dll32.zip"
13 set POPPLERLINK="https://dl.dropboxusercontent.com/u/1147076/poppler-qt5.zip"
814
915 set SCRIPTDIR=%cd%
1016
1117 rem Double-double quotes are needed in next line if the directory has a space
1218 set RESULTDIR=""%SCRIPTDIR%\Engauge Digitizer""
1319
14 mkdir "%RESULTDIR%"
20 rem Next step removes stale files like engauge.log from the release
21 if "%ARG1%" neq "norelease" (
22 if exist "%RESULTDIR%" del /Q /F "%RESULTDIR%" 2>nul
23 )
24 if not exist "%RESULTDIR%" mkdir "%RESULTDIR%"
1525
1626 rem Directory containing engauge.pro
1727 set APPVEYOR_BUILD_FOLDER="%SCRIPTDIR%\..\.."
1828
29 if not exist "%APPVEYOR_BUILD_FOLDER%" mkdir "%APPVEYOR_BUILD_FOLDER%"
30 cd "%APPVEYOR_BUILD_FOLDER%"
31
32 curl "%LOG4CPPDLLINK%" -o log4cpp_null.zip
33 curl "%FFTWLINK%" -o fftw-3.3.4-dll32.zip
34 curl "%POPPLERLINK%" -o poppler-qt5.zip
35
1936 rem Nominal Qt installation is QTDIR="C:\Qt\5.6\msvc2013" or QTDIR="C:\Qt\5.7\msvc2013"
2037 set PATH=%QTDIR%\bin;%PATH%
2138
22 mkdir "%APPVEYOR_BUILD_FOLDER%"
23 cd "%APPVEYOR_BUILD_FOLDER%"
24 curl "%LOG4CPPDLLINK%" -o log4cpp-1.1.1.zip
25 7z x log4cpp-1.1.1.zip -aoa
26 mkdir fftw-3.3.4-dll32
39 7z x log4cpp_null.zip -aoa
40
41 if not exist fftw-3.3.4-dll32 mkdir fftw-3.3.4-dll32
2742 cd fftw-3.3.4-dll32
28 curl 'ftp://ftp.fftw.org/pub/fftw/fftw-3.3.4-dll32.zip' -o fftw-3.3.4-dll32.zip
43
2944 7z x fftw-3.3.4-dll32.zip -aoa
3045 lib /def:libfftw3-3.def
3146 lib /def:libfftw3f-3.def
3247 lib /def:libfftw3l-3.def
33 mkdir include
34 mkdir lib
48 if not exist include mkdir include
49 if not exist lib mkdir lib
3550 move fftw3.h include
3651 move *dll lib
3752 move *def lib
3853 move *.lib lib
3954 cd "%APPVEYOR_BUILD_FOLDER%"
40 curl 'https://dl.dropboxusercontent.com/u/1147076/poppler-qt5.zip' -o poppler-qt5.zip
55
4156 7z x poppler-qt5.zip -aoa
4257
4358 cd "%APPVEYOR_BUILD_FOLDER%"
4560 set POPPLER_INCLUDE="%APPVEYOR_BUILD_FOLDER%\poppler-qt5\include\poppler\qt5"
4661 set POPPLER_LIB="%APPVEYOR_BUILD_FOLDER%\poppler-qt5"
4762 lrelease engauge.pro
48 qmake engauge.pro "CONFIG+=%ENGAUGE_CONFIG%"
63 qmake engauge.pro "CONFIG+=%ENGAUGE_CONFIG%" "DEFINES+=WIN_RELEASE"
4964 rem move Makefile Makefile.orig
5065 rem ps: gc Makefile.orig | %{ $_ -replace '551.lib', %QTLIBEXT% } > Makefile
66 if "%ARG1%" neq "norelease" (
67 nmake clean
68 )
5169 nmake
5270
5371 cd "%APPVEYOR_BUILD_FOLDER%"
54 mkdir "%RESULTDIR%"\documentation
55 for %%I in (%QTDIRS%) do mkdir "%RESULTDIR%\%%I"
72 if not exist "%RESULTDIR%"\documentation mkdir "%RESULTDIR%"\documentation
73 for %%I in (%QTDIRS%) do (
74 if not exist "%RESULTDIR%\%%I" mkdir "%RESULTDIR%\%%I"
75 )
5676 for %%I in (%QTDIRS%) do copy %QTDIR%\plugins\%%I\*.dll "%RESULTDIR%\%%I"
5777 for %%I in (%QTLIBS%) do copy %QTDIR%\bin\%%I.dll "%RESULTDIR%"
5878 del /S *d.dll
5979 copy bin\engauge.exe "%RESULTDIR%"
6080
61 copy "%LOG4CPP_HOME%\lib\log4cpp.dll" "%RESULTDIR%"
81 copy "%APPVEYOR_BUILD_FOLDER%\log4cpp_null\lib\log4cpp.dll" "%RESULTDIR%"
6282
6383 copy fftw-3.3.4-dll32\lib\libfftw3-3.dll "%RESULTDIR%"
6484 copy "%APPVEYOR_BUILD_FOLDER%"\poppler-qt5\*.dll "%RESULTDIR%"
6888 move engauge.qch "%RESULTDIR%"\documentation
6989 move engauge.qhc "%RESULTDIR%"\documentation
7090 cd ..
71 7z a "%RESULTDIR%.7z" "%RESULTDIR%"
7291
73 echo ***creating msi
74 cd "%SCRIPTDIR%"
75 findStr "char *VERSION_NUMBER" ..\..\src\util\Version.cpp
76 findStr "Version=" engauge.wxs | findStr /v InstallerVersion
77 set /p VERSION_NUMBER_CODE="If the version numbers are correct, enter the version number seen above to continue and build releases> "
92 copy "%APPVEYOR_BUILD_FOLDER%"\translations "%RESULTDIR%"
7893
79 candle engauge.wxs
80 candle WixUI_InstallDir_NoLicense.wxs
81 light.exe -ext WixUIExtension -ext WixUtilExtension engauge.wixobj WixUI_InstallDir_NoLicense.wixobj -o digit-exe-windows-32-bit-installer-%VERSION_NUMBER_CODE%.msi
94 if "%ARG1%" neq "norelease" (
95 7z a "%RESULTDIR%.7z" "%RESULTDIR%"
8296
83 echo *** creating zip
84 rem "Engauge Digitizer" in next line is needed since zip crashes on %RESULTDIR% due to the space
85 zip -r "digit-exe-windows-32-bit-without-installer-file-%VERSION_NUMBER_CODE%.zip" "Engauge Digitizer"
97 echo ***creating msi
98 cd "%SCRIPTDIR%"
99 findStr "char *VERSION_NUMBER" ..\..\src\util\Version.cpp
100 findStr "Version=" engauge.wxs | findStr /v InstallerVersion
101 set /p VERNUM="If the version numbers are correct, enter the version number seen above to continue and build releases>"
102 echo "Version number will be %VERNUM%"
103
104 candle engauge.wxs
105 candle WixUI_InstallDir_NoLicense.wxs
106 light.exe -ext WixUIExtension -ext WixUtilExtension engauge.wixobj WixUI_InstallDir_NoLicense.wixobj -o "digit-exe-windows-32-bit-installer-%VERNUM%.msi"
107
108 echo *** creating zip
109 rem "Engauge Digitizer" in next line is needed since zip crashes on %RESULTDIR% due to the space
110 zip -r "digit-exe-windows-32-bit-without-installer-file-%VERNUM%.zip" "Engauge Digitizer"
111 )
11 <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
22 <Product Name='Engauge Digitizer'
33 Manufacturer='Engauge Open Source Developers'
4 Id='C111CD75-C12E-45D2-AD60-F0DD78831DC0'
4 Id='1262BCFA-A719-4249-85CC-8C4085E08644'
55 UpgradeCode='00A6792B-65ED-4894-A48B-B95D63C62CC6'
66 Language='1033' Codepage='1252'
7 Version='8.3'>
7 Version='9.0'>
88 <Package Id='*' Keywords='Installer' Description="Engauge Digitizer Installer"
99 Comments='Engauge Digitizer is available from github.com' Manufacturer='Engauge Open Source Developers'
1010 InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
1313 # At some point, Qt may provide its own support for this format, at which point this can be skipped
1414 # 3) Add 'pdf' to the qmake command line to include support for PDF input files. Requires
1515 # 1) previous installation of the poppler-qt5 development package. Engauge has been tested with versions 0.24.5 and 0.44.0
16 # 2) POPPLER_INCLUDE environment variable pointing to directory containing Document.h
16 # 2) POPPLER_INCLUDE environment variable pointing to directory containing poppler-qt5.h
1717 # 3) POPPLER_LIB environment variable pointing to directory containing libpoppler-qt5.so
1818 # Sample command lines:
1919 # qmake CONFIG+=pdf
8585 src/Cmd/CmdCut.h \
8686 src/Cmd/CmdDelete.h \
8787 src/Cmd/CmdEditPointAxis.h \
88 src/Cmd/CmdEditPointGraph.h \
8889 src/Cmd/CmdFactory.h \
8990 src/Cmd/CmdMediator.h \
9091 src/Cmd/CmdMoveBy.h \
158159 src/DigitizeState/DigitizeStateSegment.h \
159160 src/DigitizeState/DigitizeStateSelect.h \
160161 src/Dlg/DlgAbout.h \
161 src/Dlg/DlgEditPoint.h \
162 src/Dlg/DlgEditPointAxis.h \
163 src/Dlg/DlgEditPointGraph.h \
164 src/Dlg/DlgEditPointGraphLineEdit.h \
162165 src/Dlg/DlgErrorReport.h \
163166 src/Dlg/DlgFilterCommand.h \
164167 src/Dlg/DlgFilterThread.h \
165168 src/Dlg/DlgFilterWorker.h \
166169 src/Dlg/DlgImportAdvanced.h \
170 src/Dlg/DlgImportCroppingNonPdf.h \
167171 src/Dlg/DlgRequiresTransform.h \
168172 src/Dlg/DlgSettingsAbstractBase.h \
169173 src/Dlg/DlgSettingsAxesChecker.h \
240244 src/Format/FormatDegreesMinutesSecondsNonPolarTheta.h \
241245 src/Format/FormatDegreesMinutesSecondsPolarTheta.h \
242246 src/Callback/functor.h \
247 src/Geometry/GeometryModel.h \
248 src/Geometry/GeometryStrategyAbstractBase.h \
249 src/Geometry/GeometryStrategyContext.h \
250 src/Geometry/GeometryStrategyFunctionSmooth.h \
251 src/Geometry/GeometryStrategyFunctionStraight.h \
252 src/Geometry/GeometryStrategyRelationSmooth.h \
253 src/Geometry/GeometryStrategyRelationStraight.h \
254 src/Geometry/GeometryWindow.h \
243255 src/Ghosts/GhostEllipse.h \
244256 src/Ghosts/GhostPath.h \
245257 src/Ghosts/GhostPolygon.h \
246258 src/Ghosts/Ghosts.h \
247259 src/Graphics/GraphicsArcItem.h \
260 src/Graphics/GraphicsItemsExtractor.h \
248261 src/Graphics/GraphicsItemType.h \
249262 src/Graphics/GraphicsLinesForCurve.h \
250263 src/Graphics/GraphicsLinesForCurves.h \
261274 src/Grid/GridInitializer.h \
262275 src/Grid/GridLine.h \
263276 src/Grid/GridLineFactory.h \
277 src/Grid/GridLineLimiter.h \
264278 src/Grid/GridLines.h \
265279 src/Grid/GridLineStyle.h \
266280 src/Grid/GridRemoval.h \
267281 src/Help/HelpBrowser.h \
268282 src/Help/HelpWindow.h \
283 src/Import/ImportCropping.h \
284 src/Import/ImportCroppingUtilBase.h \
285 src/Import/ImportCroppingUtilNonPdf.h \
269286 src/Line/LineStyle.h \
270287 src/Load/LoadFileInfo.h \
271288 src/Load/LoadImageFromUrl.h \
278295 src/Mime/MimePoints.h \
279296 src/util/mmsubs.h \
280297 src/Network/NetworkClient.h \
298 src/NonPdf/NonPdf.h \
299 src/NonPdf/NonPdfCropping.h \
300 src/NonPdf/NonPdfFrameHandle.h \
281301 src/Ordinal/OrdinalGenerator.h \
282302 src/Ordinal/OrdinalToGraphicsPoint.h \
283303 src/Pdf/PdfResolution.h \
379399 src/Cmd/CmdCut.cpp \
380400 src/Cmd/CmdDelete.cpp \
381401 src/Cmd/CmdEditPointAxis.cpp \
402 src/Cmd/CmdEditPointGraph.cpp \
382403 src/Cmd/CmdFactory.cpp \
383404 src/Cmd/CmdMediator.cpp \
384405 src/Cmd/CmdMoveBy.cpp \
449470 src/DigitizeState/DigitizeStateSegment.cpp \
450471 src/DigitizeState/DigitizeStateSelect.cpp \
451472 src/Dlg/DlgAbout.cpp \
452 src/Dlg/DlgEditPoint.cpp \
473 src/Dlg/DlgEditPointAxis.cpp \
474 src/Dlg/DlgEditPointGraph.cpp \
475 src/Dlg/DlgEditPointGraphLineEdit.cpp \
453476 src/Dlg/DlgErrorReport.cpp \
454477 src/Dlg/DlgFilterCommand.cpp \
455478 src/Dlg/DlgFilterThread.cpp \
456479 src/Dlg/DlgFilterWorker.cpp \
457480 src/Dlg/DlgImportAdvanced.cpp \
481 src/Dlg/DlgImportCroppingNonPdf.cpp \
458482 src/Dlg/DlgRequiresTransform.cpp \
459483 src/Dlg/DlgSettingsAbstractBase.cpp \
460484 src/Dlg/DlgSettingsAxesChecker.cpp \
524548 src/Format/FormatDegreesMinutesSecondsBase.cpp \
525549 src/Format/FormatDegreesMinutesSecondsNonPolarTheta.cpp \
526550 src/Format/FormatDegreesMinutesSecondsPolarTheta.cpp \
551 src/Geometry/GeometryModel.cpp \
552 src/Geometry/GeometryStrategyAbstractBase.cpp \
553 src/Geometry/GeometryStrategyContext.cpp \
554 src/Geometry/GeometryStrategyFunctionSmooth.cpp \
555 src/Geometry/GeometryStrategyFunctionStraight.cpp \
556 src/Geometry/GeometryStrategyRelationSmooth.cpp \
557 src/Geometry/GeometryStrategyRelationStraight.cpp \
558 src/Geometry/GeometryWindow.cpp \
527559 src/Ghosts/GhostEllipse.cpp \
528560 src/Ghosts/GhostPath.cpp \
529561 src/Ghosts/GhostPolygon.cpp \
530562 src/Ghosts/Ghosts.cpp \
531563 src/Graphics/GraphicsArcItem.cpp \
564 src/Graphics/GraphicsItemsExtractor.cpp \
532565 src/Graphics/GraphicsLinesForCurve.cpp \
533566 src/Graphics/GraphicsLinesForCurves.cpp \
534567 src/Graphics/GraphicsPoint.cpp \
544577 src/Grid/GridInitializer.cpp \
545578 src/Grid/GridLine.cpp \
546579 src/Grid/GridLineFactory.cpp \
580 src/Grid/GridLineLimiter.cpp \
547581 src/Grid/GridLines.cpp \
548582 src/Grid/GridRemoval.cpp \
549583 src/Help/HelpBrowser.cpp \
550584 src/Help/HelpWindow.cpp \
585 src/Import/ImportCroppingUtilBase.cpp \
586 src/Import/ImportCroppingUtilNonPdf.cpp \
551587 src/Line/LineStyle.cpp \
552588 src/Load/LoadFileInfo.cpp \
553589 src/Load/LoadImageFromUrl.cpp \
560596 src/Mime/MimePoints.cpp \
561597 src/util/mmsubs.cpp \
562598 src/Network/NetworkClient.cpp \
599 src/NonPdf/NonPdf.cpp \
600 src/NonPdf/NonPdfCropping.cpp \
601 src/NonPdf/NonPdfFrameHandle.cpp \
563602 src/Ordinal/OrdinalGenerator.cpp \
564603 src/Pdf/PdfResolution.cpp \
565604 src/Point/Point.cpp \
676715 src/FileCmd \
677716 src/Filter \
678717 src/Format \
718 src/Geometry \
679719 src/Ghosts \
680720 src/Graphics \
681721 src/Grid \
682722 src/Help \
683723 src/img \
724 src/Import \
684725 src/include \
685726 src/Line \
686727 src/Load \
688729 src/main \
689730 src/Mime \
690731 src/Network \
732 src/NonPdf \
691733 src/Ordinal \
692734 src/Pdf \
693735 src/Plot \
761803 DEFINES += "ENGAUGE_PDF"
762804 LIBS += -L$$(POPPLER_LIB) -lpoppler-qt5
763805 INCLUDEPATH += $$(POPPLER_INCLUDE)
764 HEADERS += src/Dlg/DlgPdfFrame.h \
806 HEADERS += src/Dlg/DlgImportCroppingPdf.h \
807 src/Import/ImportCroppingUtilPdf.h \
765808 src/Pdf/Pdf.h \
766 src/Pdf/PdfFrame.h \
809 src/Pdf/PdfCropping.h \
767810 src/Pdf/PdfFrameHandle.h
768 SOURCES += src/Dlg/DlgPdfFrame.cpp \
811 SOURCES += src/Dlg/DlgImportCroppingPdf.cpp \
812 src/Import/ImportCroppingUtilPdf.cpp \
769813 src/Pdf/Pdf.cpp \
770 src/Pdf/PdfFrame.cpp \
814 src/Pdf/PdfCropping.cpp \
771815 src/Pdf/PdfFrameHandle.cpp
772816
773817 } else {
0 engauge.qch
0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
1 <HTML>
2 <HEAD>
3 <TITLE>Engauge Digitizer - Discretizing</TITLE>
4 <META NAME="keywords" CONTENT="Engauge Digitizer, browser based documentation, online manual, selection, issue, problem">
5 <META NAME="description" CONTENT="Selecting Points">
6 </HEAD>
7 <BODY>
8 <H2>
9 <A HREF="index.html">
10 <IMG SRC="animation.png" ALIGN=MIDDLE ALT="" STYLE="border: 0px"></A>
11 Engauge Digitizer - Selecting Points</H2>
12 <HR WIDTH="100%">
13 <H2>Selecting one or more points</H2>
14 <P>To select one or more axis or graph points using the Select Tool, either one of the following options can be used:</P>
15 <OL>
16 <LI>Option 1 - Left click on one axis or curve point, and then release the mouse button</LI>
17 <LI>Option 2- Left click and then drag to select all curve points within the rectangular box, and then release the mouse button</LI>
18 </OL>
19 <P>If successful, the result should be one or more selected points. Each selected point will have a dashed square
20 around it.</P>
21 <H2>Editing one or more points</H2>
22 <P>To edit one or more axis or graph points, the following steps are required:</P>
23 <OL>
24 <LI>Step 1 - Select the desired point(s) using the Select Tool (see above)</LI>
25 <LI>Step 2 - Right click on one of the selected points</LI>
26 </OL>
27 <P>Note:</P>
28 <UL>
29 <LI>Axis and graph points cannot be edited at the same time, and must be edited separately.</LI>
30 <LI>Right clicking on an unselected point will have no effect</LI>
31 <LI>Double clicking on any point will have no effect</LI>
32 </BODY>
33 </HTML>
2727 </section>
2828 <section title="Answers for users who are having problems">
2929 <section title="What happened to my image?" ref="answerdiscretizing.html"></section>
30 <section title="Why am I unable to select or edit a point?" ref="answerselecting.html"></section>
3031 <section title="The coordinates are wrong, how do I fix them?" ref="fixingaxispoints.html"></section>
3132 </section>
3233 </toc>
4243 <keyword name="Multiple coordinate systems" ref="answermultiplecoordsystems.html"/>
4344 <keyword name="Point graph" ref="answerpointgraph.html"/>
4445 <keyword name="Select mode" ref="answerselectmode.html"/>
46 <keyword name="Selecting" ref="answerselecting.html"/>
4547 </keywords>
4648 <files>
4749 <file>animation.png</file>
5355 <file>answerother.html</file>
5456 <file>answerout.html</file>
5557 <file>answerpointgraph.html</file>
58 <file>answerselecting.html</file>
5659 <file>answerselectmode.html</file>
5760 <file>betteraccuracy.html</file>
5861 <file>commandlineoptions.html</file>
119119 if (anyPointsRepeatPair (m_screenInputs)) {
120120
121121 m_isError = true;
122 m_errorMessage = QObject::tr ("New axis point cannot be at the same screen position as an exisiting axis point");
122 m_errorMessage = QObject::tr ("New axis point cannot be at the same screen position as an existing axis point");
123123 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
124124
125125 } else if (anyPointsRepeatPair (m_graphOutputs)) {
213213 anyPointsRepeatPair (m_screenInputsY)) {
214214
215215 m_isError = true;
216 m_errorMessage = QObject::tr ("New axis point cannot be at the same screen position as an exisiting axis point");
216 m_errorMessage = QObject::tr ("New axis point cannot be at the same screen position as an existing axis point");
217217 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
218218
219219 } else if (anyPointsRepeatSingle (m_graphOutputsX) ||
77 #include "DataKey.h"
88 #include "Document.h"
99 #include "EngaugeAssert.h"
10 #include "GeometryWindow.h"
1011 #include "GraphicsLinesForCurves.h"
1112 #include "GraphicsScene.h"
1213 #include "Point.h"
1415
1516 CallbackSceneUpdateAfterCommand::CallbackSceneUpdateAfterCommand(GraphicsLinesForCurves &graphicsLinesForCurves,
1617 GraphicsScene &scene,
17 const Document &document) :
18 const Document &document,
19 GeometryWindow *geometryWindow) :
1820 m_graphicsLinesForCurves (graphicsLinesForCurves),
1921 m_scene (scene),
20 m_document (document)
22 m_document (document),
23 m_geometryWindow (geometryWindow)
2124 {
2225 }
2326
2932 m_graphicsLinesForCurves.updateAfterCommand (m_scene,
3033 m_document.modelCurveStyles (),
3134 curveName,
32 point);
35 point,
36 m_geometryWindow);
3337
3438 return rtn;
3539 }
1010 #include "PointStyle.h"
1111
1212 class Document;
13 class GeometryWindow;
1314 class GraphicsLinesForCurves;
1415 class GraphicsScene;
1516 class Point;
2122 /// Single constructor.
2223 CallbackSceneUpdateAfterCommand(GraphicsLinesForCurves &graphicsLinesForCurves,
2324 GraphicsScene &scene,
24 const Document &document);
25 const Document &document,
26 GeometryWindow *geometryWindow);
2527
2628 /// Callback method.
2729 CallbackSearchReturn callback (const QString & /* curveName */,
3335 GraphicsLinesForCurves &m_graphicsLinesForCurves;
3436 GraphicsScene &m_scene;
3537 const Document &m_document;
38 GeometryWindow *m_geometryWindow;
3639 };
3740
3841 #endif // CALLBACK_SCENE_UPDATE_AFTER_COMMAND_H
226226 GridLineFactory factory (m_scene,
227227 pointRadius,
228228 points,
229 modelCoords,
230 transformation);
231 m_gridLines.add (factory.createGridLine (xFrom, yFrom, xFrom, yTo ));
232 m_gridLines.add (factory.createGridLine (xFrom, yTo , xTo , yTo ));
233 m_gridLines.add (factory.createGridLine (xTo , yTo , xTo , yFrom));
234 m_gridLines.add (factory.createGridLine (xTo , yFrom, xFrom, yFrom));
229 modelCoords);
230 m_gridLines.add (factory.createGridLine (xFrom, yFrom, xFrom, yTo , transformation));
231 m_gridLines.add (factory.createGridLine (xFrom, yTo , xTo , yTo , transformation));
232 m_gridLines.add (factory.createGridLine (xTo , yTo , xTo , yFrom, transformation));
233 m_gridLines.add (factory.createGridLine (xTo , yFrom, xFrom, yFrom, transformation));
235234
236235 updateModelAxesChecker (modelAxesChecker);
237236 }
88
99 #include "CmdPointChangeBase.h"
1010 #include <QPointF>
11 #include <QString>
1112
1213 class QXmlStreamReader;
1314
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "CmdEditPointGraph.h"
7 #include "Document.h"
8 #include "DocumentSerialize.h"
9 #include "EngaugeAssert.h"
10 #include "Logger.h"
11 #include "MainWindow.h"
12 #include <QTextStream>
13 #include "QtToString.h"
14 #include <QXmlStreamReader>
15 #include "Xml.h"
16
17 const QString CMD_DESCRIPTION ("Edit curve points");
18
19 CmdEditPointGraph::CmdEditPointGraph (MainWindow &mainWindow,
20 Document &document,
21 const QStringList &pointIdentifiers,
22 bool isX,
23 bool isY,
24 double x,
25 double y) :
26 CmdPointChangeBase (mainWindow,
27 document,
28 CMD_DESCRIPTION),
29 m_pointIdentifiers (pointIdentifiers),
30 m_isX (isX),
31 m_isY (isY),
32 m_x (x),
33 m_y (y)
34 {
35 LOG4CPP_INFO_S ((*mainCat)) << "CmdEditPointGraph::CmdEditPointGraph point="
36 << pointIdentifiers.join(" ").toLatin1 ().data ()
37 << " x=" << (m_isX ? QString::number (x).toLatin1().data() : "")
38 << " y=" << (m_isY ? QString::number (y).toLatin1().data() : "");
39 }
40
41 CmdEditPointGraph::CmdEditPointGraph (MainWindow &mainWindow,
42 Document &document,
43 const QString &cmdDescription,
44 QXmlStreamReader &reader) :
45 CmdPointChangeBase (mainWindow,
46 document,
47 cmdDescription)
48 {
49 LOG4CPP_INFO_S ((*mainCat)) << "CmdEditPointGraph::CmdEditPointGraph";
50
51 QXmlStreamAttributes attributes = reader.attributes();
52
53 if (!attributes.hasAttribute(DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_X) ||
54 !attributes.hasAttribute(DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_Y) ||
55 !attributes.hasAttribute(DOCUMENT_SERIALIZE_EDIT_GRAPH_X) ||
56 !attributes.hasAttribute(DOCUMENT_SERIALIZE_EDIT_GRAPH_Y) ) {
57 xmlExitWithError (reader,
58 QString ("%1 %2, %3, %4 %5 %6")
59 .arg (QObject::tr ("Missing attribute(s)"))
60 .arg (DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_X)
61 .arg (DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_Y)
62 .arg (DOCUMENT_SERIALIZE_EDIT_GRAPH_X)
63 .arg (QObject::tr ("and/or"))
64 .arg (DOCUMENT_SERIALIZE_EDIT_GRAPH_Y));
65 } else {
66
67 // Boolean attributes
68 QString isX = attributes.value(DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_X).toString();
69 QString isY = attributes.value(DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_Y).toString();
70
71 m_isX = (isX == DOCUMENT_SERIALIZE_BOOL_TRUE);
72 m_isY = (isY == DOCUMENT_SERIALIZE_BOOL_TRUE);
73 m_x = attributes.value(DOCUMENT_SERIALIZE_EDIT_GRAPH_X).toDouble();
74 m_y = attributes.value(DOCUMENT_SERIALIZE_EDIT_GRAPH_Y).toDouble();
75
76 bool success = true;
77 while (loadNextFromReader (reader)) {
78
79 if (reader.atEnd() || reader.hasError ()) {
80 success = false;
81 break;
82 }
83
84 if ((reader.tokenType() == QXmlStreamReader::EndElement) &
85 (reader.name() == DOCUMENT_SERIALIZE_CMD)) {
86 break;
87 }
88
89 // Not done yet
90 if ((reader.tokenType() == QXmlStreamReader::StartElement) &&
91 (reader.name() == DOCUMENT_SERIALIZE_POINT)) {
92
93 // This is an entry that we need to add
94 QXmlStreamAttributes attributes = reader.attributes ();
95
96 if (attributes.hasAttribute(DOCUMENT_SERIALIZE_IDENTIFIER)) {
97
98 m_pointIdentifiers << attributes.value(DOCUMENT_SERIALIZE_IDENTIFIER).toString();
99 }
100 }
101 }
102
103 if (!success) {
104 reader.raiseError (QObject::tr ("Cannot read graph points"));
105 }
106 }
107 }
108
109 CmdEditPointGraph::~CmdEditPointGraph ()
110 {
111 }
112
113 void CmdEditPointGraph::cmdRedo ()
114 {
115 LOG4CPP_INFO_S ((*mainCat)) << "CmdEditPointGraph::cmdRedo";
116
117 saveOrCheckPreCommandDocumentStateHash (document ());
118 saveDocumentState (document ());
119 document().editPointGraph (m_isX,
120 m_isY,
121 m_x,
122 m_y,
123 m_pointIdentifiers,
124 mainWindow().transformation());
125 document().updatePointOrdinals (mainWindow().transformation());
126 mainWindow().updateAfterCommand();
127 saveOrCheckPostCommandDocumentStateHash (document ());
128 }
129
130 void CmdEditPointGraph::cmdUndo ()
131 {
132 LOG4CPP_INFO_S ((*mainCat)) << "CmdEditPointGraph::cmdUndo";
133
134 saveOrCheckPostCommandDocumentStateHash (document ());
135 restoreDocumentState (document ());
136 mainWindow().updateAfterCommand();
137 saveOrCheckPreCommandDocumentStateHash (document ());
138 }
139
140 void CmdEditPointGraph::saveXml (QXmlStreamWriter &writer) const
141 {
142 writer.writeStartElement(DOCUMENT_SERIALIZE_CMD);
143 writer.writeAttribute(DOCUMENT_SERIALIZE_CMD_TYPE, DOCUMENT_SERIALIZE_CMD_EDIT_POINT_GRAPH);
144 writer.writeAttribute(DOCUMENT_SERIALIZE_CMD_DESCRIPTION, QUndoCommand::text ());
145 writer.writeAttribute(DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_X, m_isX ?
146 DOCUMENT_SERIALIZE_BOOL_TRUE :
147 DOCUMENT_SERIALIZE_BOOL_FALSE);
148 writer.writeAttribute(DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_Y, m_isY ?
149 DOCUMENT_SERIALIZE_BOOL_TRUE :
150 DOCUMENT_SERIALIZE_BOOL_FALSE);
151 writer.writeAttribute(DOCUMENT_SERIALIZE_EDIT_GRAPH_X, QString::number (m_x));
152 writer.writeAttribute(DOCUMENT_SERIALIZE_EDIT_GRAPH_Y, QString::number (m_y));
153
154 for (int index = 0; index < m_pointIdentifiers.count(); index++) {
155
156 writer.writeStartElement (DOCUMENT_SERIALIZE_POINT);
157 writer.writeAttribute(DOCUMENT_SERIALIZE_IDENTIFIER, m_pointIdentifiers.at (index));
158 writer.writeEndElement();
159 }
160 writer.writeEndElement();
161 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef CMD_EDIT_POINT_GRAPH_H
7 #define CMD_EDIT_POINT_GRAPH_H
8
9 #include "CmdPointChangeBase.h"
10 #include <QPointF>
11 #include <QStringList>
12
13 class QXmlStreamReader;
14
15 /// Command for editing the graph coordinates of one or more graph points. The screen coordinates are
16 /// handled by another command
17 class CmdEditPointGraph : public CmdPointChangeBase
18 {
19 public:
20 /// Constructor for normal creation
21 CmdEditPointGraph(MainWindow &mainWindow,
22 Document &document,
23 const QStringList &pointIdentifiers,
24 bool isX,
25 bool isY,
26 double x,
27 double y);
28
29 /// Constructor for parsing error report file xml
30 CmdEditPointGraph(MainWindow &mainWindow,
31 Document &document,
32 const QString &cmdDescription,
33 QXmlStreamReader &reader);
34
35 virtual ~CmdEditPointGraph();
36
37 virtual void cmdRedo ();
38 virtual void cmdUndo ();
39 virtual void saveXml (QXmlStreamWriter &writer) const;
40
41 private:
42 CmdEditPointGraph();
43
44 QStringList m_pointIdentifiers;
45 bool m_isX;
46 bool m_isY;
47 double m_x;
48 double m_y;
49 };
50
51 #endif // CMD_EDIT_POINT_GRAPH_H
1111 #include "CmdCut.h"
1212 #include "CmdDelete.h"
1313 #include "CmdEditPointAxis.h"
14 #include "CmdEditPointGraph.h"
1415 #include "CmdFactory.h"
1516 #include "CmdMoveBy.h"
1617 #include "CmdPaste.h"
9192 document,
9293 cmdDescription,
9394 reader);
95 } else if (cmdType == DOCUMENT_SERIALIZE_CMD_EDIT_POINT_GRAPH) {
96 cmd = new CmdEditPointGraph (mainWindow,
97 document,
98 cmdDescription,
99 reader);
94100 } else if (cmdType == DOCUMENT_SERIALIZE_CMD_MOVE_BY) {
95101 cmd = new CmdMoveBy (mainWindow,
96102 document,
173173 {
174174 if (m_strategies.contains (colorFilterMode)) {
175175
176 return m_strategies [colorFilterMode]->pixelToZeroToOne (pixel,
177 rgbBackground);
176 // Ignore false positive cmake compiler warning about -Wreturn-stack-address in next line (bug #26396)
177 const ColorFilterStrategyAbstractBase *strategy = m_strategies [colorFilterMode];
178 return strategy->pixelToZeroToOne (pixel,
179 rgbBackground);
178180
179181 } else {
180182
189191 {
190192 if (m_strategies.contains (colorFilterMode)) {
191193
192 return m_strategies [colorFilterMode]->zeroToOneToValue (s);
194 const ColorFilterStrategyAbstractBase *strategy = m_strategies [colorFilterMode];
195 return strategy->zeroToOneToValue (s);
193196
194197 } else {
195198
135135 double ColorFilterSettings::high () const
136136 {
137137 if (m_strategies.contains (m_colorFilterMode)) {
138 return m_strategies [m_colorFilterMode]->high (*this);
138
139 // Ignore false positive cmake compiler warning about -Wreturn-stack-address in next line (bug #26396)
140 const ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies.value (m_colorFilterMode);
141 return strategy->high (*this);
139142 } else {
140143 ENGAUGE_ASSERT (false);
141144 return m_strategies [COLOR_FILTER_MODE_INTENSITY]->high (*this);
214217 double ColorFilterSettings::low () const
215218 {
216219 if (m_strategies.contains (m_colorFilterMode)) {
217 return m_strategies [m_colorFilterMode]->low (*this);
220 const ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies.value (m_colorFilterMode);
221 return strategy->low (*this);
218222 } else {
219223 ENGAUGE_ASSERT (false);
220224 return m_strategies [COLOR_FILTER_MODE_INTENSITY]->low (*this);
229233 indentation += INDENTATION_DELTA;
230234
231235 if (m_strategies.contains (m_colorFilterMode)) {
232 return m_strategies [m_colorFilterMode]->printStream (*this,
233 indentation,
234 str);
236 const ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies.value (m_colorFilterMode);
237 return strategy->printStream (*this,
238 indentation,
239 str);
235240 }
236241 }
237242
287292 void ColorFilterSettings::setHigh (double s0To1)
288293 {
289294 if (m_strategies.contains (m_colorFilterMode)) {
290 return m_strategies [m_colorFilterMode]->setHigh (*this,
291 s0To1);
295 ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies [m_colorFilterMode];
296 return strategy->setHigh (*this,
297 s0To1);
292298 } else {
293299 ENGAUGE_ASSERT (false);
294300 }
321327 void ColorFilterSettings::setLow (double s0To1)
322328 {
323329 if (m_strategies.contains (m_colorFilterMode)) {
324 return m_strategies [m_colorFilterMode]->setLow (*this,
325 s0To1);
330 ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies [m_colorFilterMode];
331 return strategy->setLow (*this,
332 s0To1);
326333 } else {
327334 ENGAUGE_ASSERT (false);
328335 }
264264 void CoordSystem::editPointAxis (const QPointF &posGraph,
265265 const QString &identifier)
266266 {
267 LOG4CPP_INFO_S ((*mainCat)) << "CoordSystem::editPointAxis posGraph=("
268 << posGraph.x () << ", " << posGraph.y () << ") identifier="
269 << identifier.toLatin1 ().data ();
270
271 m_curveAxes->editPoint (posGraph,
272 identifier);
267 LOG4CPP_INFO_S ((*mainCat)) << "CoordSystem::editPointAxis"
268 << " posGraph=(" << posGraph.x () << ", " << posGraph.y () << ") identifier="
269 << " identifier=" << identifier.toLatin1 ().data ();
270
271 m_curveAxes->editPointAxis (posGraph,
272 identifier);
273 }
274
275 void CoordSystem::editPointGraph (bool isX,
276 bool isY,
277 double x,
278 double y,
279 const QStringList &identifiers,
280 const Transformation &transformation)
281 {
282 LOG4CPP_INFO_S ((*mainCat)) << "CoordSystem::editPointGraph posGraph=("
283 << " x=" << (isX ? QString::number (x).toLatin1().data() : "")
284 << " y=" << (isY ? QString::number (y).toLatin1().data() : "")
285 << ") identifiers=" << identifiers.join(" ").toLatin1 ().data ();
286
287 m_curvesGraphs.editPointGraph (isX,
288 isY,
289 x,
290 y,
291 identifiers,
292 transformation);
273293 }
274294
275295 bool CoordSystem::isXOnly (const QString &pointIdentifier) const
2424 #include <QList>
2525 #include <QPixmap>
2626 #include <QString>
27 #include <QStringList>
2728 #include <QXmlStreamReader>
2829
2930 class Curve;
8485 virtual int curvesGraphsNumPoints (const QString &curveName) const;
8586 virtual void editPointAxis (const QPointF &posGraph,
8687 const QString &identifier);
88 virtual void editPointGraph (bool isX,
89 bool isY,
90 double x,
91 double y,
92 const QStringList &identifiers,
93 const Transformation &transformation);
8794
8895 /// Return true if y coordinate is undefined, otherwise x coordinae is undefined in DOCUMENT_AXES_POINT_REQUIRE_4 mode.
8996 /// Applies to axes points only
208208 identifier);
209209 }
210210
211 void CoordSystemContext::editPointGraph (bool isX,
212 bool isY,
213 double x,
214 double y,
215 const QStringList &identifiers,
216 const Transformation &transformation)
217 {
218 LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::editPointGraph";
219
220 m_coordSystems [m_coordSystemIndex]->editPointGraph (isX,
221 isY,
222 x,
223 y,
224 identifiers,
225 transformation);
226 }
227
211228 bool CoordSystemContext::isXOnly (const QString &pointIdentifier) const
212229 {
213230 LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::isXOnly";
8080 virtual int curvesGraphsNumPoints (const QString &curveName) const;
8181 virtual void editPointAxis (const QPointF &posGraph,
8282 const QString &identifier);
83 virtual void editPointGraph (bool isX,
84 bool isY,
85 double x,
86 double y,
87 const QStringList &identifiers,
88 const Transformation &transformation);
8389
8490 /// True/false if y/x value is empty
8591 bool isXOnly (const QString &pointIdentifier) const;
114114 virtual void editPointAxis (const QPointF &posGraph,
115115 const QString &identifier) = 0;
116116
117 /// Edit the graph coordinates of one or more graph points
118 virtual void editPointGraph (bool isX,
119 bool isY,
120 double x,
121 double y,
122 const QStringList &identifiers,
123 const Transformation &transformation) = 0;
124
117125 /// See Curve::iterateThroughCurvePoints, for the axes curve.
118126 virtual void iterateThroughCurvePointsAxes (const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback) = 0;
119127
140140 return m_curveStyle;
141141 }
142142
143 void Curve::editPoint (const QPointF &posGraph,
144 const QString &identifier)
143 void Curve::editPointAxis (const QPointF &posGraph,
144 const QString &identifier)
145145 {
146146 // Search for the point with matching identifier
147147 QList<Point>::iterator itr;
153153 point.setPosGraph (posGraph);
154154 break;
155155
156 }
157 }
158 }
159
160 void Curve::editPointGraph (bool isX,
161 bool isY,
162 double x,
163 double y,
164 const QStringList &identifiers,
165 const Transformation &transformation)
166 {
167 LOG4CPP_INFO_S ((*mainCat)) << "Curve::editPointGraph"
168 << " identifiers=" << identifiers.join(" ").toLatin1().data();
169
170 if (transformation.transformIsDefined()) {
171
172 // Search for the point with matching identifier
173 QList<Point>::iterator itr;
174 for (itr = m_points.begin(); itr != m_points.end(); itr++) {
175
176 Point &point = *itr;
177
178 if (identifiers.contains (point.identifier ())) {
179
180 // Although one or more graph coordinates are specified, it is the screen coordinates that must be
181 // moved. This is because only the screen coordinates of the graph points are tracked (not the graph coordinates).
182 // So we compute posScreen and call Point::setPosScreen instead of Point::setPosGraph
183
184 // Get original graph coordinates
185 QPointF posScreen = point.posScreen ();
186 QPointF posGraph;
187 transformation.transformScreenToRawGraph (posScreen,
188 posGraph);
189
190 // Override one or both coordinates
191 if (isX) {
192 posGraph.setX (x);
193 }
194
195 if (isY) {
196 posGraph.setY (y);
197 }
198
199 // Set the screen coordinates
200 transformation.transformRawGraphToScreen(posGraph,
201 posScreen);
202
203 point.setPosScreen (posScreen);
204 }
156205 }
157206 }
158207 }
6161 CurveStyle curveStyle() const;
6262
6363 /// Edit the graph coordinates of an axis point. This method does not apply to a graph point
64 void editPoint (const QPointF &posGraph,
65 const QString &identifier);
64 void editPointAxis (const QPointF &posGraph,
65 const QString &identifier);
66
67 /// Edit the graph coordinates of one or more graph points. This method does not apply to an axis point
68 void editPointGraph (bool isX,
69 bool isY,
70 double x,
71 double y,
72 const QStringList &identifiers,
73 const Transformation &transformation);
6674
6775 /// Export points in this Curve found in the specified point list.
6876 void exportToClipboard (const QHash<QString, bool> &selectedHash,
9292 return 0;
9393 }
9494
95 void CurvesGraphs::editPointGraph (bool isX,
96 bool isY,
97 double x,
98 double y,
99 const QStringList &identifiers,
100 const Transformation &transformation)
101 {
102 CurveList::iterator itr;
103 for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
104
105 Curve &curve = *itr;
106 curve.editPointGraph (isX,
107 isY,
108 x,
109 y,
110 identifiers,
111 transformation);
112 }
113 }
114
95115 void CurvesGraphs::iterateThroughCurvePoints (const QString &curveNameWanted,
96116 const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback)
97117 {
4343 /// Point count.
4444 int curvesGraphsNumPoints (const QString &curveName) const;
4545
46 /// Set the x and/or y coordinate values of the specified points
47 void editPointGraph (bool isX,
48 bool isY,
49 double x,
50 double y,
51 const QStringList &identifiers,
52 const Transformation &transformation);
53
4654 /// Apply functor to Points in the specified axis or graph Curve.
4755 void iterateThroughCurvePoints (const QString &curveNameWanted,
4856 const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback);
33 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
44 ******************************************************************************************************/
55
6 #include "CmdEditPointAxis.h"
76 #include "CmdMediator.h"
87 #include "DigitizeStateAbstractBase.h"
98 #include "DigitizeStateContext.h"
10 #include "DlgEditPoint.h"
119 #include "Document.h"
1210 #include "Logger.h"
1311 #include "MainWindow.h"
14 #include <QApplication>
12 #include "MainWindowModel.h"
13 #include <QCursor>
1514 #include <QGraphicsScene>
1615 #include <QImage>
17 #include <QMessageBox>
1816 #include <QTimer>
1917 #include "QtToString.h"
20 #include "Version.h"
18 #include "Transformation.h"
2119
2220 DigitizeStateAbstractBase::DigitizeStateAbstractBase(DigitizeStateContext &context) :
23 m_context (context),
24 m_isOverrideCursor (false)
21 m_context (context)
2522 {
2623 }
2724
3936 return m_context;
4037 }
4138
42 void DigitizeStateAbstractBase::handleContextMenuEvent (CmdMediator *cmdMediator,
43 const QString &pointIdentifier)
44 {
45 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateAbstractBase::handleContextMenuEvent point=" << pointIdentifier.toLatin1 ().data ();
46
47 QPointF posScreen = cmdMediator->document().positionScreen (pointIdentifier);
48 QPointF posGraphBefore = cmdMediator->document().positionGraph (pointIdentifier);
49 bool isXOnly = cmdMediator->document().isXOnly (pointIdentifier);
50
51 // Ask user for coordinates
52 double x = posGraphBefore.x();
53 double y = posGraphBefore.y();
54
55 DlgEditPoint *dlg = new DlgEditPoint(context().mainWindow(),
56 *this,
57 cmdMediator->document().modelCoords(),
58 context().mainWindow().modelMainWindow(),
59 cursor (cmdMediator),
60 context().mainWindow().transformation(),
61 cmdMediator->document().documentAxesPointsRequired(),
62 isXOnly,
63 &x,
64 &y);
65 int rtn = dlg->exec ();
66
67 QPointF posGraphAfter = dlg->posGraph (isXOnly); // This call returns new values for isXOnly and the graph position
68 delete dlg;
69
70 if (rtn == QDialog::Accepted) {
71
72 // User wants to edit this axis point, but let's perform sanity checks first
73
74 bool isError;
75 QString errorMessage;
76
77 context().mainWindow().cmdMediator()->document().checkEditPointAxis(pointIdentifier,
78 posScreen,
79 posGraphAfter,
80 isError,
81 errorMessage);
82
83 if (isError) {
84
85 QMessageBox::warning (0,
86 engaugeWindowTitle(),
87 errorMessage);
88
89 } else {
90
91 // Create a command to edit the point
92 CmdEditPointAxis *cmd = new CmdEditPointAxis (context().mainWindow(),
93 cmdMediator->document(),
94 pointIdentifier,
95 posGraphBefore,
96 posGraphAfter,
97 isXOnly);
98 context().appendNewCmd(cmdMediator,
99 cmd);
100 }
101 }
102 }
103
104 void DigitizeStateAbstractBase::handleLeave (CmdMediator * /* cmdMediator */)
105 {
106 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStateAbstractBase::handleLeave";
107
108 removeOverrideCursor ();
109 }
110
111 void DigitizeStateAbstractBase::handleSetOverrideCursor (CmdMediator * /* cmdMediator */,
112 const QCursor &cursor)
113 {
114 removeOverrideCursor ();
115
116 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateAbstractBase::handleSetOverrideCursor setOverrideCursor="
117 << QtCursorToString (cursor.shape ()).toLatin1 ().data ();
118
119 QApplication::setOverrideCursor (cursor);
120 m_isOverrideCursor = true;
121 }
122
123 void DigitizeStateAbstractBase::removeOverrideCursor ()
124 {
125 if (m_isOverrideCursor) {
126
127 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateAbstractBase::handleLeave restoreOverrideCursor="
128 << QtCursorToString (QApplication::overrideCursor ()->shape ()).toLatin1 ().data ();
129
130 // Override cursor from last QDialog must be restored
131 QApplication::restoreOverrideCursor ();
132
133 m_isOverrideCursor = false;
134 }
135 }
136
13739 void DigitizeStateAbstractBase::setCursor(CmdMediator *cmdMediator)
13840 {
13941 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStateAbstractBase::setCursor";
14042
141 removeOverrideCursor ();
142 context().view().setCursor (cursor (cmdMediator));
43 // Note that we are setting the QGraphicsView cursor and NOT the QApplication override cursor
44 m_context.view ().setCursor (cursor (cmdMediator));
14345 }
1616 class DocumentModelSegments;
1717 class QGraphicsScene;
1818 class QImage;
19 class QString;
20 class QStringList;
1921 class QTimer;
2022
2123 /// Set of possible states of Digitize toolbar.
5557 /// Method that is called at the exact moment a state is exited. Typically called just before begin for the next state
5658 virtual void end() = 0;
5759
58 /// Handle a right click that was intercepted earlier. This is done in the superclass since it works the same in all states.
59 void handleContextMenuEvent (CmdMediator *cmdMediator,
60 const QString &pointIdentifier);
60 /// Handle a right click, on an axis point, that was intercepted earlier
61 virtual void handleContextMenuEventAxis (CmdMediator *cmdMediator,
62 const QString &pointIdentifier) = 0;
63
64 /// Handle a right click, on a graph point, that was intercepted earlier
65 virtual void handleContextMenuEventGraph (CmdMediator *cmdMediator,
66 const QStringList &pointIdentifiers) = 0;
6167
6268 /// Handle the selection of a new curve. At a minimum, DigitizeStateSegment will generate a new set of Segments
6369 virtual void handleCurveChange (CmdMediator *cmdMediator) = 0;
6672 virtual void handleKeyPress (CmdMediator *cmdMediator,
6773 Qt::Key key,
6874 bool atLeastOneSelectedItem) = 0;
69
70 /// Handle leave in case an override cursor is in effect from last QDialog, by resetting the override cursor.
71 virtual void handleLeave (CmdMediator *cmdMediator);
7275
7376 /// Handle a mouse move. This is part of an experiment to see if augmenting the cursor in Point Match mode is worthwhile
7477 virtual void handleMouseMove (CmdMediator *cmdMediator,
8285 virtual void handleMouseRelease (CmdMediator *cmdMediator,
8386 QPointF pos) = 0;
8487
85 /// Handle the command to set the override cursor
86 void handleSetOverrideCursor (CmdMediator *cmdMediator,
87 const QCursor &cursor);
88
89 /// Remove the override cursor if it is in use. This is called after a leave event, and prior to displaying a QDialog
90 void removeOverrideCursor ();
91
9288 /// Update the cursor according to the current state.
9389 void setCursor(CmdMediator *cmdMediator);
9490
9591 /// State name for debugging
9692 virtual QString state() const = 0;
93
94 /// Update graphics attributes after possible new points. This is useful for highlight opacity
95 virtual void updateAfterPointAddition () = 0;
9796
9897 /// Update the digitize curve settings
9998 virtual void updateModelDigitizeCurve (CmdMediator *cmdMediator,
111110
112111 DigitizeStateContext &m_context;
113112
114 bool m_isOverrideCursor; // Checking QApplication::overrideCursor()==0 is unreliable so this tracks the override cursor state
115113 };
116114
117115 #endif // DIGITIZE_STATE_ABSTRACT_BASE_H
88 #include "CursorFactory.h"
99 #include "DigitizeStateAxis.h"
1010 #include "DigitizeStateContext.h"
11 #include "DlgEditPoint.h"
11 #include "DlgEditPointAxis.h"
1212 #include "Document.h"
1313 #include "GraphicsScene.h"
1414 #include "GraphicsView.h"
4949 {
5050 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStateAxis::createTemporaryPoint";
5151
52 // Temporary point that user can see while DlgEditPoint is active
52 GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
53
54 // Temporary point that user can see while DlgEditPointAxis is active
5355 const Curve &curveAxes = cmdMediator->curveAxes();
5456 PointStyle pointStyleAxes = curveAxes.curveStyle().pointStyle();
5557 GraphicsPoint *point = context().mainWindow().scene().createPoint(Point::temporaryPointIdentifier (),
5658 pointStyleAxes,
57 posScreen);
59 posScreen,
60 NULL_GEOMETRY_WINDOW);
5861
5962 context().mainWindow().scene().addTemporaryPoint (Point::temporaryPointIdentifier(),
6063 point);
7376 void DigitizeStateAxis::end ()
7477 {
7578 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateAxis::end";
79 }
80
81 void DigitizeStateAxis::handleContextMenuEventAxis (CmdMediator * /* cmdMediator */,
82 const QString &pointIdentifier)
83 {
84 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateAxis::handleContextMenuEventAxis "
85 << " point=" << pointIdentifier.toLatin1 ().data ();
86 }
87
88 void DigitizeStateAxis::handleContextMenuEventGraph (CmdMediator * /* cmdMediator */,
89 const QStringList &pointIdentifiers)
90 {
91 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateAxis::handleContextMenuEventGraph "
92 << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
7693 }
7794
7895 void DigitizeStateAxis::handleCurveChange(CmdMediator * /* cmdMediator */)
117134 posScreen);
118135
119136 // Ask user for coordinates
120 DlgEditPoint *dlg = new DlgEditPoint (context ().mainWindow (),
121 *this,
122 cmdMediator->document().modelCoords(),
123 context().mainWindow().modelMainWindow(),
124 cursor (cmdMediator),
125 context().mainWindow().transformation(),
126 cmdMediator->document().documentAxesPointsRequired());
137 DlgEditPointAxis *dlg = new DlgEditPointAxis (context ().mainWindow (),
138 cmdMediator->document().modelCoords(),
139 context().mainWindow().modelMainWindow(),
140 context().mainWindow().transformation(),
141 cmdMediator->document().documentAxesPointsRequired());
127142 int rtn = dlg->exec ();
128143
129144 bool isXOnly;
175190 return "DigitizeStateAxis";
176191 }
177192
193 void DigitizeStateAxis::updateAfterPointAddition ()
194 {
195 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateAxis::updateAfterPointAddition";
196 }
197
178198 void DigitizeStateAxis::updateModelDigitizeCurve (CmdMediator *cmdMediator,
179199 const DocumentModelDigitizeCurve & /*modelDigitizeCurve */)
180200 {
2424 DigitizeState previousState);
2525 virtual QCursor cursor (CmdMediator *cmdMediator) const;
2626 virtual void end();
27 virtual void handleContextMenuEventAxis (CmdMediator *cmdMediator,
28 const QString &pointIdentifier);
29 virtual void handleContextMenuEventGraph (CmdMediator *cmdMediator,
30 const QStringList &pointIdentifiers);
2731 virtual void handleCurveChange(CmdMediator *cmdMediator);
2832 virtual void handleKeyPress (CmdMediator *cmdMediator,
2933 Qt::Key key,
3539 virtual void handleMouseRelease (CmdMediator *cmdMediator,
3640 QPointF posScreen);
3741 virtual QString state() const;
42 virtual void updateAfterPointAddition ();
3843 virtual void updateModelDigitizeCurve (CmdMediator *cmdMediator,
3944 const DocumentModelDigitizeCurve &modelDigitizeCurve);
4045 virtual void updateModelSegments(const DocumentModelSegments &modelSegments);
219219 return false;
220220 }
221221
222 void DigitizeStateColorPicker::handleContextMenuEventAxis (CmdMediator * /* cmdMediator */,
223 const QString &pointIdentifier)
224 {
225 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::handleContextMenuEventAxis "
226 << " point=" << pointIdentifier.toLatin1 ().data ();
227 }
228
229 void DigitizeStateColorPicker::handleContextMenuEventGraph (CmdMediator * /* cmdMediator */,
230 const QStringList &pointIdentifiers)
231 {
232 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker ::handleContextMenuEventGraph "
233 << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
234 }
235
222236 void DigitizeStateColorPicker::handleCurveChange(CmdMediator * /* cmdMediator */)
223237 {
224238 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::handleCurveChange";
320334 return "DigitizeStateColorPicker";
321335 }
322336
337 void DigitizeStateColorPicker::updateAfterPointAddition ()
338 {
339 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::updateAfterPointAddition";
340 }
341
323342 void DigitizeStateColorPicker::updateModelDigitizeCurve (CmdMediator * /* cmdMediator */,
324343 const DocumentModelDigitizeCurve & /*modelDigitizeCurve */)
325344 {
2929 DigitizeState previousState);
3030 virtual QCursor cursor (CmdMediator *cmdMediator) const;
3131 virtual void end();
32 virtual void handleContextMenuEventAxis (CmdMediator *cmdMediator,
33 const QString &pointIdentifier);
34 virtual void handleContextMenuEventGraph (CmdMediator *cmdMediator,
35 const QStringList &pointIdentifiers);
3236 virtual void handleCurveChange(CmdMediator *cmdMediator);
3337 virtual void handleKeyPress (CmdMediator *cmdMediator,
3438 Qt::Key key,
4044 virtual void handleMouseRelease (CmdMediator *cmdMediator,
4145 QPointF posScreen);
4246 virtual QString state() const;
47 virtual void updateAfterPointAddition ();
4348 virtual void updateModelDigitizeCurve (CmdMediator *cmdMediator,
4449 const DocumentModelDigitizeCurve &modelDigitizeCurve);
4550 virtual void updateModelSegments(const DocumentModelSegments &modelSegments);
1818 #include "GraphicsView.h"
1919 #include "Logger.h"
2020 #include "MainWindow.h"
21 #include <QApplication>
2221 #include <QCursor>
2322 #include <QGraphicsScene>
2423 #include <QGraphicsView>
8887 }
8988 }
9089
91 void DigitizeStateContext::handleContextMenuEvent (CmdMediator *cmdMediator,
92 const QString &pointIdentifier)
93 {
94 m_states [m_currentState]->handleContextMenuEvent (cmdMediator,
95 pointIdentifier);
90 void DigitizeStateContext::handleContextMenuEventAxis (CmdMediator *cmdMediator,
91 const QString &pointIdentifier)
92 {
93 m_states [m_currentState]->handleContextMenuEventAxis (cmdMediator,
94 pointIdentifier);
95 }
96
97 void DigitizeStateContext::handleContextMenuEventGraph (CmdMediator *cmdMediator,
98 const QStringList &pointIdentifiers)
99 {
100 m_states [m_currentState]->handleContextMenuEventGraph (cmdMediator,
101 pointIdentifiers);
96102 }
97103
98104 void DigitizeStateContext::handleCurveChange (CmdMediator *cmdMediator)
112118
113119 }
114120
115 void DigitizeStateContext::handleLeave (CmdMediator *cmdMediator)
116 {
117 m_states [m_currentState]->handleLeave (cmdMediator);
118
119 completeRequestedStateTransitionIfExists(cmdMediator);
120
121 }
122
123121 void DigitizeStateContext::handleMouseMove (CmdMediator *cmdMediator,
124122 QPointF pos)
125123 {
147145 pos);
148146
149147 completeRequestedStateTransitionIfExists(cmdMediator);
150 }
151
152 void DigitizeStateContext::handleSetOverrideCursor (CmdMediator *cmdMediator,
153 const QCursor &cursor)
154 {
155 m_states [m_currentState]->handleSetOverrideCursor (cmdMediator,
156 cursor);
157148 }
158149
159150 bool DigitizeStateContext::isGnuplot () const
229220 return m_states [m_currentState]->state();
230221 }
231222
223 void DigitizeStateContext::updateAfterPointAddition ()
224 {
225 ENGAUGE_ASSERT (m_currentState != NUM_DIGITIZE_STATES);
226
227 m_states [m_currentState]->updateAfterPointAddition ();
228 }
229
232230 void DigitizeStateContext::updateModelDigitizeCurve (CmdMediator *cmdMediator,
233231 const DocumentModelDigitizeCurve &modelDigitizeCurve)
234232 {
1717 class DocumentModelDigitizeCurve;
1818 class DocumentModelSegments;
1919 class MainWindow;
20 class MainWindowModel;
2021 class QUndoCommand;
2122
2223 /// Container for all DigitizeStateAbstractBase subclasses. This functions as the context class in a standard state machine implementation
3839 void appendNewCmd(CmdMediator *cmdMediator,
3940 QUndoCommand *cmd);
4041
41 /// See DigitizeStateAbstractBase::handleContextMenuEvent.
42 void handleContextMenuEvent (CmdMediator *cmdMediator,
43 const QString &pointIdentifier);
42 /// See DigitizeStateAbstractBase::handleContextMenuEventAxis.
43 void handleContextMenuEventAxis (CmdMediator *cmdMediator,
44 const QString &pointIdentifier);
45
46 /// See DigitizeStateAbstractBase::handleContextMenuEventGraph.
47 void handleContextMenuEventGraph (CmdMediator *cmdMediator,
48 const QStringList &pointIdentifiers);
4449
4550 /// See DigitizeStateAbstractBase::handleCurveChange.
4651 void handleCurveChange (CmdMediator *cmdMediator);
4954 void handleKeyPress (CmdMediator *cmdMediator,
5055 Qt::Key key,
5156 bool atLeastOneSelectedItem);
52
53 /// See DigitizeStateAbstractBase::handleLeave.
54 void handleLeave (CmdMediator *cmdMediator);
5557
5658 /// See DigitizeStateAbstractBase::handleMouseMove.
5759 void handleMouseMove (CmdMediator *cmdMediator,
6466 /// See DigitizeStateAbstractBase::handleMouseRelease.
6567 void handleMouseRelease (CmdMediator *cmdMediator,
6668 QPointF pos);
67
68 /// See DigitizeStateAbstractBase::handleSetOverrideCursor
69 void handleSetOverrideCursor (CmdMediator *cmdMediator,
70 const QCursor &cursor);
7169
7270 /// Get method for gnuplot flag
7371 bool isGnuplot () const;
10199 /// State name for debugging
102100 QString state() const;
103101
102 /// Update the graphics attributes
103 void updateAfterPointAddition ();
104
104105 /// Update the digitize curve settings
105106 void updateModelDigitizeCurve (CmdMediator *cmdMediator,
106107 const DocumentModelDigitizeCurve &modelDigitizeCurve);
5454 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateCurve::end";
5555 }
5656
57 void DigitizeStateCurve::handleContextMenuEventAxis (CmdMediator * /* cmdMediator */,
58 const QString &pointIdentifier)
59 {
60 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateCurve::handleContextMenuEventAxis "
61 << " point=" << pointIdentifier.toLatin1 ().data ();
62 }
63
64 void DigitizeStateCurve::handleContextMenuEventGraph (CmdMediator * /* cmdMediator */,
65 const QStringList &pointIdentifiers)
66 {
67 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateCurve ::handleContextMenuEventGraph "
68 << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
69 }
70
5771 void DigitizeStateCurve::handleCurveChange(CmdMediator * /* cmdMediator */)
5872 {
5973 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateCurve::handleCurveChange";
105119 return "DigitizeStateCurve";
106120 }
107121
122 void DigitizeStateCurve::updateAfterPointAddition ()
123 {
124 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateCurve::updateAfterPointAddition";
125 }
126
108127 void DigitizeStateCurve::updateModelDigitizeCurve (CmdMediator *cmdMediator,
109128 const DocumentModelDigitizeCurve & /*modelDigitizeCurve */)
110129 {
2121 DigitizeState previousState);
2222 virtual QCursor cursor (CmdMediator *cmdMediator) const;
2323 virtual void end();
24 virtual void handleContextMenuEventAxis (CmdMediator *cmdMediator,
25 const QString &pointIdentifier);
26 virtual void handleContextMenuEventGraph (CmdMediator *cmdMediator,
27 const QStringList &pointIdentifiers);
2428 virtual void handleCurveChange(CmdMediator *cmdMediator);
2529 virtual void handleKeyPress (CmdMediator *cmdMediator,
2630 Qt::Key key,
3236 virtual void handleMouseRelease (CmdMediator *cmdMediator,
3337 QPointF posScreen);
3438 virtual QString state() const;
39 virtual void updateAfterPointAddition ();
3540 virtual void updateModelDigitizeCurve (CmdMediator *cmdMediator,
3641 const DocumentModelDigitizeCurve &modelDigitizeCurve);
3742 virtual void updateModelSegments(const DocumentModelSegments &modelSegments);
4444 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateEmpty::end";
4545 }
4646
47 void DigitizeStateEmpty::handleContextMenuEventAxis (CmdMediator * /* cmdMediator */,
48 const QString &pointIdentifier)
49 {
50 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateEmpty::handleContextMenuEventAxis "
51 << " point=" << pointIdentifier.toLatin1 ().data ();
52 }
53
54 void DigitizeStateEmpty::handleContextMenuEventGraph (CmdMediator * /* cmdMediator */,
55 const QStringList &pointIdentifiers)
56 {
57 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateEmpty ::handleContextMenuEventGraph "
58 << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
59 }
60
4761 void DigitizeStateEmpty::handleCurveChange(CmdMediator * /* cmdMediator */)
4862 {
4963 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateEmpty::handleCurveChange";
8094 return "DigitizeStateEmpty";
8195 }
8296
97 void DigitizeStateEmpty::updateAfterPointAddition ()
98 {
99 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateEmpty::updateAfterPointAddition";
100 }
101
83102 void DigitizeStateEmpty::updateModelDigitizeCurve (CmdMediator * /* cmdMediator */,
84103 const DocumentModelDigitizeCurve & /*modelDigitizeCurve */)
85104 {
2222 virtual QCursor cursor (CmdMediator *cmdMediator) const;
2323 virtual void end();
2424 virtual void handleCurveChange(CmdMediator *cmdMediator);
25 virtual void handleContextMenuEventAxis (CmdMediator *cmdMediator,
26 const QString &pointIdentifier);
27 virtual void handleContextMenuEventGraph (CmdMediator *cmdMediator,
28 const QStringList &pointIdentifiers);
2529 virtual void handleKeyPress (CmdMediator *cmdMediator,
2630 Qt::Key key,
2731 bool atLeastOneSelectedItem);
3236 virtual void handleMouseRelease (CmdMediator *cmdMediator,
3337 QPointF posScreen);
3438 virtual QString state() const;
39 virtual void updateAfterPointAddition ();
3540 virtual void updateModelDigitizeCurve (CmdMediator *cmdMediator,
3641 const DocumentModelDigitizeCurve &modelDigitizeCurve);
3742 virtual void updateModelSegments(const DocumentModelSegments &modelSegments);
8888 {
8989 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStatePointMatch::createTemporaryPoint";
9090
91 GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
92
9193 const DocumentModelPointMatch &modelPointMatch = cmdMediator->document().modelPointMatch();
9294
9395 // Get point style for current graph, and then override with candidate color
98100 // Temporary point that user can see while DlgEditPoint is active
99101 GraphicsPoint *point = context().mainWindow().scene().createPoint(Point::temporaryPointIdentifier (),
100102 pointStyle,
101 posScreen);
103 posScreen,
104 NULL_GEOMETRY_WINDOW);
102105
103106 context().mainWindow().scene().removeTemporaryPointIfExists(); // Only one temporary point at a time is allowed
104107
164167 }
165168
166169 return samplePointPixels;
170 }
171
172 void DigitizeStatePointMatch::handleContextMenuEventAxis (CmdMediator * /* cmdMediator */,
173 const QString &pointIdentifier)
174 {
175 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleContextMenuEventAxis "
176 << " point=" << pointIdentifier.toLatin1 ().data ();
177 }
178
179 void DigitizeStatePointMatch::handleContextMenuEventGraph (CmdMediator * /* cmdMediator */,
180 const QStringList &pointIdentifiers)
181 {
182 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch ::handleContextMenuEventGraph "
183 << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
167184 }
168185
169186 void DigitizeStatePointMatch::handleCurveChange(CmdMediator * /* cmdMediator */)
337354 return "DigitizeStatePointMatch";
338355 }
339356
357 void DigitizeStatePointMatch::updateAfterPointAddition ()
358 {
359 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::updateAfterPointAddition";
360 }
361
340362 void DigitizeStatePointMatch::updateModelDigitizeCurve (CmdMediator * /* cmdMediator */,
341363 const DocumentModelDigitizeCurve & /*modelDigitizeCurve */)
342364 {
2929 DigitizeState previousState);
3030 virtual QCursor cursor (CmdMediator *cmdMediator) const;
3131 virtual void end();
32 virtual void handleContextMenuEventAxis (CmdMediator *cmdMediator,
33 const QString &pointIdentifier);
34 virtual void handleContextMenuEventGraph (CmdMediator *cmdMediator,
35 const QStringList &pointIdentifiers);
3236 virtual void handleCurveChange(CmdMediator *cmdMediator);
3337 virtual void handleKeyPress (CmdMediator *cmdMediator,
3438 Qt::Key key,
4044 virtual void handleMouseRelease (CmdMediator *cmdMediator,
4145 QPointF posScreen);
4246 virtual QString state() const;
47 virtual void updateAfterPointAddition ();
4348 virtual void updateModelDigitizeCurve (CmdMediator *cmdMediator,
4449 const DocumentModelDigitizeCurve &modelDigitizeCurve);
4550 virtual void updateModelSegments(const DocumentModelSegments &modelSegments);
6262 segmentFactory.clearSegments(m_segments);
6363 }
6464
65 void DigitizeStateSegment::handleContextMenuEventAxis (CmdMediator * /* cmdMediator */,
66 const QString &pointIdentifier)
67 {
68 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSegment::handleContextMenuEventAxis "
69 << " point=" << pointIdentifier.toLatin1 ().data ();
70 }
71
72 void DigitizeStateSegment::handleContextMenuEventGraph (CmdMediator * /* cmdMediator */,
73 const QStringList &pointIdentifiers)
74 {
75 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSegment ::handleContextMenuEventGraph "
76 << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
77 }
78
6579 void DigitizeStateSegment::handleCurveChange(CmdMediator *cmdMediator)
6680 {
6781 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSegment::handleCurveChange";
185199 return "DigitizeStateSegment";
186200 }
187201
202 void DigitizeStateSegment::updateAfterPointAddition ()
203 {
204 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSegment::updateAfterPointAddition";
205 }
206
188207 void DigitizeStateSegment::updateModelDigitizeCurve (CmdMediator * /* cmdMediator */,
189208 const DocumentModelDigitizeCurve & /*modelDigitizeCurve */)
190209 {
2727 DigitizeState previousState);
2828 virtual QCursor cursor (CmdMediator *cmdMediator) const;
2929 virtual void end();
30 virtual void handleContextMenuEventAxis (CmdMediator *cmdMediator,
31 const QString &pointIdentifier);
32 virtual void handleContextMenuEventGraph (CmdMediator *cmdMediator,
33 const QStringList &pointIdentifiers);
3034 virtual void handleCurveChange(CmdMediator *cmdMediator);
3135 virtual void handleKeyPress (CmdMediator *cmdMediator,
3236 Qt::Key key,
3842 virtual void handleMouseRelease (CmdMediator *cmdMediator,
3943 QPointF posScreen);
4044 virtual QString state() const;
45 virtual void updateAfterPointAddition ();
4146 virtual void updateModelDigitizeCurve (CmdMediator *cmdMediator,
4247 const DocumentModelDigitizeCurve &modelDigitizeCurve);
4348 virtual void updateModelSegments(const DocumentModelSegments &modelSegments);
33 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
44 ******************************************************************************************************/
55
6 #include "CmdEditPointAxis.h"
7 #include "CmdEditPointGraph.h"
68 #include "CmdMediator.h"
79 #include "CmdMoveBy.h"
810 #include "DataKey.h"
911 #include "DigitizeStateContext.h"
1012 #include "DigitizeStateSelect.h"
13 #include "DlgEditPointAxis.h"
14 #include "DlgEditPointGraph.h"
1115 #include "EngaugeAssert.h"
16 #include "GraphicsItemsExtractor.h"
1217 #include "GraphicsItemType.h"
1318 #include "GraphicsScene.h"
1419 #include "GraphicsView.h"
1722 #include <QCursor>
1823 #include <QGraphicsItem>
1924 #include <QImage>
25 #include <QMessageBox>
2026 #include <QObject>
2127 #include <QtToString.h>
28 #include "Version.h"
2229
2330 const QString MOVE_TEXT_DOWN (QObject::tr ("Move down"));
2431 const QString MOVE_TEXT_LEFT (QObject::tr ("Move left"));
3946 return context().mainWindow().selectedGraphCurve();
4047 }
4148
49 void DigitizeStateSelect::addHoverHighlighting()
50 {
51 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSelect::addHoverHighlighting";
52
53 QList<QGraphicsItem*> items = context().mainWindow().scene().items();
54 QList<QGraphicsItem*>::iterator itr;
55 for (itr = items.begin (); itr != items.end (); itr++) {
56
57 QGraphicsItem *item = *itr;
58 if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE) == GRAPHICS_ITEM_TYPE_POINT) {
59 item->setAcceptHoverEvents(true);
60 }
61 }
62 }
63
4264 void DigitizeStateSelect::begin (CmdMediator *cmdMediator,
4365 DigitizeState /* previousState */)
4466 {
4769 setCursor(cmdMediator);
4870 context().setDragMode(QGraphicsView::RubberBandDrag);
4971
50 setCursorForPoints ();
72 addHoverHighlighting();
5173 context().mainWindow().updateViewsOfSettings(activeCurve ());
5274 }
5375
6284 {
6385 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSelect::end";
6486
65 unsetCursorForPoints ();
87 removeHoverHighlighting();
88 }
89
90 void DigitizeStateSelect::handleContextMenuEventAxis (CmdMediator *cmdMediator,
91 const QString &pointIdentifier)
92 {
93 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSelect::handleContextMenuEventAxis "
94 << " point=" << pointIdentifier.toLatin1 ().data ();
95
96 QPointF posScreen = cmdMediator->document().positionScreen (pointIdentifier);
97 QPointF posGraphBefore = cmdMediator->document().positionGraph (pointIdentifier);
98 bool isXOnly = cmdMediator->document().isXOnly (pointIdentifier);
99
100 // Ask user for coordinates
101 double x = posGraphBefore.x();
102 double y = posGraphBefore.y();
103
104 DlgEditPointAxis *dlg = new DlgEditPointAxis (context().mainWindow(),
105 cmdMediator->document().modelCoords(),
106 context().mainWindow().modelMainWindow(),
107 context().mainWindow().transformation(),
108 cmdMediator->document().documentAxesPointsRequired(),
109 isXOnly,
110 &x,
111 &y);
112 int rtn = dlg->exec ();
113
114 QPointF posGraphAfter = dlg->posGraph (isXOnly); // This call returns new values for isXOnly and the graph position
115 delete dlg;
116
117 if (rtn == QDialog::Accepted) {
118
119 // User wants to edit this axis point, but let's perform sanity checks first
120
121 bool isError;
122 QString errorMessage;
123
124 context().mainWindow().cmdMediator()->document().checkEditPointAxis(pointIdentifier,
125 posScreen,
126 posGraphAfter,
127 isError,
128 errorMessage);
129
130 if (isError) {
131
132 QMessageBox::warning (0,
133 engaugeWindowTitle(),
134 errorMessage);
135
136 } else {
137
138 // Create a command to edit the point
139 CmdEditPointAxis *cmd = new CmdEditPointAxis (context().mainWindow(),
140 cmdMediator->document(),
141 pointIdentifier,
142 posGraphBefore,
143 posGraphAfter,
144 isXOnly);
145 context().appendNewCmd(cmdMediator,
146 cmd);
147 }
148 }
149 }
150
151 void DigitizeStateSelect::handleContextMenuEventGraph (CmdMediator *cmdMediator,
152 const QStringList &pointIdentifiers)
153 {
154 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSelect::handleContextMenuEventGraph "
155 << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
156
157 double *x = 0, *y = 0;
158
159 if (pointIdentifiers.count() == 1) {
160
161 // There is exactly one point so pass its coordinates to the dialog
162 x = new double;
163 y = new double;
164
165 QPointF posScreenBefore = cmdMediator->document().positionScreen (pointIdentifiers.first());
166 QPointF posGraphBefore;
167 context().mainWindow().transformation().transformScreenToRawGraph (posScreenBefore,
168 posGraphBefore);
169
170 // Ask user for coordinates
171 *x = posGraphBefore.x();
172 *y = posGraphBefore.y();
173 }
174
175 DlgEditPointGraph *dlg = new DlgEditPointGraph (context().mainWindow(),
176 cmdMediator->document().modelCoords(),
177 context().mainWindow().modelMainWindow(),
178 context().mainWindow().transformation(),
179 x,
180 y);
181 if (x != 0) {
182 delete x;
183 x = 0;
184 }
185
186 if (y != 0) {
187 delete y;
188 y = 0;
189 }
190
191 int rtn = dlg->exec ();
192
193 bool isXGiven, isYGiven;
194 double xGiven, yGiven;
195 dlg->posGraph (isXGiven, xGiven, isYGiven, yGiven); // One or both coordinates are returned
196 delete dlg;
197
198 if (rtn == QDialog::Accepted) {
199
200 // Create a command to edit the point
201 CmdEditPointGraph *cmd = new CmdEditPointGraph (context().mainWindow(),
202 cmdMediator->document(),
203 pointIdentifiers,
204 isXGiven,
205 isYGiven,
206 xGiven,
207 yGiven);
208 context().appendNewCmd(cmdMediator,
209 cmd);
210 }
66211 }
67212
68213 void DigitizeStateSelect::handleCurveChange(CmdMediator * /* cmdMediator */)
173318 }
174319
175320 // Create command to move points
321 GraphicsItemsExtractor graphicsItemsExtractor;
322 const QList<QGraphicsItem*> &items = context().mainWindow().scene ().selectedItems();
176323 CmdMoveBy *cmd = new CmdMoveBy (context().mainWindow(),
177324 cmdMediator->document(),
178325 deltaScreen,
179326 moveText,
180 context().mainWindow().scene ().selectedPointIdentifiers ());
327 graphicsItemsExtractor.selectedPointIdentifiers (items));
181328 context().appendNewCmd (cmdMediator,
182329 cmd);
183330 }
206353 return moveText;
207354 }
208355
209 void DigitizeStateSelect::setCursorForPoints()
210 {
211 QCursor cursor (Qt::OpenHandCursor);
356 void DigitizeStateSelect::removeHoverHighlighting()
357 {
358 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSelect::removeHoverHighlighting";
212359
213360 QList<QGraphicsItem*> items = context().mainWindow().scene().items();
214361 QList<QGraphicsItem*>::iterator itr;
216363
217364 QGraphicsItem *item = *itr;
218365 if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE) == GRAPHICS_ITEM_TYPE_POINT) {
219 item->setCursor (cursor);
366 item->setAcceptHoverEvents(false);
220367 }
221368 }
222369 }
223370
224 QString DigitizeStateSelect::state() const
225 {
226 return "DigitizeStateSelect";
227 }
228
229 void DigitizeStateSelect::unsetCursorForPoints()
230 {
371 void DigitizeStateSelect::setHoverHighlighting(const MainWindowModel &modelMainWindow)
372 {
373 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSelect::addHoverHighlighting";
374
375 // Set the opacity for all points. It should be already set for pre-existing points
231376 QList<QGraphicsItem*> items = context().mainWindow().scene().items();
232377 QList<QGraphicsItem*>::iterator itr;
233378 for (itr = items.begin (); itr != items.end (); itr++) {
234379
235380 QGraphicsItem *item = *itr;
236381 if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE) == GRAPHICS_ITEM_TYPE_POINT) {
237 item->unsetCursor ();
382 item->setOpacity (modelMainWindow.highlightOpacity());
238383 }
239384 }
385 }
386
387 QString DigitizeStateSelect::state() const
388 {
389 return "DigitizeStateSelect";
390 }
391
392 void DigitizeStateSelect::updateAfterPointAddition ()
393 {
394 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSelect::updateAfterPointAddition";
395
396 addHoverHighlighting ();
240397 }
241398
242399 void DigitizeStateSelect::updateModelDigitizeCurve (CmdMediator * /* cmdMediator */,
99 #include "DigitizeStateAbstractBase.h"
1010
1111 /// Digitizing state for selecting one or more Points in the Document.
12 ///
13 /// Originally this class set the cursor for each QGraphicsItem at the beginning of the state, but that
14 /// triggered Qt bug 4190 which has the description 'If you have set the cursor for some QGraphicsItems
15 /// you can no longer change the cursor for the view in for example a mouseReleaseEvent'. In turn, that
16 /// lead to Engauge issue #155. Unfortunately, this means the user no longer has need feedback that suggests
17 /// the user can do something with the QGraphicsItems.
1218 class DigitizeStateSelect : public DigitizeStateAbstractBase
1319 {
1420 public:
2127 DigitizeState previousState);
2228 virtual QCursor cursor (CmdMediator *cmdMediator) const;
2329 virtual void end();
30 virtual void handleContextMenuEventAxis (CmdMediator *cmdMediator,
31 const QString &pointIdentifier);
32 virtual void handleContextMenuEventGraph (CmdMediator *cmdMediator,
33 const QStringList &pointIdentifiers);
2434 virtual void handleCurveChange(CmdMediator *cmdMediator);
2535 virtual void handleKeyPress (CmdMediator *cmdMediator,
2636 Qt::Key key,
3242 virtual void handleMouseRelease (CmdMediator *cmdMediator,
3343 QPointF posScreen);
3444 virtual QString state() const;
45 virtual void updateAfterPointAddition ();
3546 virtual void updateModelDigitizeCurve (CmdMediator *cmdMediator,
3647 const DocumentModelDigitizeCurve &modelDigitizeCurve);
3748 virtual void updateModelSegments(const DocumentModelSegments &modelSegments);
3950 private:
4051 DigitizeStateSelect();
4152
53 void addHoverHighlighting();
4254 void keyPressArrow (CmdMediator *cmdMediator,
4355 Qt::Key key);
4456 QString moveTextFromDeltaScreen (const QPointF &deltaScreen);
45 void setCursorForPoints();
46 void unsetCursorForPoints();
57 void removeHoverHighlighting();
58 void setHoverHighlighting(const MainWindowModel &modelMainWindow);
4759 double zoomedToUnzoomedScreenX () const;
4860 double zoomedToUnzoomedScreenY () const;
4961
+0
-324
src/Dlg/DlgEditPoint.cpp less more
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DigitizeStateAbstractBase.h"
7 #include "DlgEditPoint.h"
8 #include "DlgValidatorAbstract.h"
9 #include "DlgValidatorFactory.h"
10 #include "DocumentAxesPointsRequired.h"
11 #include "DocumentModelCoords.h"
12 #include "EngaugeAssert.h"
13 #include "FormatCoordsUnits.h"
14 #include "FormatDateTime.h"
15 #include "FormatDegreesMinutesSecondsNonPolarTheta.h"
16 #include "FormatDegreesMinutesSecondsPolarTheta.h"
17 #include "Logger.h"
18 #include "MainWindow.h"
19 #include "MainWindowModel.h"
20 #include <QDoubleValidator>
21 #include <QGridLayout>
22 #include <QGroupBox>
23 #include <QHBoxLayout>
24 #include <QLabel>
25 #include <QRect>
26 #include "QtToString.h"
27 #include <QVBoxLayout>
28 #include "Transformation.h"
29
30 const Qt::Alignment ALIGNMENT = Qt::AlignCenter;
31
32 const int MIN_WIDTH_TO_FIT_STRANGE_UNITS = 200;
33
34 const bool IS_X_THETA = true;
35 const bool IS_NOT_X_THETA = false;
36
37 DlgEditPoint::DlgEditPoint (MainWindow &mainWindow,
38 DigitizeStateAbstractBase &digitizeState,
39 const DocumentModelCoords &modelCoords,
40 const MainWindowModel &modelMainWindow,
41 const QCursor &cursorShape,
42 const Transformation &transformation,
43 DocumentAxesPointsRequired documentAxesPointsRequired,
44 bool isXOnly,
45 const double *xInitialValue,
46 const double *yInitialValue) :
47 QDialog (&mainWindow),
48 m_cursorShape (cursorShape),
49 m_documentAxesPointsRequired (documentAxesPointsRequired),
50 m_modelCoords (modelCoords),
51 m_modelMainWindow (modelMainWindow)
52 {
53 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPoint::DlgEditPoint";
54
55 // Either one or two coordinates are desired
56 bool isX = (documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) || isXOnly;
57 bool isY = (documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) || !isXOnly;
58
59 // To guarantee the override cursor is always removed, we call removeOverrideCursor here rather than in the code that
60 // allocates this DlgEditPoint. The digitizeState argument is otherwise unused.
61 digitizeState.removeOverrideCursor();
62
63 connect (this, SIGNAL (signalSetOverrideCursor (QCursor)), &mainWindow, SLOT (slotSetOverrideCursor (QCursor)));
64
65 QVBoxLayout *layout = new QVBoxLayout;
66 setLayout (layout);
67
68 setCursor (QCursor (Qt::ArrowCursor));
69 setModal(true);
70 setWindowTitle (tr ("Edit Axis Point"));
71
72 createCoords (layout);
73 createHint (layout);
74 createOkCancel (layout);
75
76 initializeGraphCoordinates (xInitialValue,
77 yInitialValue,
78 transformation,
79 isX,
80 isY);
81
82 updateControls ();
83 }
84
85 DlgEditPoint::~DlgEditPoint()
86 {
87 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPoint::~DlgEditPoint";
88
89 emit signalSetOverrideCursor (m_cursorShape);
90 }
91
92 void DlgEditPoint::createCoords (QVBoxLayout *layoutOuter)
93 {
94 // Constraints on x and y are needed for log scaling
95 bool isConstraintX = (m_modelCoords.coordScaleXTheta() == COORD_SCALE_LOG);
96 bool isConstraintY = (m_modelCoords.coordScaleYRadius() == COORD_SCALE_LOG);
97 DlgValidatorFactory dlgValidatorFactory;
98 m_validatorGraphX = dlgValidatorFactory.createCartesianOrPolarWithPolarPolar (m_modelCoords.coordScaleXTheta(),
99 isCartesian (),
100 m_modelCoords.coordUnitsX(),
101 m_modelCoords.coordUnitsTheta(),
102 m_modelCoords.coordUnitsDate(),
103 m_modelCoords.coordUnitsTime(),
104 m_modelMainWindow.locale());
105 m_validatorGraphY = dlgValidatorFactory.createCartesianOrPolarWithNonPolarPolar (m_modelCoords.coordScaleYRadius(),
106 isCartesian (),
107 m_modelCoords.coordUnitsY(),
108 m_modelCoords.coordUnitsRadius(),
109 m_modelCoords.coordUnitsDate(),
110 m_modelCoords.coordUnitsTime(),
111 m_modelMainWindow.locale());
112
113 // Label, with guidance in terms of legal ranges and units
114 QString description = QString ("%1 (%2, %3)%4%5%6%7%8%9 %10 (%11, %12):")
115 .arg (tr ("Graph Coordinates"))
116 .arg (nameXTheta ())
117 .arg (nameYRadius ())
118 .arg (isConstraintX || isConstraintY ? " with " : "")
119 .arg (isConstraintX ? QString (nameXTheta ()) : "")
120 .arg (isConstraintX ? " > 0" : "")
121 .arg (isConstraintX && isConstraintY ? " and " : "")
122 .arg ( isConstraintY ? QString (nameYRadius ()) : "")
123 .arg ( isConstraintY ? " > 0" : "")
124 .arg (tr ("as"))
125 .arg (unitsType (IS_X_THETA))
126 .arg (unitsType (IS_NOT_X_THETA));
127 QGroupBox *panel = new QGroupBox (description, this);
128 layoutOuter->addWidget (panel);
129
130 QHBoxLayout *layout = new QHBoxLayout (panel);
131 panel->setLayout (layout);
132
133 // Row
134 QLabel *labelGraphParLeft = new QLabel (tr ("("), this);
135 layout->addWidget(labelGraphParLeft, 0);
136
137 m_editGraphX = new QLineEdit;
138 m_editGraphX->setMinimumWidth(MIN_WIDTH_TO_FIT_STRANGE_UNITS);
139 m_editGraphX->setAlignment (ALIGNMENT);
140 m_editGraphX->setValidator (m_validatorGraphX);
141 // setStatusTip does not work for modal dialogs
142 m_editGraphX->setWhatsThis (tr ("Enter the first graph coordinate of the axis point.\n\n"
143 "For cartesian plots this is X. For polar plots this is the radius R.\n\n"
144 "The expected format of the coordinate value is determined by the locale setting. If "
145 "typed values are not recognized as expected, check the locale setting in Settings / Main Window..."));
146 layout->addWidget(m_editGraphX, 0);
147 connect (m_editGraphX, SIGNAL (textChanged (const QString &)), this, SLOT (slotTextChanged (const QString &)));
148
149 QLabel *labelGraphComma = new QLabel (tr (", "), this);
150 layout->addWidget(labelGraphComma, 0);
151
152 m_editGraphY = new QLineEdit;
153 m_editGraphY->setMinimumWidth(MIN_WIDTH_TO_FIT_STRANGE_UNITS);
154 m_editGraphY->setAlignment (ALIGNMENT);
155 m_editGraphY->setValidator (m_validatorGraphY);
156 // setStatusTip does not work for modal dialogs
157 m_editGraphY->setWhatsThis (tr ("Enter the second graph coordinate of the axis point.\n\n"
158 "For cartesian plots this is Y. For plot plots this is the angle Theta.\n\n"
159 "The expected format of the coordinate value is determined by the locale setting. If "
160 "typed values are not recognized as expected, check the locale setting in Settings / Main Window..."));
161 layout->addWidget(m_editGraphY, 0);
162 connect (m_editGraphY, SIGNAL (textChanged (const QString &)), this, SLOT (slotTextChanged (const QString &)));
163
164 QLabel *labelGraphParRight = new QLabel (tr (")"), this);
165 layout->addWidget(labelGraphParRight, 0);
166 }
167
168 void DlgEditPoint::createHint (QVBoxLayout *layoutOuter)
169 {
170 // Insert a hint explaining why decimal points may not be accepted. Very confusing for user to figure out the problem at first, and
171 // then figure out which setting should change to fix it. The hint is centered so it is slightly less intrusive
172
173 QWidget *widget = new QWidget;
174 layoutOuter->addWidget (widget, 0, Qt::AlignCenter);
175
176 QHBoxLayout *layout = new QHBoxLayout;
177 widget->setLayout (layout);
178
179 QString locale = QLocaleToString (m_modelMainWindow.locale ());
180 QString hint = QString ("%1: %2")
181 .arg (tr ("Number format"))
182 .arg (locale);
183 QLabel *label = new QLabel (hint);
184 layout->addWidget (label);
185 }
186
187 void DlgEditPoint::createOkCancel (QVBoxLayout *layoutOuter)
188 {
189 QWidget *panel = new QWidget (this);
190 layoutOuter->addWidget (panel, 0, Qt::AlignCenter);
191
192 QHBoxLayout *layout = new QHBoxLayout (panel);
193 panel->setLayout (layout);
194
195 m_btnOk = new QPushButton (tr ("Ok"), this);
196 layout->addWidget(m_btnOk);
197 connect (m_btnOk, SIGNAL (released ()), this, SLOT (accept ()));
198
199 m_btnCancel = new QPushButton (tr ("Cancel"), this);
200 layout->addWidget(m_btnCancel);
201 connect (m_btnCancel, SIGNAL (released ()), this, SLOT (reject ()));
202 }
203
204 void DlgEditPoint::initializeGraphCoordinates (const double *xInitialValue,
205 const double *yInitialValue,
206 const Transformation &transformation,
207 bool isX,
208 bool isY)
209 {
210 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPoint::initializeGraphCoordinates";
211
212 QString xTheta, yRadius;
213 if ((xInitialValue != 0) &&
214 (yInitialValue != 0)) {
215
216 FormatCoordsUnits format;
217 format.unformattedToFormatted (*xInitialValue,
218 *yInitialValue,
219 m_modelCoords,
220 m_modelMainWindow,
221 xTheta,
222 yRadius,
223 transformation);
224 }
225
226 if (isX) {
227 m_editGraphX->setText (xTheta);
228 } else {
229 m_editGraphX->setText ("");
230 }
231
232 if (isY) {
233 m_editGraphY->setText (yRadius);
234 } else {
235 m_editGraphY->setText ("");
236 }
237 }
238
239 bool DlgEditPoint::isCartesian () const
240 {
241 return (m_modelCoords.coordsType() == COORDS_TYPE_CARTESIAN);
242 }
243
244 QChar DlgEditPoint::nameXTheta () const
245 {
246 return (isCartesian () ? QChar ('X') : THETA);
247 }
248
249 QChar DlgEditPoint::nameYRadius () const
250 {
251 return (isCartesian () ? QChar ('Y') : QChar ('R'));
252 }
253
254 QPointF DlgEditPoint::posGraph (bool &isXOnly) const
255 {
256 double xTheta, yRadius;
257
258 FormatCoordsUnits format;
259
260 format.formattedToUnformatted (m_editGraphX->text(),
261 m_editGraphY->text(),
262 m_modelCoords,
263 m_modelMainWindow,
264 xTheta,
265 yRadius);
266
267 // If yRadius value is empty then this is the xTheta value only
268 isXOnly = m_editGraphY->text().isEmpty();
269
270 return QPointF (xTheta,
271 yRadius);
272 }
273
274 void DlgEditPoint::slotTextChanged (const QString &)
275 {
276 updateControls ();
277 }
278
279 QString DlgEditPoint::unitsType (bool isXTheta) const
280 {
281 if (isCartesian ()) {
282 if (isXTheta) {
283 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsX());
284 } else {
285 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsY());
286 }
287 } else {
288 if (isXTheta) {
289 return coordUnitsPolarThetaToBriefType (m_modelCoords.coordUnitsTheta());
290 } else {
291 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsRadius());
292 }
293 }
294 }
295
296 void DlgEditPoint::updateControls ()
297 {
298 QString textX = m_editGraphX->text();
299 QString textY = m_editGraphY->text();
300
301 int posX, posY;
302
303 if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_4) {
304
305 bool gotX = (!textX.isEmpty() &&
306 (m_validatorGraphX->validate(textX, posX) == QValidator::Acceptable));
307 bool gotY = (!textY.isEmpty() &&
308 (m_validatorGraphY->validate(textY, posY) == QValidator::Acceptable));
309
310 // Check for not empty in one coordinate and for valid number in the other coordinate
311 m_btnOk->setEnabled ((textX.isEmpty() && gotY) ||
312 (textY.isEmpty() && gotX));
313
314 } else {
315
316 // Check for not empty (which allows single minus sign) and for valid number (which prevents single minus sign)
317 m_btnOk->setEnabled (!textX.isEmpty () &&
318 !textY.isEmpty () &&
319 (m_validatorGraphX->validate(textX, posX) == QValidator::Acceptable) &&
320 (m_validatorGraphY->validate(textY, posY) == QValidator::Acceptable));
321
322 }
323 }
+0
-88
src/Dlg/DlgEditPoint.h less more
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef DLG_EDIT_POINT_H
7 #define DLG_EDIT_POINT_H
8
9 #include "CoordUnitsDate.h"
10 #include "CoordUnitsNonPolarTheta.h"
11 #include "CoordUnitsPolarTheta.h"
12 #include "CoordUnitsTime.h"
13 #include "DocumentAxesPointsRequired.h"
14 #include <QCursor>
15 #include <QDialog>
16 #include <QLineEdit>
17 #include <QPushButton>
18
19 class DigitizeStateAbstractBase;
20 class DlgValidatorAbstract;
21 class DocumentModelCoords;
22 class MainWindow;
23 class MainWindowModel;
24 class QDoubleValidator;
25 class QVBoxLayout;
26 class Transformation;
27
28 /// Dialog box for editing the information of one axis point.
29 class DlgEditPoint : public QDialog
30 {
31 Q_OBJECT;
32
33 public:
34 /// Constructor for existing point which already has graph coordinates (which may be changed using this dialog).
35 /// If initial values are unspecified then the value fields will be initially empty
36 DlgEditPoint (MainWindow &mainWindow,
37 DigitizeStateAbstractBase &digitizeState,
38 const DocumentModelCoords &modelCoords,
39 const MainWindowModel &modelMainWindow,
40 const QCursor &cursorShape,
41 const Transformation &transformation,
42 DocumentAxesPointsRequired documentAxesPointsRequired,
43 bool isXOnly = false,
44 const double *xInitialValue = 0,
45 const double *yInitialValue = 0);
46 ~DlgEditPoint ();
47
48 /// Return the graph coordinates position specified by the user. Only applies if dialog was accepted
49 QPointF posGraph (bool &isXOnly) const;
50
51 signals:
52 /// Send a signal to trigger the setting of the override cursor.
53 void signalSetOverrideCursor (QCursor);
54
55 private slots:
56 void slotTextChanged (const QString &);
57
58 private:
59 void createCoords (QVBoxLayout *layoutOuter);
60 void createHint (QVBoxLayout *layoutOuter);
61 void createOkCancel (QVBoxLayout *layoutOuter);
62 void initializeGraphCoordinates (const double *xInitialValue,
63 const double *yInitialValue,
64 const Transformation &transformation,
65 bool isX,
66 bool isY);
67 bool isCartesian () const;
68 QChar nameXTheta () const;
69 QChar nameYRadius () const;
70 QString unitsType (bool isXTheta) const;
71 void updateControls ();
72
73 QCursor m_cursorShape;
74 QLineEdit *m_editGraphX;
75 DlgValidatorAbstract *m_validatorGraphX;
76 QLineEdit *m_editGraphY;
77 DlgValidatorAbstract *m_validatorGraphY;
78 QPushButton *m_btnOk;
79 QPushButton *m_btnCancel;
80
81 DocumentAxesPointsRequired m_documentAxesPointsRequired;
82
83 const DocumentModelCoords &m_modelCoords;
84 const MainWindowModel &m_modelMainWindow;
85 };
86
87 #endif // DLG_EDIT_POINT_H
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DlgEditPointAxis.h"
7 #include "DlgValidatorAbstract.h"
8 #include "DlgValidatorFactory.h"
9 #include "DocumentAxesPointsRequired.h"
10 #include "DocumentModelCoords.h"
11 #include "EngaugeAssert.h"
12 #include "FormatCoordsUnits.h"
13 #include "FormatDateTime.h"
14 #include "FormatDegreesMinutesSecondsNonPolarTheta.h"
15 #include "FormatDegreesMinutesSecondsPolarTheta.h"
16 #include "Logger.h"
17 #include "MainWindow.h"
18 #include "MainWindowModel.h"
19 #include <QDoubleValidator>
20 #include <QGridLayout>
21 #include <QGroupBox>
22 #include <QHBoxLayout>
23 #include <QLabel>
24 #include <QRect>
25 #include "QtToString.h"
26 #include <QVBoxLayout>
27 #include "Transformation.h"
28
29 const Qt::Alignment ALIGNMENT = Qt::AlignCenter;
30
31 const int MIN_WIDTH_TO_FIT_STRANGE_UNITS = 200;
32
33 const bool IS_X_THETA = true;
34 const bool IS_NOT_X_THETA = false;
35
36 DlgEditPointAxis::DlgEditPointAxis (MainWindow &mainWindow,
37 const DocumentModelCoords &modelCoords,
38 const MainWindowModel &modelMainWindow,
39 const Transformation &transformation,
40 DocumentAxesPointsRequired documentAxesPointsRequired,
41 bool isXOnly,
42 const double *xInitialValue,
43 const double *yInitialValue) :
44 QDialog (&mainWindow),
45 m_documentAxesPointsRequired (documentAxesPointsRequired),
46 m_modelCoords (modelCoords),
47 m_modelMainWindow (modelMainWindow)
48 {
49 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointAxis::DlgEditPointAxis";
50
51 // Either one or two coordinates are desired
52 bool isX = (documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) || isXOnly;
53 bool isY = (documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) || !isXOnly;
54
55 QVBoxLayout *layout = new QVBoxLayout;
56 setLayout (layout);
57
58 setCursor (QCursor (Qt::ArrowCursor));
59 setModal(true);
60 setWindowTitle (tr ("Edit Axis Point"));
61
62 createCoords (layout);
63 createHint (layout);
64 createOkCancel (layout);
65
66 initializeGraphCoordinates (xInitialValue,
67 yInitialValue,
68 transformation,
69 isX,
70 isY);
71
72 updateControls ();
73 }
74
75 DlgEditPointAxis::~DlgEditPointAxis()
76 {
77 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointAxis::~DlgEditPointAxis";
78 }
79
80 void DlgEditPointAxis::createCoords (QVBoxLayout *layoutOuter)
81 {
82 // Constraints on x and y are needed for log scaling
83 bool isConstraintX = (m_modelCoords.coordScaleXTheta() == COORD_SCALE_LOG);
84 bool isConstraintY = (m_modelCoords.coordScaleYRadius() == COORD_SCALE_LOG);
85 DlgValidatorFactory dlgValidatorFactory;
86 m_validatorGraphX = dlgValidatorFactory.createCartesianOrPolarWithPolarPolar (m_modelCoords.coordScaleXTheta(),
87 isCartesian (),
88 m_modelCoords.coordUnitsX(),
89 m_modelCoords.coordUnitsTheta(),
90 m_modelCoords.coordUnitsDate(),
91 m_modelCoords.coordUnitsTime(),
92 m_modelMainWindow.locale());
93 m_validatorGraphY = dlgValidatorFactory.createCartesianOrPolarWithNonPolarPolar (m_modelCoords.coordScaleYRadius(),
94 isCartesian (),
95 m_modelCoords.coordUnitsY(),
96 m_modelCoords.coordUnitsRadius(),
97 m_modelCoords.coordUnitsDate(),
98 m_modelCoords.coordUnitsTime(),
99 m_modelMainWindow.locale());
100
101 // Label, with guidance in terms of legal ranges and units
102 QString description = QString ("%1 (%2, %3)%4%5%6%7%8%9 %10 (%11, %12):")
103 .arg (tr ("Graph Coordinates"))
104 .arg (nameXTheta ())
105 .arg (nameYRadius ())
106 .arg (isConstraintX || isConstraintY ? " with " : "")
107 .arg (isConstraintX ? QString (nameXTheta ()) : "")
108 .arg (isConstraintX ? " > 0" : "")
109 .arg (isConstraintX && isConstraintY ? " and " : "")
110 .arg ( isConstraintY ? QString (nameYRadius ()) : "")
111 .arg ( isConstraintY ? " > 0" : "")
112 .arg (tr ("as"))
113 .arg (unitsType (IS_X_THETA))
114 .arg (unitsType (IS_NOT_X_THETA));
115 QGroupBox *panel = new QGroupBox (description, this);
116 layoutOuter->addWidget (panel);
117
118 QHBoxLayout *layout = new QHBoxLayout (panel);
119 panel->setLayout (layout);
120
121 // Row
122 QLabel *labelGraphParLeft = new QLabel (tr ("("), this);
123 layout->addWidget(labelGraphParLeft, 0);
124
125 m_editGraphX = new QLineEdit;
126 m_editGraphX->setMinimumWidth(MIN_WIDTH_TO_FIT_STRANGE_UNITS);
127 m_editGraphX->setAlignment (ALIGNMENT);
128 m_editGraphX->setValidator (m_validatorGraphX);
129 // setStatusTip does not work for modal dialogs
130 m_editGraphX->setWhatsThis (tr ("Enter the first graph coordinate of the axis point.\n\n"
131 "For cartesian plots this is X. For polar plots this is the radius R.\n\n"
132 "The expected format of the coordinate value is determined by the locale setting. If "
133 "typed values are not recognized as expected, check the locale setting in Settings / Main Window..."));
134 layout->addWidget(m_editGraphX, 0);
135 connect (m_editGraphX, SIGNAL (textChanged (const QString &)), this, SLOT (slotTextChanged (const QString &)));
136
137 QLabel *labelGraphComma = new QLabel (tr (", "), this);
138 layout->addWidget(labelGraphComma, 0);
139
140 m_editGraphY = new QLineEdit;
141 m_editGraphY->setMinimumWidth(MIN_WIDTH_TO_FIT_STRANGE_UNITS);
142 m_editGraphY->setAlignment (ALIGNMENT);
143 m_editGraphY->setValidator (m_validatorGraphY);
144 // setStatusTip does not work for modal dialogs
145 m_editGraphY->setWhatsThis (tr ("Enter the second graph coordinate of the axis point.\n\n"
146 "For cartesian plots this is Y. For plot plots this is the angle Theta.\n\n"
147 "The expected format of the coordinate value is determined by the locale setting. If "
148 "typed values are not recognized as expected, check the locale setting in Settings / Main Window..."));
149 layout->addWidget(m_editGraphY, 0);
150 connect (m_editGraphY, SIGNAL (textChanged (const QString &)), this, SLOT (slotTextChanged (const QString &)));
151
152 QLabel *labelGraphParRight = new QLabel (tr (")"), this);
153 layout->addWidget(labelGraphParRight, 0);
154 }
155
156 void DlgEditPointAxis::createHint (QVBoxLayout *layoutOuter)
157 {
158 // Insert a hint explaining why decimal points may not be accepted. Very confusing for user to figure out the problem at first, and
159 // then figure out which setting should change to fix it. The hint is centered so it is slightly less intrusive
160
161 QWidget *widget = new QWidget;
162 layoutOuter->addWidget (widget, 0, Qt::AlignCenter);
163
164 QHBoxLayout *layout = new QHBoxLayout;
165 widget->setLayout (layout);
166
167 QString locale = QLocaleToString (m_modelMainWindow.locale ());
168 QString hint = QString ("%1: %2")
169 .arg (tr ("Number format"))
170 .arg (locale);
171 QLabel *label = new QLabel (hint);
172 layout->addWidget (label);
173 }
174
175 void DlgEditPointAxis::createOkCancel (QVBoxLayout *layoutOuter)
176 {
177 QWidget *panel = new QWidget (this);
178 layoutOuter->addWidget (panel, 0, Qt::AlignCenter);
179
180 QHBoxLayout *layout = new QHBoxLayout (panel);
181 panel->setLayout (layout);
182
183 m_btnOk = new QPushButton (tr ("Ok"), this);
184 layout->addWidget(m_btnOk);
185 connect (m_btnOk, SIGNAL (released ()), this, SLOT (accept ()));
186
187 m_btnCancel = new QPushButton (tr ("Cancel"), this);
188 layout->addWidget(m_btnCancel);
189 connect (m_btnCancel, SIGNAL (released ()), this, SLOT (reject ()));
190 }
191
192 void DlgEditPointAxis::initializeGraphCoordinates (const double *xInitialValue,
193 const double *yInitialValue,
194 const Transformation &transformation,
195 bool isX,
196 bool isY)
197 {
198 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointAxis::initializeGraphCoordinates";
199
200 QString xTheta, yRadius;
201 if ((xInitialValue != 0) &&
202 (yInitialValue != 0)) {
203
204 FormatCoordsUnits format;
205 format.unformattedToFormatted (*xInitialValue,
206 *yInitialValue,
207 m_modelCoords,
208 m_modelMainWindow,
209 xTheta,
210 yRadius,
211 transformation);
212 }
213
214 if (isX) {
215 m_editGraphX->setText (xTheta);
216 } else {
217 m_editGraphX->setText ("");
218 }
219
220 if (isY) {
221 m_editGraphY->setText (yRadius);
222 } else {
223 m_editGraphY->setText ("");
224 }
225 }
226
227 bool DlgEditPointAxis::isCartesian () const
228 {
229 return (m_modelCoords.coordsType() == COORDS_TYPE_CARTESIAN);
230 }
231
232 QChar DlgEditPointAxis::nameXTheta () const
233 {
234 return (isCartesian () ? QChar ('X') : THETA);
235 }
236
237 QChar DlgEditPointAxis::nameYRadius () const
238 {
239 return (isCartesian () ? QChar ('Y') : QChar ('R'));
240 }
241
242 QPointF DlgEditPointAxis::posGraph (bool &isXOnly) const
243 {
244 double xTheta, yRadius;
245
246 FormatCoordsUnits format;
247
248 format.formattedToUnformatted (m_editGraphX->text(),
249 m_editGraphY->text(),
250 m_modelCoords,
251 m_modelMainWindow,
252 xTheta,
253 yRadius);
254
255 // If yRadius value is empty then this is the xTheta value only
256 isXOnly = m_editGraphY->text().isEmpty();
257
258 return QPointF (xTheta,
259 yRadius);
260 }
261
262 void DlgEditPointAxis::slotTextChanged (const QString &)
263 {
264 updateControls ();
265 }
266
267 QString DlgEditPointAxis::unitsType (bool isXTheta) const
268 {
269 if (isCartesian ()) {
270 if (isXTheta) {
271 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsX());
272 } else {
273 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsY());
274 }
275 } else {
276 if (isXTheta) {
277 return coordUnitsPolarThetaToBriefType (m_modelCoords.coordUnitsTheta());
278 } else {
279 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsRadius());
280 }
281 }
282 }
283
284 void DlgEditPointAxis::updateControls ()
285 {
286 QString textX = m_editGraphX->text();
287 QString textY = m_editGraphY->text();
288
289 int posX, posY;
290
291 if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_4) {
292
293 bool gotX = (!textX.isEmpty() &&
294 (m_validatorGraphX->validate(textX, posX) == QValidator::Acceptable));
295 bool gotY = (!textY.isEmpty() &&
296 (m_validatorGraphY->validate(textY, posY) == QValidator::Acceptable));
297
298 // Check for not empty in one coordinate and for valid number in the other coordinate
299 m_btnOk->setEnabled ((textX.isEmpty() && gotY) ||
300 (textY.isEmpty() && gotX));
301
302 } else {
303
304 // Check for not empty (which allows single minus sign) and for valid number (which prevents single minus sign)
305 m_btnOk->setEnabled (!textX.isEmpty () &&
306 !textY.isEmpty () &&
307 (m_validatorGraphX->validate(textX, posX) == QValidator::Acceptable) &&
308 (m_validatorGraphY->validate(textY, posY) == QValidator::Acceptable));
309
310 }
311 }
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef DLG_EDIT_POINT_AXIS_H
7 #define DLG_EDIT_POINT_AXIS_H
8
9 #include "DocumentAxesPointsRequired.h"
10 #include <QDialog>
11 #include <QLineEdit>
12 #include <QPushButton>
13
14 class DlgValidatorAbstract;
15 class DocumentModelCoords;
16 class MainWindow;
17 class MainWindowModel;
18 class QDoubleValidator;
19 class QVBoxLayout;
20 class Transformation;
21
22 /// Dialog box for editing the information of one axis point.
23 class DlgEditPointAxis : public QDialog
24 {
25 Q_OBJECT;
26
27 public:
28 /// Constructor for existing point which already has graph coordinates (which may be changed using this dialog).
29 /// If initial values are unspecified then the value fields will be initially empty
30 DlgEditPointAxis (MainWindow &mainWindow,
31 const DocumentModelCoords &modelCoords,
32 const MainWindowModel &modelMainWindow,
33 const Transformation &transformation,
34 DocumentAxesPointsRequired documentAxesPointsRequired,
35 bool isXOnly = false,
36 const double *xInitialValue = 0,
37 const double *yInitialValue = 0);
38 ~DlgEditPointAxis ();
39
40 /// Return the graph coordinates position specified by the user. Only applies if dialog was accepted
41 QPointF posGraph (bool &isXOnly) const;
42
43 private slots:
44 void slotTextChanged (const QString &);
45
46 private:
47 void createCoords (QVBoxLayout *layoutOuter);
48 void createHint (QVBoxLayout *layoutOuter);
49 void createOkCancel (QVBoxLayout *layoutOuter);
50 void initializeGraphCoordinates (const double *xInitialValue,
51 const double *yInitialValue,
52 const Transformation &transformation,
53 bool isX,
54 bool isY);
55 bool isCartesian () const;
56 QChar nameXTheta () const;
57 QChar nameYRadius () const;
58 QString unitsType (bool isXTheta) const;
59 void updateControls ();
60
61 QLineEdit *m_editGraphX;
62 DlgValidatorAbstract *m_validatorGraphX;
63 QLineEdit *m_editGraphY;
64 DlgValidatorAbstract *m_validatorGraphY;
65 QPushButton *m_btnOk;
66 QPushButton *m_btnCancel;
67
68 DocumentAxesPointsRequired m_documentAxesPointsRequired;
69
70 const DocumentModelCoords &m_modelCoords;
71 const MainWindowModel &m_modelMainWindow;
72 };
73
74 #endif // DLG_EDIT_POINT_AXIS_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DlgEditPointGraph.h"
7 #include "DlgEditPointGraphLineEdit.h"
8 #include "DlgValidatorAbstract.h"
9 #include "DlgValidatorFactory.h"
10 #include "DocumentModelCoords.h"
11 #include "FormatCoordsUnits.h"
12 #include "Logger.h"
13 #include "MainWindow.h"
14 #include "MainWindowModel.h"
15 #include <QGroupBox>
16 #include <QLabel>
17 #include <QPushButton>
18 #include "QtToString.h"
19 #include <QVBoxLayout>
20 #include "Transformation.h"
21
22 const Qt::Alignment ALIGNMENT = Qt::AlignCenter;
23
24 const int MIN_WIDTH_TO_FIT_STRANGE_UNITS = 200;
25
26 DlgEditPointGraph::DlgEditPointGraph (MainWindow &mainWindow,
27 const DocumentModelCoords &modelCoords,
28 const MainWindowModel &modelMainWindow,
29 const Transformation &transformation,
30 const double *xInitialValue,
31 const double *yInitialValue) :
32 QDialog (&mainWindow),
33 m_changed (false),
34 m_modelCoords (modelCoords),
35 m_modelMainWindow (modelMainWindow)
36 {
37 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointGraph::DlgEditPointGraph";
38
39 QVBoxLayout *layout = new QVBoxLayout;
40 setLayout (layout);
41
42 setCursor (QCursor (Qt::ArrowCursor));
43 setModal(true);
44 setWindowTitle (tr ("Edit Curve Point(s)"));
45
46 createCoords (layout);
47 createHint (layout);
48 createOkCancel (layout);
49
50 initializeGraphCoordinates (xInitialValue,
51 yInitialValue,
52 transformation);
53
54 m_changed = false; // Initialization of coordinate vaues changed this flag so we reset it and update the controls
55 updateControls ();
56 }
57
58 DlgEditPointGraph::~DlgEditPointGraph()
59 {
60 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointGraph::~DlgEditPointGraph";
61 }
62
63 void DlgEditPointGraph::createCoords (QVBoxLayout *layoutOuter)
64 {
65 // Constraints on x and y are needed for log scaling
66 bool isConstraintX = (m_modelCoords.coordScaleXTheta() == COORD_SCALE_LOG);
67 bool isConstraintY = (m_modelCoords.coordScaleYRadius() == COORD_SCALE_LOG);
68 DlgValidatorFactory dlgValidatorFactory;
69 m_validatorGraphX = dlgValidatorFactory.createCartesianOrPolarWithPolarPolar (m_modelCoords.coordScaleXTheta(),
70 isCartesian (),
71 m_modelCoords.coordUnitsX(),
72 m_modelCoords.coordUnitsTheta(),
73 m_modelCoords.coordUnitsDate(),
74 m_modelCoords.coordUnitsTime(),
75 m_modelMainWindow.locale());
76 m_validatorGraphY = dlgValidatorFactory.createCartesianOrPolarWithNonPolarPolar (m_modelCoords.coordScaleYRadius(),
77 isCartesian (),
78 m_modelCoords.coordUnitsY(),
79 m_modelCoords.coordUnitsRadius(),
80 m_modelCoords.coordUnitsDate(),
81 m_modelCoords.coordUnitsTime(),
82 m_modelMainWindow.locale());
83
84 // Label, with guidance in terms of legal ranges and units
85 QString description = QString ("%1 (%2, %3)%4%5%6%7%8%9 %10:")
86 .arg (tr ("Graph Coordinates"))
87 .arg (nameXTheta ())
88 .arg (nameYRadius ())
89 .arg (isConstraintX || isConstraintY ? " with " : "")
90 .arg (isConstraintX ? QString (nameXTheta ()) : "")
91 .arg (isConstraintX ? " > 0" : "")
92 .arg (isConstraintX && isConstraintY ? " and " : "")
93 .arg ( isConstraintY ? QString (nameYRadius ()) : "")
94 .arg ( isConstraintY ? " > 0" : "")
95 .arg (tr ("as"));
96 QGroupBox *panel = new QGroupBox (description, this);
97 layoutOuter->addWidget (panel);
98
99 QHBoxLayout *layout = new QHBoxLayout (panel);
100 panel->setLayout (layout);
101
102 // Row
103 QLabel *labelGraphParLeft = new QLabel (tr ("("), this);
104 layout->addWidget(labelGraphParLeft, 0);
105
106 m_editGraphX = new DlgEditPointGraphLineEdit;
107 m_editGraphX->setMinimumWidth(MIN_WIDTH_TO_FIT_STRANGE_UNITS);
108 m_editGraphX->setAlignment (ALIGNMENT);
109 m_editGraphX->setValidator (m_validatorGraphX);
110 // setStatusTip does not work for modal dialogs
111 m_editGraphX->setWhatsThis (tr ("Enter the first graph coordinate value to be applied to the graph points.\n\n"
112 "Leave this field empty if no value is to be applied to the graph points.\n\n"
113 "For cartesian plots this is the X coordinate. For polar plots this is the radius R.\n\n"
114 "The expected format of the coordinate value is determined by the locale setting. If "
115 "typed values are not recognized as expected, check the locale setting in Settings / Main Window..."));
116 layout->addWidget(m_editGraphX, 0);
117 connect (m_editGraphX, SIGNAL (textChanged (const QString &)), this, SLOT (slotTextChanged (const QString &)));
118
119 QLabel *labelGraphComma = new QLabel (tr (", "), this);
120 layout->addWidget(labelGraphComma, 0);
121
122 m_editGraphY = new DlgEditPointGraphLineEdit;
123 m_editGraphY->setMinimumWidth(MIN_WIDTH_TO_FIT_STRANGE_UNITS);
124 m_editGraphY->setAlignment (ALIGNMENT);
125 m_editGraphY->setValidator (m_validatorGraphY);
126 // setStatusTip does not work for modal dialogs
127 m_editGraphY->setWhatsThis (tr ("Enter the second graph coordinate value to be applied to the graph points.\n\n"
128 "Leave this field empty if no value is to be applied to the graph points.\n\n"
129 "For cartesian plots this is the Y coordinate. For plot plots this is the angle Theta.\n\n"
130 "The expected format of the coordinate value is determined by the locale setting. If "
131 "typed values are not recognized as expected, check the locale setting in Settings / Main Window..."));
132 layout->addWidget(m_editGraphY, 0);
133 connect (m_editGraphY, SIGNAL (textChanged (const QString &)), this, SLOT (slotTextChanged (const QString &)));
134
135 QLabel *labelGraphParRight = new QLabel (tr (")"), this);
136 layout->addWidget(labelGraphParRight, 0);
137 }
138
139 void DlgEditPointGraph::createHint (QVBoxLayout *layoutOuter)
140 {
141 // Insert a hint explaining why decimal points may not be accepted. Very confusing for user to figure out the problem at first, and
142 // then figure out which setting should change to fix it. The hint is centered so it is slightly less intrusive
143
144 QWidget *widget = new QWidget;
145 layoutOuter->addWidget (widget, 0, Qt::AlignCenter);
146
147 QHBoxLayout *layout = new QHBoxLayout;
148 widget->setLayout (layout);
149
150 QString locale = QLocaleToString (m_modelMainWindow.locale ());
151 QString hint = QString ("%1: %2")
152 .arg (tr ("Number format"))
153 .arg (locale);
154 QLabel *label = new QLabel (hint);
155 layout->addWidget (label);
156 }
157
158 void DlgEditPointGraph::createOkCancel (QVBoxLayout *layoutOuter)
159 {
160 QWidget *panel = new QWidget (this);
161 layoutOuter->addWidget (panel, 0, Qt::AlignCenter);
162
163 QHBoxLayout *layout = new QHBoxLayout (panel);
164 panel->setLayout (layout);
165
166 m_btnOk = new QPushButton (tr ("Ok"), this);
167 layout->addWidget(m_btnOk);
168 connect (m_btnOk, SIGNAL (released ()), this, SLOT (accept ()));
169
170 m_btnCancel = new QPushButton (tr ("Cancel"), this);
171 layout->addWidget(m_btnCancel);
172 connect (m_btnCancel, SIGNAL (released ()), this, SLOT (reject ()));
173 }
174
175 void DlgEditPointGraph::initializeGraphCoordinates (const double *xInitialValue,
176 const double *yInitialValue,
177 const Transformation &transformation)
178 {
179 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointGraph::initializeGraphCoordinates";
180
181 QString xTheta, yRadius;
182 if ((xInitialValue != 0) &&
183 (yInitialValue != 0)) {
184
185 FormatCoordsUnits format;
186 format.unformattedToFormatted (*xInitialValue,
187 *yInitialValue,
188 m_modelCoords,
189 m_modelMainWindow,
190 xTheta,
191 yRadius,
192 transformation);
193 }
194
195 m_editGraphX->setText (xTheta);
196 m_editGraphY->setText (yRadius);
197 }
198
199 bool DlgEditPointGraph::isCartesian () const
200 {
201 return (m_modelCoords.coordsType() == COORDS_TYPE_CARTESIAN);
202 }
203
204 QChar DlgEditPointGraph::nameXTheta () const
205 {
206 return (isCartesian () ? QChar ('X') : THETA);
207 }
208
209 QChar DlgEditPointGraph::nameYRadius () const
210 {
211 return (isCartesian () ? QChar ('Y') : QChar ('R'));
212 }
213
214 void DlgEditPointGraph::posGraph (bool &isX,
215 double &x,
216 bool &isY,
217 double &y) const
218 {
219 FormatCoordsUnits format;
220
221 // Use zero for any empty coordinate
222 QString xTextNotEmpty = QString ("%1").arg (m_editGraphX->text().isEmpty () ? "0" : m_editGraphX->text());
223 QString yTextNotEmpty = QString ("%1").arg (m_editGraphY->text().isEmpty () ? "0" : m_editGraphY->text());
224
225 format.formattedToUnformatted (xTextNotEmpty,
226 yTextNotEmpty,
227 m_modelCoords,
228 m_modelMainWindow,
229 x,
230 y);
231
232 isX = !m_editGraphX->text().isEmpty();
233 isY = !m_editGraphY->text().isEmpty();
234 }
235
236 void DlgEditPointGraph::slotTextChanged (const QString &)
237 {
238 m_changed = true;
239 updateControls ();
240 }
241
242 QString DlgEditPointGraph::unitsType (bool isXTheta) const
243 {
244 if (isCartesian ()) {
245 if (isXTheta) {
246 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsX());
247 } else {
248 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsY());
249 }
250 } else {
251 if (isXTheta) {
252 return coordUnitsPolarThetaToBriefType (m_modelCoords.coordUnitsTheta());
253 } else {
254 return coordUnitsNonPolarThetaToBriefType (m_modelCoords.coordUnitsRadius());
255 }
256 }
257 }
258
259 void DlgEditPointGraph::updateControls ()
260 {
261 QString textX = m_editGraphX->text();
262 QString textY = m_editGraphY->text();
263
264 // Feedback indicating that empty coordinate will be skipped rather than applied to the selected points
265 m_editGraphX->updateBackground ();
266 m_editGraphY->updateBackground ();
267
268 // Tests that all have to be true
269 // 1) At least one value has been changed
270 // 2) At least one value is not empty
271 // 3) The values that are not empty are properly formatted. This is done remembering that we need to
272 // check for not empty (which allows single minus sign) and for valid number (which prevents single
273 // minus sign)
274 bool test2 = (!textX.isEmpty() || !textY.isEmpty());
275
276 int posX, posY;
277 bool test3 = true;
278 if (!textX.isEmpty()) {
279 test3 &= (m_validatorGraphX->validate(textX, posX) == QValidator::Acceptable);
280 }
281 if (!textY.isEmpty()) {
282 test3 &= (m_validatorGraphY->validate(textY, posY) == QValidator::Acceptable);
283 }
284
285 m_btnOk->setEnabled (m_changed && test2 && test3);
286 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef DLG_EDIT_POINT_GRAPH_H
7 #define DLG_EDIT_POINT_GRAPH_H
8
9 #include <QDialog>
10 #include <QPointF>
11 #include <QString>
12
13 class DlgEditPointGraphLineEdit;
14 class DlgValidatorAbstract;
15 class DocumentModelCoords;
16 class MainWindow;
17 class MainWindowModel;
18 class QPushButton;
19 class QVBoxLayout;
20 class Transformation;
21
22 /// Dialog box for editing the information of one or more points.
23 class DlgEditPointGraph : public QDialog
24 {
25 Q_OBJECT;
26
27 public:
28 /// Constructor for existing point which already has graph coordinates (which may be changed using this dialog).
29 /// If initial values are unspecified then the value fields will be initially empty
30 DlgEditPointGraph (MainWindow &mainWindow,
31 const DocumentModelCoords &modelCoords,
32 const MainWindowModel &modelMainWindow,
33 const Transformation &transformation,
34 const double *xInitialValue = 0,
35 const double *yInitialValue = 0);
36 ~DlgEditPointGraph ();
37
38 /// Return one or both coordinates. Only applies if dialog was accepted
39 void posGraph (bool &isX, double &x, bool &isY, double &y) const;
40
41 private slots:
42 void slotTextChanged (const QString &);
43
44 private:
45 DlgEditPointGraph ();
46
47 void createCoords (QVBoxLayout *layoutOuter);
48 void createHint (QVBoxLayout *layoutOuter);
49 void createOkCancel (QVBoxLayout *layoutOuter);
50 void initializeGraphCoordinates (const double *xInitialValue,
51 const double *yInitialValue,
52 const Transformation &transformation);
53 bool isCartesian () const;
54 QChar nameXTheta () const;
55 QChar nameYRadius () const;
56 QString unitsType (bool isXTheta) const;
57 void updateControls ();
58
59 DlgValidatorAbstract *m_validatorGraphX;
60 DlgEditPointGraphLineEdit *m_editGraphX;
61 DlgValidatorAbstract *m_validatorGraphY;
62 DlgEditPointGraphLineEdit *m_editGraphY;
63 QPushButton *m_btnOk;
64 QPushButton *m_btnCancel;
65
66 // Enable Ok button once text has changed. For simplicity, this is true even when original text is restored
67 bool m_changed;
68
69 const DocumentModelCoords &m_modelCoords;
70 const MainWindowModel &m_modelMainWindow;
71 };
72
73 #endif // DLG_EDIT_POINT_GRAPH_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DlgEditPointGraphLineEdit.h"
7 #include "Logger.h"
8 #include <QWidget>
9
10 DlgEditPointGraphLineEdit::DlgEditPointGraphLineEdit (QWidget *widget) :
11 QLineEdit (widget),
12 m_hover (false)
13 {
14 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointGraphLineEdit::DlgEditPointGraphLineEdit";
15 }
16
17 DlgEditPointGraphLineEdit::~DlgEditPointGraphLineEdit()
18 {
19 LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointGraphLineEdit::~DlgEditPointGraphLineEdit";
20 }
21
22 void DlgEditPointGraphLineEdit::enterEvent(QEvent *)
23 {
24 m_hover = true;
25 updateBackground ();
26 }
27
28 void DlgEditPointGraphLineEdit::leaveEvent (QEvent *)
29 {
30 m_hover = false;
31 updateBackground ();
32 }
33
34 void DlgEditPointGraphLineEdit::updateBackground ()
35 {
36 QString color = (m_hover || !text().isEmpty() ? QString ("white") : QString ("#d3d3d3"));
37 QString style = QString ("QLineEdit { background-color: %1; }").arg (color);
38 setStyleSheet (style);
39 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef DLG_EDIT_POINT_GRAPH_LINE_EDIT_H
7 #define DLG_EDIT_POINT_GRAPH_LINE_EDIT_H
8
9 #include <QLineEdit>
10
11 class QWidget;
12
13 /// Adds hover highlighting to QLineEdit
14 class DlgEditPointGraphLineEdit : public QLineEdit
15 {
16 Q_OBJECT;
17
18 public:
19 /// Single constructor
20 DlgEditPointGraphLineEdit (QWidget *widget = 0);
21 ~DlgEditPointGraphLineEdit ();
22
23 /// Hover entry triggers clearing of the background color so user does not think of widget as disabled and is encouraged to enter text
24 virtual void enterEvent(QEvent *);
25
26 /// Hover exit triggers restoration of the background color
27 virtual void leaveEvent (QEvent *);
28
29 /// Update background given the current state
30 void updateBackground ();
31
32 private:
33
34 bool m_hover;
35 };
36
37 #endif // DLG_EDIT_POINT_GRAPH_LINE_EDIT_H
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DlgImportCroppingNonPdf.h"
7 #include "EngaugeAssert.h"
8 #include "Logger.h"
9 #include "MainWindow.h"
10 #include "NonPdfCropping.h"
11 #include <QApplication>
12 #include <QGraphicsPixmapItem>
13 #include <QGraphicsScene>
14 #include <QImage>
15 #include <QLabel>
16 #include <QLayout>
17 #include <QPushButton>
18 #include <QSettings>
19 #include <QSpinBox>
20 #include <QTimer>
21 #include "Settings.h"
22 #include "ViewPreview.h"
23
24 int DlgImportCroppingNonPdf::MINIMUM_DIALOG_WIDTH = 350;
25 int DlgImportCroppingNonPdf::MINIMUM_PREVIEW_HEIGHT = 200;
26
27 DlgImportCroppingNonPdf::DlgImportCroppingNonPdf(const QString &fileName) :
28 m_fileName (fileName),
29 m_pixmap (0)
30 {
31 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::DlgImportCroppingNonPdf";
32
33 setWindowTitle (tr ("Image File Import Cropping"));
34 setModal (true);
35
36 QWidget *subPanel = new QWidget ();
37 QGridLayout *layout = new QGridLayout (subPanel);
38 subPanel->setLayout (layout);
39
40 int row = 0;
41
42 createPreview (layout, row);
43 finishPanel (subPanel);
44 updatePreview ();
45
46 // Bring the two middle columns together
47 layout->setColumnStretch (0, 1);
48 layout->setColumnStretch (1, 0);
49 layout->setColumnStretch (2, 0);
50 layout->setColumnStretch (3, 1);
51 }
52
53 DlgImportCroppingNonPdf::~DlgImportCroppingNonPdf()
54 {
55 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::~DlgImportCroppingNonPdf";
56 }
57
58 void DlgImportCroppingNonPdf::createNonPdfCropping ()
59 {
60 // Create frame that shows what will be included, and what will be excluded, during the import
61 m_nonPdfCropping = new NonPdfCropping (*m_scenePreview,
62 *m_viewPreview);
63 }
64
65 void DlgImportCroppingNonPdf::createPreview (QGridLayout *layout,
66 int &row)
67 {
68 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::createPreview";
69
70 QLabel *labelPreview = new QLabel (tr ("Preview"));
71 layout->addWidget (labelPreview, row++, 0, 1, 1, Qt::AlignLeft);
72
73 m_scenePreview = new QGraphicsScene (this);
74 m_viewPreview = new ViewPreview (m_scenePreview,
75 ViewPreview::VIEW_ASPECT_RATIO_ONE_TO_ONE,
76 this);
77 m_viewPreview->setWhatsThis (tr ("Preview window that shows what part of the image will be imported. "
78 "The image portion inside the rectangular frame will be imported from the currently selected page. "
79 "The frame can be moved and resized by dragging the corner handles."));
80 m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
81 m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
82 m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
83 layout->addWidget (m_viewPreview, row++, 0, 1, 4);
84
85 // More preview initialization
86 initializeFrameGeometryAndPixmap (); // Before first call to updatePreview
87 createNonPdfCropping ();
88 }
89
90 void DlgImportCroppingNonPdf::finishPanel (QWidget *subPanel)
91 {
92 const int STRETCH_OFF = 0, STRETCH_ON = 1;
93
94 QVBoxLayout *panelLayout = new QVBoxLayout (this);
95
96 setMinimumWidth (MINIMUM_DIALOG_WIDTH);
97 setLayout (panelLayout);
98
99 panelLayout->addWidget (subPanel);
100 panelLayout->setStretch (panelLayout->count () - 1, STRETCH_ON);
101
102 QWidget *panelButtons = new QWidget (this);
103 QHBoxLayout *buttonLayout = new QHBoxLayout (panelButtons);
104
105 QHBoxLayout *layoutRightSide = new QHBoxLayout;
106
107 QWidget *widgetRightSide = new QWidget;
108 widgetRightSide->setLayout (layoutRightSide);
109 buttonLayout->addWidget (widgetRightSide);
110
111 QSpacerItem *spacerExpanding = new QSpacerItem (40, 5, QSizePolicy::Expanding, QSizePolicy::Expanding);
112 layoutRightSide->addItem (spacerExpanding);
113
114 m_btnOk = new QPushButton (tr ("Ok"));
115 layoutRightSide->addWidget (m_btnOk, 0, Qt::AlignRight);
116 connect (m_btnOk, SIGNAL (released ()), this, SLOT (slotOk ()));
117
118 QSpacerItem *spacerFixed = new QSpacerItem (40, 5, QSizePolicy::Fixed, QSizePolicy::Fixed);
119 layoutRightSide->addItem (spacerFixed);
120
121 m_btnCancel = new QPushButton (tr ("Cancel"));
122 layoutRightSide->addWidget (m_btnCancel, 0, Qt::AlignRight);
123 connect (m_btnCancel, SIGNAL (released ()), this, SLOT (slotCancel ()));
124
125 panelLayout->addWidget (panelButtons, STRETCH_ON);
126 panelLayout->setStretch (panelLayout->count () - 1, STRETCH_OFF);
127 }
128
129 QImage DlgImportCroppingNonPdf::image () const
130 {
131 // If the entire page was to be returned, then this method would simply return m_image. However, only the framed
132 // portion is to be returned
133 ENGAUGE_ASSERT (m_nonPdfCropping != 0);
134 QRectF rectFramePixels = m_nonPdfCropping->frameRect ();
135
136 return m_image.copy (rectFramePixels.toRect ());
137 }
138
139 void DlgImportCroppingNonPdf::initializeFrameGeometryAndPixmap ()
140 {
141 m_image = loadImage ();
142 QGraphicsPixmapItem *pixmap = new QGraphicsPixmapItem (QPixmap::fromImage (m_image));
143 m_scenePreview->addItem (pixmap);
144
145 // Force resize so image fills preview area. We do this only once initially for speed
146 m_viewPreview->setSceneRect (pixmap->boundingRect ());
147 }
148
149 QImage DlgImportCroppingNonPdf::loadImage () const
150 {
151 QImage image;
152 image.load (m_fileName);
153
154 return image;
155 }
156
157 void DlgImportCroppingNonPdf::saveGeometryToSettings()
158 {
159 // Store the settings for use by showEvent
160 QSettings settings;
161 settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
162 settings.setValue (SETTINGS_IMPORT_CROPPING_POS, saveGeometry ());
163 settings.endGroup();
164 }
165
166 void DlgImportCroppingNonPdf::showEvent (QShowEvent * /* event */)
167 {
168 QSettings settings;
169 settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
170 if (settings.contains (SETTINGS_IMPORT_CROPPING_POS)) {
171
172 // Restore the settings that were stored by the last call to saveGeometryToSettings
173 restoreGeometry (settings.value (SETTINGS_IMPORT_CROPPING_POS).toByteArray ());
174 }
175 }
176
177 void DlgImportCroppingNonPdf::slotCancel ()
178 {
179 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::slotCancel";
180
181 // Restore cursor in case updatePreview has not already completed and then restored it
182 QApplication::restoreOverrideCursor ();
183
184 setResult (QDialog::Rejected);
185 saveGeometryToSettings();
186 hide();
187 }
188
189 void DlgImportCroppingNonPdf::slotOk ()
190 {
191 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::slotOk";
192
193 // Restore cursor in case updatePreview has not already completed and then restored it
194 QApplication::restoreOverrideCursor ();
195
196 setResult (QDialog::Accepted);
197 saveGeometryToSettings();
198 hide();
199 }
200
201 void DlgImportCroppingNonPdf::updatePreview ()
202 {
203 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::updatePreview";
204
205 if (m_pixmap != 0) {
206 m_scenePreview->removeItem (m_pixmap);
207 }
208
209 m_image = loadImage ();
210 m_pixmap = new QGraphicsPixmapItem (QPixmap::fromImage (m_image));
211 m_scenePreview->addItem (m_pixmap);
212
213 // Calculations for preview updating are now over
214 QApplication::restoreOverrideCursor ();
215 }
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef DLG_IMPORT_CROPPING_NON_PDF_H
7 #define DLG_IMPORT_CROPPING_NON_PDF_H
8
9 #include <QDialog>
10 #include <QImage>
11 #include <QObject>
12
13 class NonPdfCropping;
14 class QGraphicsPixmapItem;
15 class QGridLayout;
16 class QGraphicsScene;
17 class QRectF;
18 class QSpinBox;
19 class QString;
20 class ViewPreview;
21
22 /// Dialog for selecting a page and frame on that page when importing an image from a non-pdf file
23 class DlgImportCroppingNonPdf : public QDialog
24 {
25 Q_OBJECT;
26
27 public:
28 /// Single constructor.
29 DlgImportCroppingNonPdf (const QString &fileName);
30 virtual ~DlgImportCroppingNonPdf ();
31
32 /// Image that was selected. Value is null if loading failed
33 QImage image () const;
34
35 /// Do preparation before dialog is displayed.
36 virtual void showEvent (QShowEvent *event);
37
38 private slots:
39
40 /// Hide dialog.
41 void slotCancel();
42
43 /// Save changes entered in dialog.
44 void slotOk ();
45
46 private:
47 DlgImportCroppingNonPdf ();
48
49 void createNonPdfCropping();
50 void createPreview (QGridLayout *layout,
51 int &row);
52 void finishPanel (QWidget *subPanel);
53 void initializeFrameGeometryAndPixmap ();
54 QImage loadImage () const;
55
56 /// Dialog layout constant that guarantees every widget has sufficient room
57 static int MINIMUM_DIALOG_WIDTH;
58
59 /// Dialog layout constant that guarantees preview has sufficent room
60 static int MINIMUM_PREVIEW_HEIGHT;
61
62 void saveGeometryToSettings ();
63 void updatePreview ();
64
65 QPushButton *m_btnCancel;
66 QPushButton *m_btnOk;
67
68 const QString &m_fileName;
69 QImage m_image; // Needed so it can be passed to external code when this dialog has finished successfully
70 QGraphicsPixmapItem *m_pixmap; // Needed so old image can be removed just before new one gets added
71
72 QGraphicsScene *m_scenePreview;
73 ViewPreview *m_viewPreview;
74
75 NonPdfCropping *m_nonPdfCropping;
76 };
77
78 #endif // DLG_IMPORT_CROPPING_NON_PDF_H
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DlgImportCroppingPdf.h"
7 #include "EngaugeAssert.h"
8 #include "Logger.h"
9 #include "MainWindow.h"
10 #include "PdfCropping.h"
11 #include "poppler-qt5.h"
12 #include <QApplication>
13 #include <QGraphicsPixmapItem>
14 #include <QGraphicsScene>
15 #include <QImage>
16 #include <QLabel>
17 #include <QLayout>
18 #include <QPushButton>
19 #include <QSettings>
20 #include <QSpinBox>
21 #include <QTimer>
22 #include "Settings.h"
23 #include "ViewPreview.h"
24
25 using namespace Poppler;
26
27 int DlgImportCroppingPdf::MINIMUM_DIALOG_WIDTH = 350;
28 int DlgImportCroppingPdf::MINIMUM_PREVIEW_HEIGHT = 200;
29 const int X_TOP_LEFT = 0, Y_TOP_LEFT = 0;
30 const int WIDTH = -1, HEIGHT = -1; // Negative values give full page
31 const int FIRST_PAGE_1_BASED = 1;
32 const int SMALLEST_DELAY_MS = 500; // Below 500 triggers "double jump" bug in linux
33
34 DlgImportCroppingPdf::DlgImportCroppingPdf(const Poppler::Document &document,
35 int resolution) :
36 m_document (document),
37 m_resolution (resolution),
38 m_pixmap (0)
39 {
40 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::DlgImportCroppingPdf";
41
42 setWindowTitle (tr ("PDF File Import Cropping"));
43 setModal (true);
44
45 QWidget *subPanel = new QWidget ();
46 QGridLayout *layout = new QGridLayout (subPanel);
47 subPanel->setLayout (layout);
48
49 int row = 0;
50
51 createTimer ();
52 createPageSpinner (layout, row);
53 createPreview (layout, row);
54 finishPanel (subPanel);
55 updatePreview ();
56
57 // Bring the two middle columns together
58 layout->setColumnStretch (0, 1);
59 layout->setColumnStretch (1, 0);
60 layout->setColumnStretch (2, 0);
61 layout->setColumnStretch (3, 1);
62 }
63
64 DlgImportCroppingPdf::~DlgImportCroppingPdf()
65 {
66 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::~DlgImportCroppingPdf";
67 }
68
69 void DlgImportCroppingPdf::createPageSpinner (QGridLayout *layout,
70 int &row)
71 {
72 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::createPageSpinner";
73
74 const int MIN_WIDTH_SPINNER = 90;
75
76 QLabel *labelPage = new QLabel (tr ("Page:"));
77 layout->addWidget (labelPage, row, 1, 1, 1);
78
79 m_spinPage = new QSpinBox;
80 m_spinPage->setMinimumWidth (MIN_WIDTH_SPINNER);
81 m_spinPage->setWhatsThis (tr ("Page number that will be imported"));
82 m_spinPage->setRange (1, m_document.numPages());
83 layout->addWidget (m_spinPage, row++, 2, 1, 1);
84 connect (m_spinPage, SIGNAL (valueChanged (int)), this, SLOT (slotPage (int)));
85 }
86
87 void DlgImportCroppingPdf::createPdfCropping ()
88 {
89 // Create frame that shows what will be included, and what will be excluded, during the import
90 m_pdfCropping = new PdfCropping (*m_scenePreview,
91 *m_viewPreview);
92 }
93
94 void DlgImportCroppingPdf::createPreview (QGridLayout *layout,
95 int &row)
96 {
97 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::createPreview";
98
99 QLabel *labelPreview = new QLabel (tr ("Preview"));
100 layout->addWidget (labelPreview, row++, 0, 1, 1, Qt::AlignLeft);
101
102 m_scenePreview = new QGraphicsScene (this);
103 m_viewPreview = new ViewPreview (m_scenePreview,
104 ViewPreview::VIEW_ASPECT_RATIO_ONE_TO_ONE,
105 this);
106 m_viewPreview->setWhatsThis (tr ("Preview window that shows what part of the image will be imported. "
107 "The image portion inside the rectangular frame will be imported from the currently selected page. "
108 "The frame can be moved and resized by dragging the corner handles."));
109 m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
110 m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
111 m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
112 layout->addWidget (m_viewPreview, row++, 0, 1, 4);
113
114 // More preview initialization
115 initializeFrameGeometryAndPixmap (); // Before first call to updatePreview
116 createPdfCropping ();
117 }
118
119 void DlgImportCroppingPdf::createTimer ()
120 {
121 m_timer = new QTimer;
122 m_timer->setSingleShot (true);
123 connect (m_timer, SIGNAL (timeout ()), this, SLOT (slotTimeout ()));
124 }
125
126 void DlgImportCroppingPdf::finishPanel (QWidget *subPanel)
127 {
128 const int STRETCH_OFF = 0, STRETCH_ON = 1;
129
130 QVBoxLayout *panelLayout = new QVBoxLayout (this);
131
132 setMinimumWidth (MINIMUM_DIALOG_WIDTH);
133 setLayout (panelLayout);
134
135 panelLayout->addWidget (subPanel);
136 panelLayout->setStretch (panelLayout->count () - 1, STRETCH_ON);
137
138 QWidget *panelButtons = new QWidget (this);
139 QHBoxLayout *buttonLayout = new QHBoxLayout (panelButtons);
140
141 QHBoxLayout *layoutRightSide = new QHBoxLayout;
142
143 QWidget *widgetRightSide = new QWidget;
144 widgetRightSide->setLayout (layoutRightSide);
145 buttonLayout->addWidget (widgetRightSide);
146
147 QSpacerItem *spacerExpanding = new QSpacerItem (40, 5, QSizePolicy::Expanding, QSizePolicy::Expanding);
148 layoutRightSide->addItem (spacerExpanding);
149
150 m_btnOk = new QPushButton (tr ("Ok"));
151 layoutRightSide->addWidget (m_btnOk, 0, Qt::AlignRight);
152 connect (m_btnOk, SIGNAL (released ()), this, SLOT (slotOk ()));
153
154 QSpacerItem *spacerFixed = new QSpacerItem (40, 5, QSizePolicy::Fixed, QSizePolicy::Fixed);
155 layoutRightSide->addItem (spacerFixed);
156
157 m_btnCancel = new QPushButton (tr ("Cancel"));
158 layoutRightSide->addWidget (m_btnCancel, 0, Qt::AlignRight);
159 connect (m_btnCancel, SIGNAL (released ()), this, SLOT (slotCancel ()));
160
161 panelLayout->addWidget (panelButtons, STRETCH_ON);
162 panelLayout->setStretch (panelLayout->count () - 1, STRETCH_OFF);
163 }
164
165 QImage DlgImportCroppingPdf::image () const
166 {
167 // If the entire page was to be returned, then this method would simply return m_image. However, only the framed
168 // portion is to be returned
169 ENGAUGE_ASSERT (m_pdfCropping != 0);
170 QRectF rectFramePixels = m_pdfCropping->frameRect ();
171
172 return m_image.copy (rectFramePixels.toRect ());
173 }
174
175 void DlgImportCroppingPdf::initializeFrameGeometryAndPixmap ()
176 {
177 m_image = loadImage (FIRST_PAGE_1_BASED);
178 QGraphicsPixmapItem *pixmap = new QGraphicsPixmapItem (QPixmap::fromImage (m_image));
179 m_scenePreview->addItem (pixmap);
180
181 // Force resize so image fills preview area. We do this only once initially for speed
182 m_viewPreview->setSceneRect (pixmap->boundingRect ());
183 }
184
185 QImage DlgImportCroppingPdf::loadImage (int page1Based) const
186 {
187 QImage image;
188
189 int page0Based = page1Based - 1;
190 Page *page = m_document.page (page0Based);
191 if (page != 0) {
192
193 image = page->renderToImage (m_resolution,
194 m_resolution,
195 X_TOP_LEFT,
196 Y_TOP_LEFT,
197 WIDTH,
198 HEIGHT);
199
200 delete page;
201 }
202
203 return image;
204 }
205
206 void DlgImportCroppingPdf::saveGeometryToSettings()
207 {
208 // Store the settings for use by showEvent
209 QSettings settings;
210 settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
211 settings.setValue (SETTINGS_IMPORT_CROPPING_POS, saveGeometry ());
212 settings.endGroup();
213 }
214
215 void DlgImportCroppingPdf::showEvent (QShowEvent * /* event */)
216 {
217 QSettings settings;
218 settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
219 if (settings.contains (SETTINGS_IMPORT_CROPPING_POS)) {
220
221 // Restore the settings that were stored by the last call to saveGeometryToSettings
222 restoreGeometry (settings.value (SETTINGS_IMPORT_CROPPING_POS).toByteArray ());
223 }
224 }
225
226 void DlgImportCroppingPdf::slotCancel ()
227 {
228 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::slotCancel";
229
230 // Restore cursor in case updatePreview has not already completed and then restored it
231 QApplication::restoreOverrideCursor ();
232
233 setResult (QDialog::Rejected);
234 saveGeometryToSettings();
235 hide();
236 }
237
238 void DlgImportCroppingPdf::slotOk ()
239 {
240 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::slotOk";
241
242 // Restore cursor in case updatePreview has not already completed and then restored it
243 QApplication::restoreOverrideCursor ();
244
245 setResult (QDialog::Accepted);
246 saveGeometryToSettings();
247 hide();
248 }
249
250 void DlgImportCroppingPdf::slotPage (int page)
251 {
252 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::slotPage"
253 << " page=" << page
254 << " stepBy=" << m_spinPage->singleStep ();
255
256 // Show wait cursor until slow calculations are over
257 QApplication::setOverrideCursor (Qt::WaitCursor);
258
259 m_timer->start (SMALLEST_DELAY_MS);
260 }
261
262 void DlgImportCroppingPdf::slotTimeout ()
263 {
264 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::slotTimeout";
265
266 updatePreview ();
267 }
268
269 void DlgImportCroppingPdf::updatePreview ()
270 {
271 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::updatePreview";
272
273 if (m_pixmap != 0) {
274 m_scenePreview->removeItem (m_pixmap);
275 }
276
277 m_image = loadImage (m_spinPage->value ());
278 m_pixmap = new QGraphicsPixmapItem (QPixmap::fromImage (m_image));
279 m_scenePreview->addItem (m_pixmap);
280
281 // Calculations for preview updating are now over
282 QApplication::restoreOverrideCursor ();
283 }
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef DLG_IMPORT_CROPPING_PDF_H
7 #define DLG_IMPORT_CROPPING_PDF_H
8
9 #include <QDialog>
10 #include <QImage>
11 #include <QObject>
12
13 namespace Poppler {
14 class Document;
15 }
16 class PdfCropping;
17 class QGraphicsPixmapItem;
18 class QGridLayout;
19 class QGraphicsScene;
20 class QRectF;
21 class QSpinBox;
22 class QString;
23 class QTimer;
24 class ViewPreview;
25
26 /// Dialog for selecting a page and frame on that page when importing an image from a pdf file
27 class DlgImportCroppingPdf : public QDialog
28 {
29 Q_OBJECT;
30
31 public:
32 /// Single constructor.
33 DlgImportCroppingPdf (const Poppler::Document &document,
34 int resolution);
35 virtual ~DlgImportCroppingPdf ();
36
37 /// Image that was selected. Value is null if loading failed
38 QImage image () const;
39
40 /// Do preparation before dialog is displayed.
41 virtual void showEvent (QShowEvent *event);
42
43 private slots:
44
45 /// Hide dialog.
46 void slotCancel();
47
48 /// Save changes entered in dialog.
49 void slotOk ();
50
51 /// Page number has changed
52 void slotPage (int);
53
54 /// Slow processing of pdf is performed asynchronously using a timer so event handlers are not slowed down
55 void slotTimeout ();
56
57 private:
58 DlgImportCroppingPdf();
59
60 void createPageSpinner (QGridLayout *layout,
61 int &row);
62 void createPdfCropping ();
63 void createPreview (QGridLayout *layout,
64 int &row);
65 void createTimer ();
66 void finishPanel (QWidget *subPanel);
67 void initializeFrameGeometryAndPixmap ();
68 QImage loadImage (int page1Based) const;
69
70 /// Dialog layout constant that guarantees every widget has sufficient room
71 static int MINIMUM_DIALOG_WIDTH;
72
73 /// Dialog layout constant that guarantees preview has sufficent room
74 static int MINIMUM_PREVIEW_HEIGHT;
75
76 void saveGeometryToSettings ();
77 void updatePreview ();
78
79 QSpinBox *m_spinPage;
80 QPushButton *m_btnCancel;
81 QPushButton *m_btnOk;
82
83 QTimer *m_timer;
84 const Poppler::Document &m_document;
85 int m_resolution;
86 QImage m_image; // Needed so it can be passed to external code when this dialog has finished successfully
87 QGraphicsPixmapItem *m_pixmap; // Needed so old image can be removed just before new one gets added
88
89 QGraphicsScene *m_scenePreview;
90 ViewPreview *m_viewPreview;
91
92 PdfCropping *m_pdfCropping;
93 };
94
95 #endif // DLG_IMPORT_CROPPING_PDF_H
+0
-284
src/Dlg/DlgPdfFrame.cpp less more
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DlgPdfFrame.h"
7 #include "EngaugeAssert.h"
8 #include "Logger.h"
9 #include "MainWindow.h"
10 #include "PdfFrame.h"
11 #include "poppler-qt5.h"
12 #include <QApplication>
13 #include <QGraphicsPixmapItem>
14 #include <QGraphicsScene>
15 #include <QImage>
16 #include <QLabel>
17 #include <QLayout>
18 #include <QPushButton>
19 #include <QSettings>
20 #include <QSpinBox>
21 #include <QTimer>
22 #include "Settings.h"
23 #include "ViewPreview.h"
24
25 using namespace Poppler;
26
27 int DlgPdfFrame::MINIMUM_DIALOG_WIDTH = 350;
28 int DlgPdfFrame::MINIMUM_PREVIEW_HEIGHT = 200;
29 const int X_TOP_LEFT = 0, Y_TOP_LEFT = 0;
30 const int WIDTH = -1, HEIGHT = -1; // Negative values give full page
31 const int FIRST_PAGE_1_BASED = 1;
32 const int SMALLEST_DELAY_MS = 500; // Below 500 triggers "double jump" bug in linux
33
34 DlgPdfFrame::DlgPdfFrame(const Poppler::Document &document,
35 int resolution) :
36 m_document (document),
37 m_resolution (resolution),
38 m_pixmap (0)
39 {
40 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::DlgPdfFrame";
41
42 setWindowTitle (tr ("PDF Frame"));
43 setModal (true);
44
45 QWidget *subPanel = new QWidget ();
46 QGridLayout *layout = new QGridLayout (subPanel);
47 subPanel->setLayout (layout);
48
49 int row = 0;
50
51 createTimer ();
52 createPageSpinner (layout, row);
53 createPreview (layout, row);
54 finishPanel (subPanel);
55 updatePreview ();
56
57 // Bring the two middle columns together
58 layout->setColumnStretch (0, 1);
59 layout->setColumnStretch (1, 0);
60 layout->setColumnStretch (2, 0);
61 layout->setColumnStretch (3, 1);
62 }
63
64 DlgPdfFrame::~DlgPdfFrame()
65 {
66 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::~DlgPdfFrame";
67 }
68
69 void DlgPdfFrame::createPageSpinner (QGridLayout *layout,
70 int &row)
71 {
72 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::createPageSpinner";
73
74 const int MIN_WIDTH_SPINNER = 90;
75
76 QLabel *labelPage = new QLabel (tr ("Page:"));
77 layout->addWidget (labelPage, row, 1, 1, 1);
78
79 m_spinPage = new QSpinBox;
80 m_spinPage->setMinimumWidth (MIN_WIDTH_SPINNER);
81 m_spinPage->setWhatsThis (tr ("Page number that will be imported"));
82 m_spinPage->setRange (1, m_document.numPages());
83 layout->addWidget (m_spinPage, row++, 2, 1, 1);
84 connect (m_spinPage, SIGNAL (valueChanged (int)), this, SLOT (slotPage (int)));
85 }
86
87 void DlgPdfFrame::createPreview (QGridLayout *layout,
88 int &row)
89 {
90 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::createPreview";
91
92 QLabel *labelPreview = new QLabel (tr ("Preview"));
93 layout->addWidget (labelPreview, row++, 0, 1, 1, Qt::AlignLeft);
94
95 m_scenePreview = new QGraphicsScene (this);
96 m_viewPreview = new ViewPreview (m_scenePreview,
97 ViewPreview::VIEW_ASPECT_RATIO_ONE_TO_ONE,
98 this);
99 m_viewPreview->setWhatsThis (tr ("Preview window that shows what part of the image will be imported. "
100 "The image portion inside the rectangular frame will be imported from the currently selected page. "
101 "The frame can be moved and resized by dragging the corner handles."));
102 m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
103 m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
104 m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
105 layout->addWidget (m_viewPreview, row++, 0, 1, 4);
106
107 // More preview initialization
108 initializeFrameGeometryAndPixmap (); // Before first call to updatePreview
109 createPdfFrame ();
110 }
111
112 void DlgPdfFrame::createPdfFrame ()
113 {
114 // Create frame that shows what will be included, and what will be excluded, during the import
115 m_pdfFrame = new PdfFrame (*m_scenePreview,
116 *m_viewPreview);
117 }
118
119 void DlgPdfFrame::createTimer ()
120 {
121 m_timer = new QTimer;
122 m_timer->setSingleShot (true);
123 connect (m_timer, SIGNAL (timeout ()), this, SLOT (slotTimeout ()));
124 }
125
126 void DlgPdfFrame::finishPanel (QWidget *subPanel)
127 {
128 const int STRETCH_OFF = 0, STRETCH_ON = 1;
129
130 QVBoxLayout *panelLayout = new QVBoxLayout (this);
131
132 setMinimumWidth (MINIMUM_DIALOG_WIDTH);
133 setLayout (panelLayout);
134
135 panelLayout->addWidget (subPanel);
136 panelLayout->setStretch (panelLayout->count () - 1, STRETCH_ON);
137
138 QWidget *panelButtons = new QWidget (this);
139 QHBoxLayout *buttonLayout = new QHBoxLayout (panelButtons);
140
141 QHBoxLayout *layoutRightSide = new QHBoxLayout;
142
143 QWidget *widgetRightSide = new QWidget;
144 widgetRightSide->setLayout (layoutRightSide);
145 buttonLayout->addWidget (widgetRightSide);
146
147 QSpacerItem *spacerExpanding = new QSpacerItem (40, 5, QSizePolicy::Expanding, QSizePolicy::Expanding);
148 layoutRightSide->addItem (spacerExpanding);
149
150 m_btnOk = new QPushButton (tr ("Ok"));
151 layoutRightSide->addWidget (m_btnOk, 0, Qt::AlignRight);
152 connect (m_btnOk, SIGNAL (released ()), this, SLOT (slotOk ()));
153
154 QSpacerItem *spacerFixed = new QSpacerItem (40, 5, QSizePolicy::Fixed, QSizePolicy::Fixed);
155 layoutRightSide->addItem (spacerFixed);
156
157 m_btnCancel = new QPushButton (tr ("Cancel"));
158 layoutRightSide->addWidget (m_btnCancel, 0, Qt::AlignRight);
159 connect (m_btnCancel, SIGNAL (released ()), this, SLOT (slotCancel ()));
160
161 panelLayout->addWidget (panelButtons, STRETCH_ON);
162 panelLayout->setStretch (panelLayout->count () - 1, STRETCH_OFF);
163 }
164
165 QImage DlgPdfFrame::image () const
166 {
167 // If the entire page was to be returned, then this method would simply return m_image. However, only the framed
168 // portion is to be returned
169 ENGAUGE_ASSERT (m_pdfFrame != 0);
170 QRectF rectFramePixels = m_pdfFrame->frameRect ();
171
172 return m_image.copy (rectFramePixels.toRect ());
173 }
174
175 void DlgPdfFrame::initializeFrameGeometryAndPixmap ()
176 {
177 m_image = loadImage (FIRST_PAGE_1_BASED);
178 QGraphicsPixmapItem *pixmap = new QGraphicsPixmapItem (QPixmap::fromImage (m_image));
179 m_scenePreview->addItem (pixmap);
180
181 // Force resize so image fills preview area. We do this only once initially for speed
182 m_viewPreview->setSceneRect (pixmap->boundingRect ());
183 }
184
185 QImage DlgPdfFrame::loadImage (int page1Based) const
186 {
187 QImage image;
188
189 int page0Based = page1Based - 1;
190 Page *page = m_document.page (page0Based);
191 if (page != 0) {
192
193 image = page->renderToImage (m_resolution,
194 m_resolution,
195 X_TOP_LEFT,
196 Y_TOP_LEFT,
197 WIDTH,
198 HEIGHT);
199
200 delete page;
201 }
202
203 return image;
204 }
205
206 void DlgPdfFrame::saveGeometryToSettings()
207 {
208 // Store the settings for use by showEvent
209 QSettings settings;
210 settings.beginGroup (SETTINGS_GROUP_PDF);
211 settings.setValue (SETTINGS_PDF_POS, saveGeometry ());
212 settings.endGroup();
213 }
214
215 void DlgPdfFrame::showEvent (QShowEvent * /* event */)
216 {
217 QSettings settings;
218 settings.beginGroup (SETTINGS_GROUP_PDF);
219 if (settings.contains (SETTINGS_PDF_POS)) {
220
221 // Restore the settings that were stored by the last call to saveGeometryToSettings
222 restoreGeometry (settings.value (SETTINGS_PDF_POS).toByteArray ());
223 }
224 }
225
226 void DlgPdfFrame::slotCancel ()
227 {
228 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::slotCancel";
229
230 // Restore cursor in case updatePreview has not already completed and then restored it
231 QApplication::restoreOverrideCursor ();
232
233 setResult (QDialog::Rejected);
234 saveGeometryToSettings();
235 hide();
236 }
237
238 void DlgPdfFrame::slotOk ()
239 {
240 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::slotOk";
241
242 // Restore cursor in case updatePreview has not already completed and then restored it
243 QApplication::restoreOverrideCursor ();
244
245 setResult (QDialog::Accepted);
246 saveGeometryToSettings();
247 hide();
248 }
249
250 void DlgPdfFrame::slotPage (int page)
251 {
252 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::slotPage"
253 << " page=" << page
254 << " stepBy=" << m_spinPage->singleStep ();
255
256 // Show wait cursor until slow calculations are over
257 QApplication::setOverrideCursor (Qt::WaitCursor);
258
259 m_timer->start (SMALLEST_DELAY_MS);
260 }
261
262 void DlgPdfFrame::slotTimeout ()
263 {
264 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::slotTimeout";
265
266 updatePreview ();
267 }
268
269 void DlgPdfFrame::updatePreview ()
270 {
271 LOG4CPP_INFO_S ((*mainCat)) << "DlgPdfFrame::updatePreview";
272
273 if (m_pixmap != 0) {
274 m_scenePreview->removeItem (m_pixmap);
275 }
276
277 m_image = loadImage (m_spinPage->value ());
278 m_pixmap = new QGraphicsPixmapItem (QPixmap::fromImage (m_image));
279 m_scenePreview->addItem (m_pixmap);
280
281 // Calculations for preview updating are now over
282 QApplication::restoreOverrideCursor ();
283 }
+0
-96
src/Dlg/DlgPdfFrame.h less more
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef DLG_PDF_FRAME_H
7 #define DLG_PDF_FRAME_H
8
9 #include <QDialog>
10 #include <QImage>
11 #include <QObject>
12
13 class PdfFrame;
14 namespace Poppler {
15 class Document;
16 }
17 class QGraphicsPixmapItem;
18 class QGridLayout;
19 class QGraphicsScene;
20 class QRectF;
21 class QSpinBox;
22 class QString;
23 class QTimer;
24 class ViewPreview;
25
26 /// Dialog for selecting a page and frame on that page when importing an image from a pdf file
27 class DlgPdfFrame : public QDialog
28 {
29 Q_OBJECT;
30
31 public:
32 /// Single constructor.
33 DlgPdfFrame(const Poppler::Document &document,
34 int resolution);
35 virtual ~DlgPdfFrame();
36
37 /// Image that was selected. Value is null if loading failed
38 QImage image () const;
39
40 /// Do preparation before dialog is displayed.
41 virtual void showEvent (QShowEvent *event);
42
43 private slots:
44
45 /// Hide dialog.
46 void slotCancel();
47
48 /// Save changes entered in dialog.
49 void slotOk ();
50
51 /// Page number has changed
52 void slotPage (int);
53
54 /// Slow processing of pdf is performed asynchronously using a timer so event handlers are not slowed down
55 void slotTimeout ();
56
57 private:
58 DlgPdfFrame();
59
60 void createPageSpinner (QGridLayout *layout,
61 int &row);
62 void createPdfFrame ();
63 void createPreview (QGridLayout *layout,
64 int &row);
65 void createTimer ();
66 void finishPanel (QWidget *subPanel);
67 void initializeFrameGeometryAndPixmap ();
68 QImage loadImage (int page1Based) const;
69
70 /// Dialog layout constant that guarantees every widget has sufficient room
71 static int MINIMUM_DIALOG_WIDTH;
72
73 /// Dialog layout constant that guarantees preview has sufficent room
74 static int MINIMUM_PREVIEW_HEIGHT;
75
76 void saveGeometryToSettings ();
77 void updatePreview ();
78
79 QSpinBox *m_spinPage;
80 QPushButton *m_btnCancel;
81 QPushButton *m_btnOk;
82
83 QTimer *m_timer;
84 const Poppler::Document &m_document;
85 int m_resolution;
86 QImage m_image; // Needed so it can be passed to external code when this dialog has finished successfully
87 QGraphicsPixmapItem *m_pixmap; // Needed so old image can be removed just before new one gets added
88
89 QGraphicsScene *m_scenePreview;
90 ViewPreview *m_viewPreview;
91
92 PdfFrame *m_pdfFrame;
93 };
94
95 #endif // DLG_PDF_FRAME_H
99 #include "DlgSettingsCurveProperties.h"
1010 #include "EngaugeAssert.h"
1111 #include "EnumsToQt.h"
12 #include "GeometryWindow.h"
1213 #include "GraphicsPoint.h"
1314 #include "GraphicsPointFactory.h"
1415 #include "GraphicsView.h"
5859 DlgSettingsAbstractBase (tr ("Curve Properties"),
5960 "DlgSettingsCurveProperties",
6061 mainWindow),
62 m_modelMainWindow (mainWindow.modelMainWindow()),
6163 m_scenePreview (0),
6264 m_viewPreview (0),
6365 m_modelCurveStylesBefore (0),
325327 void DlgSettingsCurveProperties::drawPoints (const PointStyle &pointStyle)
326328 {
327329 const QString NULL_IDENTIFIER;
330 GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
328331
329332 GraphicsPointFactory pointFactory;
330333
332335 GraphicsPoint *pointLeft = pointFactory.createPoint (*m_scenePreview,
333336 NULL_IDENTIFIER,
334337 POS_LEFT,
335 pointStyle);
338 pointStyle,
339 NULL_GEOMETRY_WINDOW);
336340 pointLeft->setPointStyle (pointStyle);
337341
338342 // Center point
339343 GraphicsPoint *pointCenter = pointFactory.createPoint (*m_scenePreview,
340344 NULL_IDENTIFIER,
341345 POS_CENTER,
342 pointStyle);
346 pointStyle,
347 NULL_GEOMETRY_WINDOW);
343348 pointCenter->setPointStyle (pointStyle);
344349
345350 // Right point
346351 GraphicsPoint *pointRight = pointFactory.createPoint (*m_scenePreview,
347352 NULL_IDENTIFIER,
348353 POS_RIGHT,
349 pointStyle);
354 pointStyle,
355 NULL_GEOMETRY_WINDOW);
350356 pointRight->setPointStyle (pointStyle);
351357 }
352358
88
99 #include "CurveStyles.h"
1010 #include "DlgSettingsAbstractBase.h"
11 #include "MainWindowModel.h"
1112
1213 class GraphicsPoint;
1314 class QComboBox;
6263 void updateControls();
6364 void updatePreview();
6465
66 MainWindowModel m_modelMainWindow;
67
6568 QComboBox *m_cmbCurveName;
6669
6770 QGroupBox *m_groupPoint;
7272 layout->addWidget (labelExcluded, row++, 2);
7373
7474 m_listIncluded = new QListWidget;
75 m_listIncluded->setSortingEnabled (false); // Preserve order from Document
7576 m_listIncluded->setWhatsThis (tr ("List of curves to be included in the exported file.\n\n"
7677 "The order of the curves here does not affect the order in the exported file. That "
7778 "order is determined by the Curves settings."));
8081 connect (m_listIncluded, SIGNAL (itemSelectionChanged ()), this, SLOT (slotListIncluded()));
8182
8283 m_listExcluded = new QListWidget;
84 m_listExcluded->setSortingEnabled (false); // Preserve order from Document
8385 m_listExcluded->setWhatsThis (tr ("List of curves to be excluded from the exported file"));
8486 m_listExcluded->setSelectionMode (QAbstractItemView::MultiSelection);
8587 layout->addWidget (m_listExcluded, row++, 2, 4, 1);
125127 m_btnDelimitersTabs->setWhatsThis (tr ("Exported file will have tabs between adjacent values, unless overridden by commas in CSV files."));
126128 layoutDelimiters->addWidget (m_btnDelimitersTabs);
127129 connect (m_btnDelimitersTabs, SIGNAL (released ()), this, SLOT (slotDelimitersTabs()));
130
131 m_btnDelimitersSemicolons = new QRadioButton (exportDelimiterToString (EXPORT_DELIMITER_SEMICOLON));
132 m_btnDelimitersSemicolons->setWhatsThis (tr ("Exported file will have semicolons between adjacent values, unless overridden by commas in CSV files."));
133 layoutDelimiters->addWidget (m_btnDelimitersSemicolons);
134 connect (m_btnDelimitersSemicolons, SIGNAL (released ()), this, SLOT (slotDelimitersSemicolons()));
128135
129136 m_chkOverrideCsvTsv = new QCheckBox (tr ("Override in CSV/TSV files"));
130137 m_chkOverrideCsvTsv->setWhatsThis (tr ("Comma-separated value (CSV) files and tab-separated value (TSV) files will use commas and tabs "
554561 m_btnDelimitersCommas->setChecked (delimiter == EXPORT_DELIMITER_COMMA);
555562 m_btnDelimitersSpaces->setChecked (delimiter == EXPORT_DELIMITER_SPACE);
556563 m_btnDelimitersTabs->setChecked (delimiter == EXPORT_DELIMITER_TAB);
564 m_btnDelimitersSemicolons->setChecked (delimiter == EXPORT_DELIMITER_SEMICOLON);
557565
558566 m_chkOverrideCsvTsv->setChecked (m_modelExportAfter->overrideCsvTsv());
559567
587595 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersCommas";
588596
589597 m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_COMMA);
598 updateControls();
599 updatePreview();
600 }
601
602 void DlgSettingsExportFormat::slotDelimitersSemicolons()
603 {
604 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersSemicolons";
605
606 m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_SEMICOLON);
590607 updateControls();
591608 updatePreview();
592609 }
906923 goodIntervalRelations();
907924 enableOk (isGoodState);
908925
909 m_listIncluded->sortItems (Qt::AscendingOrder);
910 m_listExcluded->sortItems (Qt::AscendingOrder);
911
912926 int selectedForInclude = m_listExcluded->selectedItems().count();
913927 int selectedForExclude = m_listIncluded->selectedItems().count();
914928 int inInclude = m_listIncluded->count();
3939
4040 private slots:
4141 void slotDelimitersCommas();
42 void slotDelimitersSemicolons();
4243 void slotDelimitersSpaces();
4344 void slotDelimitersTabs();
4445 void slotExclude();
114115 QRadioButton *m_btnRelationsPointsRaw;
115116
116117 QRadioButton *m_btnDelimitersCommas;
118 QRadioButton *m_btnDelimitersSemicolons;
117119 QRadioButton *m_btnDelimitersSpaces;
118120 QRadioButton *m_btnDelimitersTabs;
119121 QCheckBox *m_chkOverrideCsvTsv;
594594 if (textItemsAreValid ()) {
595595
596596 GridLineFactory factory (*m_scenePreview,
597 cmdMediator ().document ().modelCoords(),
598 mainWindow ().transformation());
597 cmdMediator ().document ().modelCoords());
599598
600599 factory.createGridLinesForEvenlySpacedGrid (*m_modelGridDisplayAfter,
600 mainWindow ().modelMainWindow(),
601 mainWindow ().transformation(),
601602 m_gridLines);
602603 }
603604 }
55
66 #include "DlgSettingsMainWindow.h"
77 #include "EngaugeAssert.h"
8 #include "ImportCropping.h"
9 #include "ImportCroppingUtilBase.h"
810 #include "Logger.h"
911 #include "MainWindow.h"
1012 #include "MainWindowModel.h"
1113 #include <QCheckBox>
1214 #include <QComboBox>
15 #include <QDoubleSpinBox>
1316 #include <QGraphicsScene>
1417 #include <QGridLayout>
1518 #include <QGroupBox>
108111 connect (m_cmbLocale, SIGNAL (currentIndexChanged (int)), this, SLOT (slotLocale (int)));
109112 layout->addWidget (m_cmbLocale, row++, 2);
110113
114 QLabel *labelImportCropping = new QLabel (tr ("Import cropping:"));
115 layout->addWidget (labelImportCropping, row, 1);
116
117 m_cmbImportCropping = new QComboBox;
118 m_cmbImportCropping->setWhatsThis (tr ("Import Cropping\n\n"
119 "Enables or disables cropping of the imported image when importing. Cropping the image is useful "
120 "for removing unimportant information around a graph, but less useful when the graph already fills "
121 "the entire image."));
122 ImportCroppingUtilBase importCroppingUtil;
123 m_cmbImportCropping->addItem (importCroppingUtil.importCroppingToString (IMPORT_CROPPING_NEVER), IMPORT_CROPPING_NEVER);
124 m_cmbImportCropping->addItem (importCroppingUtil.importCroppingToString (IMPORT_CROPPING_MULTIPAGE_PDFS), IMPORT_CROPPING_MULTIPAGE_PDFS);
125 m_cmbImportCropping->addItem (importCroppingUtil.importCroppingToString (IMPORT_CROPPING_ALWAYS), IMPORT_CROPPING_ALWAYS);
126 connect (m_cmbImportCropping, SIGNAL (currentIndexChanged (int)), this, SLOT (slotImportCropping (int)));
127 layout->addWidget (m_cmbImportCropping, row++, 2);
128
111129 #ifdef ENGAUGE_PDF
112130 QLabel *labelPdfResolution = new QLabel (tr ("Import PDF resolution (dots per inch):"));
113131 layout->addWidget (labelPdfResolution, row, 1);
128146 layout->addWidget (m_cmbPdfResolution, row++, 2);
129147 #endif
130148
149 QLabel *labelMaximumGridLines = new QLabel (tr ("Maximum grid lines:"));
150 layout->addWidget (labelMaximumGridLines, row, 1);
151
152 m_spinMaximumGridLines = new QSpinBox;
153 m_spinMaximumGridLines->setMinimum (2);
154 m_spinMaximumGridLines->setWhatsThis (tr ("Maximum Grid Lines\n\n"
155 "Maximum number of grid lines to be processed. This limit is applied when the step value is too "
156 "small for the start and stop values, which would result in too many grid lines visually and "
157 "possibly extremely long processing time (since each grid line would have to be processed)"));
158 connect (m_spinMaximumGridLines, SIGNAL (valueChanged (int)), this, (SLOT (slotMaximumGridLines (int))));
159 layout->addWidget (m_spinMaximumGridLines, row++, 2);
160
161 QLabel *labelHighlightOpacity = new QLabel (tr ("Highlight opacity:"));
162 layout->addWidget (labelHighlightOpacity, row, 1);
163
164 m_spinHighlightOpacity = new QDoubleSpinBox;
165 m_spinHighlightOpacity->setRange (0, 1);
166 m_spinHighlightOpacity->setSingleStep (0.1);
167 m_spinHighlightOpacity->setWhatsThis (tr ("Highligh Opacity\n\n"
168 "Opacity to be applied when the cursor is over a curve or axis point in Select mode. The change in "
169 "appearance shows when the point can be selected."));
170 connect (m_spinHighlightOpacity, SIGNAL (valueChanged (double)), this, SLOT (slotHighlightOpacity(double)));
171 layout->addWidget (m_spinHighlightOpacity, row++, 2);
172
131173 QLabel *labelRecent = new QLabel (tr ("Recent file list:"));
132174 layout->addWidget (labelRecent, row, 1);
133175
216258 QString locLabel = QLocaleToString (m_modelMainWindowAfter->locale());
217259 index = m_cmbLocale->findText (locLabel);
218260 m_cmbLocale->setCurrentIndex(index);
261 index = m_cmbImportCropping->findData (m_modelMainWindowAfter->importCropping());
262 m_cmbImportCropping->setCurrentIndex (index);
219263 m_chkTitleBarFormat->setChecked (m_modelMainWindowAfter->mainTitleBarFormat() == MAIN_TITLE_BAR_FORMAT_PATH);
220264 index = m_cmbPdfResolution->findData (m_modelMainWindowAfter->pdfResolution());
221265 m_cmbPdfResolution->setCurrentIndex(index);
266 m_spinMaximumGridLines->setValue (m_modelMainWindowAfter->maximumGridLines());
267 m_spinHighlightOpacity->setValue (m_modelMainWindowAfter->highlightOpacity());
222268
223269 updateControls ();
224270 enableOk (false); // Disable Ok button since there not yet any changes
225271 }
226272
273 void DlgSettingsMainWindow::slotHighlightOpacity(double)
274 {
275 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::slotHighlightOpacity";
276
277 m_modelMainWindowAfter->setHighlightOpacity (m_spinHighlightOpacity->value());
278 updateControls();
279 }
280
281 void DlgSettingsMainWindow::slotImportCropping (int index)
282 {
283 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::slotImportCropping";
284
285 m_modelMainWindowAfter->setImportCropping ((ImportCropping) m_cmbImportCropping->itemData (index).toInt ());
286 updateControls();
287 }
288
227289 void DlgSettingsMainWindow::slotLocale (int index)
228290 {
229291 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::slotLocale";
230292
231293 m_modelMainWindowAfter->setLocale (m_cmbLocale->itemData (index).toLocale());
232294 updateControls();
295 }
296
297 void DlgSettingsMainWindow::slotMaximumGridLines (int limit)
298 {
299 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWIndow::slotMaximumGridLines";
300
301 m_modelMainWindowAfter->setMaximumGridLines (limit);
302 updateControls ();
233303 }
234304
235305 void DlgSettingsMainWindow::slotPdfResolution(const QString)
1111
1212 class QCheckBox;
1313 class QComboBox;
14 class QDoubleSpinBox;
1415 class QGridLayout;
1516 class QPushButton;
1617 class QSpinBox;
3536 const MainWindowModel &modelMainWindow);
3637
3738 private slots:
38 void slotTitleBarFormat(bool);
39 void slotHighlightOpacity (double);
40 void slotImportCropping (int index);
3941 void slotLocale (int index);
42 void slotMaximumGridLines (int limit);
4043 void slotPdfResolution (const QString);
4144 void slotRecentFileClear ();
45 void slotTitleBarFormat(bool);
4246 void slotZoomControl (const QString);
4347 void slotZoomFactor (const QString);
4448
5458 QComboBox *m_cmbZoomFactor;
5559 QComboBox *m_cmbZoomControl;
5660 QComboBox *m_cmbLocale;
61 QComboBox *m_cmbImportCropping;
5762 QPushButton *m_btnRecentClear;
5863 QCheckBox *m_chkTitleBarFormat;
5964 QComboBox *m_cmbPdfResolution;
65 QSpinBox *m_spinMaximumGridLines;
66 QDoubleSpinBox *m_spinHighlightOpacity;
6067
6168 MainWindowModel *m_modelMainWindowBefore;
6269 MainWindowModel *m_modelMainWindowAfter;
77 #include "CmdSettingsSegments.h"
88 #include "DlgSettingsSegments.h"
99 #include "EngaugeAssert.h"
10 #include "GeometryWindow.h"
1011 #include "Logger.h"
1112 #include "MainWindow.h"
1213 #include "PointStyle.h"
347348 const QString ARBITRARY_IDENTIFIER ("");
348349 const QColor COLOR (Qt::blue);
349350 const int RADIUS = 5;
351 GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
350352
351353 if (!m_loading) {
352354
384386 pos,
385387 COLOR,
386388 polygon,
387 BRUSH_WIDTH);
389 BRUSH_WIDTH,
390 NULL_GEOMETRY_WINDOW);
391
388392 m_points.push_back (graphicsPoint);
389393 }
390394 }
4242 const int VERSION_6 = 6;
4343 const int VERSION_7 = 7;
4444 const int VERSION_8 = 8;
45 const int VERSION_9 = 9;
4546
4647 Document::Document (const QImage &image) :
4748 m_name ("untitled"),
104105
105106 case VERSION_7:
106107 case VERSION_8:
108 case VERSION_9:
107109 loadVersions7AndUp (file);
108110 break;
109111
339341
340342 m_coordSystemContext.editPointAxis(posGraph,
341343 identifier);
344 }
345
346 void Document::editPointGraph (bool isX,
347 bool isY,
348 double x,
349 double y,
350 const QStringList &identifiers,
351 const Transformation &transformation)
352 {
353 LOG4CPP_INFO_S ((*mainCat)) << "Document::editPointCurve";
354
355 m_coordSystemContext.editPointGraph (isX,
356 isY,
357 x,
358 y,
359 identifiers,
360 transformation);
342361 }
343362
344363 void Document::generateEmptyPixmap(const QXmlStreamAttributes &attributes)
137137 void editPointAxis (const QPointF &posGraph,
138138 const QString &identifier);
139139
140 /// Edit the graph coordinates of one or more graph points
141 void editPointGraph (bool isX,
142 bool isY,
143 double x,
144 double y,
145 const QStringList &identifiers,
146 const Transformation &transformation);
147
140148 /// Initialize grid display. This is called immediately after the transformation has been defined for the first time
141149 void initializeGridDisplay (const Transformation &transformation);
142150
2323 const QString DOCUMENT_SERIALIZE_CMD_DELETE ("CmdDelete");
2424 const QString DOCUMENT_SERIALIZE_CMD_DESCRIPTION ("Description");
2525 const QString DOCUMENT_SERIALIZE_CMD_EDIT_POINT_AXIS ("CmdEditPointAxis");
26 const QString DOCUMENT_SERIALIZE_CMD_EDIT_POINT_GRAPH ("CmdEditPointGraph");
2627 const QString DOCUMENT_SERIALIZE_CMD_MEDIATOR ("CmdMediator");
2728 const QString DOCUMENT_SERIALIZE_CMD_MOVE_BY ("CmdMoveBy");
2829 const QString DOCUMENT_SERIALIZE_CMD_PASTE ("CmdPaste");
9596 const QString DOCUMENT_SERIALIZE_DIGITIZE_CURVE_CURSOR_SIZE ("CursorSize");
9697 const QString DOCUMENT_SERIALIZE_DIGITIZE_CURVE_CURSOR_STANDARD_CROSS ("CursorStandardCross");
9798 const QString DOCUMENT_SERIALIZE_DOCUMENT ("Document");
99 const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_IDENTIFIERS ("Identifiers");
100 const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_X ("IsX");
101 const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_Y ("IsY");
102 const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_X ("X");
103 const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_Y ("Y");
98104 const QString DOCUMENT_SERIALIZE_ERROR ("Error");
99105 const QString DOCUMENT_SERIALIZE_ERROR_COMMENT ("Comment");
100106 const QString DOCUMENT_SERIALIZE_ERROR_CONTEXT ("Context");
2727 extern const QString DOCUMENT_SERIALIZE_CMD_DELETE;
2828 extern const QString DOCUMENT_SERIALIZE_CMD_DESCRIPTION;
2929 extern const QString DOCUMENT_SERIALIZE_CMD_EDIT_POINT_AXIS;
30 extern const QString DOCUMENT_SERIALIZE_CMD_EDIT_POINT_GRAPH;
3031 extern const QString DOCUMENT_SERIALIZE_CMD_MEDIATOR;
3132 extern const QString DOCUMENT_SERIALIZE_CMD_MOVE_BY;
3233 extern const QString DOCUMENT_SERIALIZE_CMD_PASTE;
9899 extern const QString DOCUMENT_SERIALIZE_DIGITIZE_CURVE_CURSOR_SIZE;
99100 extern const QString DOCUMENT_SERIALIZE_DIGITIZE_CURVE_CURSOR_STANDARD_CROSS;
100101 extern const QString DOCUMENT_SERIALIZE_DOCUMENT;
102 extern const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_IDENTIFIERS;
103 extern const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_X;
104 extern const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_IS_Y;
105 extern const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_X;
106 extern const QString DOCUMENT_SERIALIZE_EDIT_GRAPH_Y;
101107 extern const QString DOCUMENT_SERIALIZE_ERROR;
102108 extern const QString DOCUMENT_SERIALIZE_ERROR_COMMENT;
103109 extern const QString DOCUMENT_SERIALIZE_ERROR_CONTEXT;
1111 switch (exportDelimiter) {
1212 case EXPORT_DELIMITER_COMMA:
1313 return QObject::tr ("Commas");
14
15 case EXPORT_DELIMITER_SEMICOLON:
16 return QObject::tr ("Semicolons");
1417
1518 case EXPORT_DELIMITER_SPACE:
1619 return QObject::tr ("Spaces");
3437 return ",";
3538 }
3639
40 case EXPORT_DELIMITER_SEMICOLON:
41 return ";";
42
3743 case EXPORT_DELIMITER_SPACE:
3844 return " ";
3945
99 #include <QString>
1010
1111 /// Delimiter values that may or may not be overridden by DOCUMENT_SERIALIZE_EXPORT_DELIMITER_OVERRIDE_CSV_TSV
12 /// for CSV and TSV files
12 /// for CSV and TSV files. EXPORT_DELIMITER_SEMICOLON is not in alphabetical order since it was added after the code was released
1313 enum ExportDelimiter {
1414 EXPORT_DELIMITER_COMMA,
1515 EXPORT_DELIMITER_SPACE,
16 EXPORT_DELIMITER_TAB
16 EXPORT_DELIMITER_TAB,
17 EXPORT_DELIMITER_SEMICOLON
1718 };
1819
1920 extern QString exportDelimiterToString (ExportDelimiter exportDelimiter); // Text appearing in logging/debugging
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "GeometryModel.h"
7 #include "GeometryWindow.h"
8 #include "Logger.h"
9
10 const int NO_HIGHLIGHTED_ROW = -1;
11
12 GeometryModel::GeometryModel () :
13 m_rowToBeHighlighted (NO_HIGHLIGHTED_ROW)
14 {
15 }
16
17 GeometryModel::~GeometryModel()
18 {
19 }
20
21 QVariant GeometryModel::data(const QModelIndex &index, int role) const
22 {
23 // LOG4CPP_DEBUG_S ((*mainCat)) << "GeometryModel::data"
24 // << " rowHighlighted=" << m_rowToBeHighlighted
25 // << " index=(row=" << index.row() << ",col=" << index.column() << ",role=" << role << ")="
26 // << " rows=" << rowCount()
27 // << " cols=" << columnCount();
28
29 if ((role == Qt::BackgroundRole) &&
30 !m_pointIdentifier.isEmpty () &&
31 (index.row () == m_rowToBeHighlighted)) {
32
33 // This row is to be highlighted
34 return QVariant (QColor (230, 230, 230));
35 }
36
37 // Standard behavior
38 return QStandardItemModel::data (index, role);
39 }
40
41 int GeometryModel::rowToBeHighlighted () const
42 {
43 LOG4CPP_INFO_S ((*mainCat)) << "GeometryModel::rowToBeHighlighted"
44 << " rows=" << rowCount()
45 << " cols=" << columnCount();
46
47 for (int row = 0; row < rowCount(); row++) {
48
49 // Look at the point identifier in the hidden column
50 QModelIndex indexPointIdentifier = index (row,
51 GeometryWindow::columnBodyPointIdentifiers ());
52 QVariant var = QStandardItemModel::data (indexPointIdentifier, Qt::DisplayRole);
53 if (var.isValid()) {
54 QString pointIdentifierGot = var.toString();
55 if (pointIdentifierGot == m_pointIdentifier) {
56
57 // Found it
58 return row;
59 }
60 }
61 }
62
63 // Fail
64 return NO_HIGHLIGHTED_ROW;
65 }
66
67 void GeometryModel::setCurrentPointIdentifier (const QString &pointIdentifier)
68 {
69 LOG4CPP_INFO_S ((*mainCat)) << "GeometryModel::setCurrentPointIdentifier"
70 << " rows=" << rowCount()
71 << " cols=" << columnCount()
72 << " identifier=" << pointIdentifier.toLatin1().data();
73
74 m_pointIdentifier = pointIdentifier;
75
76 int rowTransitioned;
77 if (!m_pointIdentifier.isEmpty ()) {
78
79 // Get new row. It will transition from unhighlighted to highlighted
80 m_rowToBeHighlighted = rowToBeHighlighted();
81 rowTransitioned = m_rowToBeHighlighted;
82
83 } else {
84
85 // Old row will transition from highlighted to unhighlighted
86 rowTransitioned = m_rowToBeHighlighted;
87 m_rowToBeHighlighted = NO_HIGHLIGHTED_ROW;
88
89 }
90
91 QModelIndex indexTopLeft = createIndex (rowTransitioned, 0);
92 QModelIndex indexBottomRight = createIndex (rowTransitioned, columnCount() - 1);
93
94 QVector<int> roles;
95 roles << Qt::BackgroundRole;
96
97 emit dataChanged (indexTopLeft,
98 indexBottomRight,
99 roles);
100 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GEOMETRY_MODEL_H
7 #define GEOMETRY_MODEL_H
8
9 #include <QStandardItemModel>
10 #include <QString>
11
12 /// Model that adds row highlighting according to the currently select point identifier
13 class GeometryModel : public QStandardItemModel
14 {
15 public:
16 /// Single constructor
17 GeometryModel ();
18 virtual ~GeometryModel ();
19
20 /// Override for special processing
21 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
22
23 /// Set the point identifier to be highlighted. Value is empty for no highlighting
24 void setCurrentPointIdentifier (const QString &pointIdentifier);
25
26 private:
27
28 int rowToBeHighlighted () const;
29
30 int m_rowToBeHighlighted;
31 QString m_pointIdentifier; // Point to be higlighted. Empty if none
32 };
33
34 #endif // GEOMETRY_MODEL_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "EngaugeAssert.h"
7 #include "FormatCoordsUnits.h"
8 #include "GeometryStrategyAbstractBase.h"
9 #include <qmath.h>
10 #include <QPointF>
11 #include "Spline.h"
12 #include "SplinePair.h"
13 #include "Transformation.h"
14 #include <vector>
15
16 using namespace std;
17
18 GeometryStrategyAbstractBase::GeometryStrategyAbstractBase()
19 {
20 }
21
22 GeometryStrategyAbstractBase::~GeometryStrategyAbstractBase()
23 {
24 }
25
26 void GeometryStrategyAbstractBase::calculatePositionsGraph (const Points &points,
27 const Transformation &transformation,
28 QVector<QPointF> &positionsGraph) const
29 {
30 positionsGraph.clear();
31
32 for (int i = 0; i < points.size(); i++) {
33 const Point &pointScreen = points [i];
34 QPointF posScreen = pointScreen.posScreen ();
35 QPointF posGraph;
36
37 transformation.transformScreenToRawGraph (posScreen,
38 posGraph);
39
40 positionsGraph.push_back (posGraph);
41 }
42 }
43
44 double GeometryStrategyAbstractBase::functionArea (const QVector<QPointF> &positionsGraph) const
45 {
46 // Integrate using trapezoidal approximation to get the area under the function
47 double sum = 0, xLast = 0, yLast = 0;
48 for (int i = 1; i < positionsGraph.size (); i++) {
49 double x = positionsGraph [i].x();
50 double y = positionsGraph [i].y();
51 double area = 0.5 * (y + yLast) * (x - xLast);
52 sum += area;
53 xLast = x;
54 yLast = y;
55 }
56
57 return sum;
58 }
59
60 void GeometryStrategyAbstractBase::insertSubintervalsAndLoadDistances (int subintervalsPerInterval,
61 const QVector<QPointF> &positionsGraph,
62 QVector<QPointF> &positionsGraphWithSubintervals,
63 QVector<QString> &distanceGraphForward,
64 QVector<QString> &distancePercentForward,
65 QVector<QString> &distanceGraphBackward,
66 QVector<QString> &distancePercentBackward) const
67 {
68 if (positionsGraph.size () > 0) {
69
70 int i;
71
72 // Fit splines to the points
73 vector<double> t;
74 vector<SplinePair> xy;
75 for (int i = 0; i < positionsGraph.size (); i++) {
76 t.push_back ((double) i);
77 xy.push_back (SplinePair (positionsGraph [i].x(),
78 positionsGraph [i].y()));
79 }
80
81 Spline spline (t,
82 xy);
83
84 // Loop over the original points, with one original point per original interval
85 QVector<double> distanceGraphDouble;
86 double xLast = 0, yLast = 0, distance = 0;
87 for (i = 0; i < positionsGraph.size(); i++) {
88
89 // In the interval i-1 to i we insert points to create smaller subintervals
90 for (int subinterval = 0; subinterval < subintervalsPerInterval; subinterval++) {
91
92 // Go from i-1 (exclusive) to i (inclusive)
93 double t = (double) (i - 1.0) + (double) (subinterval + 1) / (double) (subintervalsPerInterval);
94
95 SplinePair splinePair = spline.interpolateCoeff (t);
96
97 double x = splinePair.x ();
98 double y = splinePair.y ();
99
100 // All points from intervals where i>0, and last point from interval i=0
101 if (i > 0 || subinterval == subintervalsPerInterval - 1) {
102
103 // Insert one of several new points for each original point
104 positionsGraphWithSubintervals.push_back (QPointF (x, y));
105
106 }
107
108 if (i > 0) {
109
110 // Add to cumulative distance
111 distance += qSqrt ((x - xLast) * (x - xLast) + (y - yLast) * (y - yLast));
112
113 }
114
115 xLast = x;
116 yLast = y;
117 }
118
119 // Insert one distance entry for each original point
120 distanceGraphDouble.push_back (distance);
121 }
122
123 // Compute distance columns
124 double dTotal = qMax (1.0, distanceGraphDouble [distanceGraphDouble.size() - 1]); // qMax prevents divide by zero
125 for (i = 0; i < distanceGraphDouble.size (); i++) {
126 double d = distanceGraphDouble [i];
127 distanceGraphForward.push_back (QString::number (d));
128 distancePercentForward.push_back (QString::number (100.0 * d / dTotal));
129 distanceGraphBackward.push_back (QString::number (dTotal - d));
130 distancePercentBackward.push_back (QString::number (100.0 * (dTotal - d) / dTotal));
131 }
132 }
133 }
134
135 void GeometryStrategyAbstractBase::loadXY (const QVector<QPointF> &positionsGraph,
136 const DocumentModelCoords &modelCoords,
137 const MainWindowModel &modelMainWindow,
138 const Transformation &transformation,
139 QVector<QString> &x,
140 QVector<QString> &y) const
141 {
142 FormatCoordsUnits formatCoordsUnits;
143
144 for (int i = 0; i < positionsGraph.size(); i++) {
145
146 double xI = positionsGraph [i].x();
147 double yI = positionsGraph [i].y();
148
149 QString xFormatted, yFormatted;
150 formatCoordsUnits.unformattedToFormatted (xI,
151 yI,
152 modelCoords,
153 modelMainWindow,
154 xFormatted,
155 yFormatted,
156 transformation);
157 x.push_back (xFormatted);
158 y.push_back (yFormatted);
159
160 }
161 }
162
163 double GeometryStrategyAbstractBase::polygonAreaForSimplyConnected (const QVector<QPointF> &points) const
164 {
165 // Shoelace formula
166 int N = points.size ();
167
168 double sum = 0.0;
169 if (N > 0) {
170
171
172 for (int i = 0; i < N - 1; i++) {
173 sum += points [i].x() * points [i + 1].y() - points [i + 1].x() * points [i].y();
174 }
175
176 sum += points [N - 1].x() * points [0].y() - points [0].x() * points [N - 1].y ();
177 }
178
179 return qAbs (sum) / 2.0;
180 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GEOMETRY_STRATEGY_ABSTRACT_BASE_H
7 #define GEOMETRY_STRATEGY_ABSTRACT_BASE_H
8
9 #include "Points.h"
10 #include <QPolygonF>
11 #include <QVector>
12
13 class DocumentModelCoords;
14 class MainWindowModel;
15 class QPointF;
16 class Transformation;
17
18 /// Base class for all geometry strategies. Each strategy computes geometry parameters according to the curve's settings.
19 ///
20 /// The numbering for the strategies is specified as the CurveConnectAs enumeration
21 class GeometryStrategyAbstractBase
22 {
23 public:
24 /// Single constructor.
25 GeometryStrategyAbstractBase();
26 virtual ~GeometryStrategyAbstractBase ();
27
28 /// Calculate geometry parameters
29 virtual void calculateGeometry (const Points &points,
30 const DocumentModelCoords &modelCoords,
31 const MainWindowModel &modelMainWindow,
32 const Transformation &transformation,
33 QString &funcArea,
34 QString &polyArea,
35 QVector<QString> &x,
36 QVector<QString> &y,
37 QVector<QString> &distanceGraphForward,
38 QVector<QString> &distancePercentForward,
39 QVector<QString> &distanceGraphBackward,
40 QVector<QString> &distancePercentBackward) const = 0;
41
42 protected:
43
44 /// Convert screen positions to graph positions
45 void calculatePositionsGraph (const Points &points,
46 const Transformation &transformation,
47 QVector<QPointF> &positionsGraph) const;
48
49 /// Use trapezoidal approximation to compute area under the function. Does not apply to relation
50 double functionArea (const QVector<QPointF> &positionsGraph) const;
51
52 /// Insert the specified number of subintervals into each interval. For straight curves subintervalsPerInterval=1 so the
53 /// linearity is maintained, and for smooth curves subintervalsPerInterval>1 so the geometry calculations take into account
54 /// the curvature(s) of the line
55 void insertSubintervalsAndLoadDistances (int subintervalsPerInterval,
56 const QVector<QPointF> &positionsGraph,
57 QVector<QPointF> &positionsGraphWithSubintervals,
58 QVector<QString> &distanceGraphForward,
59 QVector<QString> &distancePercentForward,
60 QVector<QString> &distanceGraphBackward,
61 QVector<QString> &distancePercentBackward) const;
62
63 /// Load x and y coordinate vectors
64 void loadXY (const QVector<QPointF> &positionsGraph,
65 const DocumentModelCoords &modelCoords,
66 const MainWindowModel &modelMainWindow,
67 const Transformation &transformation,
68 QVector<QString> &x,
69 QVector<QString> &y) const;
70
71 /// Area in polygon using Shoelace formula, which only works if polygon is simply connected. We do not
72 /// check to see if the polygon is simply connected since that would be (1) slow and (2) much work
73 double polygonAreaForSimplyConnected (const QVector<QPointF> &points) const;
74
75 };
76
77 #endif // GEOMETRY_STRATEGY_ABSTRACT_BASE_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "CurveConnectAs.h"
7 #include "GeometryStrategyContext.h"
8 #include "GeometryStrategyFunctionSmooth.h"
9 #include "GeometryStrategyFunctionStraight.h"
10 #include "GeometryStrategyRelationSmooth.h"
11 #include "GeometryStrategyRelationStraight.h"
12 #include "Transformation.h"
13
14 GeometryStrategyContext::GeometryStrategyContext()
15 {
16 m_strategies.insert (CONNECT_AS_FUNCTION_SMOOTH , new GeometryStrategyFunctionSmooth ());
17 m_strategies.insert (CONNECT_AS_FUNCTION_STRAIGHT, new GeometryStrategyFunctionStraight ());
18 m_strategies.insert (CONNECT_AS_RELATION_SMOOTH , new GeometryStrategyRelationSmooth ());
19 m_strategies.insert (CONNECT_AS_RELATION_STRAIGHT, new GeometryStrategyRelationStraight ());
20 }
21
22 GeometryStrategyContext::~GeometryStrategyContext()
23 {
24 }
25
26 void GeometryStrategyContext::calculateGeometry (const Points &points,
27 const DocumentModelCoords &modelCoords,
28 const MainWindowModel &modelMainWindow,
29 const Transformation &transformation,
30 CurveConnectAs connectAs,
31 QString &funcArea,
32 QString &polyArea,
33 QVector<QString> &x,
34 QVector<QString> &y,
35 QVector<QString> &distanceGraphForward,
36 QVector<QString> &distancePercentForward,
37 QVector<QString> &distanceGraphBackward,
38 QVector<QString> &distancePercentBackward) const
39 {
40 m_strategies [connectAs]->calculateGeometry (points,
41 modelCoords,
42 modelMainWindow,
43 transformation,
44 funcArea,
45 polyArea,
46 x,
47 y,
48 distanceGraphForward,
49 distancePercentForward,
50 distanceGraphBackward,
51 distancePercentBackward);
52 }
53
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GEOMETRY_STRATEGY_CONTEXT_H
7 #define GEOMETRY_STRATEGY_CONTEXT_H
8
9 #include "CurveConnectAs.h"
10 #include "MainWindowModel.h"
11 #include "Points.h"
12 #include <QVector>
13
14 class DocumentModelCoords;
15 class GeometryStrategyAbstractBase;
16 class Transformation;
17
18 /// Class for that manages geometry strategies
19 class GeometryStrategyContext
20 {
21 public:
22 /// Single constructor.
23 GeometryStrategyContext();
24 virtual ~GeometryStrategyContext ();
25
26 /// Calculate geometry parameters
27 void calculateGeometry (const Points &points,
28 const DocumentModelCoords &modelCoords,
29 const MainWindowModel &modelMainWindow,
30 const Transformation &transformation,
31 CurveConnectAs connectAs,
32 QString &funcArea,
33 QString &polyArea,
34 QVector<QString> &x,
35 QVector<QString> &y,
36 QVector<QString> &distanceGraphForward,
37 QVector<QString> &distancePercentForward,
38 QVector<QString> &distanceGraphBackward,
39 QVector<QString> &distancePercentBackward) const;
40
41 private:
42
43 QVector<GeometryStrategyAbstractBase*> m_strategies;
44
45 };
46
47 #endif // GEOMETRY_STRATEGY_CONTEXT_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "GeometryStrategyFunctionSmooth.h"
7 #include "Transformation.h"
8
9 GeometryStrategyFunctionSmooth::GeometryStrategyFunctionSmooth()
10 {
11 }
12
13 GeometryStrategyFunctionSmooth::~GeometryStrategyFunctionSmooth()
14 {
15 }
16
17 void GeometryStrategyFunctionSmooth::calculateGeometry (const Points &points,
18 const DocumentModelCoords &modelCoords,
19 const MainWindowModel &modelMainWindow,
20 const Transformation &transformation,
21 QString &funcArea,
22 QString &polyArea,
23 QVector<QString> &x,
24 QVector<QString> &y,
25 QVector<QString> &distanceGraphForward,
26 QVector<QString> &distancePercentForward,
27 QVector<QString> &distanceGraphBackward,
28 QVector<QString> &distancePercentBackward) const
29 {
30 const int NUM_SUB_INTERVALS_SMOOTH = 10; // One input point becomes NUM_SUB_INTERVALS points to account for smoothing
31
32 QVector<QPointF> positionsGraph, positionsGraphWithSubintervals;
33 calculatePositionsGraph (points,
34 transformation,
35 positionsGraph);
36
37 insertSubintervalsAndLoadDistances (NUM_SUB_INTERVALS_SMOOTH,
38 positionsGraph,
39 positionsGraphWithSubintervals,
40 distanceGraphForward,
41 distancePercentForward,
42 distanceGraphBackward,
43 distancePercentBackward);
44 double fArea = functionArea (positionsGraphWithSubintervals);
45
46 loadXY (positionsGraph,
47 modelCoords,
48 modelMainWindow,
49 transformation,
50 x,
51 y);
52
53 // Set header values
54 funcArea = QString::number (fArea);
55 polyArea = "";
56 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GEOMETRY_STRATEGY_FUNCTION_SMOOTH_H
7 #define GEOMETRY_STRATEGY_FUNCTION_SMOOTH_H
8
9 #include "GeometryStrategyAbstractBase.h"
10 #include <QVector>
11
12 class Transformation;
13
14 /// Calculate for line through the points that is smoothly connected as a function
15 class GeometryStrategyFunctionSmooth : public GeometryStrategyAbstractBase
16 {
17 public:
18 /// Single constructor.
19 GeometryStrategyFunctionSmooth();
20 virtual ~GeometryStrategyFunctionSmooth ();
21
22 /// Calculate geometry parameters
23 virtual void calculateGeometry (const Points &points,
24 const DocumentModelCoords &modelCoords,
25 const MainWindowModel &modelMainWindow,
26 const Transformation &transformation,
27 QString &funcArea,
28 QString &polyArea,
29 QVector<QString> &x,
30 QVector<QString> &y,
31 QVector<QString> &distanceGraphForward,
32 QVector<QString> &distancePercentForward,
33 QVector<QString> &distanceGraphBackward,
34 QVector<QString> &distancePercentBackward) const;
35
36 };
37
38 #endif // GEOMETRY_STRATEGY_FUNCTION_SMOOTH_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "GeometryStrategyFunctionStraight.h"
7 #include "Transformation.h"
8
9 GeometryStrategyFunctionStraight::GeometryStrategyFunctionStraight()
10 {
11 }
12
13 GeometryStrategyFunctionStraight::~GeometryStrategyFunctionStraight()
14 {
15 }
16
17 void GeometryStrategyFunctionStraight::calculateGeometry (const Points &points,
18 const DocumentModelCoords &modelCoords,
19 const MainWindowModel &modelMainWindow,
20 const Transformation &transformation,
21 QString &funcArea,
22 QString &polyArea,
23 QVector<QString> &x,
24 QVector<QString> &y,
25 QVector<QString> &distanceGraphForward,
26 QVector<QString> &distancePercentForward,
27 QVector<QString> &distanceGraphBackward,
28 QVector<QString> &distancePercentBackward) const
29 {
30 const int NUM_SUB_INTERVALS_STRAIGHT = 1; // Value of one with trapezoidal integration results in calculations using straight lines between points
31
32 QVector<QPointF> positionsGraph, positionsGraphWithSubintervals;
33 calculatePositionsGraph (points,
34 transformation,
35 positionsGraph);
36
37 insertSubintervalsAndLoadDistances (NUM_SUB_INTERVALS_STRAIGHT,
38 positionsGraph,
39 positionsGraphWithSubintervals,
40 distanceGraphForward,
41 distancePercentForward,
42 distanceGraphBackward,
43 distancePercentBackward);
44 double fArea = functionArea (positionsGraphWithSubintervals);
45
46 loadXY (positionsGraph,
47 modelCoords,
48 modelMainWindow,
49 transformation,
50 x,
51 y);
52
53 // Set header values
54 funcArea = QString::number (fArea);
55 polyArea = "";
56 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GEOMETRY_STRATEGY_FUNCTION_STRAIGHT_H
7 #define GEOMETRY_STRATEGY_FUNCTION_STRAIGHT_H
8
9 #include "GeometryStrategyAbstractBase.h"
10 #include <QVector>
11
12 class Transformation;
13
14 /// Calculate for line through the points that is straightly connected as a function
15 class GeometryStrategyFunctionStraight : public GeometryStrategyAbstractBase
16 {
17 public:
18 /// Single constructor.
19 GeometryStrategyFunctionStraight();
20 virtual ~GeometryStrategyFunctionStraight ();
21
22 /// Calculate geometry parameters
23 virtual void calculateGeometry (const Points &points,
24 const DocumentModelCoords &modelCoords,
25 const MainWindowModel &modelMainWindow,
26 const Transformation &transformation,
27 QString &funcArea,
28 QString &polyArea,
29 QVector<QString> &x,
30 QVector<QString> &y,
31 QVector<QString> &distanceGraphForward,
32 QVector<QString> &distancePercentForward,
33 QVector<QString> &distanceGraphBackward,
34 QVector<QString> &distancePercentBackward) const;
35
36 };
37
38 #endif // GEOMETRY_STRATEGY_FUNCTION_STRAIGHT_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "GeometryStrategyRelationSmooth.h"
7 #include "Transformation.h"
8
9 GeometryStrategyRelationSmooth::GeometryStrategyRelationSmooth()
10 {
11 }
12
13 GeometryStrategyRelationSmooth::~GeometryStrategyRelationSmooth()
14 {
15 }
16
17 void GeometryStrategyRelationSmooth::calculateGeometry (const Points &points,
18 const DocumentModelCoords &modelCoords,
19 const MainWindowModel &modelMainWindow,
20 const Transformation &transformation,
21 QString &funcArea,
22 QString &polyArea,
23 QVector<QString> &x,
24 QVector<QString> &y,
25 QVector<QString> &distanceGraphForward,
26 QVector<QString> &distancePercentForward,
27 QVector<QString> &distanceGraphBackward,
28 QVector<QString> &distancePercentBackward) const
29 {
30 const int NUM_SUB_INTERVALS_SMOOTH = 10; // One input point becomes NUM_SUB_INTERVALS points to account for smoothing
31
32 QVector<QPointF> positionsGraph, positionsGraphWithSubintervals;
33 calculatePositionsGraph (points,
34 transformation,
35 positionsGraph);
36
37 insertSubintervalsAndLoadDistances (NUM_SUB_INTERVALS_SMOOTH,
38 positionsGraph,
39 positionsGraphWithSubintervals,
40 distanceGraphForward,
41 distancePercentForward,
42 distanceGraphBackward,
43 distancePercentBackward);
44 double pArea = polygonAreaForSimplyConnected (positionsGraphWithSubintervals);
45
46 loadXY (positionsGraph,
47 modelCoords,
48 modelMainWindow,
49 transformation,
50 x,
51 y);
52
53 // Set header values
54 funcArea = "";
55 polyArea = QString::number (pArea);
56 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GEOMETRY_STRATEGY_RELATION_SMOOTH_H
7 #define GEOMETRY_STRATEGY_RELATION_SMOOTH_H
8
9 #include "GeometryStrategyAbstractBase.h"
10 #include <QVector>
11
12 class Transformation;
13
14 /// Calculate for line through the points that is smoothly connected as a relation
15 class GeometryStrategyRelationSmooth : public GeometryStrategyAbstractBase
16 {
17 public:
18 /// Single constructor.
19 GeometryStrategyRelationSmooth();
20 virtual ~GeometryStrategyRelationSmooth ();
21
22 /// Calculate geometry parameters
23 virtual void calculateGeometry (const Points &points,
24 const DocumentModelCoords &modelCoords,
25 const MainWindowModel &modelMainWindow,
26 const Transformation &transformation,
27 QString &funcArea,
28 QString &polyArea,
29 QVector<QString> &x,
30 QVector<QString> &y,
31 QVector<QString> &distanceGraphForward,
32 QVector<QString> &distancePercentForward,
33 QVector<QString> &distanceGraphBackward,
34 QVector<QString> &distancePercentBackward) const;
35
36 };
37
38 #endif // GEOMETRY_STRATEGY_RELATION_SMOOTH_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "GeometryStrategyRelationStraight.h"
7 #include "Transformation.h"
8
9 GeometryStrategyRelationStraight::GeometryStrategyRelationStraight()
10 {
11 }
12
13 GeometryStrategyRelationStraight::~GeometryStrategyRelationStraight()
14 {
15 }
16
17 void GeometryStrategyRelationStraight::calculateGeometry (const Points &points,
18 const DocumentModelCoords &modelCoords,
19 const MainWindowModel &modelMainWindow,
20 const Transformation &transformation,
21 QString &funcArea,
22 QString &polyArea,
23 QVector<QString> &x,
24 QVector<QString> &y,
25 QVector<QString> &distanceGraphForward,
26 QVector<QString> &distancePercentForward,
27 QVector<QString> &distanceGraphBackward,
28 QVector<QString> &distancePercentBackward) const
29 {
30 const int NUM_SUB_INTERVALS_STRAIGHT = 1; // Value of one with trapezoidal integration results in calculations using straight lines between points
31
32 QVector<QPointF> positionsGraph, positionsGraphWithSubintervals;
33 calculatePositionsGraph (points,
34 transformation,
35 positionsGraph);
36
37 insertSubintervalsAndLoadDistances (NUM_SUB_INTERVALS_STRAIGHT,
38 positionsGraph,
39 positionsGraphWithSubintervals,
40 distanceGraphForward,
41 distancePercentForward,
42 distanceGraphBackward,
43 distancePercentBackward);
44 double pArea = polygonAreaForSimplyConnected (positionsGraphWithSubintervals);
45
46 loadXY (positionsGraph,
47 modelCoords,
48 modelMainWindow,
49 transformation,
50 x,
51 y);
52
53 // Set header values
54 funcArea = "";
55 polyArea = QString::number (pArea);
56 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GEOMETRY_STRATEGY_RELATION_STRAIGHT_H
7 #define GEOMETRY_STRATEGY_RELATION_STRAIGHT_H
8
9 #include "GeometryStrategyAbstractBase.h"
10 #include <QVector>
11
12 class Transformation;
13
14 /// Calculate for line through the points that is straightly connected as a relation
15 class GeometryStrategyRelationStraight : public GeometryStrategyAbstractBase
16 {
17 public:
18 /// Single constructor.
19 GeometryStrategyRelationStraight();
20 virtual ~GeometryStrategyRelationStraight ();
21
22 /// Calculate geometry parameters
23 virtual void calculateGeometry (const Points &points,
24 const DocumentModelCoords &modelCoords,
25 const MainWindowModel &modelMainWindow,
26 const Transformation &transformation,
27 QString &funcArea,
28 QString &polyArea,
29 QVector<QString> &x,
30 QVector<QString> &y,
31 QVector<QString> &distanceGraphForward,
32 QVector<QString> &distancePercentForward,
33 QVector<QString> &distanceGraphBackward,
34 QVector<QString> &distancePercentBackward) const;
35
36 };
37
38 #endif // GEOMETRY_STRATEGY_RELATION_STRAIGHT_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "CallbackGatherXThetaValuesFunctions.h"
7 #include "CmdMediator.h"
8 #include "Curve.h"
9 #include "CurveConnectAs.h"
10 #include "CurveStyle.h"
11 #include "EngaugeAssert.h"
12 #include "GeometryModel.h"
13 #include "GeometryWindow.h"
14 #include "Logger.h"
15 #include <QApplication>
16 #include <QClipboard>
17 #include <QHeaderView>
18 #include <QItemSelectionModel>
19 #include <QTableView>
20 #include <QTextStream>
21
22 // Token constraints:
23 // (1) should fit nicely into narrow columns. This eliminates details like Forward and Backward in the distance parameter tokens
24 // (2) should not have any spaces. This simplifies copying and pasting into spreadsheet programs
25 const QString TokenName (QObject::tr ("CurveName:"));
26 const QString TokenFunctionArea (QObject::tr ("FunctionArea:"));
27 const QString TokenPolygonArea (QObject::tr ("PolygonArea:"));
28 const QString TokenX (QObject::tr ("X"));
29 const QString TokenY (QObject::tr ("Y"));
30 const QString TokenIndex (QObject::tr ("Index"));
31 const QString TokenDistanceGraph (QObject::tr ("Distance"));
32 const QString TokenDistancePercent (QObject::tr ("Percent"));
33
34 GeometryWindow::GeometryWindow (QWidget *parent) :
35 QDockWidget (parent)
36 {
37 setVisible (false);
38 setAllowedAreas (Qt::AllDockWidgetAreas);
39 setWindowTitle (tr ("Geometry Window")); // Appears in title bar when undocked
40 setStatusTip (tr ("Geometry Window"));
41 setWhatsThis (tr ("Geometry Window\n\n"
42 "This table displays the following geometry data for the currently selected curve:\n\n"
43 "Function area = Area under the curve if it is a function\n\n"
44 "Polygon area = Area inside the curve if it is a relation. This value is only correct "
45 "if none of the curve lines intersect each other\n\n"
46 "X = X coordinate of each point\n\n"
47 "Y = Y coordinate of each point\n\n"
48 "Index = Point number\n\n"
49 "Distance = Distance along the curve in forward or backward direction, in either graph units "
50 "or as a percentage"));
51
52 m_model = new GeometryModel;
53
54 m_view = new QTableView;
55 m_view->setModel (m_model); // Call before setSelectionModel since this also overrides the selection model
56 m_view->horizontalHeader()->hide();
57 m_view->verticalHeader()->hide();
58 m_view->setEditTriggers(QAbstractItemView::NoEditTriggers); // Control is read only
59 connect (m_view->selectionModel(), SIGNAL (selectionChanged (const QItemSelection &, const QItemSelection &)),
60 this, SLOT (slotSelectionChanged (const QItemSelection &, const QItemSelection &)));
61
62 setWidget (m_view);
63
64 loadStrategies();
65
66 initializeHeader ();
67 }
68
69 GeometryWindow::~GeometryWindow()
70 {
71 }
72
73 void GeometryWindow::clear ()
74 {
75 // Resize table to remove stale body data
76 resizeTable (NUM_HEADER_ROWS);
77
78 // Clear stale header data values
79 for (int row = 0; row < NUM_HEADER_ROWS - 1; row++) {
80 m_model->setItem (row, COLUMN_HEADER_VALUE, new QStandardItem (""));
81 }
82 }
83
84 void GeometryWindow::closeEvent(QCloseEvent * /* event */)
85 {
86 LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::closeEvent";
87
88 emit signalGeometryWindowClosed();
89 }
90
91 int GeometryWindow::fold2dIndexes (int row,
92 int col,
93 int rowLow,
94 int colLow,
95 int colHigh) const
96 {
97 return (row - rowLow) * (colHigh - colLow + 1) + (col - colLow);
98 }
99
100 int GeometryWindow::columnBodyPointIdentifiers ()
101 {
102 return COLUMN_BODY_POINT_IDENTIFIERS;
103 }
104
105 void GeometryWindow::initializeHeader ()
106 {
107 LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::initializeHeader";
108
109 resizeTable (NUM_HEADER_ROWS);
110
111 m_model->setItem (HEADER_ROW_NAME, COLUMN_HEADER_LABEL, new QStandardItem (TokenName));
112 m_model->setItem (HEADER_ROW_FUNC_AREA, COLUMN_HEADER_LABEL, new QStandardItem (TokenFunctionArea));
113 m_model->setItem (HEADER_ROW_POLY_AREA, COLUMN_HEADER_LABEL, new QStandardItem (TokenPolygonArea));
114 m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_X, new QStandardItem (TokenX));
115 m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_Y, new QStandardItem (TokenY));
116 m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_INDEX, new QStandardItem (TokenIndex));
117 m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_DISTANCE_GRAPH_FORWARD, new QStandardItem (TokenDistanceGraph));
118 m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_DISTANCE_PERCENT_FORWARD, new QStandardItem (TokenDistancePercent));
119 m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_DISTANCE_GRAPH_BACKWARD, new QStandardItem (TokenDistanceGraph));
120 m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_DISTANCE_PERCENT_BACKWARD, new QStandardItem (TokenDistancePercent));
121 }
122
123 void GeometryWindow::loadStrategies ()
124 {
125 LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::loadStrategies";
126 }
127
128 void GeometryWindow::resizeTable (int rowCount)
129 {
130 LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::resizeTable";
131
132 unselectAll();
133
134 m_model->setRowCount (rowCount);
135 m_model->setColumnCount (NUM_BODY_COLUMNS);
136
137 }
138
139 void GeometryWindow::slotPointHoverEnter (QString pointIdentifier)
140 {
141 m_model->setCurrentPointIdentifier (pointIdentifier);
142 }
143
144 void GeometryWindow::slotPointHoverLeave (QString /* pointIdentifier */)
145 {
146 m_model->setCurrentPointIdentifier ("");
147 }
148
149 void GeometryWindow::slotSelectionChanged (const QItemSelection & /* selected */,
150 const QItemSelection & /* deselected */)
151 {
152 const bool NOT_GNUPLOT = false;
153
154 QItemSelectionModel *selectionModel = m_view->selectionModel ();
155 QModelIndexList selection = selectionModel->selectedIndexes ();
156
157 if (selection.size () > 0) {
158
159 // Gather input. A rectangular grid that encompasses all selected indexes will be copied
160 int rowLow = 0, rowHigh = 0, colLow = 0, colHigh = 0;
161 bool isFirst = true;
162 for (QModelIndexList::const_iterator itr = selection.begin(); itr != selection.end(); itr++) {
163 QModelIndex index = *itr;
164 if (isFirst || index.row () < rowLow ) rowLow = index.row ();
165 if (isFirst || index.row () > rowHigh) rowHigh = index.row ();
166 if (isFirst || index.column () < colLow ) colLow = index.column ();
167 if (isFirst || index.column () > colHigh) colHigh = index.column ();
168 isFirst = false;
169 }
170
171 int numRows = rowHigh - rowLow + 1;
172 int numCols = colHigh - colLow + 1;
173
174 // Put data into two dimensional rowXcolumn table is handled as a flattened vector. Table is initialized
175 // with empty strings
176 QVector<QString> table (numRows * numCols);
177
178 for (int i = 0; i < selection.size (); i++) {
179 QModelIndex index = selection [i];
180 QVariant data = m_model->data (index);
181 QString text = data.toString ();
182 table [fold2dIndexes (index.row(), index.column(), rowLow, colLow, colHigh)] = text;
183 }
184
185 // Concatenate table into output string
186 QString output;
187 QTextStream str (&output);
188 for (int row = rowLow; row <= rowHigh; row++) {
189 QString delimiter;
190 for (int col = colLow; col <= colHigh; col++) {
191 str << delimiter << table [fold2dIndexes (row, col, rowLow, colLow, colHigh)];
192 delimiter = exportDelimiterToText (m_modelExport.delimiter(),
193 NOT_GNUPLOT);
194 }
195 str << "\n";
196 }
197
198 // Save to clipboard
199 QApplication::clipboard ()->setText (output);
200 }
201 }
202
203 void GeometryWindow::update (const CmdMediator &cmdMediator,
204 const MainWindowModel &modelMainWindow,
205 const QString &curveSelected,
206 const Transformation &transformation)
207 {
208 LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::update";
209
210 // Save export format
211 m_modelExport = cmdMediator.document().modelExport();
212
213 // Gather and calculate geometry data
214 const Curve *curve = cmdMediator.document().curveForCurveName (curveSelected);
215
216 ENGAUGE_CHECK_PTR (curve);
217
218 const Points points = curve->points();
219
220 QString funcArea, polyArea;
221 QVector<QString> x, y, distanceGraphForward, distancePercentForward, distanceGraphBackward, distancePercentBackward;
222
223 CurveStyle curveStyle = cmdMediator.document().modelCurveStyles().curveStyle (curveSelected);
224 m_geometryStrategyContext.calculateGeometry (points,
225 cmdMediator.document().modelCoords(),
226 modelMainWindow,
227 transformation,
228 curveStyle.lineStyle().curveConnectAs(),
229 funcArea,
230 polyArea,
231 x,
232 y,
233 distanceGraphForward,
234 distancePercentForward,
235 distanceGraphBackward,
236 distancePercentBackward);
237
238 // Output to table
239 resizeTable (NUM_HEADER_ROWS + points.count());
240
241 m_model->setItem (HEADER_ROW_NAME, COLUMN_HEADER_VALUE, new QStandardItem (curveSelected));
242 m_model->setItem (HEADER_ROW_FUNC_AREA, COLUMN_HEADER_VALUE, new QStandardItem (funcArea));
243 m_model->setItem (HEADER_ROW_POLY_AREA, COLUMN_HEADER_VALUE, new QStandardItem (polyArea));
244
245 int row = NUM_HEADER_ROWS;
246 int index = 0;
247 for (; index < points.count(); row++, index++) {
248
249 const Point &point = points.at (index);
250
251 QPointF posGraph;
252 transformation.transformScreenToRawGraph (point.posScreen (),
253 posGraph);
254
255 m_model->setItem (row, COLUMN_BODY_X, new QStandardItem (x [index]));
256 m_model->setItem (row, COLUMN_BODY_Y, new QStandardItem (y [index]));
257 m_model->setItem (row, COLUMN_BODY_INDEX, new QStandardItem (QString::number (index + 1)));
258 m_model->setItem (row, COLUMN_BODY_DISTANCE_GRAPH_FORWARD, new QStandardItem (distanceGraphForward [index]));
259 m_model->setItem (row, COLUMN_BODY_DISTANCE_PERCENT_FORWARD, new QStandardItem (distancePercentForward [index]));
260 m_model->setItem (row, COLUMN_BODY_DISTANCE_GRAPH_BACKWARD, new QStandardItem (distanceGraphBackward [index]));
261 m_model->setItem (row, COLUMN_BODY_DISTANCE_PERCENT_BACKWARD, new QStandardItem (distancePercentBackward [index]));
262 m_model->setItem (row, COLUMN_BODY_POINT_IDENTIFIERS, new QStandardItem (point.identifier()));
263 }
264
265 // Unselect everything
266 unselectAll ();
267
268 // Make sure the hidden column stays hidden
269 m_view->setColumnHidden (COLUMN_BODY_POINT_IDENTIFIERS, true);
270 }
271
272 void GeometryWindow::unselectAll ()
273 {
274 QItemSelectionModel *selectionModel = m_view->selectionModel ();
275
276 selectionModel->clearSelection ();
277 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GEOMETRY_WINDOW_H
7 #define GEOMETRY_WINDOW_H
8
9 #include "DocumentModelExportFormat.h"
10 #include "GeometryStrategyContext.h"
11 #include <QDockWidget>
12
13 class CmdMediator;
14 class Curve;
15 class GeometryModel;
16 class MainWindowModel;
17 class QItemSelection;
18 class QString;
19 class QTableView;
20 class Transformation;
21
22 /// Window that displays the geometry information, as a table, for the current curve
23 ///
24 /// Column COLUMN_BODY_POINT_IDENTIFIERS is hidden. It contains the point identifiers so we can find
25 /// the line associated with a point, and then highlight that line
26 class GeometryWindow : public QDockWidget
27 {
28 Q_OBJECT;
29
30 public:
31 /// Single constructor. Parent is needed or else this widget cannot be redocked after being undocked
32 GeometryWindow (QWidget *parent);
33 virtual ~GeometryWindow ();
34
35 /// Clear stale information
36 void clear ();
37
38 /// Catch close event so corresponding menu item in MainWindow can be updated accordingly
39 virtual void closeEvent(QCloseEvent *event);
40
41 /// Hidden column that has the point identifiers
42 static int columnBodyPointIdentifiers ();
43
44 /// Populate the table with the specified Curve
45 void update (const CmdMediator &cmdMediator,
46 const MainWindowModel &modelMainWindow,
47 const QString &curveSelected,
48 const Transformation &transformation);
49
50 public slots:
51
52 /// Highlight the row for the specified point
53 void slotPointHoverEnter (QString);
54
55 /// Unhighlight the row for the specified point
56 void slotPointHoverLeave (QString);
57
58 /// Prepare for copy after selection has changed
59 void slotSelectionChanged (const QItemSelection &, const QItemSelection &);
60
61 signals:
62 /// Signal that this QDockWidget was just closed
63 void signalGeometryWindowClosed();
64
65 private:
66 GeometryWindow();
67
68 int fold2dIndexes (int row,
69 int col,
70 int rowLow,
71 int colLow,
72 int colHigh) const;
73 void initializeHeader();
74 void loadStrategies ();
75 void resizeTable (int rowCount);
76 void unselectAll (); // Unselect all cells. This cleans up nicely when Document is closed
77
78 enum ColumnsHeader {
79 COLUMN_HEADER_LABEL,
80 COLUMN_HEADER_VALUE,
81 NUM_HEADER_COLUMNS
82 };
83
84 enum ColumnsBody {
85 COLUMN_BODY_X,
86 COLUMN_BODY_Y,
87 COLUMN_BODY_INDEX,
88 COLUMN_BODY_DISTANCE_GRAPH_FORWARD,
89 COLUMN_BODY_DISTANCE_PERCENT_FORWARD,
90 COLUMN_BODY_DISTANCE_GRAPH_BACKWARD,
91 COLUMN_BODY_DISTANCE_PERCENT_BACKWARD,
92 COLUMN_BODY_POINT_IDENTIFIERS,
93 NUM_BODY_COLUMNS
94 };
95
96 enum HeaderRows {
97 HEADER_ROW_NAME,
98 HEADER_ROW_FUNC_AREA,
99 HEADER_ROW_POLY_AREA,
100 HEADER_ROW_COLUMN_NAMES,
101 NUM_HEADER_ROWS
102 };
103
104 QTableView *m_view;
105 GeometryModel *m_model;
106
107 GeometryStrategyContext m_geometryStrategyContext;
108
109 // Export format is updated after every CmdAbstractBase gets redone/undone
110 DocumentModelExportFormat m_modelExport;
111 };
112
113 #endif // GEOMETRY_WINDOW_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "Curve.h"
7 #include "DataKey.h"
8 #include "GraphicsItemsExtractor.h"
9 #include "GraphicsItemType.h"
10 #include "Logger.h"
11 #include "Point.h"
12 #include <QGraphicsItem>
13
14 GraphicsItemsExtractor::GraphicsItemsExtractor()
15 {
16 }
17
18 GraphicsItemsExtractor::~GraphicsItemsExtractor()
19 {
20 }
21
22 bool GraphicsItemsExtractor::allSelectedItemsAreEitherAxisOrGraph (const QList<QGraphicsItem*> &items,
23 AxisOrGraph axisOrGraph) const
24 {
25 bool allAreEitherAxisOrGraph = true;
26
27 QList<QGraphicsItem*>::const_iterator itr;
28 for (itr = items.begin(); itr != items.end(); itr++) {
29
30 QGraphicsItem *item = *itr;
31 GraphicsItemType type = (GraphicsItemType) item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt ();
32
33 if (type == GRAPHICS_ITEM_TYPE_POINT) {
34
35 QString pointIdentifier = item->data (DATA_KEY_IDENTIFIER).toString ();
36 QString curveName = Point::curveNameFromPointIdentifier (pointIdentifier);
37
38 bool unwantedAxisPoint = ((curveName == AXIS_CURVE_NAME) && (axisOrGraph == GRAPH_POINTS));
39 bool unwantedCurvePoint = ((curveName != AXIS_CURVE_NAME) && (axisOrGraph == AXIS_POINTS));
40
41 if (unwantedAxisPoint || unwantedCurvePoint) {
42
43 allAreEitherAxisOrGraph = false;
44 break;
45
46 }
47 } else {
48
49 allAreEitherAxisOrGraph = false;
50 break;
51
52 }
53 }
54
55 return allAreEitherAxisOrGraph;
56 }
57
58 QStringList GraphicsItemsExtractor::selectedPointIdentifiers (const QList<QGraphicsItem*> &items) const
59 {
60 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::selectedPointIdentifiers"
61 << " selectedItems=" << items.count();
62
63 QStringList selectedIds;
64 QList<QGraphicsItem*>::const_iterator itr;
65 for (itr = items.begin(); itr != items.end(); itr++) {
66
67 const QGraphicsItem* item = *itr;
68
69 // Skip the image and only keep the Points
70 bool isPoint = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_POINT);
71 if (isPoint) {
72
73 // Add Point to the list
74 selectedIds << item->data(DATA_KEY_IDENTIFIER).toString ();
75
76 }
77 }
78
79 return selectedIds;
80 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GRAPHICS_ITEMS_EXTRACTOR_H
7 #define GRAPHICS_ITEMS_EXTRACTOR_H
8
9 #include <QStringList>
10
11 class QGraphicsItem;
12
13 enum AxisOrGraph {
14 AXIS_POINTS,
15 GRAPH_POINTS
16 };
17
18 /// This class consolidates utility routines that deal with graphics items that are getting extracted from the scene
19 class GraphicsItemsExtractor
20 {
21 public:
22 /// Single constructor
23 GraphicsItemsExtractor();
24 ~GraphicsItemsExtractor();
25
26 /// Return true if all selected points are of the specified axis or graph type
27 bool allSelectedItemsAreEitherAxisOrGraph (const QList<QGraphicsItem*> &items,
28 AxisOrGraph axisOrGraph) const;
29
30 /// Return list of selected point identifiers
31 QStringList selectedPointIdentifiers (const QList<QGraphicsItem*> &items) const;
32
33 };
34
35 #endif // GRAPHICS_ITEMS_EXTRACTOR_H
66 #include "DataKey.h"
77 #include "EngaugeAssert.h"
88 #include "EnumsToQt.h"
9 #include "GeometryWindow.h"
910 #include "GraphicsItemType.h"
1011 #include "GraphicsLinesForCurve.h"
1112 #include "GraphicsPoint.h"
319320
320321 void GraphicsLinesForCurve::updateAfterCommand (GraphicsScene &scene,
321322 const PointStyle &pointStyle,
322 const Point &point)
323 const Point &point,
324 GeometryWindow *geometryWindow)
323325 {
324326 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsLinesForCurve::updateAfterCommand"
325327 << " curve=" << m_curveName.toLatin1().data()
342344 // Point does not exist in scene so create it
343345 graphicsPoint = scene.createPoint (point.identifier (),
344346 pointStyle,
345 point.posScreen());
347 point.posScreen(),
348 geometryWindow);
346349 m_graphicsPoints [point.ordinal ()] = graphicsPoint;
347350
348351 }
361364
362365 GraphicsPoint *point = itr.value();
363366 point->updateCurveStyle (curveStyle);
367 }
368 }
369
370 void GraphicsLinesForCurve::updateHighlightOpacity (double highlightOpacity)
371 {
372 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::updateCurveStyle"
373 << " curve=" << m_curveName.toLatin1().data()
374 << " highlightOpacity=" << highlightOpacity;
375
376 OrdinalToGraphicsPoint::const_iterator itr;
377 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
378
379 GraphicsPoint *point = itr.value();
380 point->setHighlightOpacity (highlightOpacity);
364381 }
365382 }
366383
1111 #include <QGraphicsPathItem>
1212
1313 class CurveStyle;
14 class GeometryWindow;
1415 class GraphicsPoint;
1516 class GraphicsScene;
1617 class LineStyle;
5859 /// Update the GraphicsScene with the specified Point from the Document. If it does not exist yet in the scene, we add it
5960 void updateAfterCommand (GraphicsScene &scene,
6061 const PointStyle &pointStyle,
61 const Point &point);
62 const Point &point,
63 GeometryWindow *geometryWindow);
6264
6365 /// Update the curve style for this curve
6466 void updateCurveStyle (const CurveStyle &curveStyle);
6567
6668 /// Calls to moveLinesWithDraggedPoint have finished so update the lines correspondingly
6769 void updateGraphicsLinesToMatchGraphicsPoints (const LineStyle &lineStyle);
70
71 /// Update the highlight opacity value. This may or may not affect the current display immediately depending on the state
72 void updateHighlightOpacity (double highlightOpacity);
6873
6974 /// See GraphicsScene::updateOrdinalsAfterDrag. Pretty much the same steps as Curve::updatePointOrdinals
7075 void updatePointOrdinalsAfterDrag (const LineStyle &lineStyle,
171171 void GraphicsLinesForCurves::updateAfterCommand (GraphicsScene &scene,
172172 const CurveStyles &curveStyles,
173173 const QString &curveName,
174 const Point &point)
174 const Point &point,
175 GeometryWindow *geometryWindow)
175176 {
176177 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsLinesForCurves::updateAfterCommand"
177178 << " point=" << point.identifier().toLatin1().data()
180181 ENGAUGE_ASSERT (m_graphicsLinesForCurve.contains (curveName));
181182 m_graphicsLinesForCurve [curveName]->updateAfterCommand (scene,
182183 curveStyles.pointStyle(curveName),
183 point);
184 point,
185 geometryWindow);
184186 }
185187
186188 void GraphicsLinesForCurves::updateCurveStyles (const CurveStyles &modelCurveStyles)
213215 }
214216 }
215217
218 void GraphicsLinesForCurves::updateHighlightOpacity (double highlightOpacity)
219 {
220 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurves::updateHighlightOpacity"
221 << " highlightOpacity=" << highlightOpacity;
222
223 GraphicsLinesContainer::const_iterator itr;
224 for (itr = m_graphicsLinesForCurve.begin (); itr != m_graphicsLinesForCurve.end (); itr++) {
225
226 QString curveName = itr.key();
227
228 m_graphicsLinesForCurve [curveName]->updateHighlightOpacity (highlightOpacity);
229 }
230 }
231
216232 void GraphicsLinesForCurves::updatePointOrdinalsAfterDrag (const CurveStyles &curveStyles,
217233 const Transformation &transformation)
218234 {
99 #include <QHash>
1010
1111 class CurveStyles;
12 class GeometryWindow;
1213 class GraphicsLinesForCurve;
1314 class GraphicsPoint;
1415 class GraphicsScene;
6566 void updateAfterCommand (GraphicsScene &scene,
6667 const CurveStyles &curveStyles,
6768 const QString &curveName,
68 const Point &point);
69 const Point &point,
70 GeometryWindow *geometryWindow);
6971
7072 /// Update the curve style for every curve
7173 void updateCurveStyles (const CurveStyles &modelCurveStyles);
7274
7375 /// Calls to moveLinesWithDraggedPoint have finished so update the lines correspondingly
7476 void updateGraphicsLinesToMatchGraphicsPoints (const CurveStyles &curveStyles);
77
78 /// Update the highlight opacity value. This may or may not affect the current display immediately depending on the state
79 void updateHighlightOpacity (double highlightOpacity);
7580
7681 /// See GraphicsScene::updateOrdinalsAfterDrag
7782 void updatePointOrdinalsAfterDrag (const CurveStyles &curveStyles,
66 #include "CurveStyle.h"
77 #include "DataKey.h"
88 #include "EnumsToQt.h"
9 #include "GeometryWindow.h"
910 #include "GraphicsItemType.h"
1011 #include "GraphicsPoint.h"
1112 #include "GraphicsPointEllipse.h"
1617 #include <QGraphicsPolygonItem>
1718 #include <QGraphicsScene>
1819 #include <QGraphicsSceneContextMenuEvent>
20 #include <QObject>
1921 #include <QPen>
2022 #include <QTextStream>
2123 #include "QtToString.h"
2224 #include "ZValues.h"
2325
26 const double DEFAULT_HIGHLIGHT_OPACITY = 0.35; // 0=transparent to 1=opaque. Values above 0.5 are very hard to notice
27 const double MAX_OPACITY = 1.0;
2428 const double ZERO_WIDTH = 0.0;
2529
2630 GraphicsPoint::GraphicsPoint(QGraphicsScene &scene,
2832 const QPointF &posScreen,
2933 const QColor &color,
3034 unsigned int radius,
31 double lineWidth) :
35 double lineWidth,
36 GeometryWindow *geometryWindow) :
3237 GraphicsPointAbstractBase (),
3338 m_scene (scene),
3439 m_graphicsItemEllipse (0),
3944 m_posScreen (posScreen),
4045 m_color (color),
4146 m_lineWidth (lineWidth),
42 m_wanted (true)
47 m_wanted (true),
48 m_highlightOpacity (DEFAULT_HIGHLIGHT_OPACITY),
49 m_geometryWindow (geometryWindow)
4350 {
4451 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::GraphicsPoint"
4552 << " identifier=" << identifier.toLatin1 ().data ();
5259 const QPointF &posScreen,
5360 const QColor &color,
5461 const QPolygonF &polygon,
55 double lineWidth) :
62 double lineWidth,
63 GeometryWindow *geometryWindow) :
5664 GraphicsPointAbstractBase (),
5765 m_scene (scene),
5866 m_graphicsItemEllipse (0),
6371 m_posScreen (posScreen),
6472 m_color (color),
6573 m_lineWidth (lineWidth),
66 m_wanted (true)
74 m_wanted (true),
75 m_highlightOpacity (DEFAULT_HIGHLIGHT_OPACITY),
76 m_geometryWindow (geometryWindow)
6777 {
6878 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::GraphicsPoint "
6979 << " identifier=" << identifier.toLatin1 ().data ();
121131 m_graphicsItemEllipse->setFlags (QGraphicsItem::ItemIsSelectable |
122132 QGraphicsItem::ItemIsMovable |
123133 QGraphicsItem::ItemSendsGeometryChanges);
124
125 m_graphicsItemEllipse->setToolTip (m_identifier);
126134 m_graphicsItemEllipse->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
135 if (m_geometryWindow != 0) {
136 QObject::connect (m_graphicsItemEllipse, SIGNAL (signalPointHoverEnter (QString)), m_geometryWindow, SLOT (slotPointHoverEnter (QString)));
137 QObject::connect (m_graphicsItemEllipse, SIGNAL (signalPointHoverLeave (QString)), m_geometryWindow, SLOT (slotPointHoverLeave (QString)));
138 }
127139
128140 // Shadow item is not selectable so it needs no stored data. Do NOT
129141 // call QGraphicsScene::addItem since the QGraphicsItem::setParentItem call adds the item
136148
137149 m_shadowZeroWidthEllipse->setPen (QPen (QBrush (m_color), ZERO_WIDTH));
138150 m_shadowZeroWidthEllipse->setEnabled (true);
151
152 m_graphicsItemEllipse->setShadow (m_shadowZeroWidthEllipse);
139153 }
140154
141155 void GraphicsPoint::createPointPolygon (const QPolygonF &polygon)
156170 m_graphicsItemPolygon->setFlags (QGraphicsItem::ItemIsSelectable |
157171 QGraphicsItem::ItemIsMovable |
158172 QGraphicsItem::ItemSendsGeometryChanges);
159
160 m_graphicsItemPolygon->setToolTip (m_identifier);
161173 m_graphicsItemPolygon->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
174 if (m_geometryWindow != 0) {
175 QObject::connect (m_graphicsItemPolygon, SIGNAL (signalPointHoverEnter (QString)), m_geometryWindow, SLOT (slotPointHoverEnter (QString)));
176 QObject::connect (m_graphicsItemPolygon, SIGNAL (signalPointHoverLeave (QString)), m_geometryWindow, SLOT (slotPointHoverLeave (QString)));
177 }
162178
163179 // Shadow item is not selectable so it needs no stored data. Do NOT
164180 // call QGraphicsScene::addItem since the QGraphicsItem::setParentItem call adds the item
168184
169185 m_shadowZeroWidthPolygon->setPen (QPen (QBrush (m_color), ZERO_WIDTH));
170186 m_shadowZeroWidthPolygon->setEnabled (true);
187
188 m_graphicsItemPolygon->setShadow (m_shadowZeroWidthPolygon);
171189 }
172190
173191 QVariant GraphicsPoint::data (int key) const
177195 } else {
178196 return m_graphicsItemEllipse->data (key);
179197 }
198 }
199
200 double GraphicsPoint::highlightOpacity () const
201 {
202 return m_highlightOpacity;
180203 }
181204
182205 QPointF GraphicsPoint::pos () const
234257 } else {
235258 m_graphicsItemEllipse->setData (key, data);
236259 }
260 }
261
262 void GraphicsPoint::setHighlightOpacity (double highlightOpacity)
263 {
264 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::setHighlightOpacity"
265 << " identifier=" << m_identifier.toLatin1().data()
266 << " highlightOpacity=" << highlightOpacity;
267
268 m_highlightOpacity = highlightOpacity;
237269 }
238270
239271 void GraphicsPoint::setPointStyle(const PointStyle &pointStyle)
293325 }
294326 }
295327
296 void GraphicsPoint::setToolTip (const QString &toolTip)
297 {
298 if (m_graphicsItemEllipse == 0) {
299 m_graphicsItemPolygon->setToolTip (toolTip);
300 } else {
301 m_graphicsItemEllipse->setToolTip (toolTip);
302 }
303 }
304
305328 void GraphicsPoint::setWanted ()
306329 {
307330 m_wanted = true;
77 #define GRAPHICS_POINT_H
88
99 #include "GraphicsPointAbstractBase.h"
10 #include "GraphicsPoint.h"
1110 #include <QColor>
1211 #include <QPointF>
1312
13 extern const double DEFAULT_HIGHLIGHT_OPACITY;
14 extern const double MAX_OPACITY;
15
1416 class CurveStyle;
17 class GeometryWindow;
1518 class GraphicsPointEllipse;
1619 class GraphicsPointPolygon;
1720 class PointStyle;
4447 const QPointF &posScreen,
4548 const QColor &color,
4649 unsigned int radius,
47 double lineWidth);
50 double lineWidth,
51 GeometryWindow *geometryWindow);
4852
4953 /// Constructor of polygon point.
5054 GraphicsPoint(QGraphicsScene &scene,
5256 const QPointF &posScreen,
5357 const QColor &color,
5458 const QPolygonF &polygon,
55 double lineWidth);
59 double lineWidth,
60 GeometryWindow *geometryWindow);
5661
5762 /// Destructor. This remove the graphics item from the scene
5863 ~GraphicsPoint ();
5964
6065 /// Proxy method for QGraphicsItem::data
6166 QVariant data (int key) const;
67
68 /// Get method for highlight opacity
69 double highlightOpacity () const;
6270
6371 /// Proxy method for QGraphicsItem::pos.
6472 QPointF pos () const;
7482 /// Proxy method for QGraphicsItem::setData
7583 void setData (int key, const QVariant &data);
7684
85 /// Set method for highlight opacity
86 void setHighlightOpacity (double highlightOpacity);
87
7788 /// Update the point style
7889 void setPointStyle (const PointStyle &pointStyle);
7990
8091 /// Update the position
8192 void setPos (const QPointF pos);
82
83 /// Proxy method for QGraphicsItem::setToolTip
84 void setToolTip (const QString &toolTip);
8593
8694 /// Mark point as wanted. Marking as unwanted is done by the reset function
8795 void setWanted ();
116124
117125 // Housekeeping
118126 bool m_wanted;
127
128 double m_highlightOpacity;
129
130 GeometryWindow *m_geometryWindow; // Can receive hover signals. Null if unused
119131 };
120132
121133 #endif // GRAPHICS_POINT_H
77 #include "GraphicsPoint.h"
88 #include "GraphicsPointEllipse.h"
99 #include "Logger.h"
10 #include <QColor>
1011 #include <QGraphicsScene>
1112 #include "QtToString.h"
1213
1314 GraphicsPointEllipse::GraphicsPointEllipse(GraphicsPoint &graphicsPoint,
1415 const QRect &rect) :
1516 QGraphicsEllipseItem (rect),
16 m_graphicsPoint (graphicsPoint)
17 m_graphicsPoint (graphicsPoint),
18 m_shadow (0)
1719 {
1820 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPointEllipse::GraphicsPointEllipse";
1921 }
3436 value);
3537 }
3638
39 void GraphicsPointEllipse::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
40 {
41 // Highlighted
42 setOpacityForSubtree (m_graphicsPoint.highlightOpacity());
43
44 emit signalPointHoverEnter (data (DATA_KEY_IDENTIFIER).toString ());
45
46 QGraphicsEllipseItem::hoverEnterEvent (event);
47 }
48
49 void GraphicsPointEllipse::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
50 {
51 // Unhighlighted
52 setOpacityForSubtree (MAX_OPACITY);
53
54 emit signalPointHoverLeave (data (DATA_KEY_IDENTIFIER).toString ());
55
56 QGraphicsEllipseItem::hoverLeaveEvent (event);
57 }
58
59 void GraphicsPointEllipse::setOpacityForSubtree (double opacity)
60 {
61 // Set this item
62 setOpacity (opacity);
63
64 if (m_shadow != 0) {
65
66 // Set the child item. Opacity < MAX_OPACITY is too dark so child is set to totally transparent
67 m_shadow->setOpacity (opacity < MAX_OPACITY ? 0.0 : opacity);
68 }
69 }
70
3771 void GraphicsPointEllipse::setRadius(int radius)
3872 {
3973 // Resize assuming symmetry about the origin, and an aspect ratio of 1:1 (so x and y scales are the same)
4074 double scale = (2 * radius) / boundingRect().width();
4175 setScale (scale);
4276 }
77
78 void GraphicsPointEllipse::setShadow (GraphicsPointEllipse *shadow)
79 {
80 m_shadow = shadow;
81 }
77 #define GRAPHICS_POINT_ELLIPSE_H
88
99 #include <QGraphicsEllipseItem>
10 #include <QObject>
1011 #include <QPointF>
1112
1213 class GraphicsPoint;
1314
1415 /// This class add event handling to QGraphicsEllipseItem
15 class GraphicsPointEllipse : public QGraphicsEllipseItem
16 class GraphicsPointEllipse : public QObject, public QGraphicsEllipseItem
1617 {
18 Q_OBJECT;
19
1720 public:
1821 /// Single constructor
1922 GraphicsPointEllipse(GraphicsPoint &graphicsPoint,
2124
2225 /// Intercept moves by dragging so moved items can be identified. This replaces unreliable hit tests.
2326 QVariant itemChange(GraphicsItemChange change, const QVariant &value);
27
28 /// Accept hover so point can be highlighted when cursor is over it as a guide to user
29 virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
30
31 /// Unhighlight this point
32 virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
33
2434 /// Update the radius
2535 void setRadius(int radius);
36
37 /// Bind this graphics item to its shadow
38 void setShadow (GraphicsPointEllipse *shadow);
39
40 signals:
41
42 /// Signal for geometry window to highlight the current point upon hover enter
43 void signalPointHoverEnter (QString);
44
45 /// Signal for geometry window to unhighlight the current point upon hover leave
46 void signalPointHoverLeave (QString);
2647
2748 private:
2849 GraphicsPointEllipse();
2950
51 void setOpacityForSubtree (double opacity);
52
3053 // Reference to the GraphicsPoint that this class belongs to
3154 GraphicsPoint &m_graphicsPoint;
55
56 GraphicsPointEllipse *m_shadow;
3257 };
3358
3459 #endif // GRAPHICS_POINT_ELLIPSE_H
55
66 #include "DataKey.h"
77 #include "EnumsToQt.h"
8 #include "GeometryWindow.h"
89 #include "GraphicsItemType.h"
910 #include "GraphicsPoint.h"
1011 #include "GraphicsPointFactory.h"
2122 GraphicsPoint *GraphicsPointFactory::createPoint (QGraphicsScene &scene,
2223 const QString &identifier,
2324 const QPointF &posScreen,
24 const PointStyle &pointStyle)
25 const PointStyle &pointStyle,
26 GeometryWindow *geometryWindow)
2527 {
2628 GraphicsPoint *item = 0;
2729
3436 posScreen,
3537 ColorPaletteToQColor (pointStyle.paletteColor ()),
3638 pointStyle.radius (),
37 pointStyle.lineWidth());
39 pointStyle.lineWidth(),
40 geometryWindow);
3841 }
3942 break;
4043
4548 posScreen,
4649 ColorPaletteToQColor (pointStyle.paletteColor ()),
4750 pointStyle.polygon (),
48 pointStyle.lineWidth());
51 pointStyle.lineWidth(),
52 geometryWindow);
4953 }
5054 break;
5155 }
88
99 #include "PointShape.h"
1010
11 class GeometryWindow;
1112 class GraphicsPoint;
1213 class PointStyle;
1314 class QGraphicsScene;
2425 GraphicsPoint *createPoint (QGraphicsScene &scene,
2526 const QString &identifier,
2627 const QPointF &posScreen,
27 const PointStyle &pointStyle);
28 const PointStyle &pointStyle,
29 GeometryWindow *geometryWindow);
2830 };
2931
3032 #endif // GRAPHICS_POINT_FACTORY_H
1313 GraphicsPointPolygon::GraphicsPointPolygon(GraphicsPoint &graphicsPoint,
1414 const QPolygonF &polygon) :
1515 QGraphicsPolygonItem (polygon),
16 m_graphicsPoint (graphicsPoint)
17
16 m_graphicsPoint (graphicsPoint),
17 m_shadow (0)
1818 {
1919 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPointPolygon::GraphicsPointPolygon";
2020 }
3535 value);
3636 }
3737
38 void GraphicsPointPolygon::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
39 {
40 // Highlighted
41 setOpacityForSubtree (m_graphicsPoint.highlightOpacity ());
42
43 emit signalPointHoverEnter (data (DATA_KEY_IDENTIFIER).toString ());
44
45 QGraphicsPolygonItem::hoverEnterEvent (event);
46 }
47
48 void GraphicsPointPolygon::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
49 {
50 // Unhighlighted
51 setOpacityForSubtree (MAX_OPACITY);
52
53 emit signalPointHoverLeave (data (DATA_KEY_IDENTIFIER).toString ());
54
55 QGraphicsPolygonItem::hoverLeaveEvent (event);
56 }
57
58 void GraphicsPointPolygon::setOpacityForSubtree (double opacity)
59 {
60 // Set this item
61 setOpacity (opacity);
62
63 if (m_shadow != 0) {
64
65 // Set the child item. Opacity < MAX_OPACITY is too dark so child is set to totally transparent
66 m_shadow->setOpacity (opacity < MAX_OPACITY ? 0.0 : opacity);
67 }
68 }
69
3870 void GraphicsPointPolygon::setRadius(int radius)
3971 {
4072 // Resize assuming symmetry about the origin, and an aspect ratio of 1:1 (so x and y scales are the same)
4173 double scale = (2 * radius) / boundingRect().width();
4274 setScale (scale);
4375 }
76
77 void GraphicsPointPolygon::setShadow (GraphicsPointPolygon *shadow)
78 {
79 m_shadow = shadow;
80 }
77 #define GRAPHICS_POINT_POLYGON_H
88
99 #include <QGraphicsPolygonItem>
10 #include <QObject>
1011 #include <QPointF>
1112
1213 class GraphicsPoint;
1314
1415 /// This class add event handling to QGraphicsPolygonItem
15 class GraphicsPointPolygon : public QGraphicsPolygonItem
16 class GraphicsPointPolygon : public QObject, public QGraphicsPolygonItem
1617 {
18 Q_OBJECT;
19
1720 public:
1821 /// Single constructor
1922 GraphicsPointPolygon(GraphicsPoint &graphicsPoint,
2225 /// Intercept moves by dragging so moved items can be identified. This replaces unreliable hit tests.
2326 QVariant itemChange(GraphicsItemChange change, const QVariant &value);
2427
28 /// Accept hover so point can be highlighted when cursor is over it as a guide to user
29 virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
30
31 /// Unhighlight this point
32 virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
33
2534 /// Update the radius
2635 void setRadius(int radius);
36
37 /// Bind this graphics item to its shadow
38 void setShadow (GraphicsPointPolygon *shadow);
39
40 signals:
41
42 /// Signal for geometry window to highlight the current point upon hover enter
43 void signalPointHoverEnter (QString);
44
45 /// Signal for geometry window to unhighlight the current point upon hover leave
46 void signalPointHoverLeave (QString);
2747
2848 private:
2949 GraphicsPointPolygon();
3050
51 void setOpacityForSubtree (double opacity);
52
3153 // Reference to the GraphicsPoint that this class belongs to
3254 GraphicsPoint &m_graphicsPoint;
55
56 GraphicsPointPolygon *m_shadow;
3357 };
3458
3559 #endif // GRAPHICS_POINT_POLYGON_H
1010 #include "DataKey.h"
1111 #include "EngaugeAssert.h"
1212 #include "EnumsToQt.h"
13 #include "GeometryWindow.h"
1314 #include "GraphicsItemType.h"
1415 #include "GraphicsPoint.h"
1516 #include "GraphicsPointFactory.h"
4243
4344 GraphicsPoint *GraphicsScene::createPoint (const QString &identifier,
4445 const PointStyle &pointStyle,
45 const QPointF &posScreen)
46 const QPointF &posScreen,
47 GeometryWindow *geometryWindow)
4648 {
4749 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::createPoint"
4850 << " identifier=" << identifier.toLatin1().data();
5557 GraphicsPoint *point = pointFactory.createPoint (*this,
5658 identifier,
5759 posScreen,
58 pointStyle);
59
60 point->setToolTip (identifier);
60 pointStyle,
61 geometryWindow);
62
6163 point->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
6264
6365 return point;
197199 }
198200 }
199201
200 QStringList GraphicsScene::selectedPointIdentifiers () const
201 {
202 const QList<QGraphicsItem*> &items = QGraphicsScene::selectedItems();
203
204 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::selectedPointIdentifiers"
205 << " selectedItems=" << items.count();
206
207 QStringList selectedIds;
208 QList<QGraphicsItem*>::const_iterator itr;
209 for (itr = items.begin(); itr != items.end(); itr++) {
210
211 const QGraphicsItem* item = *itr;
212
213 // Skip the image and only keep the Points
214 bool isPoint = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_POINT);
215 if (isPoint) {
216
217 // Add Point to the list
218 selectedIds << item->data(DATA_KEY_IDENTIFIER).toString ();
219
220 }
221 }
222
223 return selectedIds;
224 }
225
226202 void GraphicsScene::showCurves (bool show,
227203 bool showAll,
228204 const QString &curveNameWanted)
266242 }
267243 }
268244
269 void GraphicsScene::updateAfterCommand (CmdMediator &cmdMediator)
245 void GraphicsScene::updateAfterCommand (CmdMediator &cmdMediator,
246 double highlightOpacity,
247 GeometryWindow *geometryWindow)
270248 {
271249 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateAfterCommand";
272250
251 m_graphicsLinesForCurves.updateHighlightOpacity (highlightOpacity);
252
273253 updateCurves (cmdMediator);
274254
275255 // Update the points
276 updatePointMembership (cmdMediator);
256 updatePointMembership (cmdMediator,
257 geometryWindow);
277258 }
278259
279260 void GraphicsScene::updateCurves (CmdMediator &cmdMediator)
312293 }
313294 }
314295
315 void GraphicsScene::updatePointMembership (CmdMediator &cmdMediator)
296 void GraphicsScene::updatePointMembership (CmdMediator &cmdMediator,
297 GeometryWindow *geometryWindow)
316298 {
317299 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updatePointMembership";
318300
319301 CallbackSceneUpdateAfterCommand ftor (m_graphicsLinesForCurves,
320302 *this,
321 cmdMediator.document ());
303 cmdMediator.document (),
304 geometryWindow);
322305 Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
323306 &CallbackSceneUpdateAfterCommand::callback);
324307
1515 class Curve;
1616 class CurvesGraphs;
1717 class CurveStyles;
18 class GeometryWindow;
1819 class GraphicsPoint;
1920 class MainWindow;
2021 class PointStyle;
4041 /// Create one QGraphicsItem-based object that represents one Point. It is NOT added to m_graphicsLinesForCurves (see addPoint)
4142 GraphicsPoint *createPoint (const QString &identifier,
4243 const PointStyle &pointStyle,
43 const QPointF &posScreen);
44 const QPointF &posScreen,
45 GeometryWindow *geometryWindow);
4446
4547 /// Hide all graphics items, except background image, in preparation for preview during IMPORT_TYPE_ADVANCED
4648 void hideAllItemsExceptImage();
6567 /// Reset positionHasChanged flag for all items. Typically this is done as part of mousePressEvent.
6668 void resetPositionHasChangedFlags();
6769
68 /// Return a list of identifiers for the currently selected points.
69 QStringList selectedPointIdentifiers () const;
70
7170 /// Show or hide all Curves (if showAll is true) or just the selected Curve (if showAll is false);
7271 void showCurves (bool show,
7372 bool showAll = false,
7574
7675 /// Update the Points and their Curves after executing a command. After a mouse drag, the lines are already updated and
7776 /// updating would be done on out of date information (since that would be brought up to date by the NEXT command)
78 void updateAfterCommand (CmdMediator &cmdMediator);
77 void updateAfterCommand (CmdMediator &cmdMediator,
78 double highlightOpacity,
79 GeometryWindow *geometryWindow);
7980
8081 /// Update curve styles after settings changed.
8182 void updateCurveStyles(const CurveStyles &modelCurveStyles);
9697 void updateCurves (CmdMediator &cmdMediator);
9798
9899 /// Update Points using a multi-pass algorithm.
99 void updatePointMembership (CmdMediator &cmdMediator);
100 void updatePointMembership (CmdMediator &cmdMediator,
101 GeometryWindow *geometryWindow);
100102
101103 /// Curve name to GraphicsLinesForCurve
102104 GraphicsLinesForCurves m_graphicsLinesForCurves;
44 ******************************************************************************************************/
55
66 #include "DataKey.h"
7 #include "EngaugeAssert.h"
8 #include "GraphicsItemsExtractor.h"
79 #include "GraphicsItemType.h"
810 #include "GraphicsView.h"
911 #include "LoadFileInfo.h"
2729 MainWindow &mainWindow) :
2830 QGraphicsView (scene)
2931 {
30 connect (this, SIGNAL (signalContextMenuEvent (QString)), &mainWindow, SLOT (slotContextMenuEvent (QString)));
32 connect (this, SIGNAL (signalContextMenuEventAxis (QString)), &mainWindow, SLOT (slotContextMenuEventAxis (QString)));
33 connect (this, SIGNAL (signalContextMenuEventGraph (QStringList)), &mainWindow, SLOT (slotContextMenuEventGraph (QStringList)));
3134 connect (this, SIGNAL (signalDraggedDigFile (QString)), &mainWindow, SLOT (slotFileOpenDraggedDigFile (QString)));
3235 connect (this, SIGNAL (signalDraggedImage (QImage)), &mainWindow, SLOT (slotFileImportDraggedImage (QImage)));
3336 connect (this, SIGNAL (signalDraggedImageUrl (QUrl)), &mainWindow, SLOT (slotFileImportDraggedImageUrl (QUrl)));
3437 connect (this, SIGNAL (signalKeyPress (Qt::Key, bool)), &mainWindow, SLOT (slotKeyPress (Qt::Key, bool)));
35 connect (this, SIGNAL (signalLeave ()), &mainWindow, SLOT (slotLeave ()));
3638 connect (this, SIGNAL (signalMouseMove(QPointF)), &mainWindow, SLOT (slotMouseMove (QPointF)));
3739 connect (this, SIGNAL (signalMousePress (QPointF)), &mainWindow, SLOT (slotMousePress (QPointF)));
3840 connect (this, SIGNAL (signalMouseRelease (QPointF)), &mainWindow, SLOT (slotMouseRelease (QPointF)));
6668 {
6769 }
6870
69 void GraphicsView::contextMenuEvent (QContextMenuEvent *event)
70 {
71 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::contextMenuEvent";
72
73 QList<QGraphicsItem*> items = scene()->selectedItems ();
74
75 if (items.count () == 1) {
76
77 QGraphicsItem *item = items.first ();
78 QString pointIdentifier = item->data (DATA_KEY_IDENTIFIER).toString ();
79 GraphicsItemType type = (GraphicsItemType) item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt ();
80 QString curveName = Point::curveNameFromPointIdentifier (pointIdentifier);
81
82 if ((type == GRAPHICS_ITEM_TYPE_POINT) &&
83 (curveName == AXIS_CURVE_NAME)) {
71 void GraphicsView::contextMenuEvent(QContextMenuEvent *event)
72 {
73 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::contextMenuEvent"
74 << " selectedCount=" << scene()->selectedItems().count();
75
76 GraphicsItemsExtractor graphicsItemsExtractor;
77 const QList<QGraphicsItem*> &items = scene()->selectedItems();
78 QStringList pointIdentifiers = graphicsItemsExtractor.selectedPointIdentifiers(items);
79
80 if (pointIdentifiers.count() > 0) {
81
82 if (graphicsItemsExtractor.allSelectedItemsAreEitherAxisOrGraph (items,
83 GRAPH_POINTS)) {
84
85 // One or more graph points are selected so edit their coordinates
86 emit signalContextMenuEventGraph (pointIdentifiers);
87
88 } else if (graphicsItemsExtractor.allSelectedItemsAreEitherAxisOrGraph (items,
89 AXIS_POINTS) && pointIdentifiers.count() == 1) {
8490
8591 // A single axis point is selected so edit it
86 emit signalContextMenuEvent (pointIdentifier);
87 event->accept ();
88
89 return;
92 emit signalContextMenuEventAxis (pointIdentifiers.first());
93
9094 }
9195 }
9296
204208 }
205209 }
206210
207 void GraphicsView::leaveEvent (QEvent *event)
208 {
209 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsView::leaveEvent";
210
211 emit signalLeave ();
212
213 QGraphicsView::leaveEvent (event);
214 }
215
216211 void GraphicsView::mouseMoveEvent (QMouseEvent *event)
217212 {
218213 // LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsView::mouseMoveEvent cursor="
268263
269264 if (!isRightClick) {
270265
271
272266 emit signalMouseRelease (posScreen);
273267
274268 }
275269
276270 QGraphicsView::mouseReleaseEvent (event);
271 }
272
273 QStringList GraphicsView::pointIdentifiersFromSelection (const QList<QGraphicsItem*> &items) const
274 {
275 // This method assumes that all specified items are points
276
277 QStringList pointIdentifiers;
278
279 QList<QGraphicsItem*>::const_iterator itr;
280 for (itr = items.begin(); itr != items.end(); itr++) {
281
282 QGraphicsItem *item = *itr;
283 GraphicsItemType type = (GraphicsItemType) item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt ();
284 ENGAUGE_ASSERT (type == GRAPHICS_ITEM_TYPE_POINT);
285
286 QString pointIdentifier = item->data (DATA_KEY_IDENTIFIER).toString ();
287 pointIdentifiers << pointIdentifier;
288 }
289
290 return pointIdentifiers;
277291 }
278292
279293 void GraphicsView::wheelEvent(QWheelEvent *event)
2626 MainWindow &mainWindow);
2727 virtual ~GraphicsView();
2828
29 /// Intercept right click to support point editing.
30 void contextMenuEvent (QContextMenuEvent *event);
29 /// Intercept context event to support point editing
30 virtual void contextMenuEvent (QContextMenuEvent *event);
3131
3232 /// Intercept mouse drag event to support drag-and-drop.
3333 virtual void dragEnterEvent (QDragEnterEvent *event);
4040
4141 /// Intercept key press events to handle left/right/up/down moving.
4242 virtual void keyPressEvent (QKeyEvent *event);
43
44 /// Intercept leave events to manage override cursor.
45 virtual void leaveEvent (QEvent *event);
4643
4744 /// Intercept mouse move events to populate the current cursor position in StatusBar.
4845 virtual void mouseMoveEvent (QMouseEvent *event);
5855
5956 signals:
6057 /// Send right click on axis point to MainWindow for editing.
61 void signalContextMenuEvent (QString pointIdentifier);
58 void signalContextMenuEventAxis (QString pointIdentifier);
59
60 /// Send right click on graph point(s) to MainWindow for editing.
61 void signalContextMenuEventGraph (QStringList pointIdentifiers);
6262
6363 /// Send dragged dig file to MainWindow for import. This comes from dragging an engauge dig file
6464 void signalDraggedDigFile (QString);
7171
7272 /// Send keypress to MainWindow for eventual processing by DigitizeStateAbstractBase subclasses.
7373 void signalKeyPress (Qt::Key, bool atLeastOneSelectedItem);
74
75 /// Send leave to MainWindow for managing the override cursor.
76 void signalLeave ();
7774
7875 /// Send mouse move to MainWindow for eventual display of cursor coordinates in StatusBar
7976 void signalMouseMove (QPointF);
9390 private:
9491 GraphicsView();
9592
93 QStringList pointIdentifiersFromSelection (const QList<QGraphicsItem*> &items) const;
9694 bool inBounds (const QPointF &posScreen);
9795
9896 };
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
06 #ifndef GRID_LINE_H
17 #define GRID_LINE_H
28
99 #include "EnumsToQt.h"
1010 #include "GraphicsArcItem.h"
1111 #include "GridLineFactory.h"
12 #include "GridLineLimiter.h"
1213 #include "GridLines.h"
1314 #include "GridLineStyle.h"
1415 #include "Logger.h"
16 #include "MainWindowModel.h"
1517 #include <QGraphicsScene>
1618 #include <qmath.h>
1719 #include <QTextStream>
2931 const double RADIANS_TO_TICS = 5760 / TWO_PI;
3032
3133 GridLineFactory::GridLineFactory(QGraphicsScene &scene,
32 const DocumentModelCoords &modelCoords,
33 const Transformation &transformation) :
34 const DocumentModelCoords &modelCoords) :
3435 m_scene (scene),
3536 m_pointRadius (0.0),
3637 m_modelCoords (modelCoords),
37 m_transformation (transformation),
3838 m_isChecker (false)
3939 {
40 LOG4CPP_DEBUG_S ((*mainCat)) << "GridLineFactory::GridLineFactory"
41 << " transformation=" << transformation;
40 LOG4CPP_DEBUG_S ((*mainCat)) << "GridLineFactory::GridLineFactory";
4241 }
4342
4443 GridLineFactory::GridLineFactory(QGraphicsScene &scene,
4544 int pointRadius,
4645 const QList<Point> &pointsToIsolate,
47 const DocumentModelCoords &modelCoords,
48 const Transformation &transformation) :
46 const DocumentModelCoords &modelCoords) :
4947 m_scene (scene),
5048 m_pointRadius (pointRadius),
5149 m_pointsToIsolate (pointsToIsolate),
5250 m_modelCoords (modelCoords),
53 m_transformation (transformation),
5451 m_isChecker (true)
5552 {
5653 LOG4CPP_DEBUG_S ((*mainCat)) << "GridLineFactory::GridLineFactory"
5754 << " pointRadius=" << pointRadius
58 << " pointsToIsolate=" << pointsToIsolate.count()
59 << " transformation=" << transformation;
55 << " pointsToIsolate=" << pointsToIsolate.count();
6056 }
6157
6258 void GridLineFactory::bindItemToScene(QGraphicsItem *item) const
7571 GridLine *GridLineFactory::createGridLine (double xFrom,
7672 double yFrom,
7773 double xTo,
78 double yTo)
74 double yTo,
75 const Transformation &transformation)
7976 {
8077 LOG4CPP_DEBUG_S ((*mainCat)) << "GridLineFactory::createGridLine"
8178 << " xFrom=" << xFrom
117114 }
118115
119116 QPointF pointScreen;
120 m_transformation.transformRawGraphToScreen (QPointF (xGraph, yGraph),
121 pointScreen);
117 transformation.transformRawGraphToScreen (QPointF (xGraph, yGraph),
118 pointScreen);
122119
123120 double distanceToNearestPoint = minScreenDistanceFromPoints (pointScreen);
124121 if ((distanceToNearestPoint < m_pointRadius) ||
132129 pointScreen,
133130 yFrom,
134131 yTo,
132 transformation,
135133 *gridLine);
136134 stateSegmentIsActive = false;
137135
153151 }
154152
155153 void GridLineFactory::createGridLinesForEvenlySpacedGrid (const DocumentModelGridDisplay &modelGridDisplay,
154 const MainWindowModel &modelMainWindow,
155 const Transformation &transformation,
156156 GridLines &gridLines)
157157 {
158158 // At a minimum the transformation must be defined. Also, there is a brief interval between the definition of
159159 // the transformation and the initialization of modelGridDisplay (at which point this method gets called again) and
160160 // we do not want to create grid lines during that brief interval
161 if (m_transformation.transformIsDefined() &&
161 if (transformation.transformIsDefined() &&
162162 modelGridDisplay.stable()) {
163163
164164 double startX = modelGridDisplay.startX ();
168168 double stopX = modelGridDisplay.stopX ();
169169 double stopY = modelGridDisplay.stopY ();
170170
171 // Limit the number of grid lines. This is a noop if the limit is not exceeded
172 GridLineLimiter gridLineLimiter;
173 stepX = gridLineLimiter.limitedStepXTheta (m_modelCoords,
174 modelMainWindow,
175 modelGridDisplay);
176 stepY = gridLineLimiter.limitedStepYRange (m_modelCoords,
177 modelMainWindow,
178 modelGridDisplay);
179
180 // Apply if possible
171181 if (stepX != 0 &&
172182 stepY != 0) {
173183
179189 bool isLinearX = (m_modelCoords.coordScaleXTheta() == COORD_SCALE_LINEAR);
180190 for (double x = startX; x <= stopX; (isLinearX ? x += stepX : x *= stepX)) {
181191
182 GridLine *gridLine = createGridLine (x, startY, x, stopY);
192 GridLine *gridLine = createGridLine (x, startY, x, stopY, transformation);
183193 gridLine->setPen (pen);
184194 gridLines.add (gridLine);
185195 }
187197 bool isLinearY = (m_modelCoords.coordScaleYRadius() == COORD_SCALE_LINEAR);
188198 for (double y = startY; y <= stopY; (isLinearY ? y += stepY : y *= stepY)) {
189199
190 GridLine *gridLine = createGridLine (startX, y, stopX, y);
200 GridLine *gridLine = createGridLine (startX, y, stopX, y, transformation);
191201 gridLine->setPen (pen);
192202 gridLines.add (gridLine);
193203 }
317327 const QPointF &posEndScreen,
318328 double yFrom,
319329 double yTo,
330 const Transformation &transformation,
320331 GridLine &gridLine) const
321332 {
322333 LOG4CPP_DEBUG_S ((*mainCat)) << "GridLineFactory::finishActiveGridLine"
332343 // Linear cartesian radius
333344 double radiusLinearCartesian = yFrom;
334345 if (m_modelCoords.coordScaleYRadius() == COORD_SCALE_LOG) {
335 radiusLinearCartesian = m_transformation.logToLinearRadius(yFrom,
336 m_modelCoords.originRadius());
346 radiusLinearCartesian = transformation.logToLinearRadius(yFrom,
347 m_modelCoords.originRadius());
337348 } else {
338349 radiusLinearCartesian -= m_modelCoords.originRadius();
339350 }
340351
341352 // Draw along an arc since this is a side of constant radius, and we have polar coordinates
342 item = ellipseItem (m_transformation,
353 item = ellipseItem (transformation,
343354 radiusLinearCartesian,
344355 posStartScreen,
345356 posEndScreen);
1313 class DocumentModelCoords;
1414 class DocumentModelGridDisplay;
1515 class GridLines;
16 class MainWindowModel;
1617 class QGraphicsScene;
1718 class QTransform;
1819 class Transformation;
2829 public:
2930 /// Simple constructor for general use (i.e. not by Checker)
3031 GridLineFactory(QGraphicsScene &scene,
31 const DocumentModelCoords &modelCoords,
32 const Transformation &transformation);
32 const DocumentModelCoords &modelCoords);
3333
3434 /// Constructor for use by Checker, which has points that are isolated
3535 GridLineFactory(QGraphicsScene &scene,
3636 int pointRadius,
3737 const QList<Point> &pointsToIsolate,
38 const DocumentModelCoords &modelCoords,
39 const Transformation &transformation);
38 const DocumentModelCoords &modelCoords);
4039
4140 /// Create grid line, either along constant X/theta or constant Y/radius side. Line goes from pointFromGraph to pointToGraph.
4241 /// If the coordinates are polar, we go clockwise from pointFromGraph to pointToGraph (as set up by adjustPolarAngleRange).
4342 GridLine *createGridLine (double xFrom,
4443 double yFrom,
4544 double xTo,
46 double yTo);
45 double yTo,
46 const Transformation &transformation);
4747
4848 /// Create a rectangular (cartesian) or annular (polar) grid of evenly spaced grid lines.
4949 void createGridLinesForEvenlySpacedGrid (const DocumentModelGridDisplay &modelGridDisplay,
50 const MainWindowModel &modelMainWindow,
51 const Transformation &transformation,
5052 GridLines &gridLines);
5153
5254 private:
6769 const QPointF &posEndScreen,
6870 double yFrom,
6971 double yTo,
72 const Transformation &transformation,
7073 GridLine &gridLine) const;
7174 QGraphicsItem *lineItem (const QPointF &posStartScreen,
7275 const QPointF &posEndScreen) const;
7679 const int m_pointRadius;
7780 const QList<Point> m_pointsToIsolate;
7881 const DocumentModelCoords m_modelCoords;
79 const Transformation &m_transformation;
8082 bool m_isChecker;
8183 };
8284
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DocumentModelCoords.h"
7 #include "DocumentModelGridDisplay.h"
8 #include "DocumentModelGridRemoval.h"
9 #include "GridLineLimiter.h"
10 #include "MainWindowModel.h"
11 #include <qmath.h>
12
13 const int DEFAULT_MAXIMUM_GRID_LINES = 25;
14
15 GridLineLimiter::GridLineLimiter ()
16 {
17 }
18
19 double GridLineLimiter::limitedStepXTheta (const DocumentModelCoords &modelCoords,
20 const MainWindowModel &modelMainWindow,
21 const DocumentModelGridDisplay &modelGrid) const
22 {
23 double step = modelGrid.stepX();
24
25 if (modelCoords.coordScaleXTheta() == COORD_SCALE_LINEAR) {
26
27 // Linear
28 double count = 1.0 + (modelGrid.stopX() - modelGrid.startX()) / modelGrid.stepX();
29 if ((int) count > modelMainWindow.maximumGridLines()) {
30
31 // Adjust step so maximum grid lines limit is met
32 step = (modelGrid.stopX() - modelGrid.startX()) / (modelMainWindow.maximumGridLines() - 1);
33
34 }
35
36 } else {
37
38 // Log
39 double count = 1.0 + (qLn (modelGrid.stopX()) - qLn (modelGrid.startX())) / qLn (modelMainWindow.maximumGridLines());
40 if ((int) count > modelMainWindow.maximumGridLines()) {
41
42 // Adjust step so maximum grid lines limit is met
43 step = qExp ((qLn (modelGrid.stopX()) - qLn (modelGrid.startX())) / (modelMainWindow.maximumGridLines() - 1));
44
45 }
46 }
47
48 return step;
49 }
50
51 double GridLineLimiter::limitedStepYRange (const DocumentModelCoords &modelCoords,
52 const MainWindowModel &modelMainWindow,
53 const DocumentModelGridDisplay &modelGrid) const
54 {
55 double step = modelGrid.stepY();
56
57 if (modelCoords.coordScaleYRadius() == COORD_SCALE_LINEAR) {
58
59 // Linear
60 double count = 1.0 + (modelGrid.stopY() - modelGrid.startY()) / modelGrid.stepY();
61 if ((int) count > modelMainWindow.maximumGridLines()) {
62
63 // Adjust step so maximum grid lines limit is met
64 step = (modelGrid.stopY() - modelGrid.startY()) / (modelMainWindow.maximumGridLines() - 1);
65
66 }
67
68 } else {
69
70 // Log
71 double count = 1.0 + (qLn (modelGrid.stopY()) - qLn (modelGrid.startY())) / qLn (modelMainWindow.maximumGridLines());
72 if ((int) count > modelMainWindow.maximumGridLines()) {
73
74 // Adjust step so maximum grid lines limit is met
75 step = qExp ((qLn (modelGrid.stopY()) - qLn (modelGrid.startY())) / (modelMainWindow.maximumGridLines() - 1));
76
77 }
78 }
79
80 return step;
81 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef GRID_LINE_LIMITER_H
7 #define GRID_LINE_LIMITER_H
8
9 class DocumentModelCoords;
10 class DocumentModelGridDisplay;
11 class MainWindowModel;
12
13 /// Default for maximum number of grid lines
14 extern const int DEFAULT_MAXIMUM_GRID_LINES;
15
16 /// Limit the number of grid lines so a bad combination of start/step/stop value will not lead to extremely
17 /// long delays when the step size is much too small for the start/stop values
18 class GridLineLimiter
19 {
20 public:
21 /// Single constructor
22 GridLineLimiter ();
23
24 /// Limit step value for x/theta coordinate. This is a noop if the maximum grid line limit in MainWindowModel is not exceeded
25 double limitedStepXTheta (const DocumentModelCoords &modelCoords,
26 const MainWindowModel &modelMainWindow,
27 const DocumentModelGridDisplay &modelGrid) const;
28
29 /// Limit step value for y/range coordinate. This is a noop if the maximum grid line limit in MainWindowModel is not exceeded
30 double limitedStepYRange (const DocumentModelCoords &modelCoords,
31 const MainWindowModel &modelMainWindow,
32 const DocumentModelGridDisplay &modelGrid) const;
33
34 };
35
36 #endif // GRID_LINE_LIMITER_H
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
06 #ifndef GRID_LINES_H
17 #define GRID_LINES_H
28
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "ImportCropping.h"
7 #include <QObject>
8
9 const QString IMPORT_CROPPING_NEVER_STRING (QObject::tr ("Never crop during import"));
10 const QString IMPORT_CROPPING_MULTIPAGE_PDFS_STRING (QObject::tr ("Crop during import only for multiple-page pdf files"));
11 const QString IMPORT_CROPPING_ALWAYS_STRING (QObject::tr ("Always crop during import"));
12
13 const ImportCropping DEFAULT_IMPORT_CROPPING = IMPORT_CROPPING_NEVER;
14
15 QString ImportCroppingToString (ImportCropping importCropping)
16 {
17
18 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef IMPORT_CROPPING_H
7 #define IMPORT_CROPPING_H
8
9 enum ImportCropping
10 {
11 IMPORT_CROPPING_NEVER,
12 IMPORT_CROPPING_MULTIPAGE_PDFS,
13 IMPORT_CROPPING_ALWAYS,
14 NUMBER_IMPORT_CROPPING
15 };
16
17 extern const ImportCropping DEFAULT_IMPORT_CROPPING;
18
19 #endif // IMPORT_CROPPING_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "EngaugeAssert.h"
7 #include "ImportCroppingUtilBase.h"
8 #include <QHash>
9 #include <QObject>
10
11 const ImportCropping DEFAULT_IMPORT_CROPPING = IMPORT_CROPPING_NEVER; // Traditional, and simplest, option
12
13 ImportCroppingUtilBase::ImportCroppingUtilBase()
14 {
15 }
16
17 QString ImportCroppingUtilBase::importCroppingToString (ImportCropping importCropping)
18 {
19 QHash<ImportCropping, QString> lookupTable;
20
21 lookupTable.insert (IMPORT_CROPPING_NEVER, QObject::tr ("No cropping"));
22 lookupTable.insert (IMPORT_CROPPING_MULTIPAGE_PDFS, QObject::tr ("Crop pdf files with multiple pages"));
23 lookupTable.insert (IMPORT_CROPPING_ALWAYS, QObject::tr ("Always crop"));
24
25 ENGAUGE_ASSERT (lookupTable.count() == NUMBER_IMPORT_CROPPING);
26
27 QString rtn;
28
29 if (lookupTable.contains (importCropping)) {
30 rtn = lookupTable [importCropping];
31 }
32
33 return rtn;
34 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef IMPORT_CROPPING_UTIL_BASE_H
7 #define IMPORT_CROPPING_UTIL_BASE_H
8
9 #include "ImportCropping.h"
10 #include <QString>
11
12 /// Utility class for import cropping options. Default option is oldest, and simplest, behavior, which is no cropping.
13 ///
14 /// A complication is that a dialog for cropping is not wanted during batch-mode regression testing, so this class
15 /// and its subclasses offer methods for overriding the current setting during regression testing
16 class ImportCroppingUtilBase
17 {
18 public:
19 /// Single constructor
20 ImportCroppingUtilBase();
21
22 /// Option as string for display to user
23 static QString importCroppingToString (ImportCropping importCropping);
24
25 };
26
27 #endif // IMPORT_CROPPING_UTIL_BASE_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "ImportCroppingUtilNonPdf.h"
7
8 ImportCroppingUtilNonPdf::ImportCroppingUtilNonPdf()
9 {
10 }
11
12 bool ImportCroppingUtilNonPdf::applyImportCropping (bool isRegression,
13 ImportCropping importCropping) const
14 {
15 bool cropping = false;
16
17 if (!isRegression) {
18
19 cropping = (importCropping == IMPORT_CROPPING_ALWAYS);
20 }
21
22 return cropping;
23 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef IMPORT_CROPPING_UTIL_NON_PDF_H
7 #define IMPORT_CROPPING_UTIL_NON_PDF_H
8
9 #include "ImportCropping.h"
10 #include "ImportCroppingUtilBase.h"
11
12 /// Import of non-pdf files
13 class ImportCroppingUtilNonPdf : public ImportCroppingUtilBase
14 {
15 public:
16 /// Single constructor
17 ImportCroppingUtilNonPdf();
18
19 /// Skip cropping dialog during regression testing, otherwise crop if it is always turned on
20 bool applyImportCropping (bool isRegression,
21 ImportCropping importCropping) const;
22
23 };
24
25 #endif // IMPORT_CROPPING_UTIL_NON_PDF_H
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "ImportCroppingUtilPdf.h"
7 #include "poppler-qt5.h"
8 #include <QApplication>
9
10 using namespace Poppler;
11
12 ImportCroppingUtilPdf::ImportCroppingUtilPdf()
13 {
14 }
15
16 bool ImportCroppingUtilPdf::applyImportCropping (bool isErrorReportRegressionTest,
17 const QString &fileName,
18 ImportCropping importCropping,
19 Document *&document) const
20 {
21 document = 0;
22
23 bool cropping = false;
24
25 if (!isErrorReportRegressionTest) {
26
27 // Simple check to prevent complaints from poppler code
28 if (fileName.right (4).toLower () == ".pdf") {
29
30 // Try to read the file
31 QApplication::setOverrideCursor (Qt::BusyCursor); // Since load could take a while
32 document = Document::load (fileName);
33 QApplication::restoreOverrideCursor();
34 if (document != 0) {
35 if (!document->isLocked ()) {
36
37 cropping = (importCropping == IMPORT_CROPPING_ALWAYS ||
38 (importCropping == IMPORT_CROPPING_MULTIPAGE_PDFS && document->numPages () > 1));
39 }
40 }
41 }
42 }
43
44 return cropping;
45 }
0 /******************************************************************************************************
1 * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef IMPORT_CROPPING_UTIL_PDF_H
7 #define IMPORT_CROPPING_UTIL_PDF_H
8
9 #include "ImportCropping.h"
10 #include "ImportCroppingUtilBase.h"
11 #include <QString>
12
13 namespace Poppler {
14 class Document;
15 }
16
17 /// Import of pdf files
18 class ImportCroppingUtilPdf : public ImportCroppingUtilBase
19 {
20 public:
21 /// Single constructor
22 ImportCroppingUtilPdf();
23
24 /// For pdf files, skip cropping dialog during regression testing, otherwise crop if it is always turned on or if
25 /// there are multiple pages.
26 ///
27 /// For speed, the Document is returned if cropping is to be performed so the file needs to be read only once
28 bool applyImportCropping (bool isRegression,
29 const QString &fileName,
30 ImportCropping importCropping,
31 Poppler::Document *&document) const;
32
33 };
34
35 #endif // IMPORT_CROPPING_UTIL_PDF_H
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "DlgImportCroppingNonPdf.h"
7 #include "ImportCroppingUtilNonPdf.h"
8 #include "NonPdf.h"
9 #include <QApplication>
10 #include <QImage>
11 #include <QString>
12
13 NonPdf::NonPdf ()
14 {
15 }
16
17 NonPdfReturn NonPdf::load (const QString &fileName,
18 QImage &image,
19 ImportCropping importCropping,
20 bool isErrorReportRegressionTest) const
21 {
22 ImportCroppingUtilNonPdf importCroppingUtil;
23 bool cropping = importCroppingUtil.applyImportCropping (isErrorReportRegressionTest,
24 importCropping);
25
26 NonPdfReturn rtn;
27 QApplication::setOverrideCursor(Qt::BusyCursor); // Since loading can be slow
28 if (cropping) {
29
30 rtn = loadWithCropping (fileName,
31 image);
32
33 } else {
34
35 rtn = loadWithoutCropping (fileName,
36 image);
37
38 }
39 QApplication::restoreOverrideCursor();
40
41 return rtn;
42 }
43
44 NonPdfReturn NonPdf::loadWithCropping (const QString &fileName,
45 QImage &image) const
46 {
47 NonPdfReturn nonPdfReturn = NON_PDF_RETURN_FAILED;
48
49 // Get page and extent. At this point it is always true that the image can be read
50 DlgImportCroppingNonPdf dlg (fileName);
51 if (dlg.exec() == QDialog::Accepted) {
52
53 // Returned image is null if it could not be read
54 image = dlg.image ();
55
56 if (!image.isNull()) {
57 nonPdfReturn = NON_PDF_RETURN_SUCCESS;
58 }
59
60 } else {
61 nonPdfReturn = NON_PDF_RETURN_CANCELED;
62 }
63
64 return nonPdfReturn;
65 }
66
67 NonPdfReturn NonPdf::loadWithoutCropping (const QString &fileName,
68 QImage &image) const
69 {
70 NonPdfReturn nonPdfReturn = NON_PDF_RETURN_FAILED;
71
72 if (image.load (fileName)) {
73 nonPdfReturn = NON_PDF_RETURN_SUCCESS;
74 }
75
76 return nonPdfReturn;
77 }
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef NON_PDF_H
7 #define NON_PDF_H
8
9 #include "ImportCropping.h"
10
11 namespace Poppler {
12 class Document;
13 }
14 class QImage;
15 class QString;
16
17 /// Return values from load operation
18 enum NonPdfReturn {
19 NON_PDF_RETURN_CANCELED,
20 NON_PDF_RETURN_FAILED,
21 NON_PDF_RETURN_SUCCESS
22 };
23
24 /// Wrapper around the QImage class for read and importing non-PDF files.
25 class NonPdf
26 {
27 public:
28 /// Single constructor
29 NonPdf();
30
31 /// Try to load the specified file. Success is indicated in the function return value
32 NonPdfReturn load (const QString &fileName,
33 QImage &image,
34 ImportCropping importCropping,
35 bool isErrorReportRegressionTest) const;
36
37 private:
38
39 NonPdfReturn loadWithCropping (const QString &fileName,
40 QImage &image) const; // Dialog is used when not testing
41 NonPdfReturn loadWithoutCropping (const QString &fileName,
42 QImage &image) const; // No dialog is used during testing. Entire image will be loadedd
43
44 };
45
46 #endif // NON_PDF_H
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "Logger.h"
7 #include "NonPdfCropping.h"
8 #include "NonPdfFrameHandle.h"
9 #include <QGraphicsRectItem>
10 #include <QGraphicsScene>
11 #include <QRect>
12 #include "QtToString.h"
13 #include "ViewPreview.h"
14
15 const int Z_BOX = 50; // Under box and over background image
16 const int Z_HANDLE = 100; // Over box and background image
17
18 NonPdfCropping::NonPdfCropping (QGraphicsScene &scene,
19 ViewPreview &view) :
20 m_view (view)
21 {
22 createWidgets (scene);
23 }
24
25 void NonPdfCropping::createWidgets(QGraphicsScene &scene)
26 {
27 const double MARGIN_PERCENT = 5.0;
28 const int ZERO_WIDTH_IS_ALWAYS_VISIBLE = 0;
29
30 int marginHor = scene.width() * MARGIN_PERCENT / 100.0;
31 int marginVer = scene.height() * MARGIN_PERCENT / 100.0;
32
33 QRect box (scene.sceneRect().left() + marginHor,
34 scene.sceneRect().top() + marginVer,
35 scene.sceneRect().width() - 2 * marginHor,
36 scene.sceneRect().height() - 2 * marginVer);
37
38 m_handleTL = new NonPdfFrameHandle (scene, m_view, box.topLeft() , NON_PDF_CROPPING_LEFT | NON_PDF_CROPPING_TOP , *this, Z_HANDLE);
39 m_handleTR = new NonPdfFrameHandle (scene, m_view, box.topRight() , NON_PDF_CROPPING_RIGHT | NON_PDF_CROPPING_TOP , *this, Z_HANDLE);
40 m_handleBR = new NonPdfFrameHandle (scene, m_view, box.bottomRight(), NON_PDF_CROPPING_RIGHT | NON_PDF_CROPPING_BOTTOM , *this, Z_HANDLE);
41 m_handleBL = new NonPdfFrameHandle (scene, m_view, box.bottomLeft() , NON_PDF_CROPPING_LEFT | NON_PDF_CROPPING_BOTTOM , *this, Z_HANDLE);
42
43 m_box = new QGraphicsRectItem;
44 m_box->setZValue (Z_BOX);
45 m_box->setPen (QPen (QBrush (Qt::gray), ZERO_WIDTH_IS_ALWAYS_VISIBLE));
46 scene.addItem (m_box);
47
48 updateBox ();
49 }
50
51 void NonPdfCropping::disableEventsWhileMovingAutomatically ()
52 {
53 m_handleTL->setDisableEventsWhileMovingAutomatically (true);
54 m_handleTR->setDisableEventsWhileMovingAutomatically (true);
55 m_handleBR->setDisableEventsWhileMovingAutomatically (true);
56 m_handleBL->setDisableEventsWhileMovingAutomatically (true);
57 }
58
59 void NonPdfCropping::enableEventsWhileMovingAutomatically ()
60 {
61 m_handleTL->setDisableEventsWhileMovingAutomatically (false);
62 m_handleTR->setDisableEventsWhileMovingAutomatically (false);
63 m_handleBR->setDisableEventsWhileMovingAutomatically (false);
64 m_handleBL->setDisableEventsWhileMovingAutomatically (false);
65 }
66
67 QRectF NonPdfCropping::frameRect () const
68 {
69 // The x(), y(), pos(), rect() and boundingRect() will return coordinates assuming origin at the initial position of
70 // each handle. So to get the coordinates in the window reference frame it takes a two step process like
71 // QGraphicsRectItem::mapRectToScene (QGraphicsRectItem::rect())
72
73 QRectF rectTL = m_handleTL->mapRectToScene (m_handleTL->boundingRect());
74 QRectF rectBR = m_handleBR->mapRectToScene (m_handleBR->boundingRect());
75
76 QRectF rectUnited = rectTL.united (rectBR);
77
78 return rectUnited;
79 }
80
81 void NonPdfCropping::moveBL (const QPointF &newPos,
82 const QPointF &oldPos)
83 {
84 disableEventsWhileMovingAutomatically();
85
86 double deltaX = newPos.x() - oldPos.x();
87 double deltaY = newPos.y() - oldPos.y();
88
89 m_handleTL->moveBy (deltaX,
90 0);
91 m_handleBR->moveBy (0,
92 deltaY);
93
94 enableEventsWhileMovingAutomatically();
95
96 updateBox();
97 }
98
99 void NonPdfCropping::moveBR (const QPointF &newPos,
100 const QPointF &oldPos)
101 {
102 disableEventsWhileMovingAutomatically();
103
104 double deltaX = newPos.x() - oldPos.x();
105 double deltaY = newPos.y() - oldPos.y();
106
107 m_handleBL->moveBy (0,
108 deltaY);
109 m_handleTR->moveBy (deltaX,
110 0);
111
112 enableEventsWhileMovingAutomatically();
113
114 updateBox();
115 }
116
117 void NonPdfCropping::moveTL (const QPointF &newPos,
118 const QPointF &oldPos)
119 {
120 disableEventsWhileMovingAutomatically();
121
122 double deltaX = newPos.x() - oldPos.x();
123 double deltaY = newPos.y() - oldPos.y();
124
125 m_handleBL->moveBy (deltaX,
126 0);
127 m_handleTR->moveBy (0,
128 deltaY);
129
130 enableEventsWhileMovingAutomatically();
131
132 updateBox();
133 }
134
135 void NonPdfCropping::moveTR (const QPointF &newPos,
136 const QPointF &oldPos)
137 {
138 disableEventsWhileMovingAutomatically();
139
140 double deltaX = newPos.x() - oldPos.x();
141 double deltaY = newPos.y() - oldPos.y();
142
143 m_handleTL->moveBy (0,
144 deltaY);
145 m_handleBR->moveBy (deltaX,
146 0);
147
148 enableEventsWhileMovingAutomatically();
149
150 updateBox();
151 }
152
153 void NonPdfCropping::updateBox ()
154 {
155 QRectF rectUnited = frameRect ();
156
157 // Adjust by one pixel in both horizontal and vertical directions so bottom/right handles end on the box
158 rectUnited.setWidth (rectUnited.width () - 1);
159 rectUnited.setHeight (rectUnited.height () - 1);
160
161 m_box->setRect (rectUnited);
162 }
163
164 QSize NonPdfCropping::windowSize () const
165 {
166 return QSize (m_view.scene()->width(),
167 m_view.scene()->height());
168 }
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef NON_PDF_CROPPING_H
7 #define NON_PDF_CROPPING_H
8
9 #include <QRect>
10 #include <QSize>
11
12 class NonPdfFrameHandle;
13 class QGraphicsRectItem;
14 class QGraphicsScene;
15 class QPointF;
16 class ViewPreview;
17
18 /// This class shows a frame around the selected portion of the import preview window
19 ///
20 /// This class was developed as a non-pdf equivalent to the PdfCropping class. See that class for more details
21 class NonPdfCropping
22 {
23 public:
24 /// Single constructor
25 NonPdfCropping(QGraphicsScene &scene,
26 ViewPreview &view);
27
28 /// Frame rectangle selected by user
29 QRectF frameRect () const;
30
31 /// Bottom left corner handle was moved
32 void moveBL (const QPointF &newPos,
33 const QPointF &oldPos);
34
35 /// Bottom right corner handle was moved
36 void moveBR (const QPointF &newPos,
37 const QPointF &oldPos);
38
39 /// Top left corner handle was moved
40 void moveTL (const QPointF &newPos,
41 const QPointF &oldPos);
42
43 /// Top right corner handle was moved
44 void moveTR (const QPointF &newPos,
45 const QPointF &oldPos);
46
47 static const int NON_PDF_CROPPING_BOTTOM = 1; ///< Bit flag when handle is aligned with bottom edge at reference point
48 static const int NON_PDF_CROPPING_LEFT = 2; ///< Bit flag when handle is aligned with left edge at reference point
49 static const int NON_PDF_CROPPING_RIGHT = 4; ///< Bit flag when handle is aligned with right edge at reference point
50 static const int NON_PDF_CROPPING_TOP = 8; ///< Bit flag when handle is aligned with top edge at reference point
51
52 /// Size of window in scene coordinates
53 QSize windowSize () const;
54
55 private:
56 NonPdfCropping ();
57
58 void createWidgets (QGraphicsScene &scene);
59 void disableEventsWhileMovingAutomatically();
60 void enableEventsWhileMovingAutomatically();
61 QRectF rectFromTLAndBR () const;
62 void updateBox();
63
64 ViewPreview &m_view;
65
66 // Box
67 QGraphicsRectItem *m_box;
68
69 // Handles
70 NonPdfFrameHandle *m_handleTL;
71 NonPdfFrameHandle *m_handleTR;
72 NonPdfFrameHandle *m_handleBR;
73 NonPdfFrameHandle *m_handleBL;
74
75 };
76
77 #endif // NON_PDF_CROPPING_H
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "NonPdfCropping.h"
7 #include "NonPdfFrameHandle.h"
8 #include <QBrush>
9 #include <QGraphicsScene>
10 #include <QGraphicsView>
11 #include <QStyleOptionGraphicsItem>
12
13 const double HANDLE_SIZE_AS_FRACTION_OF_WINDOW_SIZE = 30;
14
15 NonPdfFrameHandle::NonPdfFrameHandle (QGraphicsScene &scene,
16 QGraphicsView &view,
17 const QPointF &pointReference,
18 int orientationFlags,
19 NonPdfCropping &nonPdfCropping,
20 int zValue) :
21 m_nonPdfCropping (nonPdfCropping),
22 m_orientationFlags (orientationFlags),
23 m_disableEventsWhileMovingAutomatically (false),
24 m_scene (scene),
25 m_view (view)
26 {
27 const double SUBTLE_OPACITY = 0.2;
28
29 // Advantages of using ItemIgnoresTransformations:
30 // 1) handles do not get bigger or smaller depending on the size of the image
31 // 2) handles never get ugly when zoomed in
32 // 3) handles never get too tiny when zoomed out
33 // Disadvantages of using ItemIgnoresTransformation:
34 // 1) Resizing the preview window with ItemIgnoresTransformations moves the handles out of position
35 // 2) More conversions back and forth between untransformed and transformed coordinates. This was the deal breaker since
36 // the transformations were undocumented and ultimately too difficult
37 // The solution is to have constant-size handles WITHOUT ItemIgnoresTransformations. This means resizing the window
38 // also involves resizing the handles, but everything else is pretty easy
39 //
40 // ItemIgnoresTransformations flag must agree with the QGraphicsRectItem used for the frame box by PdfCropping
41 setFlags (QGraphicsItem::ItemIsMovable |
42 QGraphicsItem::ItemIsSelectable |
43 QGraphicsItem::ItemSendsScenePositionChanges);
44
45 // Fill with nice color for better visibility. Note that the pen is disabled by overriding the paint method
46 setBrush (QBrush (Qt::blue));
47 setVisible (true);
48 setZValue (zValue);
49 setOpacity (SUBTLE_OPACITY);
50 setPos (pointReference); // Point position is handled in scene/view coordinates
51
52 // Add to scene
53 scene.addItem (this);
54
55 QSize handleSize = m_nonPdfCropping.windowSize() / HANDLE_SIZE_AS_FRACTION_OF_WINDOW_SIZE;
56
57 // Adjust positions of handles that are not at the top left so handles are laid out symmetrically
58 QPointF pointPos = pointReference;
59 if ((orientationFlags & NonPdfCropping::NON_PDF_CROPPING_LEFT) != 0) {
60 pointPos.setX (pointPos.x() - handleSize.width() / 2.0);
61 } else if ((orientationFlags & NonPdfCropping::NON_PDF_CROPPING_RIGHT) != 0) {
62 pointPos.setX (pointPos.x() + handleSize.width() / 2.0);
63 }
64 if ((orientationFlags & NonPdfCropping::NON_PDF_CROPPING_TOP) != 0) {
65 pointPos.setY (pointPos.y() - handleSize.height() / 2.0);
66 } else if ((orientationFlags & NonPdfCropping::NON_PDF_CROPPING_BOTTOM) != 0) {
67 pointPos.setY (pointPos.y() + handleSize.height() / 2.0);
68 }
69
70 // Start with geometry. Since point positions are handled in scene/view coordinates, we have to convert
71 // to local coordinates for the rectangle
72 QPointF topLeftLocal = mapFromScene (pointPos);
73
74 setRect (QRectF (topLeftLocal,
75 handleSize));
76 }
77
78 QVariant NonPdfFrameHandle::itemChange (GraphicsItemChange change,
79 const QVariant &value)
80 {
81 QVariant valueFiltered = value;
82
83 if (change == ItemPositionChange && scene()) {
84
85 QPointF sizeAsPointF (boundingRect().size().width(),
86 boundingRect().size().height());
87
88 // New position is in the value argument
89 QPointF newPos = valueFiltered.toPointF();
90 QPointF oldPos = pos ();
91
92 // This sequence is from http://www.qtcentre.org/threads/47248-How-to-efficiently-get-position-of-a-QGraphicsItem-in-view-coordinates
93 QRectF newRectItem (newPos,
94 QSize (boundingRect().size().width(),
95 boundingRect().size().height()));
96 QPolygonF newRectScene = mapToScene (newRectItem);
97 QPolygon newRectView = m_view.mapFromScene (newRectScene.boundingRect());
98
99 // Skip moving of this handle if it will go outside of the window
100 QRectF rectWindow = m_scene.sceneRect();
101 if (!rectWindow.contains (newRectView.boundingRect())) {
102
103 // Keep the item inside the scene rectangle
104 newPos.setX (qMin (rectWindow.right(), qMax (newPos.x(), rectWindow.left())));
105 newPos.setY (qMin (rectWindow.bottom(), qMax (newPos.y(), rectWindow.top())));
106
107 valueFiltered = (newPos);
108
109 }
110
111 // Skip moving of other handles, in response to the move of this handle, if event handling is (temporarily) off,
112 // to prevent an infinite loop
113 if (!m_disableEventsWhileMovingAutomatically) {
114
115 bool left = ((m_orientationFlags & NonPdfCropping::NON_PDF_CROPPING_LEFT ) != 0);
116 bool right = ((m_orientationFlags & NonPdfCropping::NON_PDF_CROPPING_RIGHT ) != 0);
117 bool top = ((m_orientationFlags & NonPdfCropping::NON_PDF_CROPPING_TOP ) != 0);
118 bool bottom = ((m_orientationFlags & NonPdfCropping::NON_PDF_CROPPING_BOTTOM) != 0);
119
120 if (left && top) {
121 m_nonPdfCropping.moveTL (newPos, oldPos);
122 } else if (right && top) {
123 m_nonPdfCropping.moveTR (newPos, oldPos);
124 } else if (right && bottom) {
125 m_nonPdfCropping.moveBR (newPos, oldPos);
126 } else if (left && bottom) {
127 m_nonPdfCropping.moveBL (newPos, oldPos);
128 }
129 }
130 }
131
132 return QGraphicsItem::itemChange(change, valueFiltered);
133 }
134
135 void NonPdfFrameHandle::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
136 {
137 // Temporarily remove the selected option
138 QStyleOptionGraphicsItem scrubbed (*option);
139 scrubbed.state &= ~QStyle::State_Selected;
140 QGraphicsRectItem::paint (painter, &scrubbed, widget);
141 }
142
143 void NonPdfFrameHandle::setDisableEventsWhileMovingAutomatically (bool disable)
144 {
145 m_disableEventsWhileMovingAutomatically = disable;
146 }
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef NON_PDF_FRAME_HANDLE_H
7 #define NON_PDF_FRAME_HANDLE_H
8
9 #include <QGraphicsRectItem>
10
11 class NonPdfCropping;
12 class QGraphicsScene;
13 class QGraphicsView;
14 class QPointF;
15 class QRectF;
16
17 /// This class acts as a single handle for the NonPdfCropping class
18 class NonPdfFrameHandle : public QGraphicsRectItem
19 {
20 public:
21 /// Single constructor
22 NonPdfFrameHandle(QGraphicsScene &scene,
23 QGraphicsView &view,
24 const QPointF &pointReference,
25 int orientationFlags,
26 NonPdfCropping &nonPdfCropping,
27 int zValue);
28
29 /// Intercept the drags and process them, which is the whole point of handles
30 virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
31
32 /// Override the paint method so the dashed-border-when-selected can be removed
33 virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
34
35 /// Temporarily disable event handling so code can move this object without triggering a cascade of events
36 void setDisableEventsWhileMovingAutomatically (bool disable);
37
38 private:
39 NonPdfFrameHandle();
40
41 NonPdfCropping &m_nonPdfCropping;
42 int m_orientationFlags; // From PdfCropping constants
43
44 bool m_disableEventsWhileMovingAutomatically;
45 QGraphicsScene &m_scene;
46 QGraphicsView &m_view;
47 };
48
49 #endif // NON_PDF_FRAME_HANDLE_H
33 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
44 ******************************************************************************************************/
55
6 #include "DlgPdfFrame.h"
6 #include "DlgImportCroppingPdf.h"
7 #include "ImportCroppingUtilPdf.h"
78 #include "Pdf.h"
89 #include "poppler-qt5.h"
10 #include <QApplication>
911 #include <QImage>
1012 #include <QString>
1113
2224 PdfReturn Pdf::load (const QString &fileName,
2325 QImage &image,
2426 int resolution,
27 ImportCropping importCropping,
2528 bool isErrorReportRegressionTest) const
2629 {
27 if (isErrorReportRegressionTest) {
28 return loadForTesting (fileName,
29 image,
30 resolution);
30 Document *document = 0;
31
32 ImportCroppingUtilPdf importCroppingUtil;
33 bool cropping = importCroppingUtil.applyImportCropping (isErrorReportRegressionTest,
34 fileName,
35 importCropping,
36 document);
37
38 PdfReturn rtn;
39 QApplication::setOverrideCursor(Qt::BusyCursor); // Since loading can be slow
40 if (cropping) {
41
42 rtn = loadWithCropping (document,
43 image,
44 resolution);
45
3146 } else {
32 return loadNotTesting (fileName,
33 image,
34 resolution);
47
48 rtn = loadWithoutCropping (fileName,
49 image,
50 resolution);
51
3552 }
53 QApplication::restoreOverrideCursor();
54
55 if (document != 0) {
56 delete document;
57 }
58
59 return rtn;
3660 }
3761
38 PdfReturn Pdf::loadForTesting (const QString &fileName,
39 QImage &image,
40 int resolution) const
62 PdfReturn Pdf::loadWithCropping (Document *document,
63 QImage &image,
64 int resolution) const
65 {
66 PdfReturn pdfReturn = PDF_RETURN_FAILED;
67
68 // Get page and extent. At this point it is always true that the image can be read
69 DlgImportCroppingPdf dlg (*document,
70 resolution);
71 if (dlg.exec() == QDialog::Accepted) {
72
73 // Returned image is null if it could not be read
74 image = dlg.image ();
75
76 if (!image.isNull()) {
77 pdfReturn = PDF_RETURN_SUCCESS;
78 }
79
80 } else {
81 pdfReturn = PDF_RETURN_CANCELED;
82 }
83
84 return pdfReturn;
85 }
86
87 PdfReturn Pdf::loadWithoutCropping (const QString &fileName,
88 QImage &image,
89 int resolution) const
4190 {
4291 PdfReturn pdfReturn = PDF_RETURN_FAILED;
4392
74123
75124 return pdfReturn;
76125 }
77
78 PdfReturn Pdf::loadNotTesting (const QString &fileName,
79 QImage &image,
80 int resolution) const
81 {
82 PdfReturn pdfReturn = PDF_RETURN_FAILED;
83
84 // Simple check to prevent complaints from poppler code
85 if (fileName.right (4).toLower () == ".pdf") {
86
87 // Try to read the file
88 Document *document = Document::load (fileName);
89
90 if (document != 0) {
91 if (!document->isLocked ()) {
92
93 // Get page and extent
94 DlgPdfFrame dlg (*document,
95 resolution);
96 if (dlg.exec() == QDialog::Accepted) {
97
98 // Returned image is null if it could not be read
99 image = dlg.image ();
100
101 if (!image.isNull()) {
102 pdfReturn = PDF_RETURN_SUCCESS;
103 }
104
105 } else {
106 pdfReturn = PDF_RETURN_CANCELED;
107 }
108 }
109
110 delete document;
111 }
112 }
113
114 return pdfReturn;
115 }
66 #ifndef PDF_H
77 #define PDF_H
88
9 #include "ImportCropping.h"
10
11 namespace Poppler {
12 class Document;
13 }
914 class QImage;
1015 class QString;
1116
2732
2833 /// Try to load the specified file. Success is indicated in the function return value
2934 PdfReturn load (const QString &fileName,
30 QImage &image,
31 int resolution,
32 bool isErrorReportRegressionTest) const;
35 QImage &image,
36 int resolution,
37 ImportCropping importCropping,
38 bool isErrorReportRegressionTest) const;
3339
3440 private:
3541
36 PdfReturn loadForTesting (const QString &fileName,
37 QImage &image,
38 int resolution) const; // No dialog is used during testing. Entire first page will be loaded
39 PdfReturn loadNotTesting (const QString &fileName,
40 QImage &image,
41 int resolution) const; // Dialog is used when not testing
42 PdfReturn loadWithCropping (Poppler::Document *document,
43 QImage &image,
44 int resolution) const; // Dialog is used when not testing
45 PdfReturn loadWithoutCropping (const QString &fileName,
46 QImage &image,
47 int resolution) const; // No dialog is used during testing. Entire first page will be loaded
4248
4349 };
4450
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "Logger.h"
7 #include "PdfCropping.h"
8 #include "PdfFrameHandle.h"
9 #include <QGraphicsRectItem>
10 #include <QGraphicsScene>
11 #include <QRect>
12 #include "QtToString.h"
13 #include "ViewPreview.h"
14
15 const int Z_BOX = 50; // Under box and over background image
16 const int Z_HANDLE = 100; // Over box and background image
17
18 PdfCropping::PdfCropping (QGraphicsScene &scene,
19 ViewPreview &view) :
20 m_view (view)
21 {
22 createWidgets (scene);
23 }
24
25 void PdfCropping::createWidgets(QGraphicsScene &scene)
26 {
27 const double MARGIN_PERCENT = 5.0;
28 const int ZERO_WIDTH_IS_ALWAYS_VISIBLE = 0;
29
30 int marginHor = scene.width() * MARGIN_PERCENT / 100.0;
31 int marginVer = scene.height() * MARGIN_PERCENT / 100.0;
32
33 QRect box (scene.sceneRect().left() + marginHor,
34 scene.sceneRect().top() + marginVer,
35 scene.sceneRect().width() - 2 * marginHor,
36 scene.sceneRect().height() - 2 * marginVer);
37
38 m_handleTL = new PdfFrameHandle (scene, m_view, box.topLeft() , PDF_CROPPING_LEFT | PDF_CROPPING_TOP , *this, Z_HANDLE);
39 m_handleTR = new PdfFrameHandle (scene, m_view, box.topRight() , PDF_CROPPING_RIGHT | PDF_CROPPING_TOP , *this, Z_HANDLE);
40 m_handleBR = new PdfFrameHandle (scene, m_view, box.bottomRight(), PDF_CROPPING_RIGHT | PDF_CROPPING_BOTTOM , *this, Z_HANDLE);
41 m_handleBL = new PdfFrameHandle (scene, m_view, box.bottomLeft() , PDF_CROPPING_LEFT | PDF_CROPPING_BOTTOM , *this, Z_HANDLE);
42
43 m_box = new QGraphicsRectItem;
44 m_box->setZValue (Z_BOX);
45 m_box->setPen (QPen (QBrush (Qt::gray), ZERO_WIDTH_IS_ALWAYS_VISIBLE));
46 scene.addItem (m_box);
47
48 updateBox ();
49 }
50
51 void PdfCropping::disableEventsWhileMovingAutomatically ()
52 {
53 m_handleTL->setDisableEventsWhileMovingAutomatically (true);
54 m_handleTR->setDisableEventsWhileMovingAutomatically (true);
55 m_handleBR->setDisableEventsWhileMovingAutomatically (true);
56 m_handleBL->setDisableEventsWhileMovingAutomatically (true);
57 }
58
59 void PdfCropping::enableEventsWhileMovingAutomatically ()
60 {
61 m_handleTL->setDisableEventsWhileMovingAutomatically (false);
62 m_handleTR->setDisableEventsWhileMovingAutomatically (false);
63 m_handleBR->setDisableEventsWhileMovingAutomatically (false);
64 m_handleBL->setDisableEventsWhileMovingAutomatically (false);
65 }
66
67 QRectF PdfCropping::frameRect () const
68 {
69 // The x(), y(), pos(), rect() and boundingRect() will return coordinates assuming origin at the initial position of
70 // each handle. So to get the coordinates in the window reference frame it takes a two step process like
71 // QGraphicsRectItem::mapRectToScene (QGraphicsRectItem::rect())
72
73 QRectF rectTL = m_handleTL->mapRectToScene (m_handleTL->boundingRect());
74 QRectF rectBR = m_handleBR->mapRectToScene (m_handleBR->boundingRect());
75
76 QRectF rectUnited = rectTL.united (rectBR);
77
78 return rectUnited;
79 }
80
81 void PdfCropping::moveBL (const QPointF &newPos,
82 const QPointF &oldPos)
83 {
84 disableEventsWhileMovingAutomatically();
85
86 double deltaX = newPos.x() - oldPos.x();
87 double deltaY = newPos.y() - oldPos.y();
88
89 m_handleTL->moveBy (deltaX,
90 0);
91 m_handleBR->moveBy (0,
92 deltaY);
93
94 enableEventsWhileMovingAutomatically();
95
96 updateBox();
97 }
98
99 void PdfCropping::moveBR (const QPointF &newPos,
100 const QPointF &oldPos)
101 {
102 disableEventsWhileMovingAutomatically();
103
104 double deltaX = newPos.x() - oldPos.x();
105 double deltaY = newPos.y() - oldPos.y();
106
107 m_handleBL->moveBy (0,
108 deltaY);
109 m_handleTR->moveBy (deltaX,
110 0);
111
112 enableEventsWhileMovingAutomatically();
113
114 updateBox();
115 }
116
117 void PdfCropping::moveTL (const QPointF &newPos,
118 const QPointF &oldPos)
119 {
120 disableEventsWhileMovingAutomatically();
121
122 double deltaX = newPos.x() - oldPos.x();
123 double deltaY = newPos.y() - oldPos.y();
124
125 m_handleBL->moveBy (deltaX,
126 0);
127 m_handleTR->moveBy (0,
128 deltaY);
129
130 enableEventsWhileMovingAutomatically();
131
132 updateBox();
133 }
134
135 void PdfCropping::moveTR (const QPointF &newPos,
136 const QPointF &oldPos)
137 {
138 disableEventsWhileMovingAutomatically();
139
140 double deltaX = newPos.x() - oldPos.x();
141 double deltaY = newPos.y() - oldPos.y();
142
143 m_handleTL->moveBy (0,
144 deltaY);
145 m_handleBR->moveBy (deltaX,
146 0);
147
148 enableEventsWhileMovingAutomatically();
149
150 updateBox();
151 }
152
153 void PdfCropping::updateBox ()
154 {
155 QRectF rectUnited = frameRect ();
156
157 // Adjust by one pixel in both horizontal and vertical directions so bottom/right handles end on the box
158 rectUnited.setWidth (rectUnited.width () - 1);
159 rectUnited.setHeight (rectUnited.height () - 1);
160
161 m_box->setRect (rectUnited);
162 }
163
164 QSize PdfCropping::windowSize () const
165 {
166 return QSize (m_view.scene()->width(),
167 m_view.scene()->height());
168 }
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef PDF_CROPPING_H
7 #define PDF_CROPPING_H
8
9 #include <QRect>
10 #include <QSize>
11
12 class PdfFrameHandle;
13 class QGraphicsRectItem;
14 class QGraphicsScene;
15 class QPointF;
16 class ViewPreview;
17
18 /// This class shows a frame around the selected portion of the pdf import preview window
19 ///
20 /// Originally there were 4 handles at the corners and 4 handles at the middles of the sides, but dragging
21 /// the corner handles did not result in 1/2 the movement at the middle handles. The middle handles were deemed
22 /// not worth the effort
23 class PdfCropping
24 {
25 public:
26 /// Single constructor
27 PdfCropping(QGraphicsScene &scene,
28 ViewPreview &view);
29
30 /// Frame rectangle selected by user
31 QRectF frameRect () const;
32
33 /// Bottom left corner handle was moved
34 void moveBL (const QPointF &newPos,
35 const QPointF &oldPos);
36
37 /// Bottom right corner handle was moved
38 void moveBR (const QPointF &newPos,
39 const QPointF &oldPos);
40
41 /// Top left corner handle was moved
42 void moveTL (const QPointF &newPos,
43 const QPointF &oldPos);
44
45 /// Top right corner handle was moved
46 void moveTR (const QPointF &newPos,
47 const QPointF &oldPos);
48
49 static const int PDF_CROPPING_BOTTOM = 1; ///< Bit flag when handle is aligned with bottom edge at reference point
50 static const int PDF_CROPPING_LEFT = 2; ///< Bit flag when handle is aligned with left edge at reference point
51 static const int PDF_CROPPING_RIGHT = 4; ///< Bit flag when handle is aligned with right edge at reference point
52 static const int PDF_CROPPING_TOP = 8; ///< Bit flag when handle is aligned with top edge at reference point
53
54 /// Size of window in scene coordinates
55 QSize windowSize () const;
56
57 private:
58 PdfCropping ();
59
60 void createWidgets (QGraphicsScene &scene);
61 void disableEventsWhileMovingAutomatically();
62 void enableEventsWhileMovingAutomatically();
63 QRectF rectFromTLAndBR () const;
64 void updateBox();
65
66 ViewPreview &m_view;
67
68 // Box
69 QGraphicsRectItem *m_box;
70
71 // Handles
72 PdfFrameHandle *m_handleTL;
73 PdfFrameHandle *m_handleTR;
74 PdfFrameHandle *m_handleBR;
75 PdfFrameHandle *m_handleBL;
76
77 };
78
79 #endif // PDF_CROPPING_H
+0
-169
src/Pdf/PdfFrame.cpp less more
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #include "Logger.h"
7 #include "PdfFrame.h"
8 #include "PdfFrameHandle.h"
9 #include <QGraphicsRectItem>
10 #include <QGraphicsScene>
11 #include <QRect>
12 #include "QtToString.h"
13 #include "ViewPreview.h"
14
15 const int Z_BOX = 50; // Under box and over background image
16 const int Z_HANDLE = 100; // Over box and background image
17
18 PdfFrame::PdfFrame (QGraphicsScene &scene,
19 ViewPreview &view) :
20 m_view (view)
21 {
22 createWidgets (scene);
23 }
24
25 void PdfFrame::createWidgets(QGraphicsScene &scene)
26 {
27 const double MARGIN_PERCENT = 5.0;
28 const int ZERO_WIDTH_IS_ALWAYS_VISIBLE = 0;
29
30 int marginHor = scene.width() * MARGIN_PERCENT / 100.0;
31 int marginVer = scene.height() * MARGIN_PERCENT / 100.0;
32
33 QRect box (scene.sceneRect().left() + marginHor,
34 scene.sceneRect().top() + marginVer,
35 scene.sceneRect().width() - 2 * marginHor,
36 scene.sceneRect().height() - 2 * marginVer);
37
38 m_handleTL = new PdfFrameHandle (scene, m_view, box.topLeft() , PDF_FRAME_LEFT | PDF_FRAME_TOP , *this, Z_HANDLE);
39 m_handleTR = new PdfFrameHandle (scene, m_view, box.topRight() , PDF_FRAME_RIGHT | PDF_FRAME_TOP , *this, Z_HANDLE);
40 m_handleBR = new PdfFrameHandle (scene, m_view, box.bottomRight(), PDF_FRAME_RIGHT | PDF_FRAME_BOTTOM , *this, Z_HANDLE);
41 m_handleBL = new PdfFrameHandle (scene, m_view, box.bottomLeft() , PDF_FRAME_LEFT | PDF_FRAME_BOTTOM , *this, Z_HANDLE);
42
43 m_box = new QGraphicsRectItem;
44 m_box->setZValue (Z_BOX);
45 m_box->setPen (QPen (QBrush (Qt::gray), ZERO_WIDTH_IS_ALWAYS_VISIBLE));
46 scene.addItem (m_box);
47
48 updateBox ();
49 }
50
51 void PdfFrame::disableEventsWhileMovingAutomatically ()
52 {
53 m_handleTL->setDisableEventsWhileMovingAutomatically (true);
54 m_handleTR->setDisableEventsWhileMovingAutomatically (true);
55 m_handleBR->setDisableEventsWhileMovingAutomatically (true);
56 m_handleBL->setDisableEventsWhileMovingAutomatically (true);
57 }
58
59 void PdfFrame::enableEventsWhileMovingAutomatically ()
60 {
61 m_handleTL->setDisableEventsWhileMovingAutomatically (false);
62 m_handleTR->setDisableEventsWhileMovingAutomatically (false);
63 m_handleBR->setDisableEventsWhileMovingAutomatically (false);
64 m_handleBL->setDisableEventsWhileMovingAutomatically (false);
65 }
66
67 QRectF PdfFrame::frameRect () const
68 {
69 // The x(), y(), pos(), rect() and boundingRect() will return coordinates assuming origin at the initial position of
70 // each handle. So to get the coordinates in the window reference frame it takes a two step process like
71 // QGraphicsRectItem::mapRectToScene (QGraphicsRectItem::rect())
72
73 QRectF rectTL = m_handleTL->mapRectToScene (m_handleTL->boundingRect());
74 QRectF rectBR = m_handleBR->mapRectToScene (m_handleBR->boundingRect());
75
76 QRectF rectUnited = rectTL.united (rectBR);
77
78 return rectUnited;
79 }
80
81 void PdfFrame::moveBL (const QPointF &newPos,
82 const QPointF &oldPos)
83 {
84 disableEventsWhileMovingAutomatically();
85
86 double deltaX = newPos.x() - oldPos.x();
87 double deltaY = newPos.y() - oldPos.y();
88
89 m_handleTL->moveBy (deltaX,
90 0);
91 m_handleBR->moveBy (0,
92 deltaY);
93
94 enableEventsWhileMovingAutomatically();
95
96 updateBox();
97 }
98
99 void PdfFrame::moveBR (const QPointF &newPos,
100 const QPointF &oldPos)
101 {
102 disableEventsWhileMovingAutomatically();
103
104 double deltaX = newPos.x() - oldPos.x();
105 double deltaY = newPos.y() - oldPos.y();
106
107 m_handleBL->moveBy (0,
108 deltaY);
109 m_handleTR->moveBy (deltaX,
110 0);
111
112 enableEventsWhileMovingAutomatically();
113
114 updateBox();
115 }
116
117 void PdfFrame::moveTL (const QPointF &newPos,
118 const QPointF &oldPos)
119 {
120 disableEventsWhileMovingAutomatically();
121
122 double deltaX = newPos.x() - oldPos.x();
123 double deltaY = newPos.y() - oldPos.y();
124
125 m_handleBL->moveBy (deltaX,
126 0);
127 m_handleTR->moveBy (0,
128 deltaY);
129
130 enableEventsWhileMovingAutomatically();
131
132 updateBox();
133 }
134
135 void PdfFrame::moveTR (const QPointF &newPos,
136 const QPointF &oldPos)
137 {
138 disableEventsWhileMovingAutomatically();
139
140 double deltaX = newPos.x() - oldPos.x();
141 double deltaY = newPos.y() - oldPos.y();
142
143 m_handleTL->moveBy (0,
144 deltaY);
145 m_handleBR->moveBy (deltaX,
146 0);
147
148 enableEventsWhileMovingAutomatically();
149
150 updateBox();
151 }
152
153 void PdfFrame::updateBox ()
154 {
155 QRectF rectUnited = frameRect ();
156
157 // Adjust by one pixel in both horizontal and vertical directions so bottom/right handles end on the box
158 rectUnited.setWidth (rectUnited.width () - 1);
159 rectUnited.setHeight (rectUnited.height () - 1);
160
161 m_box->setRect (rectUnited);
162 }
163
164 QSize PdfFrame::windowSize () const
165 {
166 return QSize (m_view.scene()->width(),
167 m_view.scene()->height());
168 }
+0
-80
src/Pdf/PdfFrame.h less more
0 /******************************************************************************************************
1 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
2 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
3 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
4 ******************************************************************************************************/
5
6 #ifndef PDF_FRAME_H
7 #define PDF_FRAME_H
8
9 #include <QRect>
10 #include <QSize>
11
12 class PdfFrameHandle;
13 class QGraphicsRectItem;
14 class QGraphicsScene;
15 class QPointF;
16 class ViewPreview;
17
18 /// This class shows a frame around the selected portion of the pdf import preview window
19 ///
20 /// Originally there were 4 handles at the corners and 4 handles at the middles of the sides, but dragging
21 /// the corner handles did not result in 1/2 the movement at the middle handles. The middle handles were deemed
22 /// not worth the effort
23 class PdfFrame
24 {
25 public:
26 /// Single constructor
27 PdfFrame(QGraphicsScene &scene,
28 ViewPreview &view);
29
30 /// Frame rectangle selected by user
31 QRectF frameRect () const;
32
33 /// Bottom left corner handle was moved
34 void moveBL (const QPointF &newPos,
35 const QPointF &oldPos);
36
37 /// Bottom right corner handle was moved
38 void moveBR (const QPointF &newPos,
39 const QPointF &oldPos);
40
41 /// Top left corner handle was moved
42 void moveTL (const QPointF &newPos,
43 const QPointF &oldPos);
44
45 /// Top right corner handle was moved
46 void moveTR (const QPointF &newPos,
47 const QPointF &oldPos);
48
49 static const int PDF_FRAME_BOTTOM = 1; ///< Bit flag when handle is aligned with bottom edge at reference point
50 static const int PDF_FRAME_LEFT = 2; ///< Bit flag when handle is aligned with left edge at reference point
51 static const int PDF_FRAME_RIGHT = 4; ///< Bit flag when handle is aligned with right edge at reference point
52 static const int PDF_FRAME_TOP = 8; ///< Bit flag when handle is aligned with top edge at reference point
53
54 /// Size of window in scene coordinates
55 QSize windowSize () const;
56
57 private:
58 PdfFrame();
59
60 void createWidgets (QGraphicsScene &scene);
61 void disableEventsWhileMovingAutomatically();
62 void enableEventsWhileMovingAutomatically();
63 QRectF rectFromTLAndBR () const;
64 void updateBox();
65
66 ViewPreview &m_view;
67
68 // Box
69 QGraphicsRectItem *m_box;
70
71 // Handles
72 PdfFrameHandle *m_handleTL;
73 PdfFrameHandle *m_handleTR;
74 PdfFrameHandle *m_handleBR;
75 PdfFrameHandle *m_handleBL;
76
77 };
78
79 #endif // PDF_FRAME_H
33 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
44 ******************************************************************************************************/
55
6 #include "PdfFrame.h"
6 #include "PdfCropping.h"
77 #include "PdfFrameHandle.h"
88 #include <QBrush>
99 #include <QGraphicsScene>
1616 QGraphicsView &view,
1717 const QPointF &pointReference,
1818 int orientationFlags,
19 PdfFrame &pdfFrame,
19 PdfCropping &pdfCropping,
2020 int zValue) :
21 m_pdfFrame (pdfFrame),
21 m_pdfCropping (pdfCropping),
2222 m_orientationFlags (orientationFlags),
2323 m_disableEventsWhileMovingAutomatically (false),
2424 m_scene (scene),
3737 // The solution is to have constant-size handles WITHOUT ItemIgnoresTransformations. This means resizing the window
3838 // also involves resizing the handles, but everything else is pretty easy
3939 //
40 // ItemIgnoresTransformations flag must agree with the QGraphicsRectItem used for the frame box by PdfFrame
40 // ItemIgnoresTransformations flag must agree with the QGraphicsRectItem used for the frame box by PdfCropping
4141 setFlags (QGraphicsItem::ItemIsMovable |
4242 QGraphicsItem::ItemIsSelectable |
4343 QGraphicsItem::ItemSendsScenePositionChanges);
5252 // Add to scene
5353 scene.addItem (this);
5454
55 QSize handleSize = m_pdfFrame.windowSize() / HANDLE_SIZE_AS_FRACTION_OF_WINDOW_SIZE;
55 QSize handleSize = m_pdfCropping.windowSize() / HANDLE_SIZE_AS_FRACTION_OF_WINDOW_SIZE;
5656
5757 // Adjust positions of handles that are not at the top left so handles are laid out symmetrically
5858 QPointF pointPos = pointReference;
59 if ((orientationFlags && PdfFrame::PDF_FRAME_LEFT) != 0) {
59 if ((orientationFlags && PdfCropping::PDF_CROPPING_LEFT) != 0) {
6060 pointPos.setX (pointPos.x() - handleSize.width() / 2.0);
61 } else if ((orientationFlags && PdfFrame::PDF_FRAME_RIGHT) != 0) {
61 } else if ((orientationFlags && PdfCropping::PDF_CROPPING_RIGHT) != 0) {
6262 pointPos.setX (pointPos.x() + handleSize.width() / 2.0);
6363 }
64 if ((orientationFlags && PdfFrame::PDF_FRAME_TOP) != 0) {
64 if ((orientationFlags && PdfCropping::PDF_CROPPING_TOP) != 0) {
6565 pointPos.setY (pointPos.y() - handleSize.height() / 2.0);
66 } else if ((orientationFlags && PdfFrame::PDF_FRAME_BOTTOM) != 0) {
66 } else if ((orientationFlags && PdfCropping::PDF_CROPPING_BOTTOM) != 0) {
6767 pointPos.setY (pointPos.y() + handleSize.height() / 2.0);
6868 }
6969
112112 // to prevent an infinite loop
113113 if (!m_disableEventsWhileMovingAutomatically) {
114114
115 bool left = ((m_orientationFlags & PdfFrame::PDF_FRAME_LEFT ) != 0);
116 bool right = ((m_orientationFlags & PdfFrame::PDF_FRAME_RIGHT ) != 0);
117 bool top = ((m_orientationFlags & PdfFrame::PDF_FRAME_TOP ) != 0);
118 bool bottom = ((m_orientationFlags & PdfFrame::PDF_FRAME_BOTTOM) != 0);
115 bool left = ((m_orientationFlags & PdfCropping::PDF_CROPPING_LEFT ) != 0);
116 bool right = ((m_orientationFlags & PdfCropping::PDF_CROPPING_RIGHT ) != 0);
117 bool top = ((m_orientationFlags & PdfCropping::PDF_CROPPING_TOP ) != 0);
118 bool bottom = ((m_orientationFlags & PdfCropping::PDF_CROPPING_BOTTOM) != 0);
119119
120120 if (left && top) {
121 m_pdfFrame.moveTL (newPos, oldPos);
121 m_pdfCropping.moveTL (newPos, oldPos);
122122 } else if (right && top) {
123 m_pdfFrame.moveTR (newPos, oldPos);
123 m_pdfCropping.moveTR (newPos, oldPos);
124124 } else if (right && bottom) {
125 m_pdfFrame.moveBR (newPos, oldPos);
125 m_pdfCropping.moveBR (newPos, oldPos);
126126 } else if (left && bottom) {
127 m_pdfFrame.moveBL (newPos, oldPos);
127 m_pdfCropping.moveBL (newPos, oldPos);
128128 }
129129 }
130130 }
88
99 #include <QGraphicsRectItem>
1010
11 class PdfFrame;
11 class PdfCropping;
1212 class QGraphicsScene;
1313 class QGraphicsView;
1414 class QPointF;
1515 class QRectF;
1616
17 /// This class acts as a single handle for the PdfFrame class
17 /// This class acts as a single handle for the PdfCropping class
1818 class PdfFrameHandle : public QGraphicsRectItem
1919 {
2020 public:
2323 QGraphicsView &view,
2424 const QPointF &pointReference,
2525 int orientationFlags,
26 PdfFrame &pdfFrame,
26 PdfCropping &pdfCropping,
2727 int zValue);
2828
2929 /// Intercept the drags and process them, which is the whole point of handles
3838 private:
3939 PdfFrameHandle();
4040
41 PdfFrame &m_pdfFrame;
42 int m_orientationFlags; // From PdfFrame constants
41 PdfCropping &m_pdfCropping;
42 int m_orientationFlags; // From PdfCropping constants
4343
4444 bool m_disableEventsWhileMovingAutomatically;
4545 QGraphicsScene &m_scene;
1818 const QString SETTINGS_CHECKLIST_GUIDE_DOCK_AREA ("checklistGuideDockArea");
1919 const QString SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY ("checklistGuideDockGeometry");
2020 const QString SETTINGS_CHECKLIST_GUIDE_WIZARD ("checklistGuideWizard");
21 const QString SETTINGS_GEOMETRY_WINDOW_DOCK_AREA ("geometryWIndowDockArea");
22 const QString SETTINGS_GEOMETRY_WINDOW_DOCK_GEOMETRY ("geometryWindowGeometry");
2123 const QString SETTINGS_GROUP_MAIN_WINDOW ("MainWindow"); // Capitalize both M and W since this is a group string
2224 const QString SETTINGS_HELP_POS ("helpPos");
2325 const QString SETTINGS_HELP_SIZE ("helpSize");
26 const QString SETTINGS_HIGHLIGHT_OPACITY ("highlightOpacity");
2427 const QString SETTINGS_LOCALE_COUNTRY ("country");
2528 const QString SETTINGS_LOCALE_LANGUAGE ("language");
2629 const QString SETTINGS_MAIN_TITLE_BAR_FORMAT ("titleBarFormat");
30 const QString SETTINGS_MAXIMUM_GRID_LINES ("maximumGridLines");
2731 const QString SETTINGS_POS ("pos");
2832 const QString SETTINGS_RECENT_FILE_LIST ("recentFileList");
2933 const QString SETTINGS_SIZE ("size");
5660 const QString SETTINGS_GROUP_GENERAL ("GeneralEngauge"); // "General" group name is reserved for ungrouped settings
5761
5862 // Import group
63 const QString SETTINGS_GROUP_IMPORT ("Import");
64 const QString SETTINGS_IMPORT_CROPPING ("Cropping");
5965 const QString SETTINGS_IMPORT_PDF_RESOLUTION ("PdfResolution");
60 const QString SETTINGS_GROUP_IMPORT ("Import");
6166
6267 // Export group
6368 const QString SETTINGS_EXPORT_CURVE_NAMES_NOT_EXPORTED ("curveNamesNotExported");
7479 const QString SETTINGS_EXPORT_X_LABEL ("xLabel");
7580 const QString SETTINGS_GROUP_EXPORT ("Export");
7681
77 // Pdf group
78 const QString SETTINGS_PDF_POS ("pos");
79 const QString SETTINGS_GROUP_PDF ("Pdf");
82 // Dialogs for import cropping group
83 const QString SETTINGS_GROUP_IMPORT_CROPPING ("ImportCropping");
84 const QString SETTINGS_IMPORT_CROPPING_POS ("pos");
3838 extern const QString SETTINGS_EXPORT_X_LABEL;
3939 extern const QString SETTINGS_GENERAL_CURSOR_SIZE;
4040 extern const QString SETTINGS_GENERAL_EXTRA_PRECISION;
41 extern const QString SETTINGS_GEOMETRY_WINDOW_DOCK_AREA;
42 extern const QString SETTINGS_GEOMETRY_WINDOW_DOCK_GEOMETRY;
4143 extern const QString SETTINGS_GROUP_CURVE_AXES;
4244 extern const QString SETTINGS_GROUP_CURVE_GRAPH;
4345 extern const QString SETTINGS_GROUP_CURVE_GRAPH_PLACEHOLDER;
4547 extern const QString SETTINGS_GROUP_EXPORT;
4648 extern const QString SETTINGS_GROUP_GENERAL;
4749 extern const QString SETTINGS_GROUP_IMPORT;
50 extern const QString SETTINGS_GROUP_IMPORT_CROPPING;
4851 extern const QString SETTINGS_GROUP_MAIN_WINDOW;
49 extern const QString SETTINGS_GROUP_PDF;
5052 extern const QString SETTINGS_HELP_POS;
5153 extern const QString SETTINGS_HELP_SIZE;
54 extern const QString SETTINGS_HIGHLIGHT_OPACITY;
55 extern const QString SETTINGS_IMPORT_CROPPING;
56 extern const QString SETTINGS_IMPORT_CROPPING_POS;
5257 extern const QString SETTINGS_IMPORT_PDF_RESOLUTION;
5358 extern const QString SETTINGS_LOCALE_COUNTRY;
5459 extern const QString SETTINGS_LOCALE_LANGUAGE;
5560 extern const QString SETTINGS_MAIN_TITLE_BAR_FORMAT;
56 extern const QString SETTINGS_PDF_POS;
61 extern const QString SETTINGS_MAXIMUM_GRID_LINES;
5762 extern const QString SETTINGS_POS;
5863 extern const QString SETTINGS_RECENT_FILE_LIST;
5964 extern const QString SETTINGS_SIZE;
2222 const QString NO_REGRESSION_OPEN_FILE;
2323 const bool NO_GNUPLOT_LOG_FILES = false;
2424 const bool NO_REGRESSION_IMPORT = false;
25 const bool NO_RESET = false;
2526 const bool DEBUG_FLAG = false;
2627 const QStringList NO_LOAD_STARTUP_FILES;
2728
3233 MainWindow w (NO_ERROR_REPORT_LOG_FILE,
3334 NO_REGRESSION_OPEN_FILE,
3435 NO_GNUPLOT_LOG_FILES,
36 NO_RESET,
3537 NO_REGRESSION_IMPORT,
3638 NO_LOAD_STARTUP_FILES);
3739 w.show ();
2121 const QString NO_REGRESSION_OPEN_FILE;
2222 const bool NO_GNUPLOT_LOG_FILES = false;
2323 const bool NO_REGRESSION_IMPORT = false;
24 const bool NO_RESET = false;
2425 const bool DEBUG_FLAG = false;
2526 const QStringList NO_LOAD_STARTUP_FILES;
2627
3132 MainWindow w (NO_ERROR_REPORT_LOG_FILE,
3233 NO_REGRESSION_OPEN_FILE,
3334 NO_GNUPLOT_LOG_FILES,
35 NO_RESET,
3436 NO_REGRESSION_IMPORT,
3537 NO_LOAD_STARTUP_FILES);
3638 w.show ();
2222 const QString NO_REGRESSION_OPEN_FILE;
2323 const bool NO_GNUPLOT_LOG_FILES = false;
2424 const bool NO_REGRESSION_IMPORT = false;
25 const bool NO_RESET = false;
2526 const bool DEBUG_FLAG = false;
2627 const QStringList NO_LOAD_STARTUP_FILES;
2728
3233 MainWindow w (NO_ERROR_REPORT_LOG_FILE,
3334 NO_REGRESSION_OPEN_FILE,
3435 NO_GNUPLOT_LOG_FILES,
36 NO_RESET,
3537 NO_REGRESSION_IMPORT,
3638 NO_LOAD_STARTUP_FILES);
3739 w.show ();
2929 const QString NO_REGRESSION_OPEN_FILE;
3030 const bool NO_GNUPLOT_LOG_FILES = false;
3131 const bool NO_REGRESSION_IMPORT = false;
32 const bool NO_RESET = false;
3233 const bool DEBUG_FLAG = false;
3334 const QStringList NO_LOAD_STARTUP_FILES;
3435
4041 NO_REGRESSION_OPEN_FILE,
4142 NO_GNUPLOT_LOG_FILES,
4243 NO_REGRESSION_IMPORT,
44 NO_RESET,
4345 NO_LOAD_STARTUP_FILES);
4446 w.show ();
4547 }
3333 const QString NO_REGRESSION_OPEN_FILE;
3434 const bool NO_GNUPLOT_LOG_FILES = false;
3535 const bool NO_REGRESSION_IMPORT = false;
36 const bool NO_RESET = false;
3637 const bool DEBUG_FLAG = false;
3738 const QStringList NO_LOAD_STARTUP_FILES;
3839
4445 NO_REGRESSION_OPEN_FILE,
4546 NO_GNUPLOT_LOG_FILES,
4647 NO_REGRESSION_IMPORT,
48 NO_RESET,
4749 NO_LOAD_STARTUP_FILES);
4850 m.show ();
4951 }
2525 const QString NO_REGRESSION_OPEN_FILE;
2626 const bool NO_GNUPLOT_LOG_FILES = false;
2727 const bool NO_REGRESSION_IMPORT = false;
28 const bool NO_RESET = false;
2829 const bool DEBUG_FLAG = false;
2930 const QStringList NO_LOAD_STARTUP_FILES;
3031
3637 NO_REGRESSION_OPEN_FILE,
3738 NO_GNUPLOT_LOG_FILES,
3839 NO_REGRESSION_IMPORT,
40 NO_RESET,
3941 NO_LOAD_STARTUP_FILES);
4042 w.show ();
4143 }
3535 const QString NO_REGRESSION_OPEN_FILE;
3636 const bool NO_GNUPLOT_LOG_FILES = false;
3737 const bool NO_REGRESSION_IMPORT = false;
38 const bool NO_RESET = false;
3839 const bool DEBUG_FLAG = false;
3940 const QStringList NO_LOAD_STARTUP_FILES;
4041
4647 NO_REGRESSION_OPEN_FILE,
4748 NO_GNUPLOT_LOG_FILES,
4849 NO_REGRESSION_IMPORT,
50 NO_RESET,
4951 NO_LOAD_STARTUP_FILES);
5052 w.show ();
5153 }
2323 const QString NO_REGRESSION_OPEN_FILE;
2424 const bool NO_GNUPLOT_LOG_FILES = false;
2525 const bool NO_REGRESSION_IMPORT = false;
26 const bool NO_RESET = false;
2627 const bool DEBUG_FLAG = false;
2728 const QStringList NO_LOAD_STARTUP_FILES;
2829
3435 NO_REGRESSION_OPEN_FILE,
3536 NO_GNUPLOT_LOG_FILES,
3637 NO_REGRESSION_IMPORT,
38 NO_RESET,
3739 NO_LOAD_STARTUP_FILES);
3840 w.show ();
3941 }
2828 {
2929 }
3030
31 Transformation::Transformation (const Transformation &other) :
32 m_transformIsDefined (other.transformIsDefined()),
33 m_transform (other.transformMatrix())
34 {
35 setModelCoords (other.modelCoords(),
36 other.modelMainWindow());
37 }
38
3139 Transformation &Transformation::operator=(const Transformation &other)
3240 {
3341 m_transformIsDefined = other.transformIsDefined();
3442 m_transform = other.transformMatrix ();
43 setModelCoords (other.modelCoords(),
44 other.modelMainWindow());
3545
3646 return *this;
3747 }
243253 return m_modelCoords;
244254 }
245255
256 MainWindowModel Transformation::modelMainWindow() const
257 {
258 return m_modelMainWindow;
259 }
260
246261 ostringstream &operator<<(ostringstream &strOuter,
247262 const Transformation &transformation)
248263 {
3434 public:
3535 /// Default constructor. This is marked as undefined until the proper number of axis points are added
3636 Transformation();
37
38 /// Copy constructor
39 Transformation (const Transformation &other);
3740
3841 /// Assignment operator.
3942 Transformation &operator=(const Transformation &other);
8083
8184 /// Get method for DocumentModelCoords
8285 DocumentModelCoords modelCoords() const;
86
87 /// Get method for MainWindowModel
88 MainWindowModel modelMainWindow() const;
8389
8490 /// Debugging method that supports print method of this class and printStream method of some other class(es)
8591 void printStream (QString indentation,
2626 // Normally we would need to call QGraphicsView::mouseMoveEvent at this point so that the mouse move event could be handled,
2727 // but this is unwanted since:
2828 // 1) Everywhere, except the pdf import preview, there is nothing to drag
29 // 2) Dragging of PdfFrameHandle objects in the pdf import preview is handled indirectly by PdfFrame
29 // 2) Dragging of PdfFrameHandle objects in the pdf import preview is handled indirectly by PdfCropping
3030 QGraphicsView::mouseMoveEvent (event);
3131 }
3232
1313 # qmake "CONFIG+=debug jpeg2000"
1414 # 2) Add 'pdf' to the qmake command line to include support for PDF input files. Requires
1515 # 1) previous installation of the poppler-qt5 development package
16 # 2) POPPLER_INCLUDE environment variable pointing to directory containing Document.h
16 # 2) POPPLER_INCLUDE environment variable pointing to directory containing poppler-qt5.h
1717 # 3) POPPLER_LIB environment variable pointing to directory containing libpoppler-qt5.so
1818 # Sample command lines
1919 # qmake CONFIG+=pdf
6767 Cmd/CmdCut.h \
6868 Cmd/CmdDelete.h \
6969 Cmd/CmdEditPointAxis.h \
70 Cmd/CmdEditPointGraph.h \
7071 Cmd/CmdFactory.h \
7172 Cmd/CmdMediator.h \
7273 Cmd/CmdMoveBy.h \
140141 DigitizeState/DigitizeStateSegment.h \
141142 DigitizeState/DigitizeStateSelect.h \
142143 Dlg/DlgAbout.h \
143 Dlg/DlgEditPoint.h \
144 Dlg/DlgEditPointAxis.h \
145 Dlg/DlgEditPointGraph.h \
146 Dlg/DlgEditPointGraphLineEdit.h \
144147 Dlg/DlgErrorReport.h \
145148 Dlg/DlgFilterCommand.h \
146149 Dlg/DlgFilterThread.h \
147150 Dlg/DlgFilterWorker.h \
148151 Dlg/DlgImportAdvanced.h \
152 Dlg/DlgImportCroppingNonPdf.h \
149153 Dlg/DlgRequiresTransform.h \
150154 Dlg/DlgSettingsAbstractBase.h \
151155 Dlg/DlgSettingsAxesChecker.h \
222226 Format/FormatDegreesMinutesSecondsNonPolarTheta.h \
223227 Format/FormatDegreesMinutesSecondsPolarTheta.h \
224228 Callback/functor.h \
229 Geometry/GeometryModel.h \
230 Geometry/GeometryStrategyAbstractBase.h \
231 Geometry/GeometryStrategyContext.h \
232 Geometry/GeometryStrategyFunctionSmooth.h \
233 Geometry/GeometryStrategyFunctionStraight.h \
234 Geometry/GeometryStrategyRelationSmooth.h \
235 Geometry/GeometryStrategyRelationStraight.h \
236 Geometry/GeometryWindow.h \
225237 Ghosts/GhostEllipse.h \
226238 Ghosts/GhostPath.h \
227239 Ghosts/GhostPolygon.h \
228240 Ghosts/Ghosts.h \
229241 Graphics/GraphicsArcItem.h \
242 Graphics/GraphicsItemsExtractor.h \
230243 Graphics/GraphicsItemType.h \
231244 Graphics/GraphicsLinesForCurve.h \
232245 Graphics/GraphicsLinesForCurves.h \
243256 Grid/GridInitializer.h \
244257 Grid/GridLine.h \
245258 Grid/GridLineFactory.h \
259 Grid/GridLineLimiter.h \
246260 Grid/GridLines.h \
247261 Grid/GridLineStyle.h \
248262 Grid/GridRemoval.h \
249263 Help/HelpBrowser.h \
250264 Help/HelpWindow.h \
265 Import/ImportCropping.h \
266 Import/ImportCroppingUtilBase.h \
267 Import/ImportCroppingUtilNonPdf.h \
251268 Line/LineStyle.h \
252269 Load/LoadFileInfo.h \
253270 Load/LoadImageFromUrl.h \
260277 Mime/MimePoints.h \
261278 util/mmsubs.h \
262279 Network/NetworkClient.h \
280 NonPdf/NonPdf.h \
281 NonPdf/NonPdfCropping.h \
282 NonPdf/NonPdfFrameHandle.h \
263283 Ordinal/OrdinalGenerator.h \
264284 Ordinal/OrdinalToGraphicsPoint.h \
265285 Pdf/PdfResolution.h \
362382 Cmd/CmdCut.cpp \
363383 Cmd/CmdDelete.cpp \
364384 Cmd/CmdEditPointAxis.cpp \
385 Cmd/CmdEditPointGraph.cpp \
365386 Cmd/CmdFactory.cpp \
366387 Cmd/CmdMediator.cpp \
367388 Cmd/CmdMoveBy.cpp \
432453 DigitizeState/DigitizeStateSegment.cpp \
433454 DigitizeState/DigitizeStateSelect.cpp \
434455 Dlg/DlgAbout.cpp \
435 Dlg/DlgEditPoint.cpp \
456 Dlg/DlgEditPointAxis.cpp \
457 Dlg/DlgEditPointGraph.cpp \
458 Dlg/DlgEditPointGraphLineEdit.cpp \
436459 Dlg/DlgErrorReport.cpp \
437460 Dlg/DlgFilterCommand.cpp \
438461 Dlg/DlgFilterThread.cpp \
439462 Dlg/DlgFilterWorker.cpp \
440463 Dlg/DlgImportAdvanced.cpp \
464 Dlg/DlgImportCroppingNonPdf.cpp \
441465 Dlg/DlgRequiresTransform.cpp \
442466 Dlg/DlgSettingsAbstractBase.cpp \
443467 Dlg/DlgSettingsAxesChecker.cpp \
507531 Format/FormatDegreesMinutesSecondsBase.cpp \
508532 Format/FormatDegreesMinutesSecondsNonPolarTheta.cpp \
509533 Format/FormatDegreesMinutesSecondsPolarTheta.cpp \
534 Geometry/GeometryModel.cpp \
535 Geometry/GeometryStrategyAbstractBase.cpp \
536 Geometry/GeometryStrategyContext.cpp \
537 Geometry/GeometryStrategyFunctionSmooth.cpp \
538 Geometry/GeometryStrategyFunctionStraight.cpp \
539 Geometry/GeometryStrategyRelationSmooth.cpp \
540 Geometry/GeometryStrategyRelationStraight.cpp \
541 Geometry/GeometryWindow.cpp \
510542 Ghosts/GhostEllipse.cpp \
511543 Ghosts/GhostPath.cpp \
512544 Ghosts/GhostPolygon.cpp \
513545 Ghosts/Ghosts.cpp \
514546 Graphics/GraphicsArcItem.cpp \
547 Graphics/GraphicsItemsExtractor.cpp \
515548 Graphics/GraphicsLinesForCurve.cpp \
516549 Graphics/GraphicsLinesForCurves.cpp \
517550 Graphics/GraphicsPoint.cpp \
527560 Grid/GridInitializer.cpp \
528561 Grid/GridLine.cpp \
529562 Grid/GridLineFactory.cpp \
563 Grid/GridLineLimiter.cpp \
530564 Grid/GridLines.cpp \
531565 Grid/GridRemoval.cpp \
532566 Help/HelpBrowser.cpp \
533567 Help/HelpWindow.cpp \
568 Import/ImportCroppingUtilBase.cpp \
569 Import/ImportCroppingUtilNonPdf.cpp \
534570 Line/LineStyle.cpp \
535571 Load/LoadFileInfo.cpp \
536572 Load/LoadImageFromUrl.cpp \
542578 Mime/MimePoints.cpp \
543579 util/mmsubs.cpp \
544580 Network/NetworkClient.cpp \
581 NonPdf/NonPdf.cpp \
582 NonPdf/NonPdfCropping.cpp \
583 NonPdf/NonPdfFrameHandle.cpp \
545584 Ordinal/OrdinalGenerator.cpp \
546585 Pdf/PdfResolution.cpp \
547586 Point/Point.cpp \
628667 FileCmd \
629668 Filter \
630669 Format \
670 Geometry \
631671 Ghosts \
632672 Graphics \
633673 Grid \
634674 Help \
635675 img \
676 Import \
636677 include \
637678 Line \
638679 Load \
640681 main \
641682 Mime \
642683 Network \
684 NonPdf \
643685 Ordinal \
644686 Pdf \
645687 Plot \
720762 DEFINES += "ENGAUGE_PDF"
721763 INCLUDEPATH += $$(POPPLER_INCLUDE)
722764 LIBS += -L$$(POPPLER_LIB) -lpoppler -lpoppler-qt5
723 HEADERS += Dlg/DlgPdfFrame.h \
765 HEADERS += Dlg/DlgImportCroppingPdf.h \
766 Import/ImportCroppingUtilPdf.h \
724767 Pdf/Pdf.h \
725 Pdf/PdfFrame.h \
768 Pdf/PdfCropping.h \
726769 Pdf/PdfFrameHandle.h
727 SOURCES += Dlg/DlgPdfFrame.cpp \
770 SOURCES += Dlg/DlgImportCroppingPdf.cpp \
771 Import/ImportCroppingUtilPdf.cpp \
728772 Pdf/Pdf.cpp \
729 Pdf/PdfFrame.cpp \
773 Pdf/PdfCropping.cpp \
730774 Pdf/PdfFrameHandle.cpp
731775
732776 } else {
5151 #include "ExportImageForRegression.h"
5252 #include "ExportToFile.h"
5353 #include "FileCmdScript.h"
54 #include "GeometryWindow.h"
5455 #include "Ghosts.h"
56 #include "GraphicsItemsExtractor.h"
5557 #include "GraphicsItemType.h"
5658 #include "GraphicsScene.h"
5759 #include "GraphicsView.h"
5860 #include "GridLineFactory.h"
61 #include "GridLineLimiter.h"
5962 #include "HelpWindow.h"
6063 #ifdef ENGAUGE_JPEG2000
6164 #include "Jpeg2000.h"
6669 #include "MainTitleBarFormat.h"
6770 #include "MainWindow.h"
6871 #include "NetworkClient.h"
72 #include "NonPdf.h"
6973 #ifdef ENGAUGE_PDF
7074 #include "Pdf.h"
7175 #endif // ENGAUGE_PDF
123127 const QString &fileCmdScriptFile,
124128 bool isRegressionTest,
125129 bool isGnuplot,
130 bool isReset,
126131 QStringList loadStartupFiles,
127132 QWidget *parent) :
128133 QMainWindow(parent),
165170 createStatusBar ();
166171 createMenus ();
167172 createToolBars ();
173 createDockableWidgets ();
168174 createHelpWindow ();
169175 createTutorial ();
170176 createScene ();
178184 createZoomMap ();
179185 updateControls ();
180186
181 settingsRead (); // This changes the current directory when not regression testing
187 settingsRead (isReset); // This changes the current directory when not regression testing
182188 setCurrentFile ("");
183189 setUnifiedTitleAndToolBarOnMac(true);
184190
209215 {
210216 }
211217
218 void MainWindow::addDockWindow (QDockWidget *dockWidget,
219 QSettings &settings,
220 const QString &settingsTokenArea,
221 const QString &settingsTokenGeometry,
222 Qt::DockWidgetArea dockWidgetArea)
223 {
224 // Checklist guide is docked or undocked. Default is docked so it does not get overlooked by the user (which
225 // can happen if it opens elsewhere). The user may not know it can be undocked, but at least can resize or
226 // hide it if he/she needs more room for the main window.
227 const bool DOCKED_EQUALS_NOT_FLOATING = false;
228 Qt::DockWidgetArea area = (Qt::DockWidgetArea) settings.value (settingsTokenArea,
229 Qt::NoDockWidgetArea).toInt();
230
231 if (area == Qt::NoDockWidgetArea) {
232
233 addDockWidget (dockWidgetArea,
234 dockWidget); // Add on the right to prevent error message, then immediately make undocked
235 dockWidget->setFloating(DOCKED_EQUALS_NOT_FLOATING);
236 if (settings.contains (settingsTokenGeometry)) {
237 dockWidget->restoreGeometry (settings.value (settingsTokenGeometry).toByteArray());
238 }
239
240 } else {
241
242 addDockWidget (area,
243 dockWidget);
244
245 }
246 }
247
212248 void MainWindow::applyZoomFactorAfterLoad()
213249 {
214250 ZoomFactor zoomFactor;
662698 m_actionViewChecklistGuide = new QAction (tr ("Checklist Guide Toolbar"), this);
663699 m_actionViewChecklistGuide->setCheckable (true);
664700 m_actionViewChecklistGuide->setChecked (false);
665 m_actionViewChecklistGuide->setStatusTip (tr ("Show or hide the checklist guide toolbar."));
666 m_actionViewChecklistGuide->setWhatsThis (tr ("View Checklist Guide ToolBar\n\n"
667 "Show or hide the checklist guide toolbar"));
701 m_actionViewChecklistGuide->setStatusTip (tr ("Show or hide the checklist guide."));
702 m_actionViewChecklistGuide->setWhatsThis (tr ("View Checklist Guide\n\n"
703 "Show or hide the checklist guide"));
668704 connect (m_actionViewChecklistGuide, SIGNAL (changed ()), this, SLOT (slotViewToolBarChecklistGuide()));
705
706 m_actionViewGeometryWindow = new QAction (tr ("Geometry Window"), this);
707 m_actionViewGeometryWindow->setCheckable (true);
708 m_actionViewGeometryWindow->setChecked (false);
709 m_actionViewGeometryWindow->setStatusTip (tr ("Show or hide the geometry window."));
710 m_actionViewGeometryWindow->setWhatsThis (tr ("View Geometry Window\n\n"
711 "Show or hide the geometry window"));
712 connect (m_actionViewGeometryWindow, SIGNAL (changed ()), this, SLOT (slotViewToolBarGeometryWindow()));
669713
670714 m_actionViewDigitize = new QAction (tr ("Digitizing Tools Toolbar"), this);
671715 m_actionViewDigitize->setCheckable (true);
877921 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createCommandStackShadow";
878922
879923 m_cmdStackShadow = new CmdStackShadow;
924 }
925
926 void MainWindow::createDockableWidgets ()
927 {
928 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createDockableWidgets";
929
930 // Checklist guide starts out hidden. It will be positioned in settingsRead
931 m_dockChecklistGuide = new ChecklistGuide (this);
932 connect (m_dockChecklistGuide, SIGNAL (signalChecklistClosed()), this, SLOT (slotChecklistClosed()));
933
934 // Geometry window starts out hidden since there is nothing to show initially. It will be positioned in settingsRead
935 m_dockGeometryWindow = new GeometryWindow (this);
936 connect (m_dockGeometryWindow, SIGNAL (signalGeometryWindowClosed()), this, SLOT (slotGeometryWindowClosed()));
880937 }
881938
882939 void MainWindow::createHelpWindow ()
9701027 m_menuView->addAction (m_actionViewBackground);
9711028 m_menuView->addAction (m_actionViewDigitize);
9721029 m_menuView->addAction (m_actionViewChecklistGuide);
1030 m_menuView->addAction (m_actionViewGeometryWindow);
9731031 m_menuView->addAction (m_actionViewSettingsViews);
9741032 m_menuView->addAction (m_actionViewCoordSystem);
9751033 m_menuView->insertSeparator (m_actionViewToolTips);
12251283 m_toolCoordSystem->addWidget (m_btnShowAll);
12261284 m_toolCoordSystem->addWidget (m_btnPrintAll);
12271285 addToolBar (m_toolCoordSystem);
1228
1229 // Checklist guide starts out hidden. It will be positioned in settingsRead
1230 m_dockChecklistGuide = new ChecklistGuide (this);
1231 connect (m_dockChecklistGuide, SIGNAL (signalChecklistClosed()), this, SLOT (slotChecklistClosed()));
12321286 }
12331287
12341288 void MainWindow::createTutorial ()
13701424 transformation (),
13711425 str);
13721426
1373 // Update checklist guide status
1374 m_isDocumentExported = true; // Set for next line and for all checklist guide updates after this
1375 m_dockChecklistGuide->update (*m_cmdMediator,
1376 m_isDocumentExported);
1427 updateChecklistGuide ();
13771428
13781429 } else {
13791430
14261477 PdfReturn pdfReturn = pdf.load (fileName,
14271478 image,
14281479 m_modelMainWindow.pdfResolution(),
1480 m_modelMainWindow.importCropping(),
14291481 m_isErrorReportRegressionTest);
14301482 if (pdfReturn == PDF_RETURN_CANCELED) {
14311483
14391491 #endif // ENGAUGE_PDF
14401492
14411493 if (!loaded) {
1442 loaded = image.load (fileName);
1494 NonPdf nonPdf;
1495 NonPdfReturn nonPdfReturn = nonPdf.load (fileName,
1496 image,
1497 m_modelMainWindow.importCropping(),
1498 m_isErrorReportRegressionTest);
1499 if (nonPdfReturn == NON_PDF_RETURN_CANCELED) {
1500
1501 // User canceled so exit immediately
1502 return;
1503
1504 }
1505
1506 loaded = (nonPdfReturn == NON_PDF_RETURN_SUCCESS);
14431507 }
14441508
14451509 if (!loaded) {
22972361 curveSelected);
22982362 }
22992363
2300 void MainWindow::settingsRead ()
2364 void MainWindow::settingsRead (bool isReset)
23012365 {
23022366 QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
2367
2368 if (isReset) {
2369 // Delete all settings. Default values are specified, later, for each settings as it is loaded
2370 settings.clear ();
2371 }
23032372
23042373 settingsReadEnvironment (settings);
23052374 settingsReadMainWindow (settings);
23242393 QPoint (200, 200)).toPoint ());
23252394
23262395 // Help window geometry
2396 #ifndef OSX_RELEASE
23272397 QSize helpSize = settings.value (SETTINGS_HELP_SIZE,
23282398 QSize (900, 600)).toSize();
2329 #ifndef OSX_RELEASE
23302399 m_helpWindow->resize (helpSize);
23312400 if (settings.contains (SETTINGS_HELP_POS)) {
23322401 QPoint helpPos = settings.value (SETTINGS_HELP_POS).toPoint();
23802449 m_actionStatusTemporary->setChecked (statusBarMode == STATUS_BAR_MODE_TEMPORARY);
23812450 m_actionStatusAlways->setChecked (statusBarMode == STATUS_BAR_MODE_ALWAYS);
23822451
2383 // Checklist guide is docked or undocked. Default is docked so it does not get overlooked by the user (which
2384 // can happen if it opens elsewhere). The user may not know it can be undocked, but at least can resize or
2385 // hide it if he/she needs more room for the main window.
2386 const bool DOCKED_EQUALS_NOT_FLOATING = false;
2387 Qt::DockWidgetArea area = (Qt::DockWidgetArea) settings.value (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA,
2388 Qt::NoDockWidgetArea).toInt();
2389
2390 if (area == Qt::NoDockWidgetArea) {
2391
2392 addDockWidget (Qt::RightDockWidgetArea,
2393 m_dockChecklistGuide); // Add on the right to prevent error message, then immediately make undocked
2394 m_dockChecklistGuide->setFloating(DOCKED_EQUALS_NOT_FLOATING);
2395 if (settings.contains (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY)) {
2396 m_dockChecklistGuide->restoreGeometry (settings.value (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY).toByteArray());
2397 }
2398
2399 } else {
2400
2401 addDockWidget (area,
2402 m_dockChecklistGuide);
2403
2404 }
2452 addDockWindow (m_dockChecklistGuide,
2453 settings,
2454 SETTINGS_CHECKLIST_GUIDE_DOCK_AREA,
2455 SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY,
2456 Qt::RightDockWidgetArea);
2457 addDockWindow (m_dockGeometryWindow,
2458 settings,
2459 SETTINGS_GEOMETRY_WINDOW_DOCK_AREA,
2460 SETTINGS_GEOMETRY_WINDOW_DOCK_GEOMETRY,
2461 Qt::RightDockWidgetArea);
24052462
24062463 // Main window settings. Preference for initial zoom factor is 100%, rather than fill mode, for issue #25. Some or all
24072464 // settings are saved to the application AND saved to m_modelMainWindow for use in DlgSettingsMainWindow. Note that
24242481 QVariant (MAIN_TITLE_BAR_FORMAT_PATH)).toInt());
24252482 m_modelMainWindow.setPdfResolution (settings.value (SETTINGS_IMPORT_PDF_RESOLUTION,
24262483 QVariant (DEFAULT_IMPORT_PDF_RESOLUTION)).toInt ());
2484 m_modelMainWindow.setImportCropping ((ImportCropping) settings.value (SETTINGS_IMPORT_CROPPING,
2485 QVariant (DEFAULT_IMPORT_CROPPING)).toInt ());
2486 m_modelMainWindow.setMaximumGridLines (settings.value (SETTINGS_MAXIMUM_GRID_LINES,
2487 QVariant (DEFAULT_MAXIMUM_GRID_LINES)).toInt ());
2488 m_modelMainWindow.setHighlightOpacity (settings.value (SETTINGS_HIGHLIGHT_OPACITY,
2489 QVariant (DEFAULT_HIGHLIGHT_OPACITY)).toDouble ());
24272490
24282491 updateSettingsMainWindow();
24292492
24552518 settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, dockWidgetArea (m_dockChecklistGuide));
24562519
24572520 }
2521 if (m_dockGeometryWindow->isFloating()) {
2522
2523 settings.setValue (SETTINGS_GEOMETRY_WINDOW_DOCK_AREA, Qt::NoDockWidgetArea);
2524 settings.setValue (SETTINGS_GEOMETRY_WINDOW_DOCK_GEOMETRY, m_dockGeometryWindow->saveGeometry ());
2525
2526 } else {
2527
2528 settings.setValue (SETTINGS_GEOMETRY_WINDOW_DOCK_AREA, dockWidgetArea (m_dockGeometryWindow));
2529
2530 }
2531 settings.setValue (SETTINGS_BACKGROUND_IMAGE, m_cmbBackground->currentData().toInt());
24582532 settings.setValue (SETTINGS_CHECKLIST_GUIDE_WIZARD, m_actionHelpChecklistGuideWizard->isChecked ());
2533 settings.setValue (SETTINGS_HIGHLIGHT_OPACITY, m_modelMainWindow.highlightOpacity());
2534 settings.setValue (SETTINGS_IMPORT_CROPPING, m_modelMainWindow.importCropping());
24592535 settings.setValue (SETTINGS_IMPORT_PDF_RESOLUTION, m_modelMainWindow.pdfResolution ());
24602536 settings.setValue (SETTINGS_LOCALE_LANGUAGE, m_modelMainWindow.locale().language());
24612537 settings.setValue (SETTINGS_LOCALE_COUNTRY, m_modelMainWindow.locale().country());
2538 settings.setValue (SETTINGS_MAIN_TITLE_BAR_FORMAT, m_modelMainWindow.mainTitleBarFormat());
2539 settings.setValue (SETTINGS_MAXIMUM_GRID_LINES, m_modelMainWindow.maximumGridLines());
24622540 settings.setValue (SETTINGS_VIEW_BACKGROUND_TOOLBAR, m_actionViewBackground->isChecked());
2463 settings.setValue (SETTINGS_BACKGROUND_IMAGE, m_cmbBackground->currentData().toInt());
24642541 settings.setValue (SETTINGS_VIEW_DIGITIZE_TOOLBAR, m_actionViewDigitize->isChecked ());
24652542 settings.setValue (SETTINGS_VIEW_STATUS_BAR, m_statusBar->statusBarMode ());
24662543 settings.setValue (SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR, m_actionViewSettingsViews->isChecked ());
24692546 settings.setValue (SETTINGS_ZOOM_CONTROL, m_modelMainWindow.zoomControl());
24702547 settings.setValue (SETTINGS_ZOOM_FACTOR, currentZoomFactor ());
24712548 settings.setValue (SETTINGS_ZOOM_FACTOR_INITIAL, m_modelMainWindow.zoomFactorInitial());
2472 settings.setValue (SETTINGS_MAIN_TITLE_BAR_FORMAT, m_modelMainWindow.mainTitleBarFormat());
24732549 settings.endGroup ();
24742550 }
24752551
27242800
27252801 updateViewedCurves();
27262802 updateViewsOfSettings();
2727 }
2728
2729 void MainWindow::slotContextMenuEvent (QString pointIdentifier)
2730 {
2731 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotContextMenuEvent point=" << pointIdentifier.toLatin1 ().data ();
2732
2733 m_digitizeStateContext->handleContextMenuEvent (m_cmdMediator,
2734 pointIdentifier);
2803 updateGeometryWindow();
2804 }
2805
2806 void MainWindow::slotContextMenuEventAxis (QString pointIdentifier)
2807 {
2808 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotContextMenuEventAxis point=" << pointIdentifier.toLatin1 ().data ();
2809
2810 m_digitizeStateContext->handleContextMenuEventAxis (m_cmdMediator,
2811 pointIdentifier);
2812 }
2813
2814 void MainWindow::slotContextMenuEventGraph (QStringList pointIdentifiers)
2815 {
2816 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotContextMenuEventGraph point=" << pointIdentifiers.join(",").toLatin1 ().data ();
2817
2818 m_digitizeStateContext->handleContextMenuEventGraph (m_cmdMediator,
2819 pointIdentifiers);
27352820 }
27362821
27372822 void MainWindow::slotDigitizeAxis ()
28042889 {
28052890 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCopy";
28062891
2892 GraphicsItemsExtractor graphicsItemsExtractor;
2893 const QList<QGraphicsItem*> &items = m_scene->selectedItems();
2894 QStringList pointIdentifiers = graphicsItemsExtractor.selectedPointIdentifiers (items);
2895
28072896 CmdCopy *cmd = new CmdCopy (*this,
28082897 m_cmdMediator->document(),
2809 m_scene->selectedPointIdentifiers ());
2898 pointIdentifiers);
28102899 m_digitizeStateContext->appendNewCmd (m_cmdMediator,
28112900 cmd);
28122901 }
28152904 {
28162905 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCut";
28172906
2907 GraphicsItemsExtractor graphicsItemsExtractor;
2908 const QList<QGraphicsItem*> &items = m_scene->selectedItems();
2909 QStringList pointIdentifiers = graphicsItemsExtractor.selectedPointIdentifiers (items);
2910
28182911 CmdCut *cmd = new CmdCut (*this,
28192912 m_cmdMediator->document(),
2820 m_scene->selectedPointIdentifiers ());
2913 pointIdentifiers);
28212914 m_digitizeStateContext->appendNewCmd (m_cmdMediator,
28222915 cmd);
28232916 }
28262919 {
28272920 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditDelete";
28282921
2922 GraphicsItemsExtractor graphicsItemsExtractor;
2923 const QList<QGraphicsItem*> &items = m_scene->selectedItems();
2924 QStringList pointIdentifiers = graphicsItemsExtractor.selectedPointIdentifiers (items);
2925
28292926 CmdDelete *cmd = new CmdDelete (*this,
28302927 m_cmdMediator->document(),
2831 m_scene->selectedPointIdentifiers ());
2928 pointIdentifiers);
28322929 m_digitizeStateContext->appendNewCmd (m_cmdMediator,
28332930 cmd);
28342931 }
28862983
28872984 // Remove scroll bars if they exist
28882985 m_scene->setSceneRect (QRectF (0, 0, 1, 1));
2986
2987 // Remove stale data from geometry window
2988 m_dockGeometryWindow->clear ();
28892989
28902990 // Deallocate Document
28912991 delete m_cmdMediator;
30833183 return false;
30843184 }
30853185
3186 void MainWindow::slotGeometryWindowClosed()
3187 {
3188 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotGeometryWindowClosed";
3189
3190 m_actionViewGeometryWindow->setChecked (false);
3191 }
3192
30863193 void MainWindow::slotHelpAbout()
30873194 {
30883195 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpAbout";
31093216 m_digitizeStateContext->handleKeyPress (m_cmdMediator,
31103217 key,
31113218 atLeastOneSelectedItem);
3112 }
3113
3114 void MainWindow::slotLeave ()
3115 {
3116 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotLeave";
3117
3118 m_digitizeStateContext->handleLeave (m_cmdMediator);
31193219 }
31203220
31213221 void MainWindow::slotLoadStartupFiles ()
32383338 completeText += QString (" \"%1\"").arg (text);
32393339 }
32403340 m_actionEditRedo->setText (completeText);
3241 }
3242
3243 void MainWindow::slotSetOverrideCursor (QCursor cursor)
3244 {
3245 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSetOverrideCursor";
3246
3247 m_digitizeStateContext->handleSetOverrideCursor (m_cmdMediator,
3248 cursor);
32493341 }
32503342
32513343 void MainWindow::slotSettingsAxesChecker ()
35313623 m_toolDigitize->show();
35323624 } else {
35333625 m_toolDigitize->hide();
3626 }
3627 }
3628
3629 void MainWindow::slotViewToolBarGeometryWindow ()
3630 {
3631 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarGeometryWindow";
3632
3633 if (m_actionViewGeometryWindow->isChecked ()) {
3634 m_dockGeometryWindow->show();
3635 } else {
3636 m_dockGeometryWindow->hide();
35343637 }
35353638 }
35363639
39334036 // status bar are up to date. Point coordinates in Document are also updated
39344037 updateAfterCommandStatusBarCoords ();
39354038
3936 // Update the QGraphicsScene with the populated Curves. This requires the points in the Document to be already updated
3937 // by updateAfterCommandStatusBarCoords
3938 m_scene->updateAfterCommand (*m_cmdMediator);
4039 updateHighlightOpacity ();
4040
4041 // Update graphics. Effectively, these steps do very little (just needed for highlight opacity)
4042 m_digitizeStateContext->updateAfterPointAddition (); // May or may not be needed due to point addition
39394043
39404044 updateControls ();
3941
3942 // Update checklist guide status
3943 m_dockChecklistGuide->update (*m_cmdMediator,
3944 m_isDocumentExported);
4045 updateChecklistGuide ();
4046 updateGeometryWindow();
39454047
39464048 // Final action at the end of a redo/undo is to checkpoint the Document and GraphicsScene to log files
39474049 // so proper state can be verified
39484050 writeCheckpointToLogFile ();
4051
4052 // Since focus may have drifted over to Geometry Window or some other control we se focus on the GraphicsView
4053 // so the cursor is appropriate for the current state (otherwise it often ends up as default arrow)
4054 m_view->setFocus ();
39494055 }
39504056
39514057 void MainWindow::updateAfterCommandStatusBarCoords ()
39534059 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommandStatusBarCoords";
39544060
39554061 // For some reason, mapFromGlobal(QCursor::pos) differs from event->pos by a little bit. We must compensate for
3956 // this so cursor coordinates in status bar match the DlgEditPoint inputs initially. After the mouse moves
4062 // this so cursor coordinates in status bar match the DlgEditPointAxis inputs initially. After the mouse moves
39574063 // the problem disappears since event->pos is available and QCursor::pos is no longer needed
39584064 const QPoint HACK_SO_GRAPH_COORDINATE_MATCHES_INPUT (1, 1);
39594065
39984104 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterMouseRelease";
39994105
40004106 updateControls ();
4107 }
4108
4109 void MainWindow::updateChecklistGuide ()
4110 {
4111 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateChecklistGuide";
4112
4113 m_isDocumentExported = true; // Set for next line and for all checklist guide updates after this
4114 m_dockChecklistGuide->update (*m_cmdMediator,
4115 m_isDocumentExported);
40014116 }
40024117
40034118 void MainWindow::updateControls ()
41324247 }
41334248 }
41344249
4250 void MainWindow::updateGeometryWindow ()
4251 {
4252 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateGeometryWindow";
4253
4254 // Update geometry window
4255 m_dockGeometryWindow->update (*m_cmdMediator,
4256 m_modelMainWindow,
4257 m_cmbCurve->currentText (),
4258 m_transformation);
4259 }
4260
41354261 void MainWindow::updateGraphicsLinesToMatchGraphicsPoints()
41364262 {
41374263 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateGraphicsLinesToMatchGraphicsPoints";
41494275
41504276 // Create new grid lines
41514277 GridLineFactory factory (*m_scene,
4152 m_cmdMediator->document().modelCoords(),
4153 m_transformation);
4278 m_cmdMediator->document().modelCoords());
41544279 factory.createGridLinesForEvenlySpacedGrid (m_cmdMediator->document().modelGridDisplay(),
4280 m_modelMainWindow,
4281 m_transformation,
41554282 m_gridLines);
41564283
41574284 m_gridLines.setVisible (m_actionViewGridLines->isChecked());
4285 }
4286
4287 void MainWindow::updateHighlightOpacity ()
4288 {
4289 if (m_cmdMediator != 0) {
4290
4291 // Update the QGraphicsScene with the populated Curves. This requires the points in the Document to be already updated
4292 // by updateAfterCommandStatusBarCoords
4293 m_scene->updateAfterCommand (*m_cmdMediator,
4294 m_modelMainWindow.highlightOpacity(),
4295 m_dockGeometryWindow);
4296 }
41584297 }
41594298
41604299 void MainWindow::updateRecentFileList()
42974436
42984437 }
42994438
4439 if ((m_scene != 0) &&
4440 (m_cmdMediator != 0)) {
4441 m_scene->updateCurveStyles(m_cmdMediator->document().modelCurveStyles());
4442 }
4443
4444 updateHighlightOpacity();
43004445 updateWindowTitle();
43014446 }
43024447
5252 class DocumentModelSegments;
5353 class ExportToFile;
5454 class FileCmdScript;
55 class GeometryWindow;
5556 class Ghosts;
5657 class GraphicsScene;
5758 class GraphicsView;
8889 /// \param fileCmdScriptFile Optional file command script file to be read at startup. Empty if unused. Incompatible with errorReportFile
8990 /// \param isRegressionTest True if errorReportFile or fileCmdScript is for regression testing, in which case it is executed and the program exits
9091 /// \param isGnuplot True if diagnostic gnuplot files are generated for math-intense sections of the code. Used for development and debugging
92 /// \param isReset True to reset all settings that would otherwise be restored from the previous execution of Engauge
9193 /// \param loadStartupFiles Zero or more Engauge document files to load at startup. A separate instance of Engauge is created for each file
9294 /// \param parent Optional parent widget for this widget
9395 MainWindow(const QString &errorReportFile,
9496 const QString &fileCmdScriptFile,
9597 bool isRegressionTest,
9698 bool isGnuplot,
99 bool isReset,
97100 QStringList loadStartupFiles,
98101 QWidget *parent = 0);
99102 ~MainWindow();
231234 void slotCmbBackground(int);
232235 void slotCmbCoordSystem(int);
233236 void slotCmbCurve(int);
234 void slotContextMenuEvent (QString);
237 void slotContextMenuEventAxis (QString);
238 void slotContextMenuEventGraph (QStringList);
235239 void slotDigitizeAxis ();
236240 void slotDigitizeColorPicker ();
237241 void slotDigitizeCurve ();
258262 void slotFilePrint();
259263 bool slotFileSave(); /// Slot method that is sometimes called directly with return value expected
260264 bool slotFileSaveAs(); /// Slot method that is sometimes called directly with return value expected
265 void slotGeometryWindowClosed();
261266 void slotHelpAbout();
262267 void slotHelpTutorial();
263268 void slotKeyPress (Qt::Key, bool);
264 void slotLeave ();
265269 void slotLoadStartupFiles ();
266270 void slotMouseMove (QPointF);
267271 void slotMousePress (QPointF);
269273 void slotRecentFileAction ();
270274 void slotRecentFileClear ();
271275 void slotRedoTextChanged (const QString &);
272 void slotSetOverrideCursor (QCursor);
273276 void slotSettingsAxesChecker ();
274277 void slotSettingsColorFilter ();
275278 void slotSettingsCoords ();
294297 void slotViewToolBarChecklistGuide ();
295298 void slotViewToolBarCoordSystem ();
296299 void slotViewToolBarDigitize ();
300 void slotViewToolBarGeometryWindow ();
297301 void slotViewToolBarSettingsViews ();
298302 void slotViewToolTips ();
299303 void slotViewZoom16To1 ();
325329 IMPORT_TYPE_IMAGE_REPLACE
326330 };
327331
332 void addDockWindow (QDockWidget *dockWidget,
333 QSettings &settings,
334 const QString &settingsTokenArea,
335 const QString &settingsTokenGeometry,
336 Qt::DockWidgetArea dockWidgetArea);
328337 void applyZoomFactorAfterLoad();
329338 virtual void closeEvent(QCloseEvent *event);
330339 void createActions();
336345 void createActionsView ();
337346 void createCentralWidget ();
338347 void createCommandStackShadow ();
348 void createDockableWidgets ();
339349 void createHelpWindow ();
340350 void createIcons();
341351 void createLoadImageFromUrl ();
393403 void setCurrentPathFromFile (const QString &fileName);
394404 void setPixmap (const QString &curveSelected,
395405 const QPixmap &pixmap);
396 void settingsRead ();
406 void settingsRead (bool isReset);
397407 void settingsReadEnvironment (QSettings &settings);
398408 void settingsReadMainWindow (QSettings &settings);
399409 void settingsWrite ();
406416 void startRegressionTestErrorReport (const QString &regressionInputFile);
407417 void startRegressionTestFileCmdScript ();
408418 void updateAfterCommandStatusBarCoords ();
419 void updateChecklistGuide ();
409420 void updateControls (); // Update the widgets (typically in terms of show/hide state) depending on the application state.
421 void updateGeometryWindow ();
410422 void updateGridLines();
423 void updateHighlightOpacity();
411424 void updateRecentFileList();
412425 void updateSettingsMainWindow();
413426 void updateTransformationAndItsDependencies();
462475 QAction *m_actionViewChecklistGuide;
463476 QAction *m_actionViewCoordSystem;
464477 QAction *m_actionViewDigitize;
478 QAction *m_actionViewGeometryWindow;
465479 QAction *m_actionViewSettingsViews;
466480 QAction *m_actionViewToolTips;
467481 QAction *m_actionViewGridLines;
535549 ViewSegmentFilter *m_viewSegmentFilter;
536550 QToolBar *m_toolSettingsViews;
537551 ChecklistGuide *m_dockChecklistGuide;
552 GeometryWindow *m_dockGeometryWindow;
538553
539554 QComboBox *m_cmbCoordSystem;
540555 QPushButton *m_btnPrintAll;
55
66 #include "CmdMediator.h"
77 #include "DocumentSerialize.h"
8 #include "GraphicsPoint.h"
9 #include "GridLineLimiter.h"
10 #include "ImportCroppingUtilBase.h"
811 #include "Logger.h"
912 #include "MainWindowModel.h"
1013 #include "PdfResolution.h"
2326 m_zoomControl (ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS),
2427 m_zoomFactorInitial (DEFAULT_ZOOM_FACTOR_INITIAL),
2528 m_mainTitleBarFormat (MAIN_TITLE_BAR_FORMAT_PATH),
26 m_pdfResolution (DEFAULT_IMPORT_PDF_RESOLUTION)
29 m_pdfResolution (DEFAULT_IMPORT_PDF_RESOLUTION),
30 m_importCropping (DEFAULT_IMPORT_CROPPING),
31 m_maximumGridLines (DEFAULT_MAXIMUM_GRID_LINES),
32 m_highlightOpacity (DEFAULT_HIGHLIGHT_OPACITY)
2733 {
2834 // Locale member variable m_locale is initialized to default locale when default constructor is called
2935 }
3339 m_zoomControl (other.zoomControl()),
3440 m_zoomFactorInitial (other.zoomFactorInitial()),
3541 m_mainTitleBarFormat (other.mainTitleBarFormat()),
36 m_pdfResolution (other.pdfResolution())
42 m_pdfResolution (other.pdfResolution()),
43 m_importCropping (other.importCropping()),
44 m_maximumGridLines (other.maximumGridLines()),
45 m_highlightOpacity (other.highlightOpacity())
3746 {
3847 }
3948
4453 m_zoomFactorInitial = other.zoomFactorInitial();
4554 m_mainTitleBarFormat = other.mainTitleBarFormat();
4655 m_pdfResolution = other.pdfResolution();
56 m_importCropping = other.importCropping();
57 m_maximumGridLines = other.maximumGridLines();
58 m_highlightOpacity = other.highlightOpacity();
4759
4860 return *this;
61 }
62
63 double MainWindowModel::highlightOpacity() const
64 {
65 return m_highlightOpacity;
66 }
67
68 ImportCropping MainWindowModel::importCropping() const
69 {
70 return m_importCropping;
4971 }
5072
5173 void MainWindowModel::loadXml(QXmlStreamReader &reader)
79101 return m_mainTitleBarFormat;
80102 }
81103
104 int MainWindowModel::maximumGridLines() const
105 {
106 return m_maximumGridLines;
107 }
108
82109 int MainWindowModel::pdfResolution() const
83110 {
84111 return m_pdfResolution;
98125 "NoPath" :
99126 "Path") << "\n";
100127 str << indentation << "pdfResolution=" << m_pdfResolution << "\n";
128 str << indentation << "importCropping=" << ImportCroppingUtilBase::importCroppingToString (m_importCropping).toLatin1().data() << "\n";
129 str << indentation << "maximumGridLines=" << m_maximumGridLines << "\n";
130 str << indentation << "highlightOpacity=" << m_highlightOpacity << "\n";
101131 }
102132
103133 void MainWindowModel::saveXml(QXmlStreamWriter &writer) const
106136
107137 writer.writeStartElement(DOCUMENT_SERIALIZE_MAIN_WINDOW);
108138 writer.writeEndElement();
139 }
140
141 void MainWindowModel::setHighlightOpacity(double highlightOpacity)
142 {
143 m_highlightOpacity = highlightOpacity;
144 }
145
146 void MainWindowModel::setImportCropping (ImportCropping importCropping)
147 {
148 m_importCropping = importCropping;
109149 }
110150
111151 void MainWindowModel::setLocale (QLocale::Language language,
129169 m_mainTitleBarFormat = mainTitleBarFormat;
130170 }
131171
172 void MainWindowModel::setMaximumGridLines(int maximumGridLines)
173 {
174 m_maximumGridLines = maximumGridLines;
175 }
176
132177 void MainWindowModel::setPdfResolution(int resolution)
133178 {
134179 m_pdfResolution = resolution;
77 #define MAIN_WINDOW_MODEL_H
88
99 #include "DocumentModelAbstractBase.h"
10 #include "ImportCropping.h"
1011 #include "MainTitleBarFormat.h"
1112 #include <QLocale>
1213 #include <QString>
3334
3435 virtual void loadXml(QXmlStreamReader &reader);
3536
37 /// Get method for highlight opacity
38 double highlightOpacity() const;
39
40 /// Get method for import cropping
41 ImportCropping importCropping () const;
42
3643 /// Get method for locale
3744 QLocale locale() const;
3845
3946 /// Get method for MainWindow titlebar filename format
4047 MainTitleBarFormat mainTitleBarFormat () const;
48
49 /// Maximum number of grid lines
50 int maximumGridLines () const;
4151
4252 /// Get method for resolution of imported PDF files, in dots per inch
4353 int pdfResolution () const;
4858
4959 virtual void saveXml(QXmlStreamWriter &writer) const;
5060
61 /// Set method for highlight opacity
62 void setHighlightOpacity (double highlightOpacity);
63
5164 /// Set method for locale given attributes
5265 void setLocale (QLocale::Language language,
5366 QLocale::Country country);
5568 /// Set method for locale given locale object
5669 void setLocale (const QLocale &locale);
5770
71 /// Set method for import cropping
72 void setImportCropping (ImportCropping importCropping);
73
5874 /// Set method for MainWindow titlebar filename format
5975 void setMainTitleBarFormat (MainTitleBarFormat mainTitleBarFormat);
76
77 /// Set method for maximum number of grid lines
78 void setMaximumGridLines (int maximumGridLines);
6079
6180 /// Set method for resolution of imported PDF files, in dots per inch
6281 void setPdfResolution (int resolution);
8099 ZoomFactorInitial m_zoomFactorInitial;
81100 MainTitleBarFormat m_mainTitleBarFormat;
82101 int m_pdfResolution;
102 ImportCropping m_importCropping;
103 int m_maximumGridLines;
104 double m_highlightOpacity;
83105
84106 };
85107
2424 const QString CMD_GNUPLOT ("gnuplot");
2525 const QString CMD_HELP ("help");
2626 const QString CMD_REGRESSION ("regression");
27 const QString CMD_RESET ("reset");
2728 const QString DASH ("-");
2829 const QString DASH_DEBUG ("-" + CMD_DEBUG);
2930 const QString DASH_ERROR_REPORT ("-" + CMD_ERROR_REPORT);
3132 const QString DASH_GNUPLOT ("-" + CMD_GNUPLOT);
3233 const QString DASH_HELP ("-" + CMD_HELP);
3334 const QString DASH_REGRESSION ("-" + CMD_REGRESSION);
35 const QString DASH_RESET ("-" + CMD_RESET);
3436 const QString ENGAUGE_LOG_FILE ("engauge.log");
3537
3638 // Prototypes
4143 void parseCmdLine (int argc,
4244 char **argv,
4345 bool &isDebug,
46 bool &isReset,
4447 QString &errorReportFile,
4548 QString &fileCmdScriptFile,
4649 bool &isErrorReportRegressionTest,
5861 {
5962 QString pathAndFile; // Return empty value in OSX which is unused
6063
61 #ifndef OSX_RELEASE
64 #if !defined(OSX_RELEASE) && !defined(WIN_RELEASE)
6265 QProcessEnvironment env;
6366
6467 // Make multiple attempts until a directory is found where the log file can be written
104107 TranslatorContainer translatorContainer (app); // Must exist until execution terminates
105108
106109 // Command line
107 bool isDebug, isGnuplot, isErrorReportRegressionTest;
110 bool isDebug, isReset, isGnuplot, isErrorReportRegressionTest;
108111 QString errorReportFile, fileCmdScriptFile;
109112 QStringList loadStartupFiles;
110113 parseCmdLine (argc,
111114 argv,
112115 isDebug,
116 isReset,
113117 errorReportFile,
114118 fileCmdScriptFile,
115119 isErrorReportRegressionTest,
127131 fileCmdScriptFile,
128132 isErrorReportRegressionTest,
129133 isGnuplot,
134 isReset,
130135 loadStartupFiles);
131136 w.show();
132137
137142 void parseCmdLine (int argc,
138143 char **argv,
139144 bool &isDebug,
145 bool &isReset,
140146 QString &errorReportFile,
141147 QString &fileCmdScriptFile,
142148 bool &isErrorReportRegressionTest,
152158
153159 // Defaults
154160 isDebug = false;
161 isReset = false;
155162 errorReportFile = "";
156163 fileCmdScriptFile = "";
157164 isErrorReportRegressionTest = false;
179186 showUsage = true; // User requested help
180187 } else if (strcmp (argv [i], DASH_REGRESSION.toLatin1().data()) == 0) {
181188 isErrorReportRegressionTest = true;
189 } else if (strcmp (argv [i], DASH_RESET.toLatin1().data()) == 0) {
190 isReset = true;
182191 } else if (strncmp (argv [i], DASH.toLatin1().data(), 1) == 0) {
183192 showUsage = true; // User entered an unrecognized token
184193 } else {
202211 << "[" << DASH_GNUPLOT.toLatin1().data() << "] "
203212 << "[" << DASH_HELP.toLatin1().data() << "] "
204213 << "[" << DASH_REGRESSION.toLatin1().data() << "] "
214 << "[" << DASH_RESET.toLatin1().data () << "] "
205215 << "[<load_file1>] [<load_file2>] ..." << endl
206216 << " " << DASH_DEBUG.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
207217 << QObject::tr ("Enables extra debug information. Used for debugging").toLatin1().data() << endl
215225 << QObject::tr ("Show this help information").toLatin1().data() << endl
216226 << " " << DASH_REGRESSION.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
217227 << QObject::tr ("Executes the error report file or file command script. Used for regression testing").toLatin1().data() << endl
228 << " " << DASH_RESET.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
229 << QObject::tr ("Removes all stored settings, including window positions. Used when windows start up offscreen").toLatin1().data() << endl
218230 << " " << QString ("<load file> ").leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
219231 << QObject::tr ("File(s) to be imported or opened at startup").toLatin1().data() << endl;
220232
55
66 #include "Version.h"
77
8 const char *VERSION_NUMBER = "8.3";
8 const char *VERSION_NUMBER = "9.0";
99
1010 QString engaugeWindowTitle()
1111 {
66 #include "ZValues.h"
77
88 const int Z_VALUE_BACKGROUND = 0;
9 const int Z_VALUE_GRID_LINE = 100;
109 const int Z_VALUE_CURVE = 200;
1110 const int Z_VALUE_POINT = 300;
1211
0 -errorreport ../test/cartesian_linear_linear.xml -regression
0 -errorreport ../test/cartesian_linear_linear.xml -regression -reset
0 -errorreport ../test/cartesian_linear_log.xml -regression
0 -errorreport ../test/cartesian_linear_log.xml -regression -reset
0 -errorreport ../test/cartesian_log_linear.xml -regression
0 -errorreport ../test/cartesian_log_linear.xml -regression -reset
0 -errorreport ../test/extrapolate_functions_smooth.xml -regression
0 -errorreport ../test/extrapolate_functions_smooth.xml -regression -reset
0 -errorreport ../test/extrapolate_functions_straight.xml -regression
0 -errorreport ../test/extrapolate_functions_straight.xml -regression -reset
0 -errorreport ../test/extrapolate_relations_smooth.xml -regression
0 -errorreport ../test/extrapolate_relations_smooth.xml -regression -reset
0 -errorreport ../test/extrapolate_relations_straight.xml -regression
0 -errorreport ../test/extrapolate_relations_straight.xml -regression -reset
0 -errorreport ../test/floating_axes.xml -regression
0 -errorreport ../test/floating_axes.xml -regression -reset
0 -errorreport ../test/gnuplot_format.xml -regression
0 -errorreport ../test/gnuplot_format.xml -regression -reset
0 x,red,green,blue
1 0.1052,-4.98,-8.2267,-14.5509
2 0.1087,-4.9347,-8.1743,-14.137
3 0.1203,-4.7818,-7.9873,-12.9622
4 0.1212,-4.7689,-7.9679,-12.8781
5 0.1287,-4.666,-7.7698,-12.2725
6 0.1354,-4.5754,-7.6279,-11.8019
7 0.1387,-4.533,-7.5634,-11.5938
8 0.1486,-4.4031,-7.357,-11.0357
9 0.1505,-4.3773,-7.32,-10.9436
10 0.1586,-4.2486,-7.1589,-10.2968
11 0.163,-4.1791,-7.0697,-10.1802
12 0.1686,-4.0984,-6.9525,-10.0632
13 0.172,-4.053,-6.8815,-9.9982
14 0.1781,-3.9727,-6.7557,-9.8769
15 0.1786,-3.9663,-6.7461,-9.8666
16 0.1819,-3.9235,-6.6827,-9.7918
17 0.1886,-3.8373,-6.5479,-9.6079
18 0.1894,-3.8269,-6.5289,-9.5855
19 0.1932,-3.7745,-6.422,-9.482
20 0.196,-3.7342,-6.3416,-9.4082
21 0.1968,-3.7228,-6.3208,-9.3873
22 0.2042,-3.6224,-6.1646,-9.1809
23 0.206,-3.6015,-6.1352,-9.1297
24 0.2083,-3.5764,-6.0998,-9.0639
25 0.2117,-3.5429,-6.0523,-8.9746
26 0.2211,-3.4622,-5.937,-8.7779
27 0.2217,-3.4578,-5.9307,-8.7682
28 0.2311,-3.3864,-5.8269,-8.6189
29 0.2342,-3.3633,-5.7918,-8.57
30 0.2388,-3.3299,-5.7388,-8.496
31 0.2467,-3.2708,-5.6353,-8.3636
32 0.2539,-3.2165,-5.5407,-8.2513
33 0.2564,-3.1965,-5.5088,-8.2116
34 0.2593,-3.1729,-5.4733,-8.1655
35 0.2715,-3.0678,-5.3342,-7.9644
36 0.2718,-3.0648,-5.3306,-7.9591
37 0.2791,-2.9983,-5.2515,-7.8431
38 0.2844,-2.9503,-5.1933,-7.7609
39 0.2892,-2.9079,-5.1361,-7.6844
40 0.2969,-2.8445,-5.0311,-7.5545
41 0.3019,-2.8084,-4.9656,-7.4678
42 0.3043,-2.7926,-4.9379,-7.4299
43 0.3095,-2.7596,-4.8832,-7.3564
44 0.3245,-2.672,-4.748,-7.1887
45 0.3271,-2.6569,-4.7249,-7.1582
46 0.3323,-2.6266,-4.6791,-7.0918
47 0.3422,-2.5678,-4.593,-6.96
48 0.3472,-2.5373,-4.5498,-6.9005
49 0.3599,-2.4617,-4.4435,-6.7619
50 0.3628,-2.4449,-4.4193,-6.7297
51 0.37,-2.4048,-4.3599,-6.6488
52 0.3775,-2.3645,-4.2975,-6.5637
53 0.3927,-2.2866,-4.1617,-6.3929
54 0.3952,-2.2745,-4.1373,-6.3655
55 0.3958,-2.2715,-4.1311,-6.3586
56 0.4128,-2.1873,-3.9728,-6.1673
57 0.413,-2.1866,-3.9717,-6.1658
58 0.4313,-2.098,-3.8597,-5.9844
59 0.433,-2.0899,-3.8501,-5.9692
60 0.4434,-2.0409,-3.79,-5.8811
61 0.4558,-1.9834,-3.7091,-5.7792
62 0.4669,-1.9328,-3.6309,-5.6848
63 0.4713,-1.913,-3.6001,-5.6463
64 0.4785,-1.8805,-3.5505,-5.581
65 0.4988,-1.7933,-3.4208,-5.3911
66 0.4991,-1.7916,-3.4184,-5.3874
67 0.505,-1.7675,-3.3822,-5.332
68 0.5215,-1.702,-3.2829,-5.1929
69 0.5296,-1.6711,-3.2367,-5.1377
70 0.5457,-1.6105,-3.148,-5.0358
71 0.5494,-1.5965,-3.1276,-5.0112
72 0.5626,-1.5476,-3.0549,-4.9161
73 0.5747,-1.5034,-2.9851,-4.8213
74 0.5889,-1.4535,-2.9041,-4.7123
75 0.593,-1.4394,-2.8815,-4.6818
76 0.6,-1.4159,-2.8442,-4.6313
77 0.6279,-1.326,-2.7108,-4.4496
78 0.6285,-1.324,-2.708,-4.4457
79 0.6347,-1.3048,-2.6815,-4.409
80 0.6583,-1.2312,-2.5806,-4.2679
81 0.6667,-1.2058,-2.5427,-4.2165
82 0.6805,-1.1643,-2.4742,-4.1297
83 0.6888,-1.1397,-2.4322,-4.0779
84 0.7022,-1.1007,-2.3693,-3.9965
85 0.7192,-1.0521,-2.302,-3.8962
86 0.7263,-1.032,-2.2757,-3.8548
87 0.7429,-0.9852,-2.2123,-3.7597
88 0.7496,-0.9664,-2.184,-3.7228
89 0.7746,-0.8997,-2.0736,-3.5925
90 0.781,-0.8836,-2.047,-3.5584
91 0.7826,-0.8795,-2.0404,-3.5493
92 0.8156,-0.7996,-1.9203,-3.3676
93 0.8242,-0.7789,-1.89,-3.3276
94 0.8255,-0.7757,-1.8853,-3.3217
95 0.8537,-0.7067,-1.7821,-3.2023
96 0.8649,-0.6795,-1.7413,-3.1525
97 0.8765,-0.6517,-1.7001,-3.0983
98 0.8893,-0.6216,-1.6557,-3.0371
99 0.9081,-0.5787,-1.5925,-2.9489
100 0.9274,-0.5359,-1.5298,-2.8636
101 0.9274,-0.5359,-1.5298,-2.8636
102 0.9539,-0.4779,-1.4438,-2.755
103 0.9655,-0.4529,-1.4056,-2.7066
104 0.9809,-0.4202,-1.3551,-2.6387
105 0.9997,-0.3809,-1.295,-2.5572
106 1.0036,-0.3729,-1.283,-2.5414
107 1.0344,-0.3126,-1.1937,-2.4292
108 1.0455,-0.2921,-1.1628,-2.3893
109 1.0468,-0.2897,-1.1591,-2.3844
110 1.0875,-0.2184,-1.0479,-2.2274
111 1.0904,-0.2134,-1.04,-2.2165
112 1.0939,-0.2074,-1.0305,-2.2036
113 1.1307,-0.1423,-0.9289,-2.0704
114 1.1422,-0.1217,-0.8982,-2.0289
115 1.1465,-0.1141,-0.8871,-2.0135
116 1.1714,-0.069,-0.8234,-1.9216
117 1.1906,-0.0351,-0.7742,-1.8507
118 1.2025,-0.0148,-0.7427,-1.8074
119 1.2146,0.0051,-0.7105,-1.7646
120 1.2415,0.0469,-0.642,-1.6755
121 1.2604,0.0752,-0.5981,-1.6159
122 1.2611,0.0762,-0.5966,-1.6137
123 1.2924,0.1219,-0.5262,-1.5177
124 1.3062,0.1424,-0.493,-1.4754
125 1.3172,0.159,-0.4659,-1.4414
126 1.3433,0.1999,-0.4022,-1.3609
127 1.352,0.2135,-0.3821,-1.3349
128 1.3758,0.25,-0.3301,-1.266
129 1.3968,0.2803,-0.2864,-1.2055
130 1.3978,0.2817,-0.2844,-1.2026
131 1.4344,0.3328,-0.2106,-1.0951
132 1.4462,0.3496,-0.1871,-1.0621
133 1.4503,0.3556,-0.1789,-1.0509
134 1.493,0.4156,-0.093,-0.9418
135 1.4945,0.4175,-0.0901,-0.9381
136 1.5038,0.4295,-0.0714,-0.9145
137 1.5454,0.4818,0.0126,-0.8058
138 1.5517,0.4901,0.025,-0.7895
139 1.5573,0.4978,0.0362,-0.7748
140 1.5938,0.5502,0.1073,-0.6818
141 1.6103,0.5729,0.1381,-0.6417
142 1.6133,0.5768,0.1437,-0.6344
143 1.6447,0.6137,0.1996,-0.5578
144 1.6689,0.6392,0.2422,-0.4954
145 1.6694,0.6396,0.243,-0.4943
146 1.6931,0.664,0.2856,-0.4338
147 1.7254,0.6997,0.3422,-0.3584
148 1.7301,0.7054,0.35,-0.3481
149 1.744,0.7231,0.3725,-0.318
150 1.7815,0.7716,0.4333,-0.2382
151 1.7888,0.78,0.4459,-0.2221
152 1.7975,0.7893,0.4615,-0.2022
153 1.8375,0.8264,0.5325,-0.1044
154 1.8484,0.8365,0.5503,-0.0782
155 1.85,0.838,0.5527,-0.0746
156 1.8961,0.8872,0.6236,0.0258
157 1.9019,0.8937,0.6326,0.0376
158 1.9112,0.9043,0.6474,0.0563
159 1.9522,0.9507,0.7146,0.1387
160 1.9554,0.9543,0.7197,0.1451
161 1.9698,0.9705,0.7428,0.1743
162 2.0089,1.0139,0.8027,0.2526
163 2.0108,1.016,0.8056,0.2564
164 2.031,1.0368,0.8351,0.2949
165 2.0649,1.069,0.8853,0.3601
166 2.0669,1.0708,0.8884,0.3641
167 2.0922,1.0949,0.9286,0.4157
168 2.1184,1.1221,0.9692,0.4676
169 2.1255,1.1297,0.9794,0.4808
170 2.1483,1.1529,1.0095,0.5211
171 2.1745,1.1763,1.0417,0.5669
172 2.1841,1.1843,1.054,0.5846
173 2.2069,1.2026,1.0846,0.6275
174 2.228,1.2195,1.1148,0.6662
175 2.2428,1.2318,1.1367,0.6919
176 2.2656,1.2524,1.1708,0.7303
177 2.2866,1.2732,1.2005,0.7655
178 2.3014,1.2883,1.2195,0.791
179 2.3242,1.3104,1.2451,0.8316
180 2.3426,1.3261,1.2643,0.8648
181 2.3626,1.3419,1.2858,0.9008
182 2.3855,1.3602,1.3135,0.9414
183 2.3987,1.3714,1.3307,0.964
184 2.4212,1.3911,1.3603,1.0012
185 2.4441,1.4099,1.3896,1.038
186 2.4547,1.4173,1.403,1.0551
187 2.4798,1.4335,1.4348,1.0961
188 2.4926,1.4432,1.4514,1.1169
189 2.5108,1.4595,1.4751,1.1461
190 2.5385,1.4865,1.5094,1.1891
191 2.5538,1.5012,1.5268,1.2127
192 2.5694,1.5152,1.5438,1.2371
193 2.5997,1.5396,1.5757,1.286
194 2.615,1.551,1.5921,1.3111
195 2.6255,1.5584,1.6036,1.3281
196 2.6583,1.5808,1.6419,1.3802
197 2.6762,1.5925,1.6642,1.4075
198 2.6841,1.5975,1.674,1.4192
199 2.7195,1.6209,1.7165,1.4697
200 2.7374,1.634,1.7353,1.4947
201 2.7427,1.6381,1.7404,1.5019
202 2.7781,1.6672,1.7745,1.5516
203 2.7986,1.6838,1.7956,1.5809
204 2.8013,1.6858,1.7984,1.5847
205 2.8393,1.7128,1.8408,1.6406
206 2.8573,1.7253,1.8617,1.6674
207 2.8574,1.7253,1.8618,1.6675
208 2.898,1.7546,1.907,1.7263
209 2.916,1.7668,1.9249,1.7503
210 2.916,1.7668,1.9249,1.7503
211 2.9491,1.7834,1.9557,1.7903
212 2.9592,1.7896,1.9651,1.8022
213 2.9772,1.8016,1.9824,1.8248
214 3.0104,1.8249,2.0156,1.8715
215 3.0178,1.8303,2.0231,1.8823
216 3.0358,1.8431,2.041,1.9076
217 3.0716,1.8665,2.0763,1.953
218 3.0765,1.8693,2.0811,1.959
219 3.0944,1.8789,2.0989,1.9821
220 3.1328,1.8997,2.1369,2.0363
221 3.1351,1.9011,2.1391,2.0396
222 3.1531,1.913,2.1568,2.0649
223 3.1915,1.9412,2.1948,2.1145
224 3.1938,1.9429,2.1971,2.1173
225 3.2117,1.9559,2.2153,2.1394
226 3.2524,1.9826,2.2551,2.1897
227 3.2527,1.9828,2.2554,2.1901
228 3.2729,1.9939,2.2733,2.214
229 3.3085,2.0129,2.3049,2.2536
230 3.3139,2.016,2.3101,2.2596
231 3.3315,2.027,2.3275,2.2802
232 3.3672,2.0518,2.3629,2.3262
233 3.3752,2.0575,2.3702,2.3365
234 3.3901,2.0683,2.383,2.3548
235 3.4258,2.0925,2.4127,2.3931
236 3.4364,2.0991,2.4218,2.4043
237 3.4513,2.1078,2.4349,2.421
238 3.4976,2.1323,2.4759,2.4802
239 3.51,2.1389,2.4867,2.4956
240 3.5202,2.1444,2.4956,2.5074
241 3.5588,2.1656,2.5276,2.5487
242 3.5712,2.1723,2.5373,2.5618
243 3.5814,2.1779,2.5454,2.5731
244 3.6201,2.1989,2.5767,2.6172
245 3.6298,2.2041,2.5847,2.6281
246 3.6426,2.2111,2.5951,2.6421
247 3.6813,2.2321,2.6267,2.6836
248 3.691,2.2374,2.6346,2.6944
249 3.7038,2.2443,2.6449,2.7091
250 3.7425,2.2654,2.6762,2.7532
251 3.7496,2.2693,2.682,2.7607
252 3.765,2.2777,2.6947,2.7757
253 3.8037,2.2987,2.7273,2.8117
254 3.8108,2.3024,2.7334,2.8187
255 3.8237,2.3093,2.7445,2.8322
256 3.865,2.3319,2.7792,2.8797
257 3.8695,2.3345,2.7827,2.885
258 3.8849,2.3434,2.7942,2.9025
259 3.9262,2.3652,2.8216,2.9467
260 3.9307,2.3671,2.8246,2.9512
261 3.9461,2.3733,2.8357,2.9664
262 3.99,2.3902,2.8732,3.0075
263 3.9919,2.391,2.8748,3.0093
264 4.0048,2.3972,2.8855,3.0214
265 4.0505,2.4231,2.9173,3.0673
266 4.0512,2.4235,2.9178,3.068
267 4.066,2.4322,2.927,3.0841
268 4.1117,2.4564,2.9571,3.1336
269 4.1124,2.4567,2.9577,3.1343
270 4.1272,2.463,2.9686,3.149
271 4.1729,2.4814,3.0058,3.1916
272 4.1737,2.4817,3.0065,3.1923
273 4.1884,2.4889,3.0183,3.206
274 4.2341,2.5145,3.0511,3.2496
275 4.2349,2.515,3.0516,3.2504
276 4.2471,2.5221,3.0598,3.2624
277 4.2953,2.5479,3.0925,3.3077
278 4.2961,2.5483,3.0931,3.3084
279 4.3083,2.5537,3.1014,3.3184
280 4.3565,2.5721,3.1341,3.3574
281 4.3599,2.5733,3.1364,3.3605
282 4.3695,2.5768,3.1429,3.3693
283 4.4152,2.5954,3.1738,3.4154
284 4.4212,2.5983,3.1779,3.4215
285 4.4307,2.6033,3.1844,3.4311
286 4.4764,2.6285,3.2154,3.4735
287 4.4824,2.6316,3.2195,3.4785
288 4.492,2.6361,3.2259,3.4862
289 4.5376,2.6543,3.2567,3.5232
290 4.5436,2.6566,3.2608,3.5287
291 4.5532,2.6603,3.2674,3.5376
292 4.5988,2.6791,3.2998,3.5813
293 4.6049,2.6816,3.3041,3.5866
294 4.6118,2.6844,3.3089,3.5926
295 4.66,2.7033,3.3415,3.631
296 4.6687,2.7066,3.3474,3.6382
297 4.6731,2.7083,3.3505,3.6419
298 4.7187,2.7263,3.3819,3.6808
299 4.7299,2.7316,3.3892,3.6901
300 4.7343,2.7338,3.392,3.6937
301 4.7799,2.759,3.4173,3.7306
302 4.7911,2.7649,3.423,3.7398
303 4.7955,2.767,3.4252,3.7435
304 4.8411,2.7857,3.4493,3.7804
305 4.8524,2.7899,3.4559,3.789
306 4.8567,2.7916,3.4585,3.7923
307 4.9048,2.8104,3.4906,3.8301
308 4.9162,2.8149,3.4987,3.8402
309 4.918,2.8157,3.5,3.8419
310 4.966,2.8353,3.5335,3.8882
311 4.9774,2.8399,3.5405,3.8988
312 4.9792,2.8407,3.5415,3.9005
313 5.0247,2.8594,3.5657,3.9379
314 5.0386,2.8649,3.5737,3.9476
315 5.0404,2.8657,3.5748,3.9487
316 5.0859,2.8834,3.6061,3.9794
317 5.1016,2.8897,3.6163,3.9918
318 5.1024,2.89,3.6168,3.9924
319 5.1446,2.9072,3.6394,4.0292
320 5.1629,2.9147,3.6496,4.045
321 5.1637,2.915,3.6501,4.0457
322 5.2058,2.9319,3.6788,4.079
323 5.2241,2.9396,3.6911,4.0916
324 5.2249,2.94,3.6916,4.0921
325 5.267,2.9582,3.715,4.1205
326 5.2853,2.9647,3.7244,4.1343
327 5.2861,2.965,3.7248,4.135
328 5.3282,2.9758,3.7475,4.1703
329 5.3465,2.9807,3.7576,4.1864
330 5.3499,2.9818,3.7595,4.1894
331 5.3869,2.9962,3.7796,4.22
332 5.4078,3.0053,3.7909,4.235
333 5.4112,3.0068,3.7928,4.2373
334 5.4481,3.0215,3.8128,4.2616
335 5.469,3.0295,3.8242,4.2757
336 5.475,3.0318,3.8274,4.2798
337 5.5093,3.0457,3.8461,4.3031
338 5.5302,3.0543,3.8574,4.3166
339 5.5362,3.0568,3.8607,4.3205
340 5.5705,3.0708,3.8793,4.3446
341 5.5915,3.0794,3.8907,4.3621
342 5.5974,3.0818,3.894,4.3673
343 5.6292,3.0949,3.9113,4.3944
344 5.6527,3.1039,3.924,4.4114
345 5.6612,3.1068,3.9285,4.4171
346 5.6904,3.1156,3.9442,4.4359
347 5.7139,3.1216,3.9572,4.4515
348 5.7225,3.1236,3.9622,4.4573
349 5.7516,3.1306,3.9788,4.4774
350 5.7751,3.1374,3.9905,4.4935
351 5.7837,3.1404,3.9941,4.4994
352 5.8129,3.152,4.0049,4.5189
353 5.8364,3.1614,4.0155,4.5346
354 5.8475,3.1654,4.022,4.5423
355 5.8715,3.1721,4.0385,4.5604
356 5.8976,3.1787,4.057,4.5825
357 5.9088,3.1821,4.0643,4.5919
358 5.9327,3.1914,4.0779,4.6102
359 5.9588,3.2022,4.0903,4.6253
360 5.9726,3.2072,4.096,4.6322
361 5.994,3.2132,4.1043,4.6435
362 6.0201,3.2197,4.1153,4.6601
363 6.0338,3.2239,4.122,4.6697
364 6.0552,3.2325,4.1336,4.685
365 6.0813,3.2438,4.1486,4.7029
366 6.095,3.2489,4.1564,4.7121
367 6.1164,3.2548,4.168,4.7265
368 6.1451,3.2616,4.1818,4.7465
369 6.1588,3.2657,4.1875,4.7563
370 6.1751,3.2719,4.1938,4.768
371 6.2063,3.2855,4.2069,4.7902
372 6.2201,3.2907,4.2139,4.7995
373 6.2363,3.2954,4.223,4.8095
374 6.2675,3.3028,4.2401,4.8265
375 6.2839,3.3075,4.2477,4.8351
376 6.2975,3.3126,4.2534,4.8428
377 6.3288,3.3262,4.2651,4.863
378 6.3451,3.3325,4.2713,4.8745
379 6.3587,3.3365,4.2766,4.8843
380 6.39,3.3439,4.2901,4.9067
381 6.4089,3.3493,4.2993,4.9192
382 6.42,3.3533,4.305,4.9258
383 6.4538,3.3678,4.3234,4.9438
384 6.4702,3.3743,4.3327,4.9526
385 6.4812,3.3777,4.3389,4.9591
386 6.515,3.3863,4.3567,4.9822
387 6.5314,3.391,4.3641,4.9936
388 6.5424,3.3949,4.3687,5.0006
389 6.5763,3.4086,4.3817,5.0189
390 6.5952,3.416,4.3887,5.029
391 6.6036,3.4189,4.3919,5.0339
392 6.6375,3.4283,4.4067,5.0568
393 6.6564,3.4328,4.4169,5.0699
394 6.6648,3.4349,4.4216,5.0754
395 6.6987,3.4436,4.44,5.0944
396 6.7202,3.4496,4.4495,5.1056
397 6.7261,3.4512,4.4518,5.1087
398 6.7625,3.4615,4.465,5.1294
399 6.7815,3.4663,4.4718,5.1402
400 6.7848,3.4671,4.473,5.1419
401 6.8238,3.4762,4.49,5.1622
402 6.8453,3.4831,4.5018,5.1747
403 6.846,3.4834,4.5022,5.1752
404 6.885,3.5007,4.5233,5.203
405 6.9047,3.5076,4.5316,5.2167
406 6.9065,3.5081,4.5323,5.2179
407 6.9462,3.513,4.5483,5.24
408 6.9659,3.5156,4.5586,5.25
409 6.9703,3.5166,4.5611,5.2523
410 7.0075,3.5311,4.5815,5.2722
411 7.0271,3.5399,4.5902,5.2832
412 7.0316,3.5416,4.592,5.2858
413 7.0712,3.5529,4.6066,5.3083
414 7.0858,3.5561,4.6122,5.3165
415 7.0954,3.5584,4.6161,5.3218
416 7.1325,3.5686,4.6316,5.342
417 7.147,3.5727,4.6376,5.3497
418 7.1566,3.5751,4.6415,5.3548
419 7.1937,3.5838,4.6566,5.3755
420 7.2057,3.5871,4.6615,5.383
421 7.2204,3.5919,4.6676,5.3929
422 7.255,3.607,4.6816,5.4168
423 7.2669,3.612,4.6863,5.4245
424 7.2817,3.6169,4.6921,5.4332
425 7.3188,3.6224,4.7066,5.4528
426 7.3281,3.6233,4.7104,5.4578
427 7.3455,3.6254,4.7174,5.4674
428 7.38,3.6342,4.7316,5.4863
429 7.3894,3.6371,4.7355,5.4911
430 7.4067,3.6422,4.7427,5.4989
431 7.4412,3.6507,4.7566,5.5131
432 7.4481,3.6524,4.7593,5.5161
433 7.4705,3.659,4.7681,5.5267
434 7.505,3.6731,4.7817,5.5465
435 7.5093,3.675,4.7834,5.5493
436 7.5318,3.684,4.7926,5.5653
437 7.5663,3.6938,4.8067,5.5885
438 7.5705,3.6948,4.8084,5.5908
439 7.5956,3.7007,4.8184,5.6019
440 7.6275,3.7093,4.8317,5.614
441 7.6317,3.7105,4.8336,5.6158
442 7.6568,3.7175,4.8448,5.629
443 7.6887,3.7257,4.8567,5.6481
444 7.6904,3.7262,4.8572,5.6491
445 7.7206,3.7343,4.8642,5.6655
446 7.7516,3.7436,4.8731,5.6824
447 7.7525,3.7438,4.8735,5.6829
448 7.7818,3.751,4.8884,5.7004
449 7.8103,3.7549,4.9049,5.7156
450 7.8138,3.7553,4.9067,5.7172
451 7.8457,3.7595,4.9207,5.7295
452 7.8741,3.7661,4.9314,5.7406
453 7.875,3.7663,4.9317,5.741
454 7.9095,3.7763,4.9458,5.7596
455 7.9328,3.7829,4.9548,5.7739
456 7.9388,3.7846,4.9568,5.7775
457 7.9707,3.7931,4.9654,5.7957
458 7.994,3.7991,4.9716,5.8072
459 8,3.8007,4.9735,5.8098
460 8.0345,3.8098,4.987,5.8235
461 8.0553,3.8155,4.996,5.8322
462 8.0613,3.8172,4.9985,5.835
463 8.0957,3.8266,5.0121,5.8533
464 8.1165,3.8319,5.0201,5.8654
465 8.1251,3.8341,5.0236,5.8706
466 8.1595,3.8434,5.0382,5.8906
467 8.1752,3.848,5.0445,5.8987
468 8.1863,3.8514,5.0486,5.9039
469 8.2208,3.8601,5.0585,5.9179
470 8.2364,3.8625,5.0622,5.9237
471 8.2501,3.8642,5.0653,5.9288
472 8.2846,3.8686,5.0734,5.9427
473 8.3484,3.8854,5.097,5.9812
0 -errorreport ../test/huge.xml -regression -reset
1
0 <ErrorReport>
1 <Application VersionNumber="9.0"/>
2 <Document VersionNumber="9.0" AxesPointsRequired="0">
3 <Image Height="2000" Width="4000"><![CDATA[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]]></Image>
4 <CoordSystem>
5 <General ExtraPrecision="1" CursorSize="3"/>
6 <Coords UnitsTime="2" ScaleYRadius="0" ScaleYRadiusString="Linear" TypeString="Cartesian" UnitsX="0" Type="0" UnitsY="0" UnitsRadius="0" UnitsThetaString="Degrees (DDD.DDDDD)" UnitsRadiusString="Number" ScaleXThetaString="Linear" Coords="0" UnitsDate="3" UnitsDateString="YYYY/MM/DD" ScaleXTheta="0" UnitsYString="Number" UnitsXString="Number" UnitsTheta="0" UnitsTimeString="HH:MM:SS"/>
7 <DigitizeCurve CursorInnerRadius="5" CursorLineWidth="2" CursorSize="1" CursorStandardCross="True"/>
8 <Export LayoutFunctions="0" Delimiter="0" XLabel="x" DelimiterString="Commas" PointsIntervalUnitsRelations="1" Header="1" PointsSelectionRelationsString="Interpolate" PointsSelectionFunctions="0" PointsIntervalFunctions="10" HeaderString="Simple" PointsSelectionFunctionsString="InterpolateAllCurves" LayoutFunctionsString="AllPerLine" OverrideCsvTsv="True" PointsIntervalUnitsFunctions="1" PointsSelectionRelations="0" PointsIntervalRelations="10">
9 <CurveNamesNotExported/>
10 </Export>
11 <AxesChecker Mode="1" LineColor="6" Seconds="3"/>
12 <GridDisplay StopX="1" StopY="1" Stable="False" DisableX="0" ColorString="Black" DisableY="0" CountX="2" StartX="0" StepX="1" CountY="2" StartY="0" StepY="1" Color="0"/>
13 <GridRemoval StopX="0" CoordDisableY="0" StopY="0" CloseDistance="10" CoordDisableYString="Count" CoordDisableXString="Count" Stable="False" DefinedGridLines="False" CountX="2" StartX="0" StepX="0" CountY="2" StartY="0" StepY="0" CoordDisableX="0"/>
14 <PointMatch ColorAccepted="4" ColorCandidate="7" ColorAcceptedString="Green" ColorRejectedString="Red" ColorCandidateString="Yellow" PointSize="48" ColorRejected="6"/>
15 <Segments LineColor="4" MinLength="2" LineWidth="4" FillCorners="False" LineColorString="Green" PointSeparation="25"/>
16 <Curve CurveName="Axes">
17 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
18 <CurveStyle CurveName="Axes">
19 <LineStyle ColorString="Transparent" ConnectAsString="ConnectSkipForAxisCurve" ConnectAs="4" Color="8" Width="0"/>
20 <PointStyle Radius="10" LineWidth="1" Shape="1" ShapeString="Cross" ColorString="Red" Color="6"/>
21 </CurveStyle>
22 <CurvePoints/>
23 </Curve>
24 <CurvesGraphs>
25 <Curve CurveName="Curve1">
26 <ColorFilter Mode="2" HueHigh="360" CurveName="Curve1" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
27 <CurveStyle CurveName="Curve1">
28 <LineStyle ColorString="Blue" ConnectAsString="FunctionSmooth" ConnectAs="0" Color="1" Width="1"/>
29 <PointStyle Radius="10" LineWidth="1" Shape="1" ShapeString="Cross" ColorString="Blue" Color="1"/>
30 </CurveStyle>
31 <CurvePoints/>
32 </Curve>
33 </CurvesGraphs>
34 </CoordSystem>
35 <OperatingSystem WordSize="32" Endian="LittleEndian"/>
36 <File Imported="True"/>
37 <CmdMediator>
38 <Cmd Type="CmdSettingsCurveAddRemove" Description="Curve add/remove">
39 <CurvesGraphs>
40 <Curve CurveName="Curve1">
41 <ColorFilter Mode="2" HueHigh="360" CurveName="Curve1" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
42 <CurveStyle CurveName="Curve1">
43 <LineStyle ColorString="Blue" ConnectAsString="FunctionSmooth" ConnectAs="0" Color="1" Width="1"/>
44 <PointStyle Radius="10" LineWidth="1" Shape="1" ShapeString="Cross" ColorString="Blue" Color="1"/>
45 </CurveStyle>
46 <CurvePoints/>
47 </Curve>
48 </CurvesGraphs>
49 <CurvesGraphs>
50 <Curve CurveName="red">
51 <ColorFilter Mode="2" HueHigh="360" CurveName="red" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
52 <CurveStyle CurveName="red">
53 <LineStyle ColorString="Blue" ConnectAsString="FunctionSmooth" ConnectAs="0" Color="1" Width="1"/>
54 <PointStyle Radius="10" LineWidth="1" Shape="1" ShapeString="Cross" ColorString="Blue" Color="1"/>
55 </CurveStyle>
56 <CurvePoints/>
57 </Curve>
58 <Curve CurveName="green">
59 <ColorFilter Mode="2" HueHigh="360" CurveName="green" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
60 <CurveStyle CurveName="green">
61 <LineStyle ColorString="Blue" ConnectAsString="FunctionSmooth" ConnectAs="0" Color="1" Width="1"/>
62 <PointStyle Radius="10" LineWidth="1" Shape="5" ShapeString="X" ColorString="Blue" Color="1"/>
63 </CurveStyle>
64 <CurvePoints/>
65 </Curve>
66 <Curve CurveName="blue">
67 <ColorFilter Mode="2" HueHigh="360" CurveName="blue" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
68 <CurveStyle CurveName="blue">
69 <LineStyle ColorString="Blue" ConnectAsString="FunctionSmooth" ConnectAs="0" Color="1" Width="1"/>
70 <PointStyle Radius="10" LineWidth="1" Shape="2" ShapeString="Diamond" ColorString="Blue" Color="1"/>
71 </CurveStyle>
72 <CurvePoints/>
73 </Curve>
74 </CurvesGraphs>
75 </Cmd>
76 <Cmd Type="CmdAddPointAxis" IsXOnly="False" Identifier="Axes&#x9;point&#x9;1" Description="Add axis point" ScreenX="51.6351" ScreenY="1958.13" GraphX="0" GraphY="-10" Ordinal="1"/>
77 <Cmd Type="CmdAddPointAxis" IsXOnly="False" Identifier="Axes&#x9;point&#x9;3" Description="Add axis point" ScreenX="3969.02" ScreenY="1963.05" GraphX="10" GraphY="-10" Ordinal="2"/>
78 <Cmd Type="CmdAddPointAxis" IsXOnly="False" Identifier="Axes&#x9;point&#x9;5" Description="Add axis point" ScreenX="58.5198" ScreenY="19.7044" GraphX="0" GraphY="6" Ordinal="3"/>
79 <Cmd Type="CmdSettingsColorFilter" Description="Filter settings">
80 <Filter>
81 <ColorFilter Mode="2" HueHigh="360" CurveName="red" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
82 <ColorFilter Mode="2" HueHigh="360" CurveName="blue" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
83 <ColorFilter Mode="2" HueHigh="360" CurveName="green" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
84 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
85 </Filter>
86 <Filter>
87 <ColorFilter Mode="1" HueHigh="3" CurveName="red" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="0"/>
88 <ColorFilter Mode="2" HueHigh="360" CurveName="blue" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
89 <ColorFilter Mode="2" HueHigh="360" CurveName="green" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
90 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
91 </Filter>
92 </Cmd>
93 <Cmd Type="CmdSettingsColorFilter" Description="Filter settings">
94 <Filter>
95 <ColorFilter Mode="1" HueHigh="3" CurveName="red" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="0"/>
96 <ColorFilter Mode="2" HueHigh="360" CurveName="blue" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
97 <ColorFilter Mode="2" HueHigh="360" CurveName="green" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
98 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
99 </Filter>
100 <Filter>
101 <ColorFilter Mode="1" HueHigh="3" CurveName="red" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="0"/>
102 <ColorFilter Mode="2" HueHigh="360" CurveName="blue" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
103 <ColorFilter Mode="2" HueHigh="360" CurveName="green" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
104 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
105 </Filter>
106 </Cmd>
107 <Cmd Type="CmdAddPointsGraph" CurveName="red" Description="Add graph points">
108 <Point Identifier="red&#x9;point&#x9;6" ScreenX="95" ScreenY="1350" Ordinal="1"/>
109 <Point Identifier="red&#x9;point&#x9;7" ScreenX="101" ScreenY="1326" Ordinal="1"/>
110 <Point Identifier="red&#x9;point&#x9;8" ScreenX="107" ScreenY="1301" Ordinal="1"/>
111 <Point Identifier="red&#x9;point&#x9;9" ScreenX="113" ScreenY="1277" Ordinal="1"/>
112 <Point Identifier="red&#x9;point&#x9;10" ScreenX="118" ScreenY="1253" Ordinal="1"/>
113 <Point Identifier="red&#x9;point&#x9;11" ScreenX="124" ScreenY="1228" Ordinal="1"/>
114 <Point Identifier="red&#x9;point&#x9;12" ScreenX="130" ScreenY="1204" Ordinal="1"/>
115 <Point Identifier="red&#x9;point&#x9;13" ScreenX="136" ScreenY="1180" Ordinal="1"/>
116 <Point Identifier="red&#x9;point&#x9;14" ScreenX="145" ScreenY="1157" Ordinal="1"/>
117 <Point Identifier="red&#x9;point&#x9;15" ScreenX="155" ScreenY="1134" Ordinal="1"/>
118 <Point Identifier="red&#x9;point&#x9;16" ScreenX="164" ScreenY="1110" Ordinal="1"/>
119 <Point Identifier="red&#x9;point&#x9;17" ScreenX="173" ScreenY="1087" Ordinal="1"/>
120 <Point Identifier="red&#x9;point&#x9;18" ScreenX="185" ScreenY="1065" Ordinal="1"/>
121 <Point Identifier="red&#x9;point&#x9;19" ScreenX="197" ScreenY="1043" Ordinal="1"/>
122 <Point Identifier="red&#x9;point&#x9;20" ScreenX="210" ScreenY="1022" Ordinal="1"/>
123 <Point Identifier="red&#x9;point&#x9;21" ScreenX="224" ScreenY="1001" Ordinal="1"/>
124 <Point Identifier="red&#x9;point&#x9;22" ScreenX="238" ScreenY="981" Ordinal="1"/>
125 <Point Identifier="red&#x9;point&#x9;23" ScreenX="253" ScreenY="961" Ordinal="1"/>
126 <Point Identifier="red&#x9;point&#x9;24" ScreenX="269" ScreenY="942" Ordinal="1"/>
127 <Point Identifier="red&#x9;point&#x9;25" ScreenX="286" ScreenY="923" Ordinal="1"/>
128 <Point Identifier="red&#x9;point&#x9;26" ScreenX="304" ScreenY="905" Ordinal="1"/>
129 <Point Identifier="red&#x9;point&#x9;27" ScreenX="322" ScreenY="888" Ordinal="1"/>
130 <Point Identifier="red&#x9;point&#x9;28" ScreenX="340" ScreenY="872" Ordinal="1"/>
131 <Point Identifier="red&#x9;point&#x9;29" ScreenX="359" ScreenY="856" Ordinal="1"/>
132 <Point Identifier="red&#x9;point&#x9;30" ScreenX="379" ScreenY="841" Ordinal="1"/>
133 <Point Identifier="red&#x9;point&#x9;31" ScreenX="399" ScreenY="826" Ordinal="1"/>
134 <Point Identifier="red&#x9;point&#x9;32" ScreenX="419" ScreenY="812" Ordinal="1"/>
135 <Point Identifier="red&#x9;point&#x9;33" ScreenX="440" ScreenY="798" Ordinal="1"/>
136 <Point Identifier="red&#x9;point&#x9;34" ScreenX="461" ScreenY="785" Ordinal="1"/>
137 <Point Identifier="red&#x9;point&#x9;35" ScreenX="483" ScreenY="773" Ordinal="1"/>
138 <Point Identifier="red&#x9;point&#x9;36" ScreenX="505" ScreenY="761" Ordinal="1"/>
139 <Point Identifier="red&#x9;point&#x9;37" ScreenX="527" ScreenY="749" Ordinal="1"/>
140 <Point Identifier="red&#x9;point&#x9;38" ScreenX="550" ScreenY="738" Ordinal="1"/>
141 <Point Identifier="red&#x9;point&#x9;39" ScreenX="572" ScreenY="728" Ordinal="1"/>
142 <Point Identifier="red&#x9;point&#x9;40" ScreenX="595" ScreenY="717" Ordinal="1"/>
143 <Point Identifier="red&#x9;point&#x9;41" ScreenX="618" ScreenY="707" Ordinal="1"/>
144 <Point Identifier="red&#x9;point&#x9;42" ScreenX="641" ScreenY="697" Ordinal="1"/>
145 <Point Identifier="red&#x9;point&#x9;43" ScreenX="664" ScreenY="688" Ordinal="1"/>
146 <Point Identifier="red&#x9;point&#x9;44" ScreenX="687" ScreenY="678" Ordinal="1"/>
147 <Point Identifier="red&#x9;point&#x9;45" ScreenX="710" ScreenY="670" Ordinal="1"/>
148 <Point Identifier="red&#x9;point&#x9;46" ScreenX="734" ScreenY="662" Ordinal="1"/>
149 <Point Identifier="red&#x9;point&#x9;47" ScreenX="757" ScreenY="653" Ordinal="1"/>
150 <Point Identifier="red&#x9;point&#x9;48" ScreenX="781" ScreenY="646" Ordinal="1"/>
151 <Point Identifier="red&#x9;point&#x9;49" ScreenX="805" ScreenY="638" Ordinal="1"/>
152 <Point Identifier="red&#x9;point&#x9;50" ScreenX="828" ScreenY="630" Ordinal="1"/>
153 <Point Identifier="red&#x9;point&#x9;51" ScreenX="852" ScreenY="622" Ordinal="1"/>
154 <Point Identifier="red&#x9;point&#x9;52" ScreenX="876" ScreenY="615" Ordinal="1"/>
155 <Point Identifier="red&#x9;point&#x9;53" ScreenX="898" ScreenY="608" Ordinal="1"/>
156 <Point Identifier="red&#x9;point&#x9;54" ScreenX="921" ScreenY="602" Ordinal="1"/>
157 <Point Identifier="red&#x9;point&#x9;55" ScreenX="944" ScreenY="596" Ordinal="1"/>
158 <Point Identifier="red&#x9;point&#x9;56" ScreenX="967" ScreenY="589" Ordinal="1"/>
159 <Point Identifier="red&#x9;point&#x9;57" ScreenX="991" ScreenY="583" Ordinal="1"/>
160 <Point Identifier="red&#x9;point&#x9;58" ScreenX="1014" ScreenY="577" Ordinal="1"/>
161 </Cmd>
162 <Cmd Type="CmdAddPointsGraph" CurveName="red" Description="Add graph points">
163 <Point Identifier="red&#x9;point&#x9;59" ScreenX="1212" ScreenY="532" Ordinal="53.5"/>
164 <Point Identifier="red&#x9;point&#x9;60" ScreenX="1236" ScreenY="527" Ordinal="53.5"/>
165 <Point Identifier="red&#x9;point&#x9;61" ScreenX="1260" ScreenY="522" Ordinal="53.5"/>
166 <Point Identifier="red&#x9;point&#x9;62" ScreenX="1284" ScreenY="518" Ordinal="53.5"/>
167 <Point Identifier="red&#x9;point&#x9;63" ScreenX="1307" ScreenY="513" Ordinal="53.5"/>
168 <Point Identifier="red&#x9;point&#x9;64" ScreenX="1331" ScreenY="508" Ordinal="53.5"/>
169 <Point Identifier="red&#x9;point&#x9;65" ScreenX="1355" ScreenY="504" Ordinal="53.5"/>
170 <Point Identifier="red&#x9;point&#x9;66" ScreenX="1379" ScreenY="499" Ordinal="53.5"/>
171 <Point Identifier="red&#x9;point&#x9;67" ScreenX="1403" ScreenY="494" Ordinal="53.5"/>
172 <Point Identifier="red&#x9;point&#x9;68" ScreenX="1427" ScreenY="490" Ordinal="53.5"/>
173 <Point Identifier="red&#x9;point&#x9;69" ScreenX="1451" ScreenY="486" Ordinal="53.5"/>
174 <Point Identifier="red&#x9;point&#x9;70" ScreenX="1475" ScreenY="482" Ordinal="53.5"/>
175 <Point Identifier="red&#x9;point&#x9;71" ScreenX="1499" ScreenY="478" Ordinal="53.5"/>
176 <Point Identifier="red&#x9;point&#x9;72" ScreenX="1523" ScreenY="474" Ordinal="53.5"/>
177 <Point Identifier="red&#x9;point&#x9;73" ScreenX="1547" ScreenY="470" Ordinal="53.5"/>
178 <Point Identifier="red&#x9;point&#x9;74" ScreenX="1571" ScreenY="466" Ordinal="53.5"/>
179 <Point Identifier="red&#x9;point&#x9;75" ScreenX="1595" ScreenY="462" Ordinal="53.5"/>
180 <Point Identifier="red&#x9;point&#x9;76" ScreenX="1620" ScreenY="459" Ordinal="53.5"/>
181 <Point Identifier="red&#x9;point&#x9;77" ScreenX="1644" ScreenY="455" Ordinal="53.5"/>
182 <Point Identifier="red&#x9;point&#x9;78" ScreenX="1668" ScreenY="451" Ordinal="53.5"/>
183 <Point Identifier="red&#x9;point&#x9;79" ScreenX="1692" ScreenY="448" Ordinal="53.5"/>
184 <Point Identifier="red&#x9;point&#x9;80" ScreenX="1716" ScreenY="444" Ordinal="53.5"/>
185 <Point Identifier="red&#x9;point&#x9;81" ScreenX="1740" ScreenY="440" Ordinal="53.5"/>
186 <Point Identifier="red&#x9;point&#x9;82" ScreenX="1765" ScreenY="437" Ordinal="53.5"/>
187 <Point Identifier="red&#x9;point&#x9;83" ScreenX="1789" ScreenY="434" Ordinal="53.5"/>
188 <Point Identifier="red&#x9;point&#x9;84" ScreenX="1813" ScreenY="430" Ordinal="53.5"/>
189 <Point Identifier="red&#x9;point&#x9;85" ScreenX="1837" ScreenY="427" Ordinal="53.5"/>
190 <Point Identifier="red&#x9;point&#x9;86" ScreenX="1861" ScreenY="424" Ordinal="53.5"/>
191 <Point Identifier="red&#x9;point&#x9;87" ScreenX="1886" ScreenY="421" Ordinal="53.5"/>
192 <Point Identifier="red&#x9;point&#x9;88" ScreenX="1910" ScreenY="418" Ordinal="53.5"/>
193 <Point Identifier="red&#x9;point&#x9;89" ScreenX="1934" ScreenY="414" Ordinal="53.5"/>
194 <Point Identifier="red&#x9;point&#x9;90" ScreenX="1958" ScreenY="411" Ordinal="53.5"/>
195 <Point Identifier="red&#x9;point&#x9;91" ScreenX="1983" ScreenY="408" Ordinal="53.5"/>
196 <Point Identifier="red&#x9;point&#x9;92" ScreenX="2007" ScreenY="405" Ordinal="53.5"/>
197 <Point Identifier="red&#x9;point&#x9;93" ScreenX="2031" ScreenY="402" Ordinal="53.5"/>
198 <Point Identifier="red&#x9;point&#x9;94" ScreenX="2056" ScreenY="399" Ordinal="53.5"/>
199 <Point Identifier="red&#x9;point&#x9;95" ScreenX="2080" ScreenY="396" Ordinal="53.5"/>
200 <Point Identifier="red&#x9;point&#x9;96" ScreenX="2104" ScreenY="393" Ordinal="53.5"/>
201 <Point Identifier="red&#x9;point&#x9;97" ScreenX="2128" ScreenY="390" Ordinal="53.5"/>
202 <Point Identifier="red&#x9;point&#x9;98" ScreenX="2153" ScreenY="388" Ordinal="53.5"/>
203 <Point Identifier="red&#x9;point&#x9;99" ScreenX="2177" ScreenY="385" Ordinal="53.5"/>
204 <Point Identifier="red&#x9;point&#x9;100" ScreenX="2202" ScreenY="382" Ordinal="53.5"/>
205 <Point Identifier="red&#x9;point&#x9;101" ScreenX="2226" ScreenY="379" Ordinal="53.5"/>
206 <Point Identifier="red&#x9;point&#x9;102" ScreenX="2250" ScreenY="376" Ordinal="53.5"/>
207 <Point Identifier="red&#x9;point&#x9;103" ScreenX="2275" ScreenY="373" Ordinal="53.5"/>
208 <Point Identifier="red&#x9;point&#x9;104" ScreenX="2299" ScreenY="371" Ordinal="53.5"/>
209 <Point Identifier="red&#x9;point&#x9;105" ScreenX="2323" ScreenY="369" Ordinal="53.5"/>
210 <Point Identifier="red&#x9;point&#x9;106" ScreenX="2348" ScreenY="366" Ordinal="53.5"/>
211 <Point Identifier="red&#x9;point&#x9;107" ScreenX="2372" ScreenY="364" Ordinal="53.5"/>
212 <Point Identifier="red&#x9;point&#x9;108" ScreenX="2397" ScreenY="361" Ordinal="53.5"/>
213 <Point Identifier="red&#x9;point&#x9;109" ScreenX="2421" ScreenY="359" Ordinal="53.5"/>
214 <Point Identifier="red&#x9;point&#x9;110" ScreenX="2445" ScreenY="356" Ordinal="53.5"/>
215 <Point Identifier="red&#x9;point&#x9;111" ScreenX="2470" ScreenY="354" Ordinal="53.5"/>
216 <Point Identifier="red&#x9;point&#x9;112" ScreenX="2494" ScreenY="351" Ordinal="53.5"/>
217 <Point Identifier="red&#x9;point&#x9;113" ScreenX="2519" ScreenY="349" Ordinal="53.5"/>
218 <Point Identifier="red&#x9;point&#x9;114" ScreenX="2543" ScreenY="346" Ordinal="53.5"/>
219 <Point Identifier="red&#x9;point&#x9;115" ScreenX="2568" ScreenY="344" Ordinal="53.5"/>
220 <Point Identifier="red&#x9;point&#x9;116" ScreenX="2592" ScreenY="341" Ordinal="53.5"/>
221 <Point Identifier="red&#x9;point&#x9;117" ScreenX="2616" ScreenY="339" Ordinal="53.5"/>
222 <Point Identifier="red&#x9;point&#x9;118" ScreenX="2641" ScreenY="336" Ordinal="53.5"/>
223 <Point Identifier="red&#x9;point&#x9;119" ScreenX="2665" ScreenY="334" Ordinal="53.5"/>
224 <Point Identifier="red&#x9;point&#x9;120" ScreenX="2690" ScreenY="332" Ordinal="53.5"/>
225 <Point Identifier="red&#x9;point&#x9;121" ScreenX="2714" ScreenY="330" Ordinal="53.5"/>
226 <Point Identifier="red&#x9;point&#x9;122" ScreenX="2739" ScreenY="328" Ordinal="53.5"/>
227 <Point Identifier="red&#x9;point&#x9;123" ScreenX="2763" ScreenY="325" Ordinal="53.5"/>
228 <Point Identifier="red&#x9;point&#x9;124" ScreenX="2788" ScreenY="324" Ordinal="53.5"/>
229 <Point Identifier="red&#x9;point&#x9;125" ScreenX="2812" ScreenY="321" Ordinal="53.5"/>
230 <Point Identifier="red&#x9;point&#x9;126" ScreenX="2837" ScreenY="319" Ordinal="53.5"/>
231 <Point Identifier="red&#x9;point&#x9;127" ScreenX="2861" ScreenY="317" Ordinal="53.5"/>
232 <Point Identifier="red&#x9;point&#x9;128" ScreenX="2886" ScreenY="315" Ordinal="53.5"/>
233 <Point Identifier="red&#x9;point&#x9;129" ScreenX="2910" ScreenY="312" Ordinal="53.5"/>
234 <Point Identifier="red&#x9;point&#x9;130" ScreenX="2935" ScreenY="311" Ordinal="53.5"/>
235 <Point Identifier="red&#x9;point&#x9;131" ScreenX="2959" ScreenY="309" Ordinal="53.5"/>
236 <Point Identifier="red&#x9;point&#x9;132" ScreenX="2984" ScreenY="307" Ordinal="53.5"/>
237 <Point Identifier="red&#x9;point&#x9;133" ScreenX="3008" ScreenY="304" Ordinal="53.5"/>
238 <Point Identifier="red&#x9;point&#x9;134" ScreenX="3033" ScreenY="302" Ordinal="53.5"/>
239 <Point Identifier="red&#x9;point&#x9;135" ScreenX="3057" ScreenY="300" Ordinal="53.5"/>
240 <Point Identifier="red&#x9;point&#x9;136" ScreenX="3082" ScreenY="298" Ordinal="53.5"/>
241 <Point Identifier="red&#x9;point&#x9;137" ScreenX="3106" ScreenY="296" Ordinal="53.5"/>
242 <Point Identifier="red&#x9;point&#x9;138" ScreenX="3131" ScreenY="295" Ordinal="53.5"/>
243 <Point Identifier="red&#x9;point&#x9;139" ScreenX="3156" ScreenY="293" Ordinal="53.5"/>
244 <Point Identifier="red&#x9;point&#x9;140" ScreenX="3180" ScreenY="291" Ordinal="53.5"/>
245 <Point Identifier="red&#x9;point&#x9;141" ScreenX="3205" ScreenY="289" Ordinal="53.5"/>
246 <Point Identifier="red&#x9;point&#x9;142" ScreenX="3229" ScreenY="287" Ordinal="53.5"/>
247 <Point Identifier="red&#x9;point&#x9;143" ScreenX="3254" ScreenY="285" Ordinal="53.5"/>
248 <Point Identifier="red&#x9;point&#x9;144" ScreenX="3278" ScreenY="283" Ordinal="53.5"/>
249 <Point Identifier="red&#x9;point&#x9;145" ScreenX="3303" ScreenY="282" Ordinal="53.5"/>
250 <Point Identifier="red&#x9;point&#x9;146" ScreenX="3328" ScreenY="280" Ordinal="53.5"/>
251 </Cmd>
252 <Cmd Type="CmdAddPointsGraph" CurveName="red" Description="Add graph points">
253 <Point Identifier="red&#x9;point&#x9;173" ScreenX="1033" ScreenY="573" Ordinal="53.5"/>
254 <Point Identifier="red&#x9;point&#x9;174" ScreenX="1057" ScreenY="566" Ordinal="53.5"/>
255 <Point Identifier="red&#x9;point&#x9;175" ScreenX="1081" ScreenY="560" Ordinal="53.5"/>
256 <Point Identifier="red&#x9;point&#x9;176" ScreenX="1105" ScreenY="555" Ordinal="53.5"/>
257 <Point Identifier="red&#x9;point&#x9;177" ScreenX="1129" ScreenY="550" Ordinal="53.5"/>
258 <Point Identifier="red&#x9;point&#x9;178" ScreenX="1153" ScreenY="544" Ordinal="53.5"/>
259 <Point Identifier="red&#x9;point&#x9;179" ScreenX="1176" ScreenY="539" Ordinal="53.5"/>
260 <Point Identifier="red&#x9;point&#x9;180" ScreenX="1199" ScreenY="534" Ordinal="53.5"/>
261 </Cmd>
262 <Cmd Type="CmdSettingsColorFilter" Description="Filter settings">
263 <Filter>
264 <ColorFilter Mode="1" HueHigh="3" CurveName="red" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="0"/>
265 <ColorFilter Mode="2" HueHigh="360" CurveName="blue" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
266 <ColorFilter Mode="2" HueHigh="360" CurveName="green" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
267 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
268 </Filter>
269 <Filter>
270 <ColorFilter Mode="1" HueHigh="3" CurveName="red" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="0"/>
271 <ColorFilter Mode="2" HueHigh="360" CurveName="blue" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
272 <ColorFilter Mode="1" HueHigh="122" CurveName="green" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="115"/>
273 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
274 </Filter>
275 </Cmd>
276 <Cmd Type="CmdAddPointsGraph" CurveName="green" Description="Add graph points">
277 <Point Identifier="green&#x9;point&#x9;181" ScreenX="95" ScreenY="1737" Ordinal="1"/>
278 <Point Identifier="green&#x9;point&#x9;182" ScreenX="100" ScreenY="1712" Ordinal="1"/>
279 <Point Identifier="green&#x9;point&#x9;183" ScreenX="103" ScreenY="1688" Ordinal="1"/>
280 <Point Identifier="green&#x9;point&#x9;184" ScreenX="107" ScreenY="1663" Ordinal="1"/>
281 <Point Identifier="green&#x9;point&#x9;185" ScreenX="111" ScreenY="1638" Ordinal="1"/>
282 <Point Identifier="green&#x9;point&#x9;186" ScreenX="115" ScreenY="1614" Ordinal="1"/>
283 <Point Identifier="green&#x9;point&#x9;187" ScreenX="119" ScreenY="1589" Ordinal="1"/>
284 <Point Identifier="green&#x9;point&#x9;188" ScreenX="123" ScreenY="1564" Ordinal="1"/>
285 <Point Identifier="green&#x9;point&#x9;189" ScreenX="127" ScreenY="1540" Ordinal="1"/>
286 <Point Identifier="green&#x9;point&#x9;190" ScreenX="130" ScreenY="1515" Ordinal="1"/>
287 <Point Identifier="green&#x9;point&#x9;191" ScreenX="134" ScreenY="1490" Ordinal="1"/>
288 <Point Identifier="green&#x9;point&#x9;192" ScreenX="140" ScreenY="1466" Ordinal="1"/>
289 <Point Identifier="green&#x9;point&#x9;193" ScreenX="147" ScreenY="1442" Ordinal="1"/>
290 <Point Identifier="green&#x9;point&#x9;194" ScreenX="153" ScreenY="1418" Ordinal="1"/>
291 <Point Identifier="green&#x9;point&#x9;195" ScreenX="160" ScreenY="1393" Ordinal="1"/>
292 <Point Identifier="green&#x9;point&#x9;196" ScreenX="167" ScreenY="1369" Ordinal="1"/>
293 <Point Identifier="green&#x9;point&#x9;197" ScreenX="173" ScreenY="1345" Ordinal="1"/>
294 <Point Identifier="green&#x9;point&#x9;198" ScreenX="181" ScreenY="1322" Ordinal="1"/>
295 <Point Identifier="green&#x9;point&#x9;199" ScreenX="190" ScreenY="1298" Ordinal="1"/>
296 <Point Identifier="green&#x9;point&#x9;200" ScreenX="199" ScreenY="1275" Ordinal="1"/>
297 <Point Identifier="green&#x9;point&#x9;201" ScreenX="208" ScreenY="1251" Ordinal="1"/>
298 <Point Identifier="green&#x9;point&#x9;202" ScreenX="216" ScreenY="1228" Ordinal="1"/>
299 <Point Identifier="green&#x9;point&#x9;203" ScreenX="228" ScreenY="1206" Ordinal="1"/>
300 <Point Identifier="green&#x9;point&#x9;204" ScreenX="239" ScreenY="1183" Ordinal="1"/>
301 <Point Identifier="green&#x9;point&#x9;205" ScreenX="250" ScreenY="1161" Ordinal="1"/>
302 <Point Identifier="green&#x9;point&#x9;206" ScreenX="262" ScreenY="1139" Ordinal="1"/>
303 <Point Identifier="green&#x9;point&#x9;207" ScreenX="275" ScreenY="1117" Ordinal="1"/>
304 <Point Identifier="green&#x9;point&#x9;208" ScreenX="287" ScreenY="1096" Ordinal="1"/>
305 <Point Identifier="green&#x9;point&#x9;209" ScreenX="301" ScreenY="1075" Ordinal="1"/>
306 <Point Identifier="green&#x9;point&#x9;210" ScreenX="316" ScreenY="1055" Ordinal="1"/>
307 <Point Identifier="green&#x9;point&#x9;211" ScreenX="330" ScreenY="1034" Ordinal="1"/>
308 <Point Identifier="green&#x9;point&#x9;212" ScreenX="346" ScreenY="1015" Ordinal="1"/>
309 <Point Identifier="green&#x9;point&#x9;213" ScreenX="361" ScreenY="995" Ordinal="1"/>
310 <Point Identifier="green&#x9;point&#x9;214" ScreenX="378" ScreenY="976" Ordinal="1"/>
311 <Point Identifier="green&#x9;point&#x9;215" ScreenX="394" ScreenY="958" Ordinal="1"/>
312 <Point Identifier="green&#x9;point&#x9;216" ScreenX="411" ScreenY="940" Ordinal="1"/>
313 <Point Identifier="green&#x9;point&#x9;217" ScreenX="429" ScreenY="922" Ordinal="1"/>
314 <Point Identifier="green&#x9;point&#x9;218" ScreenX="447" ScreenY="904" Ordinal="1"/>
315 <Point Identifier="green&#x9;point&#x9;219" ScreenX="465" ScreenY="888" Ordinal="1"/>
316 <Point Identifier="green&#x9;point&#x9;220" ScreenX="484" ScreenY="872" Ordinal="1"/>
317 <Point Identifier="green&#x9;point&#x9;221" ScreenX="503" ScreenY="856" Ordinal="1"/>
318 <Point Identifier="green&#x9;point&#x9;222" ScreenX="522" ScreenY="841" Ordinal="1"/>
319 <Point Identifier="green&#x9;point&#x9;223" ScreenX="542" ScreenY="825" Ordinal="1"/>
320 <Point Identifier="green&#x9;point&#x9;224" ScreenX="562" ScreenY="811" Ordinal="1"/>
321 <Point Identifier="green&#x9;point&#x9;225" ScreenX="582" ScreenY="796" Ordinal="1"/>
322 <Point Identifier="green&#x9;point&#x9;226" ScreenX="603" ScreenY="782" Ordinal="1"/>
323 <Point Identifier="green&#x9;point&#x9;227" ScreenX="624" ScreenY="769" Ordinal="1"/>
324 <Point Identifier="green&#x9;point&#x9;228" ScreenX="645" ScreenY="756" Ordinal="1"/>
325 <Point Identifier="green&#x9;point&#x9;229" ScreenX="666" ScreenY="743" Ordinal="1"/>
326 <Point Identifier="green&#x9;point&#x9;230" ScreenX="688" ScreenY="730" Ordinal="1"/>
327 <Point Identifier="green&#x9;point&#x9;231" ScreenX="710" ScreenY="718" Ordinal="1"/>
328 <Point Identifier="green&#x9;point&#x9;232" ScreenX="732" ScreenY="706" Ordinal="1"/>
329 <Point Identifier="green&#x9;point&#x9;233" ScreenX="754" ScreenY="695" Ordinal="1"/>
330 <Point Identifier="green&#x9;point&#x9;234" ScreenX="776" ScreenY="683" Ordinal="1"/>
331 <Point Identifier="green&#x9;point&#x9;235" ScreenX="799" ScreenY="672" Ordinal="1"/>
332 <Point Identifier="green&#x9;point&#x9;236" ScreenX="821" ScreenY="661" Ordinal="1"/>
333 <Point Identifier="green&#x9;point&#x9;237" ScreenX="844" ScreenY="650" Ordinal="1"/>
334 <Point Identifier="green&#x9;point&#x9;238" ScreenX="866" ScreenY="640" Ordinal="1"/>
335 <Point Identifier="green&#x9;point&#x9;239" ScreenX="889" ScreenY="629" Ordinal="1"/>
336 <Point Identifier="green&#x9;point&#x9;240" ScreenX="912" ScreenY="620" Ordinal="1"/>
337 <Point Identifier="green&#x9;point&#x9;241" ScreenX="935" ScreenY="610" Ordinal="1"/>
338 <Point Identifier="green&#x9;point&#x9;242" ScreenX="958" ScreenY="600" Ordinal="1"/>
339 <Point Identifier="green&#x9;point&#x9;243" ScreenX="982" ScreenY="592" Ordinal="1"/>
340 <Point Identifier="green&#x9;point&#x9;244" ScreenX="1005" ScreenY="583" Ordinal="1"/>
341 <Point Identifier="green&#x9;point&#x9;245" ScreenX="1028" ScreenY="574" Ordinal="1"/>
342 <Point Identifier="green&#x9;point&#x9;246" ScreenX="1051" ScreenY="565" Ordinal="1"/>
343 <Point Identifier="green&#x9;point&#x9;247" ScreenX="1075" ScreenY="557" Ordinal="1"/>
344 <Point Identifier="green&#x9;point&#x9;248" ScreenX="1098" ScreenY="549" Ordinal="1"/>
345 <Point Identifier="green&#x9;point&#x9;249" ScreenX="1122" ScreenY="540" Ordinal="1"/>
346 <Point Identifier="green&#x9;point&#x9;250" ScreenX="1145" ScreenY="533" Ordinal="1"/>
347 <Point Identifier="green&#x9;point&#x9;251" ScreenX="1169" ScreenY="525" Ordinal="1"/>
348 <Point Identifier="green&#x9;point&#x9;252" ScreenX="1192" ScreenY="517" Ordinal="1"/>
349 <Point Identifier="green&#x9;point&#x9;253" ScreenX="1216" ScreenY="510" Ordinal="1"/>
350 <Point Identifier="green&#x9;point&#x9;254" ScreenX="1239" ScreenY="503" Ordinal="1"/>
351 <Point Identifier="green&#x9;point&#x9;255" ScreenX="1262" ScreenY="496" Ordinal="1"/>
352 <Point Identifier="green&#x9;point&#x9;256" ScreenX="1285" ScreenY="489" Ordinal="1"/>
353 <Point Identifier="green&#x9;point&#x9;257" ScreenX="1308" ScreenY="482" Ordinal="1"/>
354 <Point Identifier="green&#x9;point&#x9;258" ScreenX="1331" ScreenY="475" Ordinal="1"/>
355 <Point Identifier="green&#x9;point&#x9;259" ScreenX="1353" ScreenY="469" Ordinal="1"/>
356 <Point Identifier="green&#x9;point&#x9;260" ScreenX="1376" ScreenY="462" Ordinal="1"/>
357 <Point Identifier="green&#x9;point&#x9;261" ScreenX="1399" ScreenY="456" Ordinal="1"/>
358 </Cmd>
359 <Cmd Type="CmdAddPointsGraph" CurveName="green" Description="Add graph points">
360 <Point Identifier="green&#x9;point&#x9;262" ScreenX="1436" ScreenY="446" Ordinal="81.5"/>
361 <Point Identifier="green&#x9;point&#x9;263" ScreenX="1460" ScreenY="440" Ordinal="81.5"/>
362 <Point Identifier="green&#x9;point&#x9;264" ScreenX="1484" ScreenY="434" Ordinal="81.5"/>
363 <Point Identifier="green&#x9;point&#x9;265" ScreenX="1508" ScreenY="428" Ordinal="81.5"/>
364 <Point Identifier="green&#x9;point&#x9;266" ScreenX="1532" ScreenY="422" Ordinal="81.5"/>
365 <Point Identifier="green&#x9;point&#x9;267" ScreenX="1555" ScreenY="416" Ordinal="81.5"/>
366 <Point Identifier="green&#x9;point&#x9;268" ScreenX="1579" ScreenY="410" Ordinal="81.5"/>
367 <Point Identifier="green&#x9;point&#x9;269" ScreenX="1603" ScreenY="405" Ordinal="81.5"/>
368 <Point Identifier="green&#x9;point&#x9;270" ScreenX="1626" ScreenY="399" Ordinal="81.5"/>
369 <Point Identifier="green&#x9;point&#x9;271" ScreenX="1650" ScreenY="394" Ordinal="81.5"/>
370 <Point Identifier="green&#x9;point&#x9;272" ScreenX="1674" ScreenY="389" Ordinal="81.5"/>
371 <Point Identifier="green&#x9;point&#x9;273" ScreenX="1698" ScreenY="383" Ordinal="81.5"/>
372 <Point Identifier="green&#x9;point&#x9;274" ScreenX="1721" ScreenY="378" Ordinal="81.5"/>
373 <Point Identifier="green&#x9;point&#x9;275" ScreenX="1745" ScreenY="373" Ordinal="81.5"/>
374 <Point Identifier="green&#x9;point&#x9;276" ScreenX="1769" ScreenY="368" Ordinal="81.5"/>
375 <Point Identifier="green&#x9;point&#x9;277" ScreenX="1793" ScreenY="363" Ordinal="81.5"/>
376 <Point Identifier="green&#x9;point&#x9;278" ScreenX="1817" ScreenY="358" Ordinal="81.5"/>
377 <Point Identifier="green&#x9;point&#x9;279" ScreenX="1841" ScreenY="353" Ordinal="81.5"/>
378 <Point Identifier="green&#x9;point&#x9;280" ScreenX="1864" ScreenY="348" Ordinal="81.5"/>
379 <Point Identifier="green&#x9;point&#x9;281" ScreenX="1888" ScreenY="343" Ordinal="81.5"/>
380 <Point Identifier="green&#x9;point&#x9;282" ScreenX="1912" ScreenY="338" Ordinal="81.5"/>
381 <Point Identifier="green&#x9;point&#x9;283" ScreenX="1936" ScreenY="334" Ordinal="81.5"/>
382 <Point Identifier="green&#x9;point&#x9;284" ScreenX="1960" ScreenY="330" Ordinal="81.5"/>
383 <Point Identifier="green&#x9;point&#x9;285" ScreenX="1984" ScreenY="325" Ordinal="81.5"/>
384 <Point Identifier="green&#x9;point&#x9;286" ScreenX="2008" ScreenY="320" Ordinal="81.5"/>
385 <Point Identifier="green&#x9;point&#x9;287" ScreenX="2032" ScreenY="316" Ordinal="81.5"/>
386 <Point Identifier="green&#x9;point&#x9;288" ScreenX="2056" ScreenY="311" Ordinal="81.5"/>
387 <Point Identifier="green&#x9;point&#x9;289" ScreenX="2080" ScreenY="307" Ordinal="81.5"/>
388 <Point Identifier="green&#x9;point&#x9;290" ScreenX="2104" ScreenY="302" Ordinal="81.5"/>
389 <Point Identifier="green&#x9;point&#x9;291" ScreenX="2128" ScreenY="298" Ordinal="81.5"/>
390 <Point Identifier="green&#x9;point&#x9;292" ScreenX="2152" ScreenY="294" Ordinal="81.5"/>
391 <Point Identifier="green&#x9;point&#x9;293" ScreenX="2176" ScreenY="290" Ordinal="81.5"/>
392 <Point Identifier="green&#x9;point&#x9;294" ScreenX="2200" ScreenY="286" Ordinal="81.5"/>
393 <Point Identifier="green&#x9;point&#x9;295" ScreenX="2224" ScreenY="282" Ordinal="81.5"/>
394 <Point Identifier="green&#x9;point&#x9;296" ScreenX="2248" ScreenY="278" Ordinal="81.5"/>
395 <Point Identifier="green&#x9;point&#x9;297" ScreenX="2272" ScreenY="274" Ordinal="81.5"/>
396 <Point Identifier="green&#x9;point&#x9;298" ScreenX="2296" ScreenY="270" Ordinal="81.5"/>
397 <Point Identifier="green&#x9;point&#x9;299" ScreenX="2320" ScreenY="266" Ordinal="81.5"/>
398 <Point Identifier="green&#x9;point&#x9;300" ScreenX="2344" ScreenY="263" Ordinal="81.5"/>
399 <Point Identifier="green&#x9;point&#x9;301" ScreenX="2368" ScreenY="258" Ordinal="81.5"/>
400 <Point Identifier="green&#x9;point&#x9;302" ScreenX="2392" ScreenY="254" Ordinal="81.5"/>
401 <Point Identifier="green&#x9;point&#x9;303" ScreenX="2416" ScreenY="251" Ordinal="81.5"/>
402 <Point Identifier="green&#x9;point&#x9;304" ScreenX="2440" ScreenY="247" Ordinal="81.5"/>
403 <Point Identifier="green&#x9;point&#x9;305" ScreenX="2465" ScreenY="243" Ordinal="81.5"/>
404 <Point Identifier="green&#x9;point&#x9;306" ScreenX="2489" ScreenY="240" Ordinal="81.5"/>
405 <Point Identifier="green&#x9;point&#x9;307" ScreenX="2513" ScreenY="236" Ordinal="81.5"/>
406 <Point Identifier="green&#x9;point&#x9;308" ScreenX="2537" ScreenY="233" Ordinal="81.5"/>
407 <Point Identifier="green&#x9;point&#x9;309" ScreenX="2561" ScreenY="230" Ordinal="81.5"/>
408 <Point Identifier="green&#x9;point&#x9;310" ScreenX="2586" ScreenY="226" Ordinal="81.5"/>
409 <Point Identifier="green&#x9;point&#x9;311" ScreenX="2610" ScreenY="222" Ordinal="81.5"/>
410 <Point Identifier="green&#x9;point&#x9;312" ScreenX="2634" ScreenY="219" Ordinal="81.5"/>
411 <Point Identifier="green&#x9;point&#x9;313" ScreenX="2658" ScreenY="216" Ordinal="81.5"/>
412 <Point Identifier="green&#x9;point&#x9;314" ScreenX="2682" ScreenY="212" Ordinal="81.5"/>
413 <Point Identifier="green&#x9;point&#x9;315" ScreenX="2707" ScreenY="209" Ordinal="81.5"/>
414 <Point Identifier="green&#x9;point&#x9;316" ScreenX="2731" ScreenY="206" Ordinal="81.5"/>
415 <Point Identifier="green&#x9;point&#x9;317" ScreenX="2755" ScreenY="202" Ordinal="81.5"/>
416 <Point Identifier="green&#x9;point&#x9;318" ScreenX="2779" ScreenY="199" Ordinal="81.5"/>
417 <Point Identifier="green&#x9;point&#x9;319" ScreenX="2803" ScreenY="195" Ordinal="81.5"/>
418 <Point Identifier="green&#x9;point&#x9;320" ScreenX="2828" ScreenY="192" Ordinal="81.5"/>
419 <Point Identifier="green&#x9;point&#x9;321" ScreenX="2852" ScreenY="189" Ordinal="81.5"/>
420 <Point Identifier="green&#x9;point&#x9;322" ScreenX="2876" ScreenY="186" Ordinal="81.5"/>
421 <Point Identifier="green&#x9;point&#x9;323" ScreenX="2900" ScreenY="183" Ordinal="81.5"/>
422 <Point Identifier="green&#x9;point&#x9;324" ScreenX="2925" ScreenY="180" Ordinal="81.5"/>
423 <Point Identifier="green&#x9;point&#x9;325" ScreenX="2949" ScreenY="177" Ordinal="81.5"/>
424 <Point Identifier="green&#x9;point&#x9;326" ScreenX="2973" ScreenY="174" Ordinal="81.5"/>
425 <Point Identifier="green&#x9;point&#x9;327" ScreenX="2998" ScreenY="171" Ordinal="81.5"/>
426 <Point Identifier="green&#x9;point&#x9;328" ScreenX="3022" ScreenY="168" Ordinal="81.5"/>
427 <Point Identifier="green&#x9;point&#x9;329" ScreenX="3046" ScreenY="165" Ordinal="81.5"/>
428 <Point Identifier="green&#x9;point&#x9;330" ScreenX="3070" ScreenY="162" Ordinal="81.5"/>
429 <Point Identifier="green&#x9;point&#x9;331" ScreenX="3095" ScreenY="160" Ordinal="81.5"/>
430 <Point Identifier="green&#x9;point&#x9;332" ScreenX="3119" ScreenY="156" Ordinal="81.5"/>
431 <Point Identifier="green&#x9;point&#x9;333" ScreenX="3143" ScreenY="153" Ordinal="81.5"/>
432 <Point Identifier="green&#x9;point&#x9;334" ScreenX="3168" ScreenY="150" Ordinal="81.5"/>
433 <Point Identifier="green&#x9;point&#x9;335" ScreenX="3192" ScreenY="148" Ordinal="81.5"/>
434 <Point Identifier="green&#x9;point&#x9;336" ScreenX="3216" ScreenY="145" Ordinal="81.5"/>
435 <Point Identifier="green&#x9;point&#x9;337" ScreenX="3241" ScreenY="142" Ordinal="81.5"/>
436 <Point Identifier="green&#x9;point&#x9;338" ScreenX="3265" ScreenY="139" Ordinal="81.5"/>
437 <Point Identifier="green&#x9;point&#x9;339" ScreenX="3290" ScreenY="137" Ordinal="81.5"/>
438 </Cmd>
439 <Cmd Type="CmdSettingsColorFilter" Description="Filter settings">
440 <Filter>
441 <ColorFilter Mode="1" HueHigh="3" CurveName="red" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="0"/>
442 <ColorFilter Mode="2" HueHigh="360" CurveName="blue" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
443 <ColorFilter Mode="1" HueHigh="122" CurveName="green" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="115"/>
444 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
445 </Filter>
446 <Filter>
447 <ColorFilter Mode="1" HueHigh="3" CurveName="red" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="0"/>
448 <ColorFilter Mode="1" HueHigh="241" CurveName="blue" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="233"/>
449 <ColorFilter Mode="1" HueHigh="122" CurveName="green" ModeString="Hue" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="115"/>
450 <ColorFilter Mode="2" HueHigh="360" CurveName="Axes" ModeString="Intensity" IntensityLow="0" ForegroundHigh="10" SaturationLow="50" ValueHigh="50" ForegroundLow="0" SaturationHigh="100" ValueLow="0" IntensityHigh="50" HueLow="180"/>
451 </Filter>
452 </Cmd>
453 <Cmd Type="CmdAddPointsGraph" CurveName="blue" Description="Add graph points">
454 <Point Identifier="blue&#x9;point&#x9;368" ScreenX="119" ScreenY="1958" Ordinal="1"/>
455 <Point Identifier="blue&#x9;point&#x9;369" ScreenX="123" ScreenY="1933" Ordinal="1"/>
456 <Point Identifier="blue&#x9;point&#x9;370" ScreenX="126" ScreenY="1908" Ordinal="1"/>
457 <Point Identifier="blue&#x9;point&#x9;371" ScreenX="129" ScreenY="1884" Ordinal="1"/>
458 <Point Identifier="blue&#x9;point&#x9;372" ScreenX="132" ScreenY="1859" Ordinal="1"/>
459 <Point Identifier="blue&#x9;point&#x9;373" ScreenX="135" ScreenY="1834" Ordinal="1"/>
460 <Point Identifier="blue&#x9;point&#x9;374" ScreenX="139" ScreenY="1809" Ordinal="1"/>
461 <Point Identifier="blue&#x9;point&#x9;375" ScreenX="144" ScreenY="1785" Ordinal="1"/>
462 <Point Identifier="blue&#x9;point&#x9;376" ScreenX="149" ScreenY="1760" Ordinal="1"/>
463 <Point Identifier="blue&#x9;point&#x9;377" ScreenX="154" ScreenY="1736" Ordinal="1"/>
464 <Point Identifier="blue&#x9;point&#x9;378" ScreenX="159" ScreenY="1711" Ordinal="1"/>
465 <Point Identifier="blue&#x9;point&#x9;379" ScreenX="164" ScreenY="1687" Ordinal="1"/>
466 <Point Identifier="blue&#x9;point&#x9;380" ScreenX="169" ScreenY="1662" Ordinal="1"/>
467 <Point Identifier="blue&#x9;point&#x9;381" ScreenX="174" ScreenY="1638" Ordinal="1"/>
468 <Point Identifier="blue&#x9;point&#x9;382" ScreenX="181" ScreenY="1614" Ordinal="1"/>
469 <Point Identifier="blue&#x9;point&#x9;383" ScreenX="187" ScreenY="1590" Ordinal="1"/>
470 <Point Identifier="blue&#x9;point&#x9;384" ScreenX="194" ScreenY="1566" Ordinal="1"/>
471 <Point Identifier="blue&#x9;point&#x9;385" ScreenX="201" ScreenY="1542" Ordinal="1"/>
472 <Point Identifier="blue&#x9;point&#x9;386" ScreenX="208" ScreenY="1518" Ordinal="1"/>
473 <Point Identifier="blue&#x9;point&#x9;387" ScreenX="215" ScreenY="1494" Ordinal="1"/>
474 <Point Identifier="blue&#x9;point&#x9;388" ScreenX="223" ScreenY="1470" Ordinal="1"/>
475 <Point Identifier="blue&#x9;point&#x9;389" ScreenX="232" ScreenY="1447" Ordinal="1"/>
476 <Point Identifier="blue&#x9;point&#x9;390" ScreenX="241" ScreenY="1423" Ordinal="1"/>
477 <Point Identifier="blue&#x9;point&#x9;391" ScreenX="249" ScreenY="1400" Ordinal="1"/>
478 <Point Identifier="blue&#x9;point&#x9;392" ScreenX="258" ScreenY="1376" Ordinal="1"/>
479 <Point Identifier="blue&#x9;point&#x9;393" ScreenX="269" ScreenY="1354" Ordinal="1"/>
480 <Point Identifier="blue&#x9;point&#x9;394" ScreenX="279" ScreenY="1331" Ordinal="1"/>
481 <Point Identifier="blue&#x9;point&#x9;395" ScreenX="289" ScreenY="1308" Ordinal="1"/>
482 <Point Identifier="blue&#x9;point&#x9;396" ScreenX="300" ScreenY="1286" Ordinal="1"/>
483 <Point Identifier="blue&#x9;point&#x9;397" ScreenX="312" ScreenY="1264" Ordinal="1"/>
484 <Point Identifier="blue&#x9;point&#x9;398" ScreenX="324" ScreenY="1241" Ordinal="1"/>
485 <Point Identifier="blue&#x9;point&#x9;399" ScreenX="336" ScreenY="1219" Ordinal="1"/>
486 <Point Identifier="blue&#x9;point&#x9;400" ScreenX="348" ScreenY="1198" Ordinal="1"/>
487 <Point Identifier="blue&#x9;point&#x9;401" ScreenX="361" ScreenY="1177" Ordinal="1"/>
488 <Point Identifier="blue&#x9;point&#x9;402" ScreenX="374" ScreenY="1155" Ordinal="1"/>
489 <Point Identifier="blue&#x9;point&#x9;403" ScreenX="389" ScreenY="1135" Ordinal="1"/>
490 <Point Identifier="blue&#x9;point&#x9;404" ScreenX="403" ScreenY="1115" Ordinal="1"/>
491 <Point Identifier="blue&#x9;point&#x9;405" ScreenX="418" ScreenY="1094" Ordinal="1"/>
492 <Point Identifier="blue&#x9;point&#x9;406" ScreenX="433" ScreenY="1075" Ordinal="1"/>
493 <Point Identifier="blue&#x9;point&#x9;407" ScreenX="448" ScreenY="1055" Ordinal="1"/>
494 <Point Identifier="blue&#x9;point&#x9;408" ScreenX="465" ScreenY="1036" Ordinal="1"/>
495 <Point Identifier="blue&#x9;point&#x9;409" ScreenX="481" ScreenY="1017" Ordinal="1"/>
496 <Point Identifier="blue&#x9;point&#x9;410" ScreenX="498" ScreenY="998" Ordinal="1"/>
497 <Point Identifier="blue&#x9;point&#x9;411" ScreenX="514" ScreenY="980" Ordinal="1"/>
498 <Point Identifier="blue&#x9;point&#x9;412" ScreenX="531" ScreenY="961" Ordinal="1"/>
499 <Point Identifier="blue&#x9;point&#x9;413" ScreenX="549" ScreenY="943" Ordinal="1"/>
500 <Point Identifier="blue&#x9;point&#x9;414" ScreenX="567" ScreenY="926" Ordinal="1"/>
501 <Point Identifier="blue&#x9;point&#x9;415" ScreenX="585" ScreenY="909" Ordinal="1"/>
502 <Point Identifier="blue&#x9;point&#x9;416" ScreenX="603" ScreenY="893" Ordinal="1"/>
503 <Point Identifier="blue&#x9;point&#x9;417" ScreenX="622" ScreenY="876" Ordinal="1"/>
504 <Point Identifier="blue&#x9;point&#x9;418" ScreenX="641" ScreenY="861" Ordinal="1"/>
505 <Point Identifier="blue&#x9;point&#x9;419" ScreenX="661" ScreenY="845" Ordinal="1"/>
506 <Point Identifier="blue&#x9;point&#x9;420" ScreenX="680" ScreenY="830" Ordinal="1"/>
507 <Point Identifier="blue&#x9;point&#x9;421" ScreenX="700" ScreenY="815" Ordinal="1"/>
508 <Point Identifier="blue&#x9;point&#x9;422" ScreenX="719" ScreenY="800" Ordinal="1"/>
509 <Point Identifier="blue&#x9;point&#x9;423" ScreenX="739" ScreenY="786" Ordinal="1"/>
510 <Point Identifier="blue&#x9;point&#x9;424" ScreenX="760" ScreenY="772" Ordinal="1"/>
511 <Point Identifier="blue&#x9;point&#x9;425" ScreenX="780" ScreenY="757" Ordinal="1"/>
512 <Point Identifier="blue&#x9;point&#x9;426" ScreenX="801" ScreenY="743" Ordinal="1"/>
513 <Point Identifier="blue&#x9;point&#x9;427" ScreenX="822" ScreenY="730" Ordinal="1"/>
514 <Point Identifier="blue&#x9;point&#x9;428" ScreenX="843" ScreenY="717" Ordinal="1"/>
515 <Point Identifier="blue&#x9;point&#x9;429" ScreenX="865" ScreenY="704" Ordinal="1"/>
516 <Point Identifier="blue&#x9;point&#x9;430" ScreenX="886" ScreenY="691" Ordinal="1"/>
517 <Point Identifier="blue&#x9;point&#x9;431" ScreenX="908" ScreenY="679" Ordinal="1"/>
518 <Point Identifier="blue&#x9;point&#x9;432" ScreenX="929" ScreenY="667" Ordinal="1"/>
519 <Point Identifier="blue&#x9;point&#x9;433" ScreenX="952" ScreenY="655" Ordinal="1"/>
520 <Point Identifier="blue&#x9;point&#x9;434" ScreenX="974" ScreenY="643" Ordinal="1"/>
521 <Point Identifier="blue&#x9;point&#x9;435" ScreenX="996" ScreenY="631" Ordinal="1"/>
522 <Point Identifier="blue&#x9;point&#x9;436" ScreenX="1018" ScreenY="620" Ordinal="1"/>
523 <Point Identifier="blue&#x9;point&#x9;437" ScreenX="1040" ScreenY="609" Ordinal="1"/>
524 <Point Identifier="blue&#x9;point&#x9;438" ScreenX="1063" ScreenY="598" Ordinal="1"/>
525 <Point Identifier="blue&#x9;point&#x9;439" ScreenX="1085" ScreenY="587" Ordinal="1"/>
526 <Point Identifier="blue&#x9;point&#x9;440" ScreenX="1108" ScreenY="576" Ordinal="1"/>
527 <Point Identifier="blue&#x9;point&#x9;441" ScreenX="1131" ScreenY="566" Ordinal="1"/>
528 <Point Identifier="blue&#x9;point&#x9;442" ScreenX="1154" ScreenY="556" Ordinal="1"/>
529 <Point Identifier="blue&#x9;point&#x9;443" ScreenX="1176" ScreenY="546" Ordinal="1"/>
530 <Point Identifier="blue&#x9;point&#x9;444" ScreenX="1199" ScreenY="536" Ordinal="1"/>
531 <Point Identifier="blue&#x9;point&#x9;445" ScreenX="1223" ScreenY="527" Ordinal="1"/>
532 <Point Identifier="blue&#x9;point&#x9;446" ScreenX="1246" ScreenY="517" Ordinal="1"/>
533 <Point Identifier="blue&#x9;point&#x9;447" ScreenX="1269" ScreenY="508" Ordinal="1"/>
534 <Point Identifier="blue&#x9;point&#x9;448" ScreenX="1292" ScreenY="498" Ordinal="1"/>
535 <Point Identifier="blue&#x9;point&#x9;449" ScreenX="1315" ScreenY="489" Ordinal="1"/>
536 <Point Identifier="blue&#x9;point&#x9;450" ScreenX="1339" ScreenY="480" Ordinal="1"/>
537 <Point Identifier="blue&#x9;point&#x9;451" ScreenX="1362" ScreenY="472" Ordinal="1"/>
538 <Point Identifier="blue&#x9;point&#x9;452" ScreenX="1385" ScreenY="463" Ordinal="1"/>
539 <Point Identifier="blue&#x9;point&#x9;453" ScreenX="1409" ScreenY="455" Ordinal="1"/>
540 <Point Identifier="blue&#x9;point&#x9;454" ScreenX="1432" ScreenY="446" Ordinal="1"/>
541 <Point Identifier="blue&#x9;point&#x9;455" ScreenX="1456" ScreenY="438" Ordinal="1"/>
542 <Point Identifier="blue&#x9;point&#x9;456" ScreenX="1479" ScreenY="430" Ordinal="1"/>
543 <Point Identifier="blue&#x9;point&#x9;457" ScreenX="1503" ScreenY="422" Ordinal="1"/>
544 <Point Identifier="blue&#x9;point&#x9;458" ScreenX="1526" ScreenY="414" Ordinal="1"/>
545 <Point Identifier="blue&#x9;point&#x9;459" ScreenX="1550" ScreenY="407" Ordinal="1"/>
546 <Point Identifier="blue&#x9;point&#x9;460" ScreenX="1573" ScreenY="399" Ordinal="1"/>
547 <Point Identifier="blue&#x9;point&#x9;461" ScreenX="1597" ScreenY="391" Ordinal="1"/>
548 <Point Identifier="blue&#x9;point&#x9;462" ScreenX="1621" ScreenY="384" Ordinal="1"/>
549 <Point Identifier="blue&#x9;point&#x9;463" ScreenX="1644" ScreenY="377" Ordinal="1"/>
550 <Point Identifier="blue&#x9;point&#x9;464" ScreenX="1668" ScreenY="369" Ordinal="1"/>
551 <Point Identifier="blue&#x9;point&#x9;465" ScreenX="1692" ScreenY="362" Ordinal="1"/>
552 <Point Identifier="blue&#x9;point&#x9;466" ScreenX="1716" ScreenY="355" Ordinal="1"/>
553 <Point Identifier="blue&#x9;point&#x9;467" ScreenX="1740" ScreenY="348" Ordinal="1"/>
554 <Point Identifier="blue&#x9;point&#x9;468" ScreenX="1764" ScreenY="342" Ordinal="1"/>
555 <Point Identifier="blue&#x9;point&#x9;469" ScreenX="1787" ScreenY="335" Ordinal="1"/>
556 <Point Identifier="blue&#x9;point&#x9;470" ScreenX="1811" ScreenY="328" Ordinal="1"/>
557 <Point Identifier="blue&#x9;point&#x9;471" ScreenX="1835" ScreenY="322" Ordinal="1"/>
558 <Point Identifier="blue&#x9;point&#x9;472" ScreenX="1859" ScreenY="315" Ordinal="1"/>
559 <Point Identifier="blue&#x9;point&#x9;473" ScreenX="1883" ScreenY="309" Ordinal="1"/>
560 <Point Identifier="blue&#x9;point&#x9;474" ScreenX="1906" ScreenY="303" Ordinal="1"/>
561 <Point Identifier="blue&#x9;point&#x9;475" ScreenX="1930" ScreenY="297" Ordinal="1"/>
562 <Point Identifier="blue&#x9;point&#x9;476" ScreenX="1954" ScreenY="291" Ordinal="1"/>
563 <Point Identifier="blue&#x9;point&#x9;477" ScreenX="1979" ScreenY="285" Ordinal="1"/>
564 <Point Identifier="blue&#x9;point&#x9;478" ScreenX="2003" ScreenY="278" Ordinal="1"/>
565 <Point Identifier="blue&#x9;point&#x9;479" ScreenX="2026" ScreenY="272" Ordinal="1"/>
566 <Point Identifier="blue&#x9;point&#x9;480" ScreenX="2050" ScreenY="267" Ordinal="1"/>
567 <Point Identifier="blue&#x9;point&#x9;481" ScreenX="2073" ScreenY="261" Ordinal="1"/>
568 <Point Identifier="blue&#x9;point&#x9;482" ScreenX="2097" ScreenY="255" Ordinal="1"/>
569 <Point Identifier="blue&#x9;point&#x9;483" ScreenX="2121" ScreenY="250" Ordinal="1"/>
570 <Point Identifier="blue&#x9;point&#x9;484" ScreenX="2145" ScreenY="244" Ordinal="1"/>
571 <Point Identifier="blue&#x9;point&#x9;485" ScreenX="2168" ScreenY="238" Ordinal="1"/>
572 <Point Identifier="blue&#x9;point&#x9;486" ScreenX="2192" ScreenY="233" Ordinal="1"/>
573 <Point Identifier="blue&#x9;point&#x9;487" ScreenX="2216" ScreenY="228" Ordinal="1"/>
574 <Point Identifier="blue&#x9;point&#x9;488" ScreenX="2240" ScreenY="223" Ordinal="1"/>
575 <Point Identifier="blue&#x9;point&#x9;489" ScreenX="2263" ScreenY="217" Ordinal="1"/>
576 <Point Identifier="blue&#x9;point&#x9;490" ScreenX="2287" ScreenY="212" Ordinal="1"/>
577 <Point Identifier="blue&#x9;point&#x9;491" ScreenX="2311" ScreenY="207" Ordinal="1"/>
578 <Point Identifier="blue&#x9;point&#x9;492" ScreenX="2335" ScreenY="202" Ordinal="1"/>
579 <Point Identifier="blue&#x9;point&#x9;493" ScreenX="2358" ScreenY="197" Ordinal="1"/>
580 <Point Identifier="blue&#x9;point&#x9;494" ScreenX="2382" ScreenY="191" Ordinal="1"/>
581 <Point Identifier="blue&#x9;point&#x9;495" ScreenX="2406" ScreenY="187" Ordinal="1"/>
582 <Point Identifier="blue&#x9;point&#x9;496" ScreenX="2430" ScreenY="182" Ordinal="1"/>
583 <Point Identifier="blue&#x9;point&#x9;497" ScreenX="2454" ScreenY="177" Ordinal="1"/>
584 <Point Identifier="blue&#x9;point&#x9;498" ScreenX="2477" ScreenY="172" Ordinal="1"/>
585 <Point Identifier="blue&#x9;point&#x9;499" ScreenX="2501" ScreenY="167" Ordinal="1"/>
586 <Point Identifier="blue&#x9;point&#x9;500" ScreenX="2525" ScreenY="163" Ordinal="1"/>
587 <Point Identifier="blue&#x9;point&#x9;501" ScreenX="2549" ScreenY="158" Ordinal="1"/>
588 <Point Identifier="blue&#x9;point&#x9;502" ScreenX="2573" ScreenY="153" Ordinal="1"/>
589 <Point Identifier="blue&#x9;point&#x9;503" ScreenX="2597" ScreenY="149" Ordinal="1"/>
590 <Point Identifier="blue&#x9;point&#x9;504" ScreenX="2621" ScreenY="144" Ordinal="1"/>
591 <Point Identifier="blue&#x9;point&#x9;505" ScreenX="2645" ScreenY="140" Ordinal="1"/>
592 <Point Identifier="blue&#x9;point&#x9;506" ScreenX="2669" ScreenY="135" Ordinal="1"/>
593 <Point Identifier="blue&#x9;point&#x9;507" ScreenX="2693" ScreenY="131" Ordinal="1"/>
594 <Point Identifier="blue&#x9;point&#x9;508" ScreenX="2716" ScreenY="127" Ordinal="1"/>
595 <Point Identifier="blue&#x9;point&#x9;509" ScreenX="2740" ScreenY="123" Ordinal="1"/>
596 <Point Identifier="blue&#x9;point&#x9;510" ScreenX="2763" ScreenY="118" Ordinal="1"/>
597 <Point Identifier="blue&#x9;point&#x9;511" ScreenX="2787" ScreenY="114" Ordinal="1"/>
598 <Point Identifier="blue&#x9;point&#x9;512" ScreenX="2811" ScreenY="110" Ordinal="1"/>
599 <Point Identifier="blue&#x9;point&#x9;513" ScreenX="2834" ScreenY="106" Ordinal="1"/>
600 <Point Identifier="blue&#x9;point&#x9;514" ScreenX="2858" ScreenY="102" Ordinal="1"/>
601 <Point Identifier="blue&#x9;point&#x9;515" ScreenX="2881" ScreenY="98" Ordinal="1"/>
602 <Point Identifier="blue&#x9;point&#x9;516" ScreenX="2905" ScreenY="93" Ordinal="1"/>
603 <Point Identifier="blue&#x9;point&#x9;517" ScreenX="2929" ScreenY="89" Ordinal="1"/>
604 <Point Identifier="blue&#x9;point&#x9;518" ScreenX="2953" ScreenY="85" Ordinal="1"/>
605 <Point Identifier="blue&#x9;point&#x9;519" ScreenX="2976" ScreenY="82" Ordinal="1"/>
606 <Point Identifier="blue&#x9;point&#x9;520" ScreenX="3000" ScreenY="78" Ordinal="1"/>
607 <Point Identifier="blue&#x9;point&#x9;521" ScreenX="3024" ScreenY="73" Ordinal="1"/>
608 <Point Identifier="blue&#x9;point&#x9;522" ScreenX="3048" ScreenY="70" Ordinal="1"/>
609 <Point Identifier="blue&#x9;point&#x9;523" ScreenX="3071" ScreenY="66" Ordinal="1"/>
610 <Point Identifier="blue&#x9;point&#x9;524" ScreenX="3095" ScreenY="62" Ordinal="1"/>
611 <Point Identifier="blue&#x9;point&#x9;525" ScreenX="3118" ScreenY="58" Ordinal="1"/>
612 <Point Identifier="blue&#x9;point&#x9;526" ScreenX="3143" ScreenY="55" Ordinal="1"/>
613 <Point Identifier="blue&#x9;point&#x9;527" ScreenX="3166" ScreenY="51" Ordinal="1"/>
614 <Point Identifier="blue&#x9;point&#x9;528" ScreenX="3190" ScreenY="47" Ordinal="1"/>
615 <Point Identifier="blue&#x9;point&#x9;529" ScreenX="3214" ScreenY="44" Ordinal="1"/>
616 <Point Identifier="blue&#x9;point&#x9;530" ScreenX="3238" ScreenY="40" Ordinal="1"/>
617 <Point Identifier="blue&#x9;point&#x9;531" ScreenX="3261" ScreenY="36" Ordinal="1"/>
618 <Point Identifier="blue&#x9;point&#x9;532" ScreenX="3285" ScreenY="33" Ordinal="1"/>
619 </Cmd>
620 </CmdMediator>
621 <Error Context="Shift+Control+E" Comment="userTriggered" File="src/main/MainWindow.cpp" Line="1355"/>
622 </Document>
623 </ErrorReport>
0 -filecmdscript ../test/jpeg2000/jpeg2000.test.xml -regression
0 -filecmdscript ../test/jpeg2000/jpeg2000.xml -regression
+0
-3
test/jpeg2000/jpeg2000.test.xml less more
0 <Script>
1 <Cmd Type="CmdFileImport" FileName="../test/jpeg2000/jpeg2000.jp2" />
2 </Script>
0 <Script>
1 <Cmd Type="CmdFileImport" FileName="../test/jpeg2000/jpeg2000.jp2" />
2 </Script>
0 -errorreport ../test/multi_coord_systems_curve_rename.xml -regression
0 -errorreport ../test/multi_coord_systems_curve_rename.xml -regression -reset
0 -filecmdscript ../test/pdf/pdf_one_page.test.xml -regression
0 -filecmdscript ../test/pdf/pdf_one_page.xml -regression
+0
-3
test/pdf/pdf_one_page.test.xml less more
0 <Script>
1 <Cmd Type="CmdFileImport" FileName="../test/pdf/pdf_one_page.pdf" />
2 </Script>
0 <Script>
1 <Cmd Type="CmdFileImport" FileName="../test/pdf/pdf_one_page.pdf" />
2 </Script>
0 x,Curve1
1 41.77,0.0802
2 57.23,-0.0586
3 70.26,0.0904
4 80.51,1e-10
0 -errorreport ../test/points_along_axes.xml -regression -reset
0 <ErrorReport>
1 <Application VersionNumber="9.0"/>
2 <Document AxesPointsRequired="0" VersionNumber="9.0">
3 <Image Height="607" Width="1042"><![CDATA[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]]></Image>
4 <CoordSystem>
5 <General CursorSize="3" ExtraPrecision="1"/>
6 <Coords UnitsYString="Number" UnitsRadius="0" UnitsXString="Number" UnitsTime="2" ScaleYRadius="0" UnitsTheta="0" ScaleXTheta="0" ScaleXThetaString="Linear" ScaleYRadiusString="Linear" TypeString="Cartesian" UnitsX="0" UnitsY="0" UnitsRadiusString="Number" UnitsDate="3" Type="0" UnitsDateString="YYYY/MM/DD" Coords="0" UnitsThetaString="Degrees (DDD.DDDDD)" UnitsTimeString="HH:MM:SS"/>
7 <DigitizeCurve CursorLineWidth="2" CursorSize="1" CursorStandardCross="True" CursorInnerRadius="5"/>
8 <Export PointsIntervalFunctions="10" PointsSelectionRelations="0" Header="1" PointsSelectionRelationsString="Interpolate" DelimiterString="Commas" PointsIntervalUnitsRelations="1" LayoutFunctionsString="AllPerLine" PointsSelectionFunctionsString="InterpolateAllCurves" PointsIntervalRelations="10" OverrideCsvTsv="True" HeaderString="Simple" PointsSelectionFunctions="0" XLabel="x" Delimiter="0" PointsIntervalUnitsFunctions="1" LayoutFunctions="0">
9 <CurveNamesNotExported/>
10 </Export>
11 <AxesChecker Mode="1" LineColor="6" Seconds="3"/>
12 <GridDisplay DisableY="0" StopY="1" Stable="False" CountX="2" StartX="0" CountY="2" StartY="0" StepX="1" StepY="1" Color="0" ColorString="Black" DisableX="0" StopX="1"/>
13 <GridRemoval CoordDisableY="0" StopY="0" CoordDisableXString="Count" Stable="False" CloseDistance="10" CountX="2" StartX="0" CountY="2" StartY="0" DefinedGridLines="False" StepX="0" StepY="0" CoordDisableX="0" StopX="0" CoordDisableYString="Count"/>
14 <PointMatch ColorAccepted="4" ColorAcceptedString="Green" ColorCandidate="7" ColorCandidateString="Yellow" ColorRejectedString="Red" PointSize="48" ColorRejected="6"/>
15 <Segments LineColor="4" MinLength="2" LineWidth="4" LineColorString="Green" FillCorners="False" PointSeparation="25"/>
16 <Curve CurveName="Axes">
17 <ColorFilter ModeString="Intensity" Mode="2" CurveName="Axes" ValueLow="0" ForegroundHigh="10" SaturationHigh="100" ValueHigh="50" HueLow="180" SaturationLow="50" IntensityLow="0" ForegroundLow="0" HueHigh="360" IntensityHigh="50"/>
18 <CurveStyle CurveName="Axes">
19 <LineStyle ConnectAs="4" ConnectAsString="ConnectSkipForAxisCurve" Color="8" ColorString="Transparent" Width="0"/>
20 <PointStyle Radius="10" LineWidth="1" Shape="1" ShapeString="Cross" Color="6" ColorString="Red"/>
21 </CurveStyle>
22 <CurvePoints/>
23 </Curve>
24 <CurvesGraphs>
25 <Curve CurveName="Curve1">
26 <ColorFilter ModeString="Intensity" Mode="2" CurveName="Curve1" ValueLow="0" ForegroundHigh="10" SaturationHigh="100" ValueHigh="50" HueLow="180" SaturationLow="50" IntensityLow="0" ForegroundLow="0" HueHigh="360" IntensityHigh="50"/>
27 <CurveStyle CurveName="Curve1">
28 <LineStyle ConnectAs="0" ConnectAsString="FunctionSmooth" Color="1" ColorString="Blue" Width="1"/>
29 <PointStyle Radius="10" LineWidth="1" Shape="1" ShapeString="Cross" Color="1" ColorString="Blue"/>
30 </CurveStyle>
31 <CurvePoints/>
32 </Curve>
33 </CurvesGraphs>
34 </CoordSystem>
35 <OperatingSystem Endian="LittleEndian" WordSize="32"/>
36 <File Imported="True"/>
37 <CmdMediator>
38 <Cmd Type="CmdAddPointAxis" ScreenX="68.5817" ScreenY="356.569" GraphX="1" Ordinal="1" GraphY="0" Description="Add axis point" Identifier="Axes&#x9;point&#x9;1" IsXOnly="False"/>
39 <Cmd Type="CmdAddPointAxis" ScreenX="1019.14" ScreenY="357.263" GraphX="121" Ordinal="2" GraphY="0" Description="Add axis point" Identifier="Axes&#x9;point&#x9;3" IsXOnly="False"/>
40 <Cmd Type="CmdAddPointAxis" ScreenX="69.3192" ScreenY="27.7486" GraphX="1" Ordinal="3" GraphY="1.5" Description="Add axis point" Identifier="Axes&#x9;point&#x9;5" IsXOnly="False"/>
41 <Cmd Type="CmdAddPointGraph" CurveName="Curve1" ScreenX="391.58" ScreenY="339.226" Ordinal="1" Description="Add graph point" Identifier="Curve1&#x9;point&#x9;6"/>
42 <Cmd Type="CmdAddPointGraph" CurveName="Curve1" ScreenX="513.994" ScreenY="369.75" Ordinal="1" Description="Add graph point" Identifier="Curve1&#x9;point&#x9;7"/>
43 <Cmd Type="CmdAddPointGraph" CurveName="Curve1" ScreenX="617.236" ScreenY="337.145" Ordinal="2.5" Description="Add graph point" Identifier="Curve1&#x9;point&#x9;8"/>
44 <Cmd Type="CmdAddPointGraph" CurveName="Curve1" ScreenX="698.354" ScreenY="366.975" Ordinal="3.5" Description="Add graph point" Identifier="Curve1&#x9;point&#x9;9"/>
45 <Cmd Type="CmdEditPointGraph" IsX="False" X="0" IsY="True" Y="0" Description="Edit curve points">
46 <Point Identifier="Curve1&#x9;point&#x9;7"/>
47 <Point Identifier="Curve1&#x9;point&#x9;8"/>
48 <Point Identifier="Curve1&#x9;point&#x9;6"/>
49 <Point Identifier="Curve1&#x9;point&#x9;9"/>
50 </Cmd>
51 </CmdMediator>
52 <Error File="src/main/MainWindow.cpp" Line="1305" Context="Shift+Control+E" Comment="userTriggered"/>
53 </Document>
54 </ErrorReport>
0 -errorreport ../test/polar_linear_linear_3curve.xml -regression
0 -errorreport ../test/polar_linear_linear_3curve.xml -regression -reset
0 -errorreport ../test/polar_linear_linear_nonzero_center.xml -regression
0 -errorreport ../test/polar_linear_linear_nonzero_center.xml -regression -reset
0 -errorreport ../test/undo_redo.xml -regression
0 -errorreport ../test/undo_redo.xml -regression -reset
0 -filecmdscript ../test/version5_1.test.xml
0 -filecmdscript ../test/version5_1.xml -regression -reset
+0
-7
test/version5_1.test.xml less more
0 <Script>
1 <Cmd Type="CmdFileOpen" FileName="../test/version5_1.dig" />
2 <Cmd Type="CmdFileClose" />
3 <Cmd Type="CmdFileOpen" FileName="../test/version5_1.dig" />
4 <Cmd Type="CmdFileClose" />
5 </Script>
6
0 <Script>
1 <Cmd Type="CmdFileOpen" FileName="../test/version5_1.dig" />
2 <Cmd Type="CmdFileClose" />
3 <Cmd Type="CmdFileOpen" FileName="../test/version5_1.dig" />
4 <Cmd Type="CmdFileClose" />
5 </Script>
6
0 -errorreport ../test/version5_2.dig -regression
0 -errorreport ../test/version5_2.dig -regression -reset
11
0 -filecmdscript ../test/version6_1.test.xml
0 -filecmdscript ../test/version6_1.xml -regression -reset
+0
-7
test/version6_1.test.xml less more
0 <Script>
1 <Cmd Type="CmdFileOpen" FileName="../test/version6_1.dig" />
2 <Cmd Type="CmdFileClose" />
3 <Cmd Type="CmdFileOpen" FileName="../test/version6_1.dig" />
4 <Cmd Type="CmdFileClose" />
5 </Script>
6
0 <Script>
1 <Cmd Type="CmdFileOpen" FileName="../test/version6_1.dig" />
2 <Cmd Type="CmdFileClose" />
3 <Cmd Type="CmdFileOpen" FileName="../test/version6_1.dig" />
4 <Cmd Type="CmdFileClose" />
5 </Script>
6
0 -errorreport ../test/version6_2.dig -regression
0 -errorreport ../test/version6_2.dig -regression -reset
11
0 -filecmdscript ../test/version7.1_1.test.xml
0 -filecmdscript ../test/version7.1_1.xml -regression -reset
+0
-9
test/version7.1_1.test.xml less more
0 <Script>
1 <Cmd Type="CmdFileOpen" FileName="../test/version7.1_1.dig" />
2 <Cmd Type="CmdFileClose" />
3 <Cmd Type="CmdFileOpen" FileName="../test/version7.1_1.dig" />
4 <Cmd Type="CmdFileClose" />
5 <Cmd Type="CmdFileImport" FileName="../samples/huge.png" />
6 <Cmd Type="CmdFileClose" />
7 </Script>
8
0 <Script>
1 <Cmd Type="CmdFileOpen" FileName="../test/version7.1_1.dig" />
2 <Cmd Type="CmdFileClose" />
3 <Cmd Type="CmdFileOpen" FileName="../test/version7.1_1.dig" />
4 <Cmd Type="CmdFileClose" />
5 <Cmd Type="CmdFileImport" FileName="../samples/huge.png" />
6 <Cmd Type="CmdFileClose" />
7 </Script>
8
0 -errorreport ../test/version7.1_2.dig -regression
0 -errorreport ../test/version7.1_2.dig -regression -reset
11
0 -filecmdscript ../test/version7_1.test.xml
0 -filecmdscript ../test/version7_1.xml -regression -reset
+0
-9
test/version7_1.test.xml less more
0 <Script>
1 <Cmd Type="CmdFileOpen" FileName="../test/version7_1.dig" />
2 <Cmd Type="CmdFileClose" />
3 <Cmd Type="CmdFileOpen" FileName="../test/version7_1.dig" />
4 <Cmd Type="CmdFileClose" />
5 <Cmd Type="CmdFileImport" FileName="../samples/huge.png" />
6 <Cmd Type="CmdFileClose" />
7 </Script>
8
0 <Script>
1 <Cmd Type="CmdFileOpen" FileName="../test/version7_1.dig" />
2 <Cmd Type="CmdFileClose" />
3 <Cmd Type="CmdFileOpen" FileName="../test/version7_1.dig" />
4 <Cmd Type="CmdFileClose" />
5 <Cmd Type="CmdFileImport" FileName="../samples/huge.png" />
6 <Cmd Type="CmdFileClose" />
7 </Script>
8
0 -errorreport ../test/version7_2.dig -regression
0 -errorreport ../test/version7_2.dig -regression -reset
11
0 -errorreport ../test/version8_1.dig -regression
0 -errorreport ../test/version8_1.dig -regression -reset
11
0 -errorreport ../test/version8_2.dig -regression
0 -errorreport ../test/version8_2.dig -regression -reset
11
0 x;Curve1
1 -9.936;6.032
2 -9.675;6.388
3 -9.347;6.711
4 -8.976;7.002
5 -8.517;7.212
6 -7.971;7.276
7 -7.468;7.146
8 -7.053;6.918
9 -6.965;6.87
10 -6.593;6.577
11 -6.265;6.253
12 -5.937;5.929
13 -5.652;5.572
14 -5.368;5.231
15 -5.083;4.875
16 -4.842;4.518
17 -4.579;4.161
18 -4.316;3.821
19 -4.054;3.448
20 -3.813;3.092
21 -3.55;2.735
22 -3.265;2.394
23 -3.003;2.038
24 -2.696;1.697
25 -2.39;1.357
26 -2.061;1.032
27 -1.711;0.724
28 -1.339;0.448
29 -0.902;0.188
30 0.65;0.089
31 1.131;0.282
32 1.524;0.541
33 1.917;0.848
34 2.244;1.155
35 2.549;1.495
36 2.855;1.834
37 3.139;2.174
38 3.4;2.53
39 3.684;2.869
40 3.924;3.242
41 4.186;3.597
42 4.448;3.953
43 4.709;4.309
44 4.971;4.665
45 5.211;5.021
46 5.517;5.36
47 5.778;5.716
48 6.084;6.04
49 6.411;6.363
50 6.76;6.686
51 7.044;6.88
52 7.481;7.123
53 7.984;7.251
54 8.508;7.186
55 8.967;6.991
56 9.361;6.699
57 9.69;6.374
58 9.952;6.018
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!DOCTYPE engauge>
2 <Document VersionNumber="9.0" AxesPointsRequired="0">
3 <Image Width="1000" Height="800"><![CDATA[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]]></Image>
4 <CoordSystem>
5 <General CursorSize="3" ExtraPrecision="1"/>
6 <Coords Type="0" TypeString="Cartesian" Coords="0" ScaleXTheta="0" ScaleXThetaString="Linear" ScaleYRadius="0" ScaleYRadiusString="Linear" UnitsX="0" UnitsXString="Number" UnitsY="0" UnitsYString="Number" UnitsTheta="0" UnitsThetaString="Degrees (DDD.DDDDD)" UnitsRadius="0" UnitsRadiusString="Number" UnitsDate="3" UnitsDateString="YYYY/MM/DD" UnitsTime="2" UnitsTimeString="HH:MM:SS"/>
7 <DigitizeCurve CursorInnerRadius="5" CursorLineWidth="2" CursorSize="1" CursorStandardCross="True"/>
8 <Export PointsSelectionFunctions="0" PointsSelectionFunctionsString="InterpolateAllCurves" PointsIntervalFunctions="10" PointsIntervalUnitsFunctions="1" PointsSelectionRelations="0" PointsSelectionRelationsString="Interpolate" PointsIntervalUnitsRelations="1" PointsIntervalRelations="10" LayoutFunctions="0" LayoutFunctionsString="AllPerLine" Delimiter="3" OverrideCsvTsv="True" DelimiterString="Semicolons" Header="1" HeaderString="Simple" XLabel="x">
9 <CurveNamesNotExported/>
10 </Export>
11 <AxesChecker Mode="1" Seconds="3" LineColor="6"/>
12 <GridDisplay Stable="True" DisableX="0" CountX="5" StartX="-10" StepX="5" StopX="10" DisableY="0" CountY="4" StartY="-5" StepY="5" StopY="10" Color="0" ColorString="Black"/>
13 <GridRemoval Stable="False" DefinedGridLines="False" CloseDistance="10" CoordDisableX="0" CoordDisableXString="Count" CountX="9" StartX="-10.0058" StepX="2.49611" StopX="9.96305" CoordDisableY="0" CoordDisableYString="Count" CountY="14" StartY="-2.01332" StepY="0.923125" StopY="9.98731"/>
14 <PointMatch PointSize="48" ColorAccepted="4" ColorAcceptedString="Green" ColorCandidate="7" ColorCandidateString="Yellow" ColorRejected="6" ColorRejectedString="Red"/>
15 <Segments PointSeparation="25" MinLength="2" FillCorners="False" LineWidth="4" LineColor="4" LineColorString="Green"/>
16 <Curve CurveName="Axes">
17 <ColorFilter CurveName="Axes" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
18 <CurveStyle CurveName="Axes">
19 <LineStyle Width="0" Color="8" ColorString="Transparent" ConnectAs="4" ConnectAsString="ConnectSkipForAxisCurve"/>
20 <PointStyle Radius="10" LineWidth="1" Color="6" ColorString="Red" Shape="1" ShapeString="Cross"/>
21 </CurveStyle>
22 <CurvePoints>
23 <Point Identifier="Axes&#9;point&#9;13" Ordinal="1" IsAxisPoint="True" IsXOnly="False" Index="76">
24 <PositionScreen X="54.5868" Y="760.999"/>
25 <PositionGraph X="-10" Y="-2"/>
26 </Point>
27 <Point Identifier="Axes&#9;point&#9;15" Ordinal="2" IsAxisPoint="True" IsXOnly="False" Index="76">
28 <PositionScreen X="969.674" Y="759.096"/>
29 <PositionGraph X="10" Y="-2"/>
30 </Point>
31 <Point Identifier="Axes&#9;point&#9;17" Ordinal="3" IsAxisPoint="True" IsXOnly="False" Index="76">
32 <PositionScreen X="55.345" Y="19.9762"/>
33 <PositionGraph X="-10" Y="10"/>
34 </Point>
35 </CurvePoints>
36 </Curve>
37 <CurvesGraphs>
38 <Curve CurveName="Curve1">
39 <ColorFilter CurveName="Curve1" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
40 <CurveStyle CurveName="Curve1">
41 <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
42 <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="1" ShapeString="Cross"/>
43 </CurveStyle>
44 <CurvePoints>
45 <Point Identifier="Curve1&#9;point&#9;18" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="76">
46 <PositionScreen X="58" Y="265"/>
47 </Point>
48 <Point Identifier="Curve1&#9;point&#9;19" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="76">
49 <PositionScreen X="70" Y="243"/>
50 </Point>
51 <Point Identifier="Curve1&#9;point&#9;20" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="76">
52 <PositionScreen X="85" Y="223"/>
53 </Point>
54 <Point Identifier="Curve1&#9;point&#9;21" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="76">
55 <PositionScreen X="102" Y="205"/>
56 </Point>
57 <Point Identifier="Curve1&#9;point&#9;22" Ordinal="4" IsAxisPoint="False" IsXOnly="False" Index="76">
58 <PositionScreen X="123" Y="192"/>
59 </Point>
60 <Point Identifier="Curve1&#9;point&#9;23" Ordinal="5" IsAxisPoint="False" IsXOnly="False" Index="76">
61 <PositionScreen X="148" Y="188"/>
62 </Point>
63 <Point Identifier="Curve1&#9;point&#9;24" Ordinal="6" IsAxisPoint="False" IsXOnly="False" Index="76">
64 <PositionScreen X="171" Y="196"/>
65 </Point>
66 <Point Identifier="Curve1&#9;point&#9;25" Ordinal="7" IsAxisPoint="False" IsXOnly="False" Index="76">
67 <PositionScreen X="190" Y="210"/>
68 </Point>
69 <Point Identifier="Curve1&#9;point&#9;26" Ordinal="8" IsAxisPoint="False" IsXOnly="False" Index="76">
70 <PositionScreen X="194" Y="213"/>
71 </Point>
72 <Point Identifier="Curve1&#9;point&#9;27" Ordinal="9" IsAxisPoint="False" IsXOnly="False" Index="76">
73 <PositionScreen X="211" Y="231"/>
74 </Point>
75 <Point Identifier="Curve1&#9;point&#9;28" Ordinal="10" IsAxisPoint="False" IsXOnly="False" Index="76">
76 <PositionScreen X="226" Y="251"/>
77 </Point>
78 <Point Identifier="Curve1&#9;point&#9;29" Ordinal="11" IsAxisPoint="False" IsXOnly="False" Index="76">
79 <PositionScreen X="241" Y="271"/>
80 </Point>
81 <Point Identifier="Curve1&#9;point&#9;30" Ordinal="12" IsAxisPoint="False" IsXOnly="False" Index="76">
82 <PositionScreen X="254" Y="293"/>
83 </Point>
84 <Point Identifier="Curve1&#9;point&#9;31" Ordinal="13" IsAxisPoint="False" IsXOnly="False" Index="76">
85 <PositionScreen X="267" Y="314"/>
86 </Point>
87 <Point Identifier="Curve1&#9;point&#9;32" Ordinal="14" IsAxisPoint="False" IsXOnly="False" Index="76">
88 <PositionScreen X="280" Y="336"/>
89 </Point>
90 <Point Identifier="Curve1&#9;point&#9;33" Ordinal="15" IsAxisPoint="False" IsXOnly="False" Index="76">
91 <PositionScreen X="291" Y="358"/>
92 </Point>
93 <Point Identifier="Curve1&#9;point&#9;34" Ordinal="16" IsAxisPoint="False" IsXOnly="False" Index="76">
94 <PositionScreen X="303" Y="380"/>
95 </Point>
96 <Point Identifier="Curve1&#9;point&#9;35" Ordinal="17" IsAxisPoint="False" IsXOnly="False" Index="76">
97 <PositionScreen X="315" Y="401"/>
98 </Point>
99 <Point Identifier="Curve1&#9;point&#9;36" Ordinal="18" IsAxisPoint="False" IsXOnly="False" Index="76">
100 <PositionScreen X="327" Y="424"/>
101 </Point>
102 <Point Identifier="Curve1&#9;point&#9;37" Ordinal="19" IsAxisPoint="False" IsXOnly="False" Index="76">
103 <PositionScreen X="338" Y="446"/>
104 </Point>
105 <Point Identifier="Curve1&#9;point&#9;38" Ordinal="20" IsAxisPoint="False" IsXOnly="False" Index="76">
106 <PositionScreen X="350" Y="468"/>
107 </Point>
108 <Point Identifier="Curve1&#9;point&#9;39" Ordinal="21" IsAxisPoint="False" IsXOnly="False" Index="76">
109 <PositionScreen X="363" Y="489"/>
110 </Point>
111 <Point Identifier="Curve1&#9;point&#9;40" Ordinal="22" IsAxisPoint="False" IsXOnly="False" Index="76">
112 <PositionScreen X="375" Y="511"/>
113 </Point>
114 <Point Identifier="Curve1&#9;point&#9;41" Ordinal="23" IsAxisPoint="False" IsXOnly="False" Index="76">
115 <PositionScreen X="389" Y="532"/>
116 </Point>
117 <Point Identifier="Curve1&#9;point&#9;42" Ordinal="24" IsAxisPoint="False" IsXOnly="False" Index="76">
118 <PositionScreen X="403" Y="553"/>
119 </Point>
120 <Point Identifier="Curve1&#9;point&#9;43" Ordinal="25" IsAxisPoint="False" IsXOnly="False" Index="76">
121 <PositionScreen X="418" Y="573"/>
122 </Point>
123 <Point Identifier="Curve1&#9;point&#9;44" Ordinal="26" IsAxisPoint="False" IsXOnly="False" Index="76">
124 <PositionScreen X="434" Y="592"/>
125 </Point>
126 <Point Identifier="Curve1&#9;point&#9;45" Ordinal="27" IsAxisPoint="False" IsXOnly="False" Index="76">
127 <PositionScreen X="451" Y="609"/>
128 </Point>
129 <Point Identifier="Curve1&#9;point&#9;46" Ordinal="28" IsAxisPoint="False" IsXOnly="False" Index="76">
130 <PositionScreen X="471" Y="625"/>
131 </Point>
132 <Point Identifier="Curve1&#9;point&#9;47" Ordinal="29" IsAxisPoint="False" IsXOnly="False" Index="76">
133 <PositionScreen X="542" Y="631"/>
134 </Point>
135 <Point Identifier="Curve1&#9;point&#9;48" Ordinal="30" IsAxisPoint="False" IsXOnly="False" Index="76">
136 <PositionScreen X="564" Y="619"/>
137 </Point>
138 <Point Identifier="Curve1&#9;point&#9;49" Ordinal="31" IsAxisPoint="False" IsXOnly="False" Index="76">
139 <PositionScreen X="582" Y="603"/>
140 </Point>
141 <Point Identifier="Curve1&#9;point&#9;50" Ordinal="32" IsAxisPoint="False" IsXOnly="False" Index="76">
142 <PositionScreen X="600" Y="584"/>
143 </Point>
144 <Point Identifier="Curve1&#9;point&#9;51" Ordinal="33" IsAxisPoint="False" IsXOnly="False" Index="76">
145 <PositionScreen X="615" Y="565"/>
146 </Point>
147 <Point Identifier="Curve1&#9;point&#9;52" Ordinal="34" IsAxisPoint="False" IsXOnly="False" Index="76">
148 <PositionScreen X="629" Y="544"/>
149 </Point>
150 <Point Identifier="Curve1&#9;point&#9;53" Ordinal="35" IsAxisPoint="False" IsXOnly="False" Index="76">
151 <PositionScreen X="643" Y="523"/>
152 </Point>
153 <Point Identifier="Curve1&#9;point&#9;54" Ordinal="36" IsAxisPoint="False" IsXOnly="False" Index="76">
154 <PositionScreen X="656" Y="502"/>
155 </Point>
156 <Point Identifier="Curve1&#9;point&#9;55" Ordinal="37" IsAxisPoint="False" IsXOnly="False" Index="76">
157 <PositionScreen X="668" Y="480"/>
158 </Point>
159 <Point Identifier="Curve1&#9;point&#9;56" Ordinal="38" IsAxisPoint="False" IsXOnly="False" Index="76">
160 <PositionScreen X="681" Y="459"/>
161 </Point>
162 <Point Identifier="Curve1&#9;point&#9;57" Ordinal="39" IsAxisPoint="False" IsXOnly="False" Index="76">
163 <PositionScreen X="692" Y="436"/>
164 </Point>
165 <Point Identifier="Curve1&#9;point&#9;58" Ordinal="40" IsAxisPoint="False" IsXOnly="False" Index="76">
166 <PositionScreen X="704" Y="414"/>
167 </Point>
168 <Point Identifier="Curve1&#9;point&#9;59" Ordinal="41" IsAxisPoint="False" IsXOnly="False" Index="76">
169 <PositionScreen X="716" Y="392"/>
170 </Point>
171 <Point Identifier="Curve1&#9;point&#9;60" Ordinal="42" IsAxisPoint="False" IsXOnly="False" Index="76">
172 <PositionScreen X="728" Y="370"/>
173 </Point>
174 <Point Identifier="Curve1&#9;point&#9;61" Ordinal="43" IsAxisPoint="False" IsXOnly="False" Index="76">
175 <PositionScreen X="740" Y="348"/>
176 </Point>
177 <Point Identifier="Curve1&#9;point&#9;62" Ordinal="44" IsAxisPoint="False" IsXOnly="False" Index="76">
178 <PositionScreen X="751" Y="326"/>
179 </Point>
180 <Point Identifier="Curve1&#9;point&#9;63" Ordinal="45" IsAxisPoint="False" IsXOnly="False" Index="76">
181 <PositionScreen X="765" Y="305"/>
182 </Point>
183 <Point Identifier="Curve1&#9;point&#9;64" Ordinal="46" IsAxisPoint="False" IsXOnly="False" Index="76">
184 <PositionScreen X="777" Y="283"/>
185 </Point>
186 <Point Identifier="Curve1&#9;point&#9;65" Ordinal="47" IsAxisPoint="False" IsXOnly="False" Index="76">
187 <PositionScreen X="791" Y="263"/>
188 </Point>
189 <Point Identifier="Curve1&#9;point&#9;66" Ordinal="48" IsAxisPoint="False" IsXOnly="False" Index="76">
190 <PositionScreen X="806" Y="243"/>
191 </Point>
192 <Point Identifier="Curve1&#9;point&#9;67" Ordinal="49" IsAxisPoint="False" IsXOnly="False" Index="76">
193 <PositionScreen X="822" Y="223"/>
194 </Point>
195 <Point Identifier="Curve1&#9;point&#9;68" Ordinal="50" IsAxisPoint="False" IsXOnly="False" Index="76">
196 <PositionScreen X="835" Y="211"/>
197 </Point>
198 <Point Identifier="Curve1&#9;point&#9;69" Ordinal="51" IsAxisPoint="False" IsXOnly="False" Index="76">
199 <PositionScreen X="855" Y="196"/>
200 </Point>
201 <Point Identifier="Curve1&#9;point&#9;70" Ordinal="52" IsAxisPoint="False" IsXOnly="False" Index="76">
202 <PositionScreen X="878" Y="188"/>
203 </Point>
204 <Point Identifier="Curve1&#9;point&#9;71" Ordinal="53" IsAxisPoint="False" IsXOnly="False" Index="76">
205 <PositionScreen X="902" Y="192"/>
206 </Point>
207 <Point Identifier="Curve1&#9;point&#9;72" Ordinal="54" IsAxisPoint="False" IsXOnly="False" Index="76">
208 <PositionScreen X="923" Y="204"/>
209 </Point>
210 <Point Identifier="Curve1&#9;point&#9;73" Ordinal="55" IsAxisPoint="False" IsXOnly="False" Index="76">
211 <PositionScreen X="941" Y="222"/>
212 </Point>
213 <Point Identifier="Curve1&#9;point&#9;74" Ordinal="56" IsAxisPoint="False" IsXOnly="False" Index="76">
214 <PositionScreen X="956" Y="242"/>
215 </Point>
216 <Point Identifier="Curve1&#9;point&#9;75" Ordinal="57" IsAxisPoint="False" IsXOnly="False" Index="76">
217 <PositionScreen X="968" Y="264"/>
218 </Point>
219 </CurvePoints>
220 </Curve>
221 </CurvesGraphs>
222 </CoordSystem>
223 </Document>
0 -errorreport ../test/version9_1.dig -regression -reset
1
31483148 <message>
31493149 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31503150 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3151 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3151 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31523152 <translation type="unfinished"></translation>
31533153 </message>
31543154 <message>
31913191 <message>
31923192 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3194 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3194 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31953195 <translation type="unfinished"></translation>
31963196 </message>
31973197 <message>
31923192 <message>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31943194 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3195 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3195 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31963196 <translation type="unfinished"/>
31973197 </message>
31983198 <message>
31913191 <message>
31923192 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3194 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3194 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31953195 <translation type="unfinished"></translation>
31963196 </message>
31973197 <message>
35083508 <message>
35093509 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
35103510 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3511 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3512 <translation>Nuevo punto de eje no puede estar en la misma posición de la pantalla como un punto del eje exisiting</translation>
3511 <source>New axis point cannot be at the same screen position as an existing axis point</source>
3512 <translation>Nuevo punto de eje no puede estar en la misma posición de la pantalla como un punto del eje existente</translation>
35133513 </message>
35143514 <message>
35153515 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="129"/>
32013201 <message>
32023202 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
32033203 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3204 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3204 <source>New axis point cannot be at the same screen position as an existing axis point</source>
32053205 <translation type="unfinished"/>
32063206 </message>
32073207 <message>
31913191 <message>
31923192 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3194 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3194 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31953195 <translation type="unfinished"></translation>
31963196 </message>
31973197 <message>
31913191 <message>
31923192 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3194 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3194 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31953195 <translation type="unfinished"></translation>
31963196 </message>
31973197 <message>
31913191 <message>
31923192 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3194 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3194 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31953195 <translation type="unfinished"></translation>
31963196 </message>
31973197 <message>
31913191 <message>
31923192 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3194 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3194 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31953195 <translation type="unfinished"></translation>
31963196 </message>
31973197 <message>
31913191 <message>
31923192 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3194 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3194 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31953195 <translation type="unfinished"></translation>
31963196 </message>
31973197 <message>
35123512 <message>
35133513 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
35143514 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3515 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3516 <translation>Novo ponto de eixo não pode ser na mesma posição da tela como um ponto de eixo exisiting</translation>
3515 <source>New axis point cannot be at the same screen position as an existing axis point</source>
3516 <translation>Novo ponto de eixo não pode ser na mesma posição da tela como um ponto de eixo exisitente</translation>
35173517 </message>
35183518 <message>
35193519 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="129"/>
31913191 <message>
31923192 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
31933193 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3194 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3194 <source>New axis point cannot be at the same screen position as an existing axis point</source>
31953195 <translation type="unfinished"></translation>
31963196 </message>
31973197 <message>
32003200 <message>
32013201 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="123"/>
32023202 <location filename="../src/Callback/CallbackAxisPointsAbstract.cpp" line="217"/>
3203 <source>New axis point cannot be at the same screen position as an exisiting axis point</source>
3203 <source>New axis point cannot be at the same screen position as an existing axis point</source>
32043204 <translation type="unfinished"/>
32053205 </message>
32063206 <message>