codendium 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codendium-1.0.0.dist-info/METADATA +332 -0
- codendium-1.0.0.dist-info/RECORD +45 -0
- codendium-1.0.0.dist-info/WHEEL +5 -0
- codendium-1.0.0.dist-info/entry_points.txt +6 -0
- codendium-1.0.0.dist-info/licenses/LICENSE +201 -0
- codendium-1.0.0.dist-info/top_level.txt +1 -0
- copyright_deposit/__init__.py +15 -0
- copyright_deposit/__main__.py +34 -0
- copyright_deposit/assets/__init__.py +5 -0
- copyright_deposit/assets/fonts/README.md +31 -0
- copyright_deposit/assets/logo.svg +26 -0
- copyright_deposit/cli.py +314 -0
- copyright_deposit/config.py +269 -0
- copyright_deposit/core/__init__.py +1 -0
- copyright_deposit/core/deposit.py +117 -0
- copyright_deposit/core/discovery.py +260 -0
- copyright_deposit/core/encoding.py +136 -0
- copyright_deposit/core/languages.py +190 -0
- copyright_deposit/core/layout.py +349 -0
- copyright_deposit/core/lineranges.py +219 -0
- copyright_deposit/core/manifest.py +282 -0
- copyright_deposit/core/metrics.py +279 -0
- copyright_deposit/core/ordering.py +349 -0
- copyright_deposit/core/pipeline.py +386 -0
- copyright_deposit/core/redaction.py +162 -0
- copyright_deposit/core/render.py +242 -0
- copyright_deposit/core/scanning/__init__.py +61 -0
- copyright_deposit/core/scanning/secrets.py +181 -0
- copyright_deposit/core/scanning/thirdparty.py +190 -0
- copyright_deposit/core/strip/__init__.py +337 -0
- copyright_deposit/core/strip/cfamily_strip.py +235 -0
- copyright_deposit/core/strip/pygments_strip.py +85 -0
- copyright_deposit/core/strip/python_strip.py +131 -0
- copyright_deposit/gui/__init__.py +1 -0
- copyright_deposit/gui/app.py +34 -0
- copyright_deposit/gui/branding.py +83 -0
- copyright_deposit/gui/history.py +192 -0
- copyright_deposit/gui/main_window.py +617 -0
- copyright_deposit/gui/panels/__init__.py +1 -0
- copyright_deposit/gui/panels/estimate.py +166 -0
- copyright_deposit/gui/panels/files.py +635 -0
- copyright_deposit/gui/panels/identification.py +193 -0
- copyright_deposit/gui/panels/options.py +445 -0
- copyright_deposit/gui/panels/preflight.py +260 -0
- copyright_deposit/gui/workers.py +96 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""The estimate: page count, which pages get deposited, and what to change.
|
|
2
|
+
|
|
3
|
+
The number shown here is not a projection. Estimating runs the same
|
|
4
|
+
discovery, stripping and layout the renderer uses and stops just before
|
|
5
|
+
writing the PDF, so the page count is exact.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from PySide6.QtCore import Qt, Signal
|
|
11
|
+
from PySide6.QtGui import QFont, QGuiApplication
|
|
12
|
+
from PySide6.QtWidgets import (
|
|
13
|
+
QAbstractItemView,
|
|
14
|
+
QGroupBox,
|
|
15
|
+
QHBoxLayout,
|
|
16
|
+
QHeaderView,
|
|
17
|
+
QLabel,
|
|
18
|
+
QListWidget,
|
|
19
|
+
QPushButton,
|
|
20
|
+
QTableWidget,
|
|
21
|
+
QTableWidgetItem,
|
|
22
|
+
QVBoxLayout,
|
|
23
|
+
QWidget,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from ...core.deposit import MODE_ENTIRE
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _cell(text: str) -> QTableWidgetItem:
|
|
30
|
+
item = QTableWidgetItem(text)
|
|
31
|
+
item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable)
|
|
32
|
+
return item
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class EstimatePanel(QWidget):
|
|
36
|
+
whatIfRequested = Signal()
|
|
37
|
+
|
|
38
|
+
def __init__(self, parent=None) -> None:
|
|
39
|
+
super().__init__(parent)
|
|
40
|
+
layout = QVBoxLayout(self)
|
|
41
|
+
|
|
42
|
+
self.page_count = QLabel("-")
|
|
43
|
+
big = QFont()
|
|
44
|
+
big.setPointSize(20)
|
|
45
|
+
big.setBold(True)
|
|
46
|
+
self.page_count.setFont(big)
|
|
47
|
+
|
|
48
|
+
self.rule_line = QLabel("Run an estimate to see the page count.")
|
|
49
|
+
self.rule_line.setWordWrap(True)
|
|
50
|
+
self.grid_line = QLabel("")
|
|
51
|
+
self.grid_line.setStyleSheet("color: palette(placeholderText);")
|
|
52
|
+
|
|
53
|
+
summary = QGroupBox("Result")
|
|
54
|
+
summary_layout = QVBoxLayout(summary)
|
|
55
|
+
summary_layout.addWidget(self.page_count)
|
|
56
|
+
summary_layout.addWidget(self.rule_line)
|
|
57
|
+
summary_layout.addWidget(self.grid_line)
|
|
58
|
+
|
|
59
|
+
self.statement = QLabel("")
|
|
60
|
+
self.statement.setWordWrap(True)
|
|
61
|
+
self.statement.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse)
|
|
62
|
+
self.statement.setStyleSheet(
|
|
63
|
+
"QLabel { background: palette(base); border: 1px solid palette(mid); padding: 8px; }"
|
|
64
|
+
)
|
|
65
|
+
statement_row = QHBoxLayout()
|
|
66
|
+
statement_row.addWidget(self.statement, 1)
|
|
67
|
+
self.copy_button = QPushButton("Copy")
|
|
68
|
+
self.copy_button.setToolTip("Copy the statement to give the Copyright Office")
|
|
69
|
+
self.copy_button.clicked.connect(self._copy_statement)
|
|
70
|
+
statement_row.addWidget(self.copy_button)
|
|
71
|
+
summary_layout.addWidget(QLabel("Statement for the application:"))
|
|
72
|
+
summary_layout.addLayout(statement_row)
|
|
73
|
+
|
|
74
|
+
layout.addWidget(summary)
|
|
75
|
+
|
|
76
|
+
what_if = QGroupBox("Page count by comment policy")
|
|
77
|
+
what_if_layout = QVBoxLayout(what_if)
|
|
78
|
+
hint = QLabel(
|
|
79
|
+
"If the whole program fits in the threshold you may deposit all of it, "
|
|
80
|
+
"which is simpler than the first-25/last-25 split."
|
|
81
|
+
)
|
|
82
|
+
hint.setWordWrap(True)
|
|
83
|
+
hint.setStyleSheet("color: palette(placeholderText);")
|
|
84
|
+
what_if_layout.addWidget(hint)
|
|
85
|
+
|
|
86
|
+
self.what_if_table = QTableWidget(0, 3)
|
|
87
|
+
self.what_if_table.setHorizontalHeaderLabels(["Policy", "Pages", "Deposit"])
|
|
88
|
+
self.what_if_table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
|
|
89
|
+
self.what_if_table.horizontalHeader().setSectionResizeMode(
|
|
90
|
+
0, QHeaderView.ResizeMode.Stretch
|
|
91
|
+
)
|
|
92
|
+
self.what_if_table.setMaximumHeight(150)
|
|
93
|
+
what_if_layout.addWidget(self.what_if_table)
|
|
94
|
+
|
|
95
|
+
self.compare_button = QPushButton("Compare policies")
|
|
96
|
+
self.compare_button.clicked.connect(self.whatIfRequested.emit)
|
|
97
|
+
what_if_layout.addWidget(self.compare_button)
|
|
98
|
+
layout.addWidget(what_if)
|
|
99
|
+
|
|
100
|
+
details = QHBoxLayout()
|
|
101
|
+
|
|
102
|
+
omitted_box = QGroupBox("Files the Office will not see")
|
|
103
|
+
omitted_layout = QVBoxLayout(omitted_box)
|
|
104
|
+
self.omitted_list = QListWidget()
|
|
105
|
+
omitted_layout.addWidget(self.omitted_list)
|
|
106
|
+
details.addWidget(omitted_box, 1)
|
|
107
|
+
|
|
108
|
+
warnings_box = QGroupBox("Warnings")
|
|
109
|
+
warnings_layout = QVBoxLayout(warnings_box)
|
|
110
|
+
self.warnings_list = QListWidget()
|
|
111
|
+
warnings_layout.addWidget(self.warnings_list)
|
|
112
|
+
details.addWidget(warnings_box, 1)
|
|
113
|
+
|
|
114
|
+
layout.addLayout(details, 1)
|
|
115
|
+
|
|
116
|
+
# -- population --------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
def apply_estimate(self, estimate) -> None:
|
|
119
|
+
selection = estimate.selection
|
|
120
|
+
total = estimate.page_count
|
|
121
|
+
self.page_count.setText(f"{total} page{'s' if total != 1 else ''}")
|
|
122
|
+
|
|
123
|
+
if selection.mode == MODE_ENTIRE:
|
|
124
|
+
self.rule_line.setText(
|
|
125
|
+
f"At or under the {estimate.settings.deposit.threshold}-page threshold, "
|
|
126
|
+
"so the entire program is deposited."
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
first, last = selection.omitted or (0, 0)
|
|
130
|
+
self.rule_line.setText(
|
|
131
|
+
f"Over the threshold: the deposit contains "
|
|
132
|
+
f"{estimate.settings.deposit.head_pages} + "
|
|
133
|
+
f"{estimate.settings.deposit.tail_pages} pages "
|
|
134
|
+
f"({selection.deposited_pages} sheets); pages {first}-{last} are omitted."
|
|
135
|
+
)
|
|
136
|
+
self.grid_line.setText(
|
|
137
|
+
f"{estimate.geometry_note} | {len(estimate.prepared)} files, "
|
|
138
|
+
f"{estimate.layout.rendered_lines} lines "
|
|
139
|
+
f"({estimate.layout.wrapped_lines} wrapped)"
|
|
140
|
+
)
|
|
141
|
+
self.statement.setText(selection.filing_statement())
|
|
142
|
+
|
|
143
|
+
self.omitted_list.clear()
|
|
144
|
+
omitted = estimate.omitted_files()
|
|
145
|
+
if omitted:
|
|
146
|
+
self.omitted_list.addItems(omitted)
|
|
147
|
+
else:
|
|
148
|
+
self.omitted_list.addItem("(every file appears in the deposit)")
|
|
149
|
+
|
|
150
|
+
self.warnings_list.clear()
|
|
151
|
+
if estimate.warnings:
|
|
152
|
+
self.warnings_list.addItems(estimate.warnings)
|
|
153
|
+
else:
|
|
154
|
+
self.warnings_list.addItem("(no warnings)")
|
|
155
|
+
|
|
156
|
+
def apply_what_if(self, rows: list[tuple[str, int, str]]) -> None:
|
|
157
|
+
self.what_if_table.setRowCount(len(rows))
|
|
158
|
+
for row, (label, pages, mode) in enumerate(rows):
|
|
159
|
+
self.what_if_table.setItem(row, 0, _cell(label))
|
|
160
|
+
self.what_if_table.setItem(row, 1, _cell(str(pages)))
|
|
161
|
+
self.what_if_table.setItem(row, 2, _cell(mode))
|
|
162
|
+
|
|
163
|
+
def _copy_statement(self) -> None:
|
|
164
|
+
clipboard = QGuiApplication.clipboard()
|
|
165
|
+
if clipboard is not None:
|
|
166
|
+
clipboard.setText(self.statement.text())
|