From 7ba395b654bc00d0f398a63e03db29a274d3b3fa Mon Sep 17 00:00:00 2001 From: pegasis Date: Thu, 26 Nov 2020 06:31:08 -0500 Subject: [PATCH 1/4] add ui scaling in settings --- gui/settings.py | 66 ++++++++++++++++++++++++++++++++++++++----------- rema.py | 27 +++++++++++--------- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/gui/settings.py b/gui/settings.py index 0588399..a43506b 100644 --- a/gui/settings.py +++ b/gui/settings.py @@ -17,6 +17,7 @@ def __init__(self, root, font_size): self.rm_client=RemarkableClient() self.item_manager = ItemManager() + root.grid_columnconfigure(4, minsize=180) root.grid_rowconfigure(1, minsize=50) root.grid_rowconfigure(2, minsize=30) @@ -26,7 +27,9 @@ def __init__(self, root, font_size): root.grid_rowconfigure(7, minsize=30) root.grid_rowconfigure(8, minsize=30) root.grid_rowconfigure(9, minsize=50) - + root.grid_rowconfigure(13, minsize=50) + root.grid_rowconfigure(14, minsize=50) + # gaps between columns label = tk.Label(root, text=" ") label.grid(row=1, column=1) @@ -35,11 +38,12 @@ def __init__(self, root, font_size): label = tk.Label(root, text=" ") label.grid(row=1, column=5) + # Authentication label = tk.Label(root, text="Authentication", font="Helvetica 14 bold") label.grid(row=1, column=2, sticky="W") self.onetime_code_link = "https://my.remarkable.com/connect/remarkable" - self.label_onetime_code = tk.Label(root, justify="left", anchor="w", + self.label_onetime_code = tk.Label(root, justify="left", anchor="w", fg="blue", cursor="hand2", text="\nDownload one-time code from \n" + self.onetime_code_link) self.label_onetime_code.grid(row=2, column=7, sticky="SW") self.label_onetime_code.bind("", lambda e: webbrowser.open_new(self.onetime_code_link)) @@ -53,11 +57,12 @@ def __init__(self, root, font_size): label.grid(row=3, column=2, sticky="W") self.entry_onetime_code_text = tk.StringVar() self.entry_onetime_code = tk.Entry(root, textvariable=self.entry_onetime_code_text) - self.entry_onetime_code.grid(row=3, column=4, sticky="W") + self.entry_onetime_code.grid(row=3, column=4, sticky="W") self.btn_sign_in = tk.Button(root, text="Sign In", command=self.btn_sign_in_click, width=17) self.btn_sign_in.grid(row=4, column=4, sticky="W") + # General label = tk.Label(root, text="General", font="Helvetica 14 bold") label.grid(row=6, column=2, sticky="W") @@ -66,10 +71,10 @@ def __init__(self, root, font_size): self.entry_templates_text = tk.StringVar() self.entry_templates_text.set(cfg.get("general.templates", default="")) self.entry_templates = tk.Entry(root, textvariable=self.entry_templates_text) - self.entry_templates.grid(row=7, column=4, sticky="W") + self.entry_templates.grid(row=7, column=4, sticky="W") label = tk.Label(root, justify="left", anchor="w", text="A local folder that contains all template PNG files. \nYou can copy the template files from your tablet: \n'/usr/share/remarkable'") - label.grid(row=7, column=7, sticky="W") + label.grid(row=7, column=7, sticky="W") label = tk.Label(root, text="Backup root path:") label.grid(row=8, column=2, sticky="W") @@ -81,11 +86,12 @@ def __init__(self, root, font_size): self.entry_backup_root.grid(row=8, column=4, sticky="W") label = tk.Label(root, justify="left", anchor="w", text="A local folder that will be used as the root folder for backups.") - label.grid(row=8, column=7, sticky="W") + label.grid(row=8, column=7, sticky="W") self.btn_save = tk.Button(root, text="Save", command=self.btn_save_click, width=17) self.btn_save.grid(row=9, column=4, sticky="W") + # Backup label = tk.Label(root, text="Backup", font="Helvetica 14 bold") label.grid(row=10, column=2, sticky="W") @@ -102,15 +108,33 @@ def __init__(self, root, font_size): self.label_backup_progress.grid(row=11, column=6) label = tk.Label(root, justify="left", anchor="w", text="Copy currently downloaded and annotated PDF files \ninto the given directory. Note that those files can not \nbe restored on the tablet.") - label.grid(row=11, column=7, sticky="W") + label.grid(row=11, column=7, sticky="W") self.btn_create_backup = tk.Button(root, text="Create backup", command=self.btn_create_backup, width=17) self.btn_create_backup.grid(row=12, column=4, sticky="W") - # Subscribe to sign in event. Outer logic (i.e. main) can try to + # UI + label = tk.Label(root, text="UI", font="Helvetica 14 bold") + label.grid(row=13, column=2, sticky="W") + + label = tk.Label(root, text="Scaling") + label.grid(row=14, column=2, sticky="W") + + self.scaling_text = tk.StringVar() + self.scaling_text.set(str(cfg.get("scaling",1/root.tk.call('tk', 'scaling'))*100)+"%") + self.entry_scaling=tk.Entry(root, textvariable=self.scaling_text) + self.entry_scaling.grid(row=14,column=4, sticky="W") + + label = tk.Label(root, justify="left", anchor="w", text="UI scalling will be applied after a restart.") + label.grid(row=14, column=7, sticky="W") + + self.btn_apply_scaling = tk.Button(root, text="Save scaling", command=self.btn_apply_scaling, width=17) + self.btn_apply_scaling.grid(row=15, column=4, sticky="W") + + # Subscribe to sign in event. Outer logic (i.e. main) can try to # sign in automatically... self.rm_client.listen_sign_in_event(self) - + # # EVENT HANDLER @@ -134,14 +158,14 @@ def sign_in_event_handler(self, event, config): self.entry_backup_folder.config(state="normal") self.entry_templates.config(state="normal") self.label_auth_status.config(text="Successfully signed in", fg="green") - + elif event == api.remarkable_client.EVENT_USER_TOKEN_FAILED: self.label_auth_status.config(text="Could not renew user token\n(please try again).", fg="red") self.entry_onetime_code.config(state="disabled") elif event == api.remarkable_client.EVENT_ONETIMECODE_NEEDED: self.label_auth_status.config(text="Enter one-time code.", fg="red") - + else: self.label_auth_status.config(text="Could not sign in.", fg="red") @@ -149,8 +173,8 @@ def sign_in_event_handler(self, event, config): def btn_sign_in_click(self): onetime_code = self.entry_onetime_code_text.get() self.rm_client.sign_in(onetime_code) - - + + def btn_save_click(self): general = { @@ -162,7 +186,7 @@ def btn_save_click(self): def btn_create_backup(self): message = "If your explorer is not synchronized, some files are not included in the backup. Should we continue?" - result = messagebox.askquestion("Info", message, icon='warning') + result = messagebox.askquestion("Info", message, icon='warning') if result != "yes": return @@ -175,7 +199,19 @@ def btn_create_backup(self): def run(): self.item_manager.create_backup(backup_path) self.label_backup_progress.config(text="") - messagebox.showinfo("Info", "Successfully created backup '%s'" % backup_path) + messagebox.showinfo("Info", "Successfully created backup '%s'" % backup_path) threading.Thread(target=run).start() + def btn_apply_scaling(self): + scaling_text=self.scaling_text.get().strip() + try: + if len(scaling_text)>=2 and scaling_text[-1]=="%": + scaling=float(scaling_text[0:-1])/100 + else: + scaling=float(scaling_text) + except ValueError: + return + + print("scaling: ",scaling) + cfg.save({"scaling":scaling}) diff --git a/rema.py b/rema.py index a07b988..7e845b1 100755 --- a/rema.py +++ b/rema.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import os +import utils.config as cfg from pathlib import Path import tkinter as tk from tkinter import * @@ -21,10 +22,13 @@ def __init__(self, window): self.rm_client = RemarkableClient() # Define app settings - font_size = 38 - row_height = 30 - window_width = 750 - window_height = 650 + scale=cfg.get("scaling",1/window.tk.call('tk', 'scaling')) + print(scale) + window.tk.call('tk', 'scaling',1/scale) + font_size = int(38*scale) + row_height = int(30*scale) + window_width = 750*scale + window_height = 650*scale # Subscribe to events self.rm_client.listen_sign_in_event(self) @@ -33,7 +37,7 @@ def __init__(self, window): window.title("RemaPy Explorer") # Try to start remapy always on the first screen and in the middle. - # We assume a resolution width of 1920... if 1920 is too large use + # We assume a resolution width of 1920... if 1920 is too large use # the real resolution x = min(window.winfo_screenwidth(), 1920) / 2 - (window_width / 2) y = (window.winfo_screenheight() / 2) - (window_height / 2) @@ -62,23 +66,23 @@ def __init__(self, window): frame = ttk.Frame(self.notebook) self.settings = Settings(frame, font_size) self.notebook.add(frame, text="Settings") - + frame = ttk.Frame(self.notebook) self.about = About(frame) self.notebook.add(frame, text="About") - # Try to sign in to the rm cloud without a onetime code i.e. we - # assume that the user token is already available. If it is not + # Try to sign in to the rm cloud without a onetime code i.e. we + # assume that the user token is already available. If it is not # possible we get a signal to disable "My remarkable" and settings # are shown... self.rm_client.sign_in() - + # # EVENT HANDLER # def sign_in_event_handler(self, event, data): - # If we fail to get a user token, we are e.g. offline. So we continue + # If we fail to get a user token, we are e.g. offline. So we continue # and try if we can get it later; otherwise we go into an offline mode if event == api.remarkable_client.EVENT_SUCCESS or event == api.remarkable_client.EVENT_USER_TOKEN_FAILED: self.notebook.tab(0, state="normal") @@ -91,10 +95,11 @@ def sign_in_event_handler(self, event, data): # def main(): window = tk.Tk(className="RemaPy") + Path(utils.config.PATH).mkdir(parents=True, exist_ok=True) app = Main(window) window.mainloop() if __name__ == '__main__': - main() \ No newline at end of file + main() From 1c899261a96509c57aace63d68641b8ded5977b3 Mon Sep 17 00:00:00 2001 From: pegasis Date: Thu, 26 Nov 2020 07:08:47 -0500 Subject: [PATCH 2/4] scale font size --- gui/file_explorer.py | 210 ++++++++++++++++++++++--------------------- gui/settings.py | 39 ++++---- rema.py | 30 +++---- 3 files changed, 138 insertions(+), 141 deletions(-) diff --git a/gui/file_explorer.py b/gui/file_explorer.py index 0702802..4db9eb2 100644 --- a/gui/file_explorer.py +++ b/gui/file_explorer.py @@ -31,15 +31,17 @@ class FileExplorer(object): all your rm documents and collections. """ - def __init__(self, root, window, font_size=14, row_height=14): - + def __init__(self, root, window): + self.root = root self.window = window self.app_dir = os.path.dirname(__file__) self.icon_dir = os.path.join(self.app_dir, 'icons/') self._cached_icons = {} self._icon_lock = threading.Lock() - self.row_height = row_height + scaling=utils.config.get("scaling",1/root.tk.call('tk', 'scaling')) + self.row_height=int(30*scaling) + self.font="TkDefaultFont %d"%int(12*scaling) # Create tkinter elements self.nodes = dict() @@ -47,10 +49,10 @@ def __init__(self, root, window, font_size=14, row_height=14): self.item_manager = ItemManager() self.tree_style = ttk.Style() - self.tree_style.configure("remapy.style.Treeview", highlightthickness=0, bd=0, font=font_size, rowheight=row_height) - self.tree_style.configure("remapy.style.Treeview.Heading", font=font_size) + self.tree_style.configure("remapy.style.Treeview", highlightthickness=0, bd=0, font=self.font, rowheight=self.row_height) + self.tree_style.configure("remapy.style.Treeview.Heading", font=self.font) self.tree_style.layout("remapy.style.Treeview", [('remapy.style.Treeview.treearea', {'sticky': 'nswe'})]) - + self.upper_frame = tk.Frame(root) self.upper_frame.pack(expand=True, fill=tk.BOTH) @@ -68,7 +70,7 @@ def __init__(self, root, window, font_size=14, row_height=14): self.tree.pack(side=tk.LEFT, expand=True, fill=tk.BOTH) self.tree.bind("", self.tree_focus_out_event_handler) self.tree.bind("", self.tree_focus_in_event_handler) - + self.vsb = ttk.Scrollbar(self.upper_frame, orient="vertical", command=self.tree.yview) self.vsb.pack(side=tk.LEFT, fill='y') self.tree.configure(yscrollcommand=self.vsb.set) @@ -78,23 +80,23 @@ def __init__(self, root, window, font_size=14, row_height=14): self.tree.configure(xscrollcommand=self.hsb.set) self.tree["columns"]=("#1","#2") - self.tree.column("#0", minwidth=250) - self.tree.column("#1", width=180, minwidth=180, stretch=tk.NO) - self.tree.column("#2", width=150, minwidth=150, anchor="center", stretch=tk.NO) + self.tree.column("#0", minwidth=int(250*scaling)) + self.tree.column("#1", width=int(200*scaling), stretch=tk.NO) + self.tree.column("#2", width=int(130*scaling), anchor="center", stretch=tk.NO) self.tree.heading("#0",text="Name", anchor="center") self.tree.heading("#1", text="Date modified", anchor="center") self.tree.heading("#2", text="Current Page", anchor="center") - self.tree.tag_configure('move', background='#FF9800') + self.tree.tag_configure('move', background='#FF9800') self.tree.focus_set() self.window.bind("", self.key_binding_escape) - + # Context menu on right click # Check out drag and drop: https://stackoverflow.com/questions/44887576/how-can-i-create-a-drag-and-drop-interface self.tree.bind("", self.tree_right_click) - self.context_menu =tk.Menu(root, tearoff=0, font=font_size) + self.context_menu =tk.Menu(root, tearoff=0, font=self.font) self.context_menu.add_command(label='Open', accelerator="Return", command=self.btn_open_item_click) self.context_menu.add_command(label='Open annotated pages ', command=self.btn_open_oap_item_click) self.context_menu.add_command(label='Open raw', command=self.btn_open_item_original_click) @@ -130,9 +132,9 @@ def __init__(self, root, window, font_size=14, row_height=14): self.log_widget.insert(tk.END, "RemaPy Explorer v0.1") self.log_widget.config(state=tk.DISABLED) self.log_widget.pack(expand=True, fill=tk.X) - + self.rm_client.listen_sign_in_event(self) - + def _set_online_mode(self, mode): self.btn_sync.config(state=mode) @@ -159,7 +161,7 @@ def log_console(self, text): self.log_widget.insert(tk.END, "\n[%s] %s" % (str(now), text)) self.log_widget.config(state=tk.DISABLED) self.log_widget.see(tk.END) - + # # Tree # @@ -171,7 +173,7 @@ def tree_focus_out_event_handler(self, *args): self.window.unbind("") self.window.unbind("") self.window.unbind("") - + def tree_focus_in_event_handler(self, *args): self.window.bind("", self.key_binding_filter) @@ -184,8 +186,8 @@ def tree_focus_in_event_handler(self, *args): def sign_in_event_handler(self, event, data): - # Also if the login failed (e.g. we are offline) we try again - # if we can sync the items (e.g. with old user key) and otherwise + # Also if the login failed (e.g. we are offline) we try again + # if we can sync the items (e.g. with old user key) and otherwise # we switch to the offline mode if event == api.remarkable_client.EVENT_SUCCESS or event == api.remarkable_client.EVENT_USER_TOKEN_FAILED: self.btn_sync_click() @@ -193,7 +195,7 @@ def sign_in_event_handler(self, event, data): def key_binding_filter(self, event): self.entry_filter.focus_set() - + def key_binding_escape(self, event): self.tree.focus_set() @@ -202,16 +204,16 @@ def key_binding_escape(self, event): self.tree.focus(children[0]) else: self.tree.focus() - + def filter_changed_event_handler(self, placeholder, *args): if self.entry_filter is None: - return + return filter_text = self.entry_filter_var.get() if filter_text == self.entry_filter.placeholder: filter_text = None - + root = self.item_manager.get_root() self.tree.delete(*self.tree.get_children()) self._update_tree(root, filter_text) @@ -224,8 +226,8 @@ def _update_tree(self, item, filter=None): is_match, is_direct_match = self._match_filter(item, filter) if is_match: self.tree.insert( - item.parent().id(), - 0 if item.id() != "trash" else 99999, + item.parent().id(), + 0 if item.id() != "trash" else 99999, item.id(), open=filter!=None) @@ -250,15 +252,15 @@ def _update_tree(self, item, filter=None): self.tree.delete(item.id()) except: pass - - def _match_filter(self, item, filter): - """ Returns whether we have a match on this path (to include all + + def _match_filter(self, item, filter): + """ Returns whether we have a match on this path (to include all parent folders) and whether the given item was the matching one. """ if filter is None or filter == "": return True, True - + if filter.startswith("!b "): bookmarked_only = True text_filter = filter[3:] @@ -270,7 +272,7 @@ def _match_filter(self, item, filter): text_filter = filter is_match = (text_filter.lower() in item.name().lower()) - + if bookmarked_only: is_match = is_match and item.bookmarked() @@ -283,7 +285,7 @@ def _match_filter(self, item, filter): return child_match, False return False, False - + def tree_right_click(self, event): selected_ids = self.tree.selection() @@ -292,16 +294,16 @@ def tree_right_click(self, event): for item in items: for possile_child in items: if not item.is_parent_of(possile_child): - continue - + continue + messagebox.showerror( - "Invalid operation", + "Invalid operation", "Your selection is invalid. You can not perform an \ action on a folder and one of its child items.") return - self.context_menu.tk_popup(event.x_root, event.y_root) - pass + self.context_menu.tk_popup(event.x_root, event.y_root) + pass else: # mouse pointer not over item pass @@ -313,27 +315,27 @@ def _update_tree_item(self, item): else: icon = self._get_icon(item) self.tree.item( - item.id(), - image=icon, + item.id(), + image=icon, text=" " + item.name(), values=( - item.modified_time().strftime("%Y-%m-%d %H:%M:%S"), + item.modified_time().strftime("%Y-%m-%d %H:%M:%S"), item.current_page())) def _get_icon(self, item): if item.is_collection(): if item.id() == "trash": - return self._create_tree_icon("trash") + return self._create_tree_icon("trash") if item.state == model.item.STATE_SYNCED: return self._create_tree_icon("collection", item.bookmarked()) else: return self._create_tree_icon("collection_syncing") - + if item.state == model.document.STATE_NOT_SYNCED: return self._create_tree_icon("cloud") - + elif item.state == model.item.STATE_SYNCING: return self._create_tree_icon("document_syncing") @@ -342,7 +344,7 @@ def _get_icon(self, item): return self._create_tree_icon("pdf", item.bookmarked()) elif item.type == model.document.TYPE_EPUB: return self._create_tree_icon("epub", item.bookmarked()) - else: + else: return self._create_tree_icon("notebook", item.bookmarked()) if item.state == model.document.STATE_OUT_OF_SYNC: @@ -350,12 +352,12 @@ def _get_icon(self, item): return self._create_tree_icon("pdf_out_of_sync") elif item.type == model.document.TYPE_EPUB: return self._create_tree_icon("epub_out_of_sync") - else: + else: return self._create_tree_icon("notebook_out_of_sync") - + return self._create_tree_icon("weird") - + def _create_tree_icon(self, name, bookmarked=False): key = "%s_%s" % (name, bookmarked) if key in self._cached_icons: @@ -367,7 +369,7 @@ def _create_tree_icon(self, name, bookmarked=False): # Double check if key is in cached icons if key in self._cached_icons: return self._cached_icons[key] - + icon_size = self.row_height-4 path = "%s%s.png" % (self.icon_dir, name) icon = Image.open(path) @@ -377,7 +379,7 @@ def _create_tree_icon(self, name, bookmarked=False): icon_star = Image.open("%s%s.png" % (self.icon_dir, "star")) icon_star = icon_star.resize((icon_size, icon_size)) icon.paste(icon_star, None, icon_star) - + self._cached_icons[key] = itk.PhotoImage(icon) return self._cached_icons[key] @@ -391,13 +393,13 @@ def btn_rename_item_click(self): if len(selected_ids) != 1: messagebox.showerror("Error", "Select exactly one item to rename.", icon='error') return - + item = self.item_manager.get_item(selected_ids[0]) if item.name() == "Quick sheets" and item.parent().is_root(): messagebox.showerror("Error", "You can not rename the Quick sheets.", icon='error') return - + if item.name() == "Trash" and item.parent().is_root(): messagebox.showerror("Error", "You can not rename the Trash.", icon='error') return @@ -413,19 +415,19 @@ def key_binding_resync(self, event): def btn_resync_item_click(self): self._sync_selection_async( - force=True, - open_file=False, + force=True, + open_file=False, open_original=False) def tree_double_click(self, event): selected_ids = self.tree.selection() item = self.item_manager.get_item(selected_ids[0]) - + if item.is_document(): self._sync_selection_async( - force=False, - open_file=True, + force=False, + open_file=True, open_original=False) @@ -435,22 +437,22 @@ def key_binding_return(self, event): def btn_open_item_click(self): self._sync_selection_async( - force=False, - open_file=True, + force=False, + open_file=True, open_original=False) - + def btn_open_oap_item_click(self): self._sync_selection_async( - force=False, - open_file=True, + force=False, + open_file=True, open_oap=True) def btn_open_item_original_click(self): self._sync_selection_async( - force=False, - open_file=True, + force=False, + open_file=True, open_original=True) @@ -460,11 +462,11 @@ def btn_resync_click(self): message = "Do you really want to delete ALL local files and download ALL documents again?" else: message = "Do you really want resync without a connection to the remarkable cloud?" - + result = messagebox.askquestion("Warning", message, icon='warning') if result != "yes": - return + return # Clean everything, also if some (old) things exist shutil.rmtree(utils.config.PATH, ignore_errors=True) @@ -492,8 +494,8 @@ def btn_sync_click(self): self._update_tree(root) self._sync_items_async([self.item_manager.get_root()], - force=False, - open_file=False, + force=False, + open_file=False, open_original=False, open_oap=False) @@ -520,7 +522,7 @@ def worker(): item = q.get() if item is None: break - + try: self._sync_and_open_item(item, force, open_file, open_original, open_oap) except Exception as e: @@ -529,7 +531,7 @@ def worker(): else: self.log_console("(Error) Could not sync '%s'" % item.name()) print(e) - + q.task_done() num_worker_threads = 10 @@ -537,11 +539,11 @@ def worker(): t = threading.Thread(target=worker) t.start() threads.append(t) - + # Add all items and child items for item in items: self.item_manager.traverse_tree(fun=q.put, item = item) - + q.join() # stop workers @@ -549,10 +551,10 @@ def worker(): q.put(None) for t in threads: t.join() - - def _sync_and_open_item(self, item, force, open_file, open_original, open_oap): - + + def _sync_and_open_item(self, item, force, open_file, open_original, open_oap): + if item.state == model.item.STATE_SYNCING: self.log_console("Already syncing '%s'" % item.full_name()) return @@ -571,9 +573,9 @@ def _sync_and_open_item(self, item, force, open_file, open_original, open_oap): if file_to_open == None: messagebox.showinfo("Information", "Document is not annotated.", icon='info') return - else: + else: file_to_open = item.ann_or_orig_file() - + if sys.platform == "win32": os.startfile(os.path.normpath(file_to_open)) else: @@ -582,7 +584,7 @@ def _sync_and_open_item(self, item, force, open_file, open_original, open_oap): current_page = 0 if open_oap else item.current_page() subprocess.call(["evince", "-i", str(current_page), file_to_open]) except: - subprocess.call(["xdg-open", file_to_open]) + subprocess.call(["xdg-open", file_to_open]) else: subprocess.call(["xdg-open", file_to_open]) @@ -597,16 +599,16 @@ def key_binding_delete(self, event): def btn_delete_item_click(self): selected_ids = self.tree.selection() items = [self.item_manager.get_item(id) for id in selected_ids] - + count = [0, 0] for item in items: if item.is_document(): count[0] += 1 continue - + child_count = item.get_exact_children_count() count = np.add(count, child_count) - + message = "Do you really want to delete (or trash) %d collection(s) and %d file(s)?" % (count[1], count[0]) result = messagebox.askquestion("Delete", message, icon='warning') @@ -618,18 +620,18 @@ def run(): if item.name() == "Quick sheets" and item.parent().is_root(): self.log_console("(Warning) You can not delete the Quick sheets.") continue - + if item.name() == "Trash" and item.parent().is_root(): self.log_console("(Warning) You can not delete the trash.") continue - + if item.parent().id() == "trash": item.delete() self.log_console("Deleted %s" % item.full_name()) - else: + else: trash = self.item_manager.trash self._move(item, trash) - + threading.Thread(target=run).start() @@ -645,9 +647,9 @@ def run(): if item.parent().id() != "trash": self.log_console("(Warning) Restore of '%s' not necessary." % item.full_name()) continue - + self._move(item, self.item_manager.root) - + threading.Thread(target=run).start() @@ -661,12 +663,12 @@ def _move(self, item, new_parent): old_parent_children = list(self.tree.get_children(old_parent_id)) old_parent_children.remove(item.id()) self.tree.set_children(old_parent_id, *old_parent_children) - + # Add to trash (tree view) new_parent_children = list(self.tree.get_children(new_parent.id())) new_parent_children.append(item.id()) self.tree.set_children(new_parent.id(), *new_parent_children) - + self.log_console("Moved '%s' into '%s'" % (item.full_name(), new_parent.full_name())) # @@ -678,18 +680,18 @@ def key_binding_paste(self, event): def btn_paste_async_click(self): selected_ids = self.tree.selection() - + if len(selected_ids) > 1: messagebox.showerror("Paste error", "Can paste only into one collection.") return - + elif len(selected_ids) == 1: item = self.item_manager.get_item(selected_ids[0]) parent_id = str(item.parent().id() if item.is_document() else item.id()) - + else: - parent_id = "" - + parent_id = "" + def is_file(path): if not os.path.exists(path): return None @@ -697,12 +699,12 @@ def is_file(path): return "pdf" elif path.endswith(".epub"): return "epub" - return None - + return None + def is_url(url): return url.startswith("http") - # Some versions of nautilus include "x-special/nautilus-clipboard file://..." + # Some versions of nautilus include "x-special/nautilus-clipboard file://..." # Or dolphin simple adds "file://..." # See also issue #11 paths = self.root.clipboard_get().split("\n") @@ -711,12 +713,12 @@ def is_url(url): if len(paths) <= 0: messagebox.showerror( - "Failed to copy from clipboard", + "Failed to copy from clipboard", "The given clipboard is invalid. Only .pdf, .epub and urls are supported.\n\n%s" % self.root.clipboard_get()) return - - def run(clipboard): - id = str(uuid.uuid4()) + + def run(clipboard): + id = str(uuid.uuid4()) filetype = is_file(clipboard) if filetype != None: name = os.path.splitext(os.path.basename(clipboard))[0] @@ -739,7 +741,7 @@ def run(clipboard): image=self._create_tree_icon("document_upload")) options = { - # Here we can manually set some cookies to + # Here we can manually set some cookies to # for example automatically accept terms of usage etc. 'cookie': [ ('DSGVO_ZUSAGE_V1', 'true') @@ -749,7 +751,7 @@ def run(clipboard): filetype = "pdf" except Exception as e: messagebox.showerror( - "Failed to convert html to pdf", + "Failed to convert html to pdf", "Please ensure that you installed pdfkit and wkhtmltopdf correctly https://pypi.org/project/pdfkit/") self.tree.delete(id) return @@ -759,7 +761,7 @@ def run(clipboard): # Upload item = self.item_manager.upload_file( - id, parent_id, name, + id, parent_id, name, filetype, data, self._update_tree_item) self.log_console("Successfully uploaded %s" % item.full_name()) @@ -780,10 +782,10 @@ def btn_open_in_file_explorer(self): os.startfile(os.path.normpath(item.path_remapy)) else: subprocess.call(('xdg-open', item.path_remapy)) - + def key_binding_toggle_bookmark(self, event): self.btn_toggle_bookmark() - + def btn_toggle_bookmark(self): selected_ids = self.tree.selection() items = [self.item_manager.get_item(id) for id in selected_ids] diff --git a/gui/settings.py b/gui/settings.py index a43506b..f0070b4 100644 --- a/gui/settings.py +++ b/gui/settings.py @@ -1,22 +1,23 @@ -from datetime import date -import time -import webbrowser -import tkinter as tk -import tkinter.ttk as ttk -from tkinter import messagebox import threading +import tkinter as tk +import webbrowser +from datetime import date from pathlib import Path +from tkinter import messagebox import api.remarkable_client -from api.remarkable_client import RemarkableClient import utils.config as cfg +from api.remarkable_client import RemarkableClient from model.item_manager import ItemManager + class Settings(object): - def __init__(self, root, font_size): + def __init__(self, root): self.rm_client=RemarkableClient() self.item_manager = ItemManager() + scaling = cfg.get("scaling", 1 / root.tk.call('tk', 'scaling')) + title_font = "Helvetica %d bold" % int(14 * scaling) root.grid_columnconfigure(4, minsize=180) root.grid_rowconfigure(1, minsize=50) @@ -39,7 +40,7 @@ def __init__(self, root, font_size): label.grid(row=1, column=5) # Authentication - label = tk.Label(root, text="Authentication", font="Helvetica 14 bold") + label = tk.Label(root, text="Authentication", font=title_font) label.grid(row=1, column=2, sticky="W") self.onetime_code_link = "https://my.remarkable.com/connect/remarkable" @@ -63,7 +64,7 @@ def __init__(self, root, font_size): self.btn_sign_in.grid(row=4, column=4, sticky="W") # General - label = tk.Label(root, text="General", font="Helvetica 14 bold") + label = tk.Label(root, text="General", font=title_font) label.grid(row=6, column=2, sticky="W") label = tk.Label(root, text="Templates path:") @@ -92,7 +93,7 @@ def __init__(self, root, font_size): self.btn_save.grid(row=9, column=4, sticky="W") # Backup - label = tk.Label(root, text="Backup", font="Helvetica 14 bold") + label = tk.Label(root, text="Backup", font=title_font) label.grid(row=10, column=2, sticky="W") label = tk.Label(root, text="Backup path:") @@ -114,7 +115,7 @@ def __init__(self, root, font_size): self.btn_create_backup.grid(row=12, column=4, sticky="W") # UI - label = tk.Label(root, text="UI", font="Helvetica 14 bold") + label = tk.Label(root, text="UI", font=title_font) label.grid(row=13, column=2, sticky="W") label = tk.Label(root, text="Scaling") @@ -125,7 +126,7 @@ def __init__(self, root, font_size): self.entry_scaling=tk.Entry(root, textvariable=self.scaling_text) self.entry_scaling.grid(row=14,column=4, sticky="W") - label = tk.Label(root, justify="left", anchor="w", text="UI scalling will be applied after a restart.") + label = tk.Label(root, justify="left", anchor="w", text="UI scaling will be applied after a restart.") label.grid(row=14, column=7, sticky="W") self.btn_apply_scaling = tk.Button(root, text="Save scaling", command=self.btn_apply_scaling, width=17) @@ -204,14 +205,14 @@ def run(): threading.Thread(target=run).start() def btn_apply_scaling(self): - scaling_text=self.scaling_text.get().strip() + scaling_text = self.scaling_text.get().strip() try: - if len(scaling_text)>=2 and scaling_text[-1]=="%": - scaling=float(scaling_text[0:-1])/100 + if len(scaling_text) >= 2 and scaling_text[-1] == "%": + scaling = float(scaling_text[0:-1]) / 100 else: - scaling=float(scaling_text) + scaling = float(scaling_text) except ValueError: return - print("scaling: ",scaling) - cfg.save({"scaling":scaling}) + print("scaling: ", scaling) + cfg.save({"scaling": scaling}) diff --git a/rema.py b/rema.py index 7e845b1..525b2f1 100755 --- a/rema.py +++ b/rema.py @@ -1,20 +1,17 @@ #!/usr/bin/env python3 -import os -import utils.config as cfg -from pathlib import Path import tkinter as tk -from tkinter import * -from tkinter import scrolledtext import tkinter.ttk as ttk +from pathlib import Path -from gui.file_explorer import FileExplorer +import api.remarkable_client +import utils.config +import utils.config as cfg +from api.remarkable_client import RemarkableClient from gui.about import About +from gui.file_explorer import FileExplorer from gui.settings import Settings -import api.remarkable_client -from api.remarkable_client import RemarkableClient -import utils.config class Main(object): @@ -22,13 +19,10 @@ def __init__(self, window): self.rm_client = RemarkableClient() # Define app settings - scale=cfg.get("scaling",1/window.tk.call('tk', 'scaling')) - print(scale) - window.tk.call('tk', 'scaling',1/scale) - font_size = int(38*scale) - row_height = int(30*scale) - window_width = 750*scale - window_height = 650*scale + scale = cfg.get("scaling", 1 / window.tk.call('tk', 'scaling')) + window.tk.call('tk', 'scaling', 1 / scale) + window_width = 750 * scale + window_height = 650 * scale # Subscribe to events self.rm_client.listen_sign_in_event(self) @@ -48,7 +42,7 @@ def __init__(self, window): self.notebook.pack(expand=1, fill="both") frame = ttk.Frame(self.notebook) - self.file_explorer = FileExplorer(frame, window, font_size=font_size, row_height=row_height) + self.file_explorer = FileExplorer(frame, window) self.notebook.add(frame, text="File Explorer") frame = ttk.Frame(self.notebook) @@ -64,7 +58,7 @@ def __init__(self, window): self.notebook.add(frame, text="SSH", state="hidden") frame = ttk.Frame(self.notebook) - self.settings = Settings(frame, font_size) + self.settings = Settings(frame) self.notebook.add(frame, text="Settings") frame = ttk.Frame(self.notebook) From 3b1f619f19aa5f67cc12096bd4189bb22246c067 Mon Sep 17 00:00:00 2001 From: pegasis Date: Thu, 26 Nov 2020 07:11:09 -0500 Subject: [PATCH 3/4] make the window a bit taller so scalling settings can be seen --- rema.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rema.py b/rema.py index 525b2f1..7a31782 100755 --- a/rema.py +++ b/rema.py @@ -22,7 +22,7 @@ def __init__(self, window): scale = cfg.get("scaling", 1 / window.tk.call('tk', 'scaling')) window.tk.call('tk', 'scaling', 1 / scale) window_width = 750 * scale - window_height = 650 * scale + window_height = 700 * scale # Subscribe to events self.rm_client.listen_sign_in_event(self) From 4421ada671e10ddac10ac6955a748f56d50a208a Mon Sep 17 00:00:00 2001 From: pegasis Date: Mon, 14 Dec 2020 00:38:15 -0500 Subject: [PATCH 4/4] default scaling to 100% instead of window.tk.call('tk', 'scaling') --- gui/file_explorer.py | 2 +- gui/settings.py | 4 ++-- rema.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gui/file_explorer.py b/gui/file_explorer.py index 4db9eb2..c50a68c 100644 --- a/gui/file_explorer.py +++ b/gui/file_explorer.py @@ -39,7 +39,7 @@ def __init__(self, root, window): self.icon_dir = os.path.join(self.app_dir, 'icons/') self._cached_icons = {} self._icon_lock = threading.Lock() - scaling=utils.config.get("scaling",1/root.tk.call('tk', 'scaling')) + scaling=utils.config.get("scaling",1) self.row_height=int(30*scaling) self.font="TkDefaultFont %d"%int(12*scaling) diff --git a/gui/settings.py b/gui/settings.py index f0070b4..ded4a91 100644 --- a/gui/settings.py +++ b/gui/settings.py @@ -16,7 +16,7 @@ def __init__(self, root): self.rm_client=RemarkableClient() self.item_manager = ItemManager() - scaling = cfg.get("scaling", 1 / root.tk.call('tk', 'scaling')) + scaling = cfg.get("scaling", 1) title_font = "Helvetica %d bold" % int(14 * scaling) root.grid_columnconfigure(4, minsize=180) @@ -122,7 +122,7 @@ def __init__(self, root): label.grid(row=14, column=2, sticky="W") self.scaling_text = tk.StringVar() - self.scaling_text.set(str(cfg.get("scaling",1/root.tk.call('tk', 'scaling'))*100)+"%") + self.scaling_text.set(str(cfg.get("scaling")*100)+"%") self.entry_scaling=tk.Entry(root, textvariable=self.scaling_text) self.entry_scaling.grid(row=14,column=4, sticky="W") diff --git a/rema.py b/rema.py index 7a31782..4a3630b 100755 --- a/rema.py +++ b/rema.py @@ -19,7 +19,7 @@ def __init__(self, window): self.rm_client = RemarkableClient() # Define app settings - scale = cfg.get("scaling", 1 / window.tk.call('tk', 'scaling')) + scale = cfg.get("scaling", 1) window.tk.call('tk', 'scaling', 1 / scale) window_width = 750 * scale window_height = 700 * scale