Skip to content

Commit

Permalink
Implement printing.
Browse files Browse the repository at this point in the history
We support printing only for certain file types, currently: `.gif`,
`.jpg`, `.md`, `.pdf`, `.png`, `.rtf`, `.txt`. For all other formats,
open them in their corresponding applications first and print from
there.
  • Loading branch information
rsmmr committed Jan 20, 2024
1 parent 1459f2a commit d1fa14b
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
<key>qlview-adhoc.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
<integer>0</integer>
</dict>
<key>qlview-signed.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
<integer>1</integer>
</dict>
<key>qlview.xcscheme_^#shared#^_</key>
<dict>
Expand Down
14 changes: 9 additions & 5 deletions qlview/app.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ extension FocusedValues {
struct qlviewApp: App {
@Environment(\.dismiss) private var dismiss
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@FocusedBinding(\.document) var document
@FocusedBinding(\.document) var document_binding

var document : Document? {
guard let document = document_binding else { return nil }
return document
}

@State private var showAbout = false

var body: some Scene {
WindowGroup(for: Document.self) { $doc in
ContentView(doc: doc)
Expand Down Expand Up @@ -50,7 +56,6 @@ struct qlviewApp: App {

Button("Open in App") {
guard let document = document else { return }
guard let document = document else { return }

document.open()
NSApplication.shared.keyWindow?.close()
Expand All @@ -59,7 +64,6 @@ struct qlviewApp: App {

Button("Move To ...") {
guard let document = document else { return }
guard let document = document else { return }

if document.move() {
NSApplication.shared.keyWindow?.close()
Expand All @@ -72,11 +76,11 @@ struct qlviewApp: App {

Button("Print ...") {
guard let document = document else { return }
guard let document = document else { return }

document.print()
}
.keyboardShortcut("p", modifiers: .command)
.disabled(document == nil || !document!.canPrint())
})
}
}
Expand Down
150 changes: 136 additions & 14 deletions qlview/document.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import SwiftUI
import PDFKit
import WebKit

struct Document: Identifiable, Codable, Hashable {
var url: URL
Expand Down Expand Up @@ -37,22 +39,142 @@ struct Document: Identifiable, Codable, Hashable {
}
}
}
return false
return false
}


func print() {
showAlert(msg: "Error", sub: "Printing not yet implemented.", style: .critical)
// let nsview = view.makeNSView(context: nil)
//
// let view = QLView(url: url, qlview: nsview)
// let renderer = ImageRenderer(content: AnyView(view) )
// let nsview = view.makeNSView(context: nil)
// let printInfo = NSPrintInfo()
// let printOperation = NSPrintOperation(view: view)
// printOperation.showsPrintPanel = true
// printOperation.showsProgressPanel = true
// printOperation.run()
// Printing

func isHTML() -> Bool {
return url.pathExtension == "html"
}

func isImage() -> Bool {
return url.pathExtension == "png" || url.pathExtension == "gif" || url.pathExtension == "jpg" || url.pathExtension == "jpeg";
}

func isMarkdown() -> Bool {
return url.pathExtension == "md"
}

func isPDF() -> Bool {
return url.pathExtension == "pdf"
}

func isTxt() -> NSAttributedString.DocumentType? {
if url.pathExtension == "txt" {
return .plain
}

if url.pathExtension == "rtf" {
return .rtf
}

return nil
}

func canPrint() -> Bool {
return isPDF() || isMarkdown() || isImage() || isTxt() != nil // TODO: isHTML() currently no working
}

func print() {
guard canPrint() else { return }

let info = NSPrintInfo.shared
let paper_size = NSRect(x: 0, y: 0, width: info.paperSize.width, height: info.paperSize.height)

info.horizontalPagination = .automatic
info.verticalPagination = .automatic
info.verticalPagination = .fit
info.horizontalPagination = .fit
info.orientation = .portrait
info.isHorizontallyCentered = false
info.isVerticallyCentered = false

var op : NSPrintOperation?

if isHTML() {
// TODO: This doesn't work, printed docoument is always empty.
// We currently don't get here.
assert(false)

// let html = WKWebView(frame: paper_size)
// html.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())
// html.bounds = paper_size
//
// // op = html.printOperation(with: printInfo)
// op = NSPrintOperation(view: html)
}

else if ( isImage() ) {
guard let image = NSImage(contentsOf: url) else { return }
let imageView = NSImageView(image: image)
imageView.frame = NSRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
imageView.imageScaling = .scaleProportionallyDown

info.isHorizontallyCentered = false
info.isVerticallyCentered = false
op = NSPrintOperation(view: imageView)
}

else if isMarkdown() {
do {
let txt = try NSMutableAttributedString(markdown: "Hello, **World**!")

let view = NSTextView()
view.frame = paper_size
view.textStorage?.setAttributedString(txt)
op = NSPrintOperation(view: view, printInfo: info)
}
catch {
showAlert(msg: "Printing Error", sub: "Cannot load markdown document.")
}
}

else if isPDF() {
let pdf = PDFDocument(url: self.url)
let scale: PDFPrintScalingMode = .pageScaleNone
op = pdf?.printOperation(for: info, scalingMode: scale, autoRotate: true)
}

else if let type = isTxt() {
do {
let txt = try NSMutableAttributedString(url: url, options:
[.documentType: type,
.characterEncoding: String.Encoding.utf8.rawValue,
.baseURL: url, // not really used
.readAccessURL: url.deletingLastPathComponent() // not really used
], documentAttributes: nil)

let style = NSMutableParagraphStyle()
style.lineBreakMode = .byCharWrapping

txt.setAttributes([
.font: NSFont.monospacedSystemFont(ofSize: 10, weight: .regular),
.paragraphStyle: style
], range: NSMakeRange(0, txt.length))


let view = NSTextView()
view.frame = paper_size
view.textStorage?.setAttributedString(txt)
op = NSPrintOperation(view: view, printInfo: info)
}
catch {
showAlert(msg: "Printing Error", sub: "Cannot load text document.")
}
}

if op == nil {
showAlert(msg: "Print failure", sub: "Cannot print document type")
return
}

op?.jobTitle = url.lastPathComponent
op?.showsPrintPanel = true
op?.showsProgressPanel = true

DispatchQueue.main.async {
op?.run()
}
}
}
6 changes: 4 additions & 2 deletions qlview/view.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,12 @@ struct ContentView: View {

Button(action: { doc.print() }) {
Image(systemName: "printer")
}.help("Print")
}
.disabled(!doc.canPrint())
.help("Print")

ShareLink(item: doc.url)
.help("Share ...")
.help("Share ...")
}

ToolbarItemGroup(placement: .automatic) {
Expand Down

0 comments on commit d1fa14b

Please sign in to comment.