Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ee9747156 |
@@ -135,18 +135,11 @@ jobs:
|
|||||||
./Scripts/package_release.sh "${{ matrix.platform.arch }}" "${PREFIX}"
|
./Scripts/package_release.sh "${{ matrix.platform.arch }}" "${PREFIX}"
|
||||||
(cd build/release-assets && shasum -a 256 "${PREFIX}.app.zip" "${PREFIX}.dmg" | tee "${PREFIX}.SHA256.txt")
|
(cd build/release-assets && shasum -a 256 "${PREFIX}.app.zip" "${PREFIX}.dmg" | tee "${PREFIX}.SHA256.txt")
|
||||||
|
|
||||||
- name: Archive ${{ matrix.platform.arch }} .app (for universal lipo)
|
|
||||||
working-directory: ${{ env.PROJECT_ROOT }}
|
|
||||||
run: |
|
|
||||||
ditto -c -k --keepParent \
|
|
||||||
"build/apps/${{ matrix.platform.arch }}/TargetPrint.app" \
|
|
||||||
"build/apps/${{ matrix.platform.arch }}/TargetPrint.app.zip"
|
|
||||||
|
|
||||||
- name: Upload ${{ matrix.platform.arch }} .app (for universal lipo)
|
- name: Upload ${{ matrix.platform.arch }} .app (for universal lipo)
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: app-${{ matrix.platform.arch }}
|
name: app-${{ matrix.platform.arch }}
|
||||||
path: ${{ env.PROJECT_ROOT }}/build/apps/${{ matrix.platform.arch }}/TargetPrint.app.zip
|
path: ${{ env.PROJECT_ROOT }}/build/apps/${{ matrix.platform.arch }}/TargetPrint.app
|
||||||
|
|
||||||
- name: Upload ${{ matrix.platform.arch }} packages
|
- name: Upload ${{ matrix.platform.arch }} packages
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
@@ -155,7 +148,7 @@ jobs:
|
|||||||
path: ${{ env.PROJECT_ROOT }}/build/release-assets/${{ env.PREFIX }}.*
|
path: ${{ env.PROJECT_ROOT }}/build/release-assets/${{ env.PREFIX }}.*
|
||||||
|
|
||||||
- name: Upload Release Assets to Gitea
|
- name: Upload Release Assets to Gitea
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/') && success() }}
|
if: ${{ startsWith(github.ref, 'refs/tags/') && !cancelled() }}
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
SERVER_URL: ${{ github.server_url }}
|
SERVER_URL: ${{ github.server_url }}
|
||||||
@@ -248,46 +241,20 @@ jobs:
|
|||||||
MACOS_CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
|
MACOS_CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
|
||||||
run: |
|
run: |
|
||||||
export MACOS_CODESIGN_IDENTITY="${MACOS_CODESIGN_IDENTITY:--}"
|
export MACOS_CODESIGN_IDENTITY="${MACOS_CODESIGN_IDENTITY:--}"
|
||||||
|
# upload-artifact may nest as TargetPrint.app/ or as Contents/ at the root
|
||||||
for arch in x86_64 arm64; do
|
for arch in x86_64 arm64; do
|
||||||
base="build/apps/${arch}"
|
base="build/apps/${arch}"
|
||||||
echo "==> Preparing ${arch} in ${base}"
|
if [ ! -x "${base}/TargetPrint.app/Contents/MacOS/TargetPrint" ] \
|
||||||
|
&& [ -x "${base}/Contents/MacOS/TargetPrint" ]; then
|
||||||
# 1. If downloaded as zip (from ditto -c -k), unpack it cleanly
|
|
||||||
ZIP_FILE="$(find "${base}" -maxdepth 2 -name "*.zip" 2>/dev/null | head -n 1 || true)"
|
|
||||||
if [ -n "${ZIP_FILE}" ] && [ -f "${ZIP_FILE}" ]; then
|
|
||||||
echo "Extracting bundle archive: ${ZIP_FILE}"
|
|
||||||
ditto -x -k "${ZIP_FILE}" "${base}"
|
|
||||||
rm -f "${ZIP_FILE}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 2. If uncompressed bundle contents were downloaded without TargetPrint.app folder
|
|
||||||
if [ ! -d "${base}/TargetPrint.app" ] && [ -d "${base}/Contents" ]; then
|
|
||||||
echo "Reconstructing TargetPrint.app from root Contents/ in ${base}..."
|
|
||||||
mkdir -p "${base}/TargetPrint.app"
|
mkdir -p "${base}/TargetPrint.app"
|
||||||
|
# Move bundle contents into TargetPrint.app
|
||||||
shopt -s dotglob
|
shopt -s dotglob
|
||||||
mv "${base}/Contents" "${base}/PkgInfo" "${base}/Resources" "${base}/Info.plist" \
|
mv "${base}/Contents" "${base}/PkgInfo" "${base}/Resources" "${base}/Info.plist" \
|
||||||
"${base}/_CodeSignature" "${base}/TargetPrint.app/" 2>/dev/null || true
|
"${base}/_CodeSignature" "${base}/TargetPrint.app/" 2>/dev/null || true
|
||||||
shopt -u dotglob
|
shopt -u dotglob
|
||||||
fi
|
fi
|
||||||
|
test -x "${base}/TargetPrint.app/Contents/MacOS/TargetPrint"
|
||||||
# 3. If nested inside a subfolder (e.g. app-x86_64/TargetPrint.app)
|
lipo -info "${base}/TargetPrint.app/Contents/MacOS/TargetPrint"
|
||||||
NESTED_APP="$(find "${base}" -mindepth 2 -maxdepth 3 -name "TargetPrint.app" -type d 2>/dev/null | head -n 1 || true)"
|
|
||||||
if [ -n "${NESTED_APP}" ] && [ "${NESTED_APP}" != "${base}/TargetPrint.app" ]; then
|
|
||||||
echo "Moving nested app from ${NESTED_APP} to ${base}/TargetPrint.app..."
|
|
||||||
rm -rf "${base}/TargetPrint.app"
|
|
||||||
mv "${NESTED_APP}" "${base}/TargetPrint.app"
|
|
||||||
fi
|
|
||||||
|
|
||||||
BIN="${base}/TargetPrint.app/Contents/MacOS/TargetPrint"
|
|
||||||
if [ ! -f "${BIN}" ]; then
|
|
||||||
echo "ERROR: Missing binary at ${BIN}" >&2
|
|
||||||
ls -laR "${base}" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
chmod +x "${BIN}"
|
|
||||||
echo "==> Verified binary for ${arch}:"
|
|
||||||
ls -l "${BIN}"
|
|
||||||
lipo -info "${BIN}"
|
|
||||||
done
|
done
|
||||||
./Scripts/make_universal.sh
|
./Scripts/make_universal.sh
|
||||||
lipo -info build/apps/universal/TargetPrint.app/Contents/MacOS/TargetPrint
|
lipo -info build/apps/universal/TargetPrint.app/Contents/MacOS/TargetPrint
|
||||||
@@ -321,7 +288,7 @@ jobs:
|
|||||||
path: ${{ env.PROJECT_ROOT }}/build/release-assets/vendor-iccery
|
path: ${{ env.PROJECT_ROOT }}/build/release-assets/vendor-iccery
|
||||||
|
|
||||||
- name: Upload Release Assets to Gitea
|
- name: Upload Release Assets to Gitea
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/') && success() }}
|
if: ${{ startsWith(github.ref, 'refs/tags/') && !cancelled() }}
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
SERVER_URL: ${{ github.server_url }}
|
SERVER_URL: ${{ github.server_url }}
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ final class PreviewWindowController: NSWindowController {
|
|||||||
engine.mediaSize = parsed.printSettings.mediaSize
|
engine.mediaSize = parsed.printSettings.mediaSize
|
||||||
engine.mediaType = parsed.printSettings.mediaType
|
engine.mediaType = parsed.printSettings.mediaType
|
||||||
engine.paperSource = parsed.printSettings.paperSource
|
engine.paperSource = parsed.printSettings.paperSource
|
||||||
engine.printQuality = parsed.printSettings.printQuality
|
|
||||||
engine.resolution = parsed.printSettings.resolution
|
engine.resolution = parsed.printSettings.resolution
|
||||||
engine.scaling = parsed.printSettings.scaling
|
engine.scaling = parsed.printSettings.scaling
|
||||||
engine.centered = parsed.printSettings.centered
|
engine.centered = parsed.printSettings.centered
|
||||||
|
|||||||
@@ -8,32 +8,9 @@ struct PrintSettings: Equatable {
|
|||||||
var mediaType: String?
|
var mediaType: String?
|
||||||
var paperSource: String?
|
var paperSource: String?
|
||||||
var resolution: String?
|
var resolution: String?
|
||||||
var printQuality: String?
|
|
||||||
var scaling: Double
|
var scaling: Double
|
||||||
var centered: Bool
|
var centered: Bool
|
||||||
var forceUnmanagedColor: Bool
|
var forceUnmanagedColor: Bool
|
||||||
|
|
||||||
init(
|
|
||||||
printerName: String,
|
|
||||||
mediaSize: String,
|
|
||||||
mediaType: String? = nil,
|
|
||||||
paperSource: String? = nil,
|
|
||||||
resolution: String? = nil,
|
|
||||||
printQuality: String? = nil,
|
|
||||||
scaling: Double,
|
|
||||||
centered: Bool,
|
|
||||||
forceUnmanagedColor: Bool
|
|
||||||
) {
|
|
||||||
self.printerName = printerName
|
|
||||||
self.mediaSize = mediaSize
|
|
||||||
self.mediaType = mediaType
|
|
||||||
self.paperSource = paperSource
|
|
||||||
self.resolution = resolution
|
|
||||||
self.printQuality = printQuality
|
|
||||||
self.scaling = scaling
|
|
||||||
self.centered = centered
|
|
||||||
self.forceUnmanagedColor = forceUnmanagedColor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIPolicy: Equatable {
|
struct UIPolicy: Equatable {
|
||||||
@@ -140,7 +117,6 @@ enum TargetJobParser {
|
|||||||
mediaType: stringValue(obj["mediaType"]),
|
mediaType: stringValue(obj["mediaType"]),
|
||||||
paperSource: stringValue(obj["paperSource"]),
|
paperSource: stringValue(obj["paperSource"]),
|
||||||
resolution: stringValue(obj["resolution"]),
|
resolution: stringValue(obj["resolution"]),
|
||||||
printQuality: stringValue(obj["printQuality"]),
|
|
||||||
scaling: scaling,
|
scaling: scaling,
|
||||||
centered: centered,
|
centered: centered,
|
||||||
forceUnmanagedColor: force
|
forceUnmanagedColor: force
|
||||||
@@ -168,7 +144,6 @@ enum TargetJobParser {
|
|||||||
if let v = job.printSettings.mediaType { ps["mediaType"] = v }
|
if let v = job.printSettings.mediaType { ps["mediaType"] = v }
|
||||||
if let v = job.printSettings.paperSource { ps["paperSource"] = v }
|
if let v = job.printSettings.paperSource { ps["paperSource"] = v }
|
||||||
if let v = job.printSettings.resolution { ps["resolution"] = v }
|
if let v = job.printSettings.resolution { ps["resolution"] = v }
|
||||||
if let v = job.printSettings.printQuality { ps["printQuality"] = v }
|
|
||||||
let obj: [String: Any] = [
|
let obj: [String: Any] = [
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"jobTitle": job.jobTitle,
|
"jobTitle": job.jobTitle,
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ struct PrinterQueue: Equatable {
|
|||||||
var trays: [String]
|
var trays: [String]
|
||||||
var trayChoices: [PPDChoice]
|
var trayChoices: [PPDChoice]
|
||||||
var trayKeyword: String?
|
var trayKeyword: String?
|
||||||
var qualityChoices: [PPDChoice]
|
|
||||||
var qualityKeyword: String?
|
|
||||||
var resolutions: [String]
|
var resolutions: [String]
|
||||||
var resolutionChoices: [PPDChoice]
|
|
||||||
var ppdText: String
|
var ppdText: String
|
||||||
|
|
||||||
init(
|
init(
|
||||||
@@ -45,10 +42,7 @@ struct PrinterQueue: Equatable {
|
|||||||
trays: [String],
|
trays: [String],
|
||||||
trayChoices: [PPDChoice] = [],
|
trayChoices: [PPDChoice] = [],
|
||||||
trayKeyword: String? = nil,
|
trayKeyword: String? = nil,
|
||||||
qualityChoices: [PPDChoice] = [],
|
|
||||||
qualityKeyword: String? = nil,
|
|
||||||
resolutions: [String],
|
resolutions: [String],
|
||||||
resolutionChoices: [PPDChoice] = [],
|
|
||||||
ppdText: String
|
ppdText: String
|
||||||
) {
|
) {
|
||||||
self.name = name
|
self.name = name
|
||||||
@@ -65,10 +59,7 @@ struct PrinterQueue: Equatable {
|
|||||||
self.trays = trays
|
self.trays = trays
|
||||||
self.trayChoices = trayChoices
|
self.trayChoices = trayChoices
|
||||||
self.trayKeyword = trayKeyword
|
self.trayKeyword = trayKeyword
|
||||||
self.qualityChoices = qualityChoices
|
|
||||||
self.qualityKeyword = qualityKeyword
|
|
||||||
self.resolutions = resolutions
|
self.resolutions = resolutions
|
||||||
self.resolutionChoices = resolutionChoices
|
|
||||||
self.ppdText = ppdText
|
self.ppdText = ppdText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,10 +112,7 @@ enum CUPSManager {
|
|||||||
trays: options.trays,
|
trays: options.trays,
|
||||||
trayChoices: options.trayChoices,
|
trayChoices: options.trayChoices,
|
||||||
trayKeyword: options.trayKeyword,
|
trayKeyword: options.trayKeyword,
|
||||||
qualityChoices: options.qualityChoices,
|
|
||||||
qualityKeyword: options.qualityKeyword,
|
|
||||||
resolutions: options.resolutions,
|
resolutions: options.resolutions,
|
||||||
resolutionChoices: options.resolutionChoices,
|
|
||||||
ppdText: ppdText
|
ppdText: ppdText
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -158,10 +146,7 @@ enum CUPSManager {
|
|||||||
var trays: [String] = []
|
var trays: [String] = []
|
||||||
var trayChoices: [PPDChoice] = []
|
var trayChoices: [PPDChoice] = []
|
||||||
var trayKeyword: String? = nil
|
var trayKeyword: String? = nil
|
||||||
var qualityChoices: [PPDChoice] = []
|
|
||||||
var qualityKeyword: String? = nil
|
|
||||||
var resolutions: [String] = []
|
var resolutions: [String] = []
|
||||||
var resolutionChoices: [PPDChoice] = []
|
|
||||||
var colorChoices: [(keyword: String, choice: String)] = []
|
var colorChoices: [(keyword: String, choice: String)] = []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,16 +172,7 @@ enum CUPSManager {
|
|||||||
out.trayChoices = trays.choices
|
out.trayChoices = trays.choices
|
||||||
out.trays = trays.choices.map { $0.title }
|
out.trays = trays.choices.map { $0.title }
|
||||||
|
|
||||||
let quality = discoverOptionChoices(
|
out.resolutions = optionChoices(in: ppdText, keyword: "Resolution")
|
||||||
in: ppdText,
|
|
||||||
candidateKeywords: ["CNIJPrintQuality", "EPIJ_Qual", "cupsPrintQuality", "PrintQuality", "CNIJPrintMode2", "Quality", "StpQuality"],
|
|
||||||
openUITargets: ["print quality", "quality"]
|
|
||||||
)
|
|
||||||
out.qualityKeyword = quality.keyword
|
|
||||||
out.qualityChoices = quality.choices
|
|
||||||
|
|
||||||
out.resolutionChoices = optionDetails(in: ppdText, keyword: "Resolution")
|
|
||||||
out.resolutions = out.resolutionChoices.map { $0.name }
|
|
||||||
// Walk every *OpenUI for Colour/Color keys (SPEC §10.3 generic).
|
// Walk every *OpenUI for Colour/Color keys (SPEC §10.3 generic).
|
||||||
let lines = ppdText.split(whereSeparator: \.isNewline)
|
let lines = ppdText.split(whereSeparator: \.isNewline)
|
||||||
var currentKeyword: String?
|
var currentKeyword: String?
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ final class PrintEngine {
|
|||||||
var mediaSize: String
|
var mediaSize: String
|
||||||
var mediaType: String?
|
var mediaType: String?
|
||||||
var paperSource: String?
|
var paperSource: String?
|
||||||
var printQuality: String?
|
|
||||||
var resolution: String?
|
var resolution: String?
|
||||||
var scaling: Double
|
var scaling: Double
|
||||||
var centered: Bool
|
var centered: Bool
|
||||||
@@ -25,7 +24,6 @@ final class PrintEngine {
|
|||||||
mediaSize = job.printSettings.mediaSize
|
mediaSize = job.printSettings.mediaSize
|
||||||
mediaType = job.printSettings.mediaType
|
mediaType = job.printSettings.mediaType
|
||||||
paperSource = job.printSettings.paperSource
|
paperSource = job.printSettings.paperSource
|
||||||
printQuality = job.printSettings.printQuality
|
|
||||||
resolution = job.printSettings.resolution
|
resolution = job.printSettings.resolution
|
||||||
scaling = job.printSettings.scaling
|
scaling = job.printSettings.scaling
|
||||||
centered = job.printSettings.centered
|
centered = job.printSettings.centered
|
||||||
@@ -41,7 +39,6 @@ final class PrintEngine {
|
|||||||
mediaSize = "A4"
|
mediaSize = "A4"
|
||||||
mediaType = nil
|
mediaType = nil
|
||||||
paperSource = nil
|
paperSource = nil
|
||||||
printQuality = nil
|
|
||||||
resolution = nil
|
resolution = nil
|
||||||
scaling = 1.0
|
scaling = 1.0
|
||||||
centered = true
|
centered = true
|
||||||
@@ -51,7 +48,6 @@ final class PrintEngine {
|
|||||||
allowBasicDriverChanges = true
|
allowBasicDriverChanges = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures `NSPrintInfo` for `NSPrintOperation` (SPEC §4.4, §10.3).
|
|
||||||
func makePrintInfo() throws -> NSPrintInfo {
|
func makePrintInfo() throws -> NSPrintInfo {
|
||||||
let info = NSPrintInfo.shared.copy() as! NSPrintInfo
|
let info = NSPrintInfo.shared.copy() as! NSPrintInfo
|
||||||
info.jobDisposition = .spool
|
info.jobDisposition = .spool
|
||||||
@@ -110,44 +106,6 @@ final class PrintEngine {
|
|||||||
extras[key] = paperSource
|
extras[key] = paperSource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let printQuality = printQuality {
|
|
||||||
let key = queue?.qualityKeyword ?? "PrintQuality"
|
|
||||||
let resolvedCode: String
|
|
||||||
if let match = queue?.qualityChoices.first(where: { $0.name == printQuality || $0.title.caseInsensitiveCompare(printQuality) == .orderedSame }) {
|
|
||||||
resolvedCode = match.name
|
|
||||||
} else {
|
|
||||||
resolvedCode = printQuality
|
|
||||||
}
|
|
||||||
|
|
||||||
if key == "CNIJPrintQuality" {
|
|
||||||
switch resolvedCode {
|
|
||||||
case "0": // Super Fine (notch 5 — Custom mode)
|
|
||||||
extras["CNIJPrintQuality"] = "0"
|
|
||||||
extras["CNIJPrintMode2"] = "5"
|
|
||||||
extras["CNIJPQualitySlider"] = "5"
|
|
||||||
case "5": // Fine (notch 4 — High preset)
|
|
||||||
extras["CNIJPrintQuality"] = "5"
|
|
||||||
extras["CNIJPrintMode2"] = "1"
|
|
||||||
extras["CNIJPQualitySlider"] = "4"
|
|
||||||
case "10": // Normal(Fine) (notch 3 — Standard preset)
|
|
||||||
extras["CNIJPrintQuality"] = "10"
|
|
||||||
extras["CNIJPrintMode2"] = "2"
|
|
||||||
extras["CNIJPQualitySlider"] = "3"
|
|
||||||
case "15": // Normal(Fast) (notch 2)
|
|
||||||
extras["CNIJPrintQuality"] = "15"
|
|
||||||
extras["CNIJPrintMode2"] = "5"
|
|
||||||
extras["CNIJPQualitySlider"] = "2"
|
|
||||||
case "20": // Fast (notch 1 — Fast preset)
|
|
||||||
extras["CNIJPrintQuality"] = "20"
|
|
||||||
extras["CNIJPrintMode2"] = "3"
|
|
||||||
extras["CNIJPQualitySlider"] = "1"
|
|
||||||
default:
|
|
||||||
extras["CNIJPrintQuality"] = resolvedCode
|
|
||||||
}
|
|
||||||
} else if resolvedCode.lowercased() != "auto" || key == "cupsPrintQuality" {
|
|
||||||
extras[key] = resolvedCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let resolution = resolution { extras["Resolution"] = resolution }
|
if let resolution = resolution { extras["Resolution"] = resolution }
|
||||||
if extras.isEmpty { return }
|
if extras.isEmpty { return }
|
||||||
CUPSManager.applyVendorBypass(extras, to: info)
|
CUPSManager.applyVendorBypass(extras, to: info)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ final class InspectorView: NSView {
|
|||||||
let mediaPop = NSPopUpButton()
|
let mediaPop = NSPopUpButton()
|
||||||
let typePop = NSPopUpButton()
|
let typePop = NSPopUpButton()
|
||||||
let trayPop = NSPopUpButton()
|
let trayPop = NSPopUpButton()
|
||||||
let qualityPop = NSPopUpButton()
|
|
||||||
let resolutionPop = NSPopUpButton()
|
let resolutionPop = NSPopUpButton()
|
||||||
let scaleSlider = NSSlider()
|
let scaleSlider = NSSlider()
|
||||||
let scaleLabel = NSTextField(labelWithString: "100%")
|
let scaleLabel = NSTextField(labelWithString: "100%")
|
||||||
@@ -47,7 +46,6 @@ final class InspectorView: NSView {
|
|||||||
mediaPop.target = self; mediaPop.action = #selector(changed)
|
mediaPop.target = self; mediaPop.action = #selector(changed)
|
||||||
typePop.target = self; typePop.action = #selector(changed)
|
typePop.target = self; typePop.action = #selector(changed)
|
||||||
trayPop.target = self; trayPop.action = #selector(changed)
|
trayPop.target = self; trayPop.action = #selector(changed)
|
||||||
qualityPop.target = self; qualityPop.action = #selector(changed)
|
|
||||||
resolutionPop.target = self; resolutionPop.action = #selector(changed)
|
resolutionPop.target = self; resolutionPop.action = #selector(changed)
|
||||||
scaleSlider.minValue = 0.5
|
scaleSlider.minValue = 0.5
|
||||||
scaleSlider.maxValue = 1.5
|
scaleSlider.maxValue = 1.5
|
||||||
@@ -81,7 +79,6 @@ final class InspectorView: NSView {
|
|||||||
section("Media size", mediaPop),
|
section("Media size", mediaPop),
|
||||||
section("Media type", typePop),
|
section("Media type", typePop),
|
||||||
section("Tray", trayPop),
|
section("Tray", trayPop),
|
||||||
section("Print quality", qualityPop),
|
|
||||||
section("Resolution", resolutionPop),
|
section("Resolution", resolutionPop),
|
||||||
section("Scale", scaleRow()),
|
section("Scale", scaleRow()),
|
||||||
centeredCheck,
|
centeredCheck,
|
||||||
@@ -104,7 +101,6 @@ final class InspectorView: NSView {
|
|||||||
mediaPop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
mediaPop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
||||||
typePop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
typePop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
||||||
trayPop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
trayPop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
||||||
qualityPop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
|
||||||
resolutionPop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
resolutionPop.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
||||||
colorSeg.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
colorSeg.widthAnchor.constraint(equalTo: stack.widthAnchor),
|
||||||
])
|
])
|
||||||
@@ -130,7 +126,6 @@ final class InspectorView: NSView {
|
|||||||
select(mediaPop, engine.mediaSize)
|
select(mediaPop, engine.mediaSize)
|
||||||
if let t = engine.mediaType { selectChoice(typePop, t) }
|
if let t = engine.mediaType { selectChoice(typePop, t) }
|
||||||
if let t = engine.paperSource { selectChoice(trayPop, t) }
|
if let t = engine.paperSource { selectChoice(trayPop, t) }
|
||||||
if let q = engine.printQuality { selectChoice(qualityPop, q) }
|
|
||||||
if let r = engine.resolution { select(resolutionPop, r) }
|
if let r = engine.resolution { select(resolutionPop, r) }
|
||||||
scaleSlider.doubleValue = engine.scaling
|
scaleSlider.doubleValue = engine.scaling
|
||||||
scaleLabel.stringValue = String(format: "%.0f%%", engine.scaling * 100)
|
scaleLabel.stringValue = String(format: "%.0f%%", engine.scaling * 100)
|
||||||
@@ -150,7 +145,6 @@ final class InspectorView: NSView {
|
|||||||
engine.mediaSize = mediaPop.titleOfSelectedItem ?? engine.mediaSize
|
engine.mediaSize = mediaPop.titleOfSelectedItem ?? engine.mediaSize
|
||||||
engine.mediaType = (typePop.selectedItem?.representedObject as? String) ?? emptyToNil(typePop.titleOfSelectedItem)
|
engine.mediaType = (typePop.selectedItem?.representedObject as? String) ?? emptyToNil(typePop.titleOfSelectedItem)
|
||||||
engine.paperSource = (trayPop.selectedItem?.representedObject as? String) ?? emptyToNil(trayPop.titleOfSelectedItem)
|
engine.paperSource = (trayPop.selectedItem?.representedObject as? String) ?? emptyToNil(trayPop.titleOfSelectedItem)
|
||||||
engine.printQuality = (qualityPop.selectedItem?.representedObject as? String) ?? emptyToNil(qualityPop.titleOfSelectedItem)
|
|
||||||
engine.resolution = emptyToNil(resolutionPop.titleOfSelectedItem)
|
engine.resolution = emptyToNil(resolutionPop.titleOfSelectedItem)
|
||||||
engine.scaling = scaleSlider.doubleValue
|
engine.scaling = scaleSlider.doubleValue
|
||||||
engine.centered = centeredCheck.state == .on
|
engine.centered = centeredCheck.state == .on
|
||||||
@@ -167,7 +161,6 @@ final class InspectorView: NSView {
|
|||||||
mediaPop.isEnabled = mediaEnabled
|
mediaPop.isEnabled = mediaEnabled
|
||||||
typePop.isEnabled = mediaEnabled
|
typePop.isEnabled = mediaEnabled
|
||||||
trayPop.isEnabled = mediaEnabled
|
trayPop.isEnabled = mediaEnabled
|
||||||
qualityPop.isEnabled = mediaEnabled && (selectedQueue?.qualityChoices.isEmpty == false)
|
|
||||||
resolutionPop.isEnabled = !jobLocked
|
resolutionPop.isEnabled = !jobLocked
|
||||||
landscapeCheck.isEnabled = mediaEnabled
|
landscapeCheck.isEnabled = mediaEnabled
|
||||||
scaleSlider.isEnabled = !jobLocked
|
scaleSlider.isEnabled = !jobLocked
|
||||||
@@ -195,9 +188,6 @@ final class InspectorView: NSView {
|
|||||||
refillChoices(typePop, mediaChoices)
|
refillChoices(typePop, mediaChoices)
|
||||||
let trayChoices = (q?.trayChoices.isEmpty == false) ? q!.trayChoices : [PPDChoice(name: "Auto", title: "Auto")]
|
let trayChoices = (q?.trayChoices.isEmpty == false) ? q!.trayChoices : [PPDChoice(name: "Auto", title: "Auto")]
|
||||||
refillChoices(trayPop, trayChoices)
|
refillChoices(trayPop, trayChoices)
|
||||||
let qualityChoices = (q?.qualityChoices.isEmpty == false) ? q!.qualityChoices : [PPDChoice(name: "Auto", title: "Auto")]
|
|
||||||
refillChoices(qualityPop, qualityChoices)
|
|
||||||
qualityPop.isEnabled = allowBasicDriverChanges && !jobLocked && (q?.qualityChoices.isEmpty == false)
|
|
||||||
refill(resolutionPop, q?.resolutions ?? [])
|
refill(resolutionPop, q?.resolutions ?? [])
|
||||||
updateAirPrint()
|
updateAirPrint()
|
||||||
}
|
}
|
||||||
@@ -225,8 +215,7 @@ final class InspectorView: NSView {
|
|||||||
pop.addItem(withTitle: choice.title)
|
pop.addItem(withTitle: choice.title)
|
||||||
pop.lastItem?.representedObject = choice.name
|
pop.lastItem?.representedObject = choice.name
|
||||||
}
|
}
|
||||||
if let current = currentChoice,
|
if let current = currentChoice {
|
||||||
choices.contains(where: { $0.name == current || $0.title == current }) {
|
|
||||||
selectChoice(pop, current)
|
selectChoice(pop, current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,106 +220,6 @@ final class PPDOptionsTests: XCTestCase {
|
|||||||
let canonSettings = canonPrintInfo.dictionary()[settingsKey] as? NSDictionary
|
let canonSettings = canonPrintInfo.dictionary()[settingsKey] as? NSDictionary
|
||||||
XCTAssertEqual(canonSettings?["CNIJMediaType"] as? String, "92")
|
XCTAssertEqual(canonSettings?["CNIJMediaType"] as? String, "92")
|
||||||
XCTAssertEqual(canonSettings?["CNIJMediaSupply"] as? String, "7")
|
XCTAssertEqual(canonSettings?["CNIJMediaSupply"] as? String, "7")
|
||||||
|
|
||||||
// Canon 5-notch Custom quality tests
|
|
||||||
let canonQualityPPD = """
|
|
||||||
*OpenUI *CNIJPrintQuality/Print Quality: PickOne
|
|
||||||
*CNIJPrintQuality 0/Super Fine: ""
|
|
||||||
*CNIJPrintQuality 5/Fine: ""
|
|
||||||
*CNIJPrintQuality 10/Normal(Fine): ""
|
|
||||||
*CNIJPrintQuality 15/Normal(Fast): ""
|
|
||||||
*CNIJPrintQuality 20/Fast: ""
|
|
||||||
*CloseUI: *CNIJPrintQuality
|
|
||||||
"""
|
|
||||||
let canonQOpts = CUPSManager.discoverPPDOptions(canonQualityPPD)
|
|
||||||
XCTAssertEqual(canonQOpts.qualityKeyword, "CNIJPrintQuality")
|
|
||||||
XCTAssertEqual(canonQOpts.qualityChoices, [
|
|
||||||
PPDChoice(name: "0", title: "Super Fine"),
|
|
||||||
PPDChoice(name: "5", title: "Fine"),
|
|
||||||
PPDChoice(name: "10", title: "Normal(Fine)"),
|
|
||||||
PPDChoice(name: "15", title: "Normal(Fast)"),
|
|
||||||
PPDChoice(name: "20", title: "Fast")
|
|
||||||
])
|
|
||||||
|
|
||||||
let canonQQueue = PrinterQueue(
|
|
||||||
name: "TestCanonQ",
|
|
||||||
displayName: "Test Canon Quality",
|
|
||||||
uri: "usb://canon",
|
|
||||||
make: "Canon",
|
|
||||||
model: "Pro9500",
|
|
||||||
isAirPrint: false,
|
|
||||||
mediaSizes: ["A4"],
|
|
||||||
mediaTypes: [],
|
|
||||||
mediaTypeChoices: [],
|
|
||||||
mediaTypeKeyword: nil,
|
|
||||||
trays: [],
|
|
||||||
trayChoices: [],
|
|
||||||
trayKeyword: nil,
|
|
||||||
qualityChoices: canonQOpts.qualityChoices,
|
|
||||||
qualityKeyword: canonQOpts.qualityKeyword,
|
|
||||||
resolutions: [],
|
|
||||||
ppdText: canonQualityPPD
|
|
||||||
)
|
|
||||||
|
|
||||||
// Super Fine: custom mode 5, slider notch 5, quality 0
|
|
||||||
let superFineEngine = PrintEngine()
|
|
||||||
superFineEngine.printQuality = "Super Fine"
|
|
||||||
let superFineInfo = NSPrintInfo()
|
|
||||||
superFineEngine.applyOptionalPPDKeys(to: superFineInfo, queue: canonQQueue)
|
|
||||||
let superFineSettings = superFineInfo.dictionary()[settingsKey] as? NSDictionary
|
|
||||||
XCTAssertEqual(superFineSettings?["CNIJPrintQuality"] as? String, "0")
|
|
||||||
XCTAssertEqual(superFineSettings?["CNIJPrintMode2"] as? String, "5")
|
|
||||||
XCTAssertEqual(superFineSettings?["CNIJPQualitySlider"] as? String, "5")
|
|
||||||
|
|
||||||
// Fine: preset mode 1, slider notch 4, quality 5
|
|
||||||
let fineEngine = PrintEngine()
|
|
||||||
fineEngine.printQuality = "Fine"
|
|
||||||
let fineInfo = NSPrintInfo()
|
|
||||||
fineEngine.applyOptionalPPDKeys(to: fineInfo, queue: canonQQueue)
|
|
||||||
let fineSettings = fineInfo.dictionary()[settingsKey] as? NSDictionary
|
|
||||||
XCTAssertEqual(fineSettings?["CNIJPrintQuality"] as? String, "5")
|
|
||||||
XCTAssertEqual(fineSettings?["CNIJPrintMode2"] as? String, "1")
|
|
||||||
XCTAssertEqual(fineSettings?["CNIJPQualitySlider"] as? String, "4")
|
|
||||||
|
|
||||||
// Epson quality test
|
|
||||||
let epsonQualityPPD = """
|
|
||||||
*OpenUI *EPIJ_Qual/Quality: PickOne
|
|
||||||
*EPIJ_Qual 307/Best Quality: ""
|
|
||||||
*EPIJ_Qual 305/Quality: ""
|
|
||||||
*EPIJ_Qual 304/Fine: ""
|
|
||||||
*CloseUI: *EPIJ_Qual
|
|
||||||
"""
|
|
||||||
let epsonQOpts = CUPSManager.discoverPPDOptions(epsonQualityPPD)
|
|
||||||
XCTAssertEqual(epsonQOpts.qualityKeyword, "EPIJ_Qual")
|
|
||||||
XCTAssertEqual(epsonQOpts.qualityChoices.count, 3)
|
|
||||||
XCTAssertEqual(epsonQOpts.qualityChoices.first?.name, "307")
|
|
||||||
XCTAssertEqual(epsonQOpts.qualityChoices.first?.title, "Best Quality")
|
|
||||||
|
|
||||||
let epsonQQueue = PrinterQueue(
|
|
||||||
name: "TestEpsonQ",
|
|
||||||
displayName: "Test Epson Quality",
|
|
||||||
uri: "usb://epson",
|
|
||||||
make: "Epson",
|
|
||||||
model: "XP-55",
|
|
||||||
isAirPrint: false,
|
|
||||||
mediaSizes: ["A4"],
|
|
||||||
mediaTypes: [],
|
|
||||||
mediaTypeChoices: [],
|
|
||||||
mediaTypeKeyword: nil,
|
|
||||||
trays: [],
|
|
||||||
trayChoices: [],
|
|
||||||
trayKeyword: nil,
|
|
||||||
qualityChoices: epsonQOpts.qualityChoices,
|
|
||||||
qualityKeyword: epsonQOpts.qualityKeyword,
|
|
||||||
resolutions: [],
|
|
||||||
ppdText: epsonQualityPPD
|
|
||||||
)
|
|
||||||
let epsonQEngine = PrintEngine()
|
|
||||||
epsonQEngine.printQuality = "Best Quality"
|
|
||||||
let epsonQInfo = NSPrintInfo()
|
|
||||||
epsonQEngine.applyOptionalPPDKeys(to: epsonQInfo, queue: epsonQQueue)
|
|
||||||
let epsonQSettings = epsonQInfo.dictionary()[settingsKey] as? NSDictionary
|
|
||||||
XCTAssertEqual(epsonQSettings?["EPIJ_Qual"] as? String, "307")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -199,106 +199,6 @@ struct TestRunner {
|
|||||||
expectEqual(canonSettings?["CNIJMediaType"] as? String, Optional("92"))
|
expectEqual(canonSettings?["CNIJMediaType"] as? String, Optional("92"))
|
||||||
expectEqual(canonSettings?["CNIJMediaSupply"] as? String, Optional("7"))
|
expectEqual(canonSettings?["CNIJMediaSupply"] as? String, Optional("7"))
|
||||||
|
|
||||||
// Canon 5-notch Custom quality tests
|
|
||||||
let canonQualityPPD = """
|
|
||||||
*OpenUI *CNIJPrintQuality/Print Quality: PickOne
|
|
||||||
*CNIJPrintQuality 0/Super Fine: ""
|
|
||||||
*CNIJPrintQuality 5/Fine: ""
|
|
||||||
*CNIJPrintQuality 10/Normal(Fine): ""
|
|
||||||
*CNIJPrintQuality 15/Normal(Fast): ""
|
|
||||||
*CNIJPrintQuality 20/Fast: ""
|
|
||||||
*CloseUI: *CNIJPrintQuality
|
|
||||||
"""
|
|
||||||
let canonQOpts = CUPSManager.discoverPPDOptions(canonQualityPPD)
|
|
||||||
expectEqual(canonQOpts.qualityKeyword, "CNIJPrintQuality")
|
|
||||||
expectEqual(canonQOpts.qualityChoices, [
|
|
||||||
PPDChoice(name: "0", title: "Super Fine"),
|
|
||||||
PPDChoice(name: "5", title: "Fine"),
|
|
||||||
PPDChoice(name: "10", title: "Normal(Fine)"),
|
|
||||||
PPDChoice(name: "15", title: "Normal(Fast)"),
|
|
||||||
PPDChoice(name: "20", title: "Fast")
|
|
||||||
])
|
|
||||||
|
|
||||||
let canonQQueue = PrinterQueue(
|
|
||||||
name: "TestCanonQ",
|
|
||||||
displayName: "Test Canon Quality",
|
|
||||||
uri: "usb://canon",
|
|
||||||
make: "Canon",
|
|
||||||
model: "Pro9500",
|
|
||||||
isAirPrint: false,
|
|
||||||
mediaSizes: ["A4"],
|
|
||||||
mediaTypes: [],
|
|
||||||
mediaTypeChoices: [],
|
|
||||||
mediaTypeKeyword: nil,
|
|
||||||
trays: [],
|
|
||||||
trayChoices: [],
|
|
||||||
trayKeyword: nil,
|
|
||||||
qualityChoices: canonQOpts.qualityChoices,
|
|
||||||
qualityKeyword: canonQOpts.qualityKeyword,
|
|
||||||
resolutions: [],
|
|
||||||
ppdText: canonQualityPPD
|
|
||||||
)
|
|
||||||
|
|
||||||
// Super Fine: custom mode 5, slider notch 5, quality 0
|
|
||||||
let superFineEngine = PrintEngine()
|
|
||||||
superFineEngine.printQuality = "Super Fine"
|
|
||||||
let superFineInfo = NSPrintInfo()
|
|
||||||
superFineEngine.applyOptionalPPDKeys(to: superFineInfo, queue: canonQQueue)
|
|
||||||
let superFineSettings = superFineInfo.dictionary()[settingsKey] as? NSDictionary
|
|
||||||
expectEqual(superFineSettings?["CNIJPrintQuality"] as? String, Optional("0"))
|
|
||||||
expectEqual(superFineSettings?["CNIJPrintMode2"] as? String, Optional("5"))
|
|
||||||
expectEqual(superFineSettings?["CNIJPQualitySlider"] as? String, Optional("5"))
|
|
||||||
|
|
||||||
// Fine: preset mode 1, slider notch 4, quality 5
|
|
||||||
let fineEngine = PrintEngine()
|
|
||||||
fineEngine.printQuality = "Fine"
|
|
||||||
let fineInfo = NSPrintInfo()
|
|
||||||
fineEngine.applyOptionalPPDKeys(to: fineInfo, queue: canonQQueue)
|
|
||||||
let fineSettings = fineInfo.dictionary()[settingsKey] as? NSDictionary
|
|
||||||
expectEqual(fineSettings?["CNIJPrintQuality"] as? String, Optional("5"))
|
|
||||||
expectEqual(fineSettings?["CNIJPrintMode2"] as? String, Optional("1"))
|
|
||||||
expectEqual(fineSettings?["CNIJPQualitySlider"] as? String, Optional("4"))
|
|
||||||
|
|
||||||
// Epson quality test
|
|
||||||
let epsonQualityPPD = """
|
|
||||||
*OpenUI *EPIJ_Qual/Quality: PickOne
|
|
||||||
*EPIJ_Qual 307/Best Quality: ""
|
|
||||||
*EPIJ_Qual 305/Quality: ""
|
|
||||||
*EPIJ_Qual 304/Fine: ""
|
|
||||||
*CloseUI: *EPIJ_Qual
|
|
||||||
"""
|
|
||||||
let epsonQOpts = CUPSManager.discoverPPDOptions(epsonQualityPPD)
|
|
||||||
expectEqual(epsonQOpts.qualityKeyword, "EPIJ_Qual")
|
|
||||||
expectEqual(epsonQOpts.qualityChoices.count, 3)
|
|
||||||
expectEqual(epsonQOpts.qualityChoices.first?.name, "307")
|
|
||||||
expectEqual(epsonQOpts.qualityChoices.first?.title, "Best Quality")
|
|
||||||
|
|
||||||
let epsonQQueue = PrinterQueue(
|
|
||||||
name: "TestEpsonQ",
|
|
||||||
displayName: "Test Epson Quality",
|
|
||||||
uri: "usb://epson",
|
|
||||||
make: "Epson",
|
|
||||||
model: "XP-55",
|
|
||||||
isAirPrint: false,
|
|
||||||
mediaSizes: ["A4"],
|
|
||||||
mediaTypes: [],
|
|
||||||
mediaTypeChoices: [],
|
|
||||||
mediaTypeKeyword: nil,
|
|
||||||
trays: [],
|
|
||||||
trayChoices: [],
|
|
||||||
trayKeyword: nil,
|
|
||||||
qualityChoices: epsonQOpts.qualityChoices,
|
|
||||||
qualityKeyword: epsonQOpts.qualityKeyword,
|
|
||||||
resolutions: [],
|
|
||||||
ppdText: epsonQualityPPD
|
|
||||||
)
|
|
||||||
let epsonQEngine = PrintEngine()
|
|
||||||
epsonQEngine.printQuality = "Best Quality"
|
|
||||||
let epsonQInfo = NSPrintInfo()
|
|
||||||
epsonQEngine.applyOptionalPPDKeys(to: epsonQInfo, queue: epsonQQueue)
|
|
||||||
let epsonQSettings = epsonQInfo.dictionary()[settingsKey] as? NSDictionary
|
|
||||||
expectEqual(epsonQSettings?["EPIJ_Qual"] as? String, Optional("307"))
|
|
||||||
|
|
||||||
print(" [PASS] PPDOptionsTests")
|
print(" [PASS] PPDOptionsTests")
|
||||||
|
|
||||||
// MARK: - 2. AirPrintTests
|
// MARK: - 2. AirPrintTests
|
||||||
@@ -349,7 +249,6 @@ struct TestRunner {
|
|||||||
"mediaType": "PremiumGlossy",
|
"mediaType": "PremiumGlossy",
|
||||||
"paperSource": "Auto",
|
"paperSource": "Auto",
|
||||||
"resolution": "5760x1440dpi",
|
"resolution": "5760x1440dpi",
|
||||||
"printQuality": "Super Fine",
|
|
||||||
"scaling": 1.0,
|
"scaling": 1.0,
|
||||||
"centered": true,
|
"centered": true,
|
||||||
"forceUnmanagedColor": true
|
"forceUnmanagedColor": true
|
||||||
@@ -367,11 +266,9 @@ struct TestRunner {
|
|||||||
expectEqual(parsed.jobTitle, "Epson_XP55_IlfordLustre_Target_P1-2")
|
expectEqual(parsed.jobTitle, "Epson_XP55_IlfordLustre_Target_P1-2")
|
||||||
expectEqual(parsed.files.count, 2)
|
expectEqual(parsed.files.count, 2)
|
||||||
expectEqual(parsed.printSettings.mediaType, "PremiumGlossy")
|
expectEqual(parsed.printSettings.mediaType, "PremiumGlossy")
|
||||||
expectEqual(parsed.printSettings.printQuality, "Super Fine")
|
|
||||||
let serialized = try TargetJobParser.serialize(parsed)
|
let serialized = try TargetJobParser.serialize(parsed)
|
||||||
let again = try TargetJobParser.parse(data: serialized)
|
let again = try TargetJobParser.parse(data: serialized)
|
||||||
expectEqual(parsed, again)
|
expectEqual(parsed, again)
|
||||||
expectEqual(again.printSettings.printQuality, "Super Fine")
|
|
||||||
} catch {
|
} catch {
|
||||||
fputs("TargetJob parsing error: \(error)\n", stderr)
|
fputs("TargetJob parsing error: \(error)\n", stderr)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user