Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Text box can be used to set DPI #960

Merged
merged 17 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions data/ui/ResolutionRow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@
<property name="can-focus">False</property>
<property name="border-width">12</property>
<property name="spacing">6</property>
<child>
<object class="GtkEntry" id="dpi_entry">
<property name="visible">True</property>
<property name="halign">start</property>
<signal name="activate" handler="_on_dpi_entry_activate" swapped="no"/>
<signal name="insert-text" handler="_on_dpi_entry_insert_text" swapped="no"/>
<signal name="focus-in-event" handler="_on_dpi_entry_focus_in" swapped="no"/>
<signal name="focus-out-event" handler="_on_dpi_entry_focus_out" swapped="no"/>
</object>
</child>
<child>
<object class="GtkLabel" id="dpi_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label">0 DPI</property>
<property name="label">DPI</property>
</object>
<packing>
<property name="expand">True</property>
Expand Down Expand Up @@ -66,7 +76,7 @@
<object class="GtkScale" id="scale">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="tooltip-text" translatable="yes">Set this resolution's dpi</property>
<property name="tooltip-text" translatable="yes">Set this resolution's DPI</property>
<property name="round-digits">0</property>
<property name="digits">0</property>
<property name="draw-value">False</property>
Expand Down
66 changes: 58 additions & 8 deletions piper/resolutionrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

import gi

from gi.repository import GObject, Gdk, Gtk # noqa
from .ratbagd import RatbagdResolution
from .util.gobject import connect_signal_with_weak_ref

gi.require_version("Gtk", "3.0")
from gi.repository import GObject, Gdk, Gtk # noqa
sizzlesloth marked this conversation as resolved.
Show resolved Hide resolved


@Gtk.Template(resource_path="/org/freedesktop/Piper/ui/ResolutionRow.ui")
Expand All @@ -22,17 +22,22 @@ class ResolutionRow(Gtk.ListBoxRow):
active_label: Gtk.Label = Gtk.Template.Child() # type: ignore
disable_button: Gtk.Button = Gtk.Template.Child() # type: ignore
dpi_label: Gtk.Label = Gtk.Template.Child() # type: ignore
dpi_entry: Gtk.Entry = Gtk.Template.Child() # type: ignore
revealer: Gtk.Revealer = Gtk.Template.Child() # type: ignore
scale: Gtk.Scale = Gtk.Template.Child() # type: ignore

CAP_SEPARATE_XY_RESOLUTION = False
CAP_DISABLE = False

def __init__(self, resolution: RatbagdResolution, *args, **kwargs) -> None:
def __init__(
self, resolution: RatbagdResolution, resolutions_page, *args, **kwargs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I wonder if we could type-hint 'resolutions_page'. My Python is rusty.

) -> None:
Gtk.ListBoxRow.__init__(self, *args, **kwargs)

self.resolutions_page = resolutions_page
self._resolution = resolution
self.resolutions = resolution.resolutions
self.previous_dpi_entry_value = None
sizzlesloth marked this conversation as resolved.
Show resolved Hide resolved
self._scale_handler = self.scale.connect(
"value-changed", self._on_scale_value_changed
)
Expand Down Expand Up @@ -60,6 +65,12 @@ def __init__(self, resolution: RatbagdResolution, *args, **kwargs) -> None:
res = resolution.resolution[0]
minres = resolution.resolutions[0]
maxres = resolution.resolutions[-1]
res_num_chars = len(str(maxres))

# Set the max width and length for the DPI text boxes, based on the max res value.
self.dpi_entry.set_width_chars(res_num_chars)
self.dpi_entry.set_max_length(res_num_chars)

with self.scale.handler_block(self._scale_handler):
self.scale.props.adjustment.configure(res, minres, maxres, 50, 50, 0)
self.scale.set_value(res)
Expand All @@ -82,6 +93,7 @@ def _on_change_value(
value = lo if value - lo < hi - value else hi

scale.set_value(value)
self.dpi_entry.set_text(str(value))

# libratbag provides a fake-exponential range with the deltas
# increasing as the resolution goes up. Make sure we set our
Expand All @@ -102,12 +114,12 @@ def _on_disable_button_toggled(self, togglebutton: Gtk.Button) -> None:
self._on_status_changed(self._resolution, pspec=None)

@Gtk.Template.Callback("_on_active_button_clicked")
def _on_active_button_clicked(self, togglebutton: Gtk.Button) -> None:
def _on_active_button_clicked(self, _togglebutton: Gtk.Button) -> None:
# The set active button has been clicked, update RatbagdResolution.
self._resolution.set_active()

@Gtk.Template.Callback("_on_scroll_event")
def _on_scroll_event(self, widget: Gtk.Widget, event: Gdk.EventScroll) -> bool:
def _on_scroll_event(self, widget: Gtk.Widget, _event: Gdk.EventScroll) -> bool:
# Prevent a scroll in the list to get caught by the scale.
GObject.signal_stop_emission_by_name(widget, "scroll-event")
return False
Expand Down Expand Up @@ -136,10 +148,12 @@ def _on_status_changed(
self.disable_button.set_active(True)
self.active_button.set_sensitive(False)
self.dpi_label.set_sensitive(False)
self.dpi_entry.set_sensitive(False)
self.scale.set_sensitive(False)
else:
self.disable_button.set_active(False)
self.dpi_label.set_sensitive(True)
self.dpi_entry.set_sensitive(True)
self.scale.set_sensitive(True)

def toggle_revealer(self) -> None:
Expand All @@ -149,20 +163,56 @@ def toggle_revealer(self) -> None:

def _on_dpi_values_changed(self, res: Optional[int] = None) -> None:
# Freeze the notify::resolution signal from firing and
# update dpi label and resolution values.
# update DPI text box and resolution values.
if res is None:
res = self._resolution.resolution[0]
new_res = (res, res) if self.CAP_SEPARATE_XY_RESOLUTION else (res,)
self.dpi_label.set_text(f"{res} DPI")
self.dpi_entry.set_text(str(res))

# Only update new resolution if changed
if new_res != self._resolution.resolution:
self._resolution.resolution = new_res

@Gtk.Template.Callback("_on_dpi_entry_insert_text")
def _on_dpi_entry_insert_text(
self, entry: Gtk.Entry, text: str, _length: int, _position: int
):
# Remove any non-numeric characters from the input
if not text.isdigit():
entry.stop_emission("insert-text")

@Gtk.Template.Callback("_on_dpi_entry_activate")
def _on_dpi_entry_activate(self, entry: Gtk.Entry) -> None:
# The DPI entry has been changed, update the scale and RatbagdResolution's resolution.
try:
res = int(entry.get_text())
# Get the resolution closest to what has been entered
closest_res = min(self.resolutions, key=lambda x: abs(x - res))
entry.set_text(str(closest_res))

if closest_res != self.previous_dpi_entry_value:
self._on_dpi_values_changed(res=closest_res)

with self.scale.handler_block(self._scale_handler):
self.scale.set_value(res)
except ValueError:
# If the input is not a valid integer, reset to the current value.
entry.set_text(str(self._resolution.resolution[0]))

@Gtk.Template.Callback("_on_dpi_entry_focus_in")
def _on_dpi_entry_focus_in(self, _entry: Gtk.Entry, _event_focus: Gdk.EventFocus):
if not self.revealer.get_reveal_child():
self.resolutions_page._on_row_activated(None, self)

@Gtk.Template.Callback("_on_dpi_entry_focus_out")
def _on_dpi_entry_focus_out(self, entry: Gtk.Entry, _event_focus: Gdk.EventFocus):
# Apply the DPI value on focus out
self._on_dpi_entry_activate(entry)

def _on_profile_resolution_changed(
self, resolution: RatbagdResolution, pspec: GObject.ParamSpec
self, resolution: RatbagdResolution, _pspec: GObject.ParamSpec
) -> None:
with self.scale.handler_block(self._scale_handler):
res = resolution.resolution[0]
self.scale.set_value(res)
self.dpi_label.set_text(f"{res} DPI")
self.dpi_entry.set_text(str(res))
2 changes: 1 addition & 1 deletion piper/resolutionspage.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def __init__(

self.listbox.foreach(Gtk.Widget.destroy)
for resolution in profile.resolutions:
row = ResolutionRow(resolution)
row = ResolutionRow(resolution, self)
self.listbox.insert(row, resolution.index)

@Gtk.Template.Callback("_on_row_activated")
Expand Down