Few small different syntex fixes and so on
This commit is contained in:
@@ -1,29 +1,30 @@
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from pynput import keyboard
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from core.updater import update_repository, is_update_available
|
||||
from pynput import keyboard
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from core.config import Config
|
||||
from core.discord_presence import presence
|
||||
from core.dukto import Peer
|
||||
from core.file_search import find
|
||||
from core.web_search import MullvadLetaWrapper
|
||||
from core.http_share import FileShareServer
|
||||
from core.config import Config
|
||||
|
||||
from core.updater import is_update_available, update_repository
|
||||
from core.web_search import MullvadLetaWrapper
|
||||
from windows.app_launcher import AppLauncherDialog
|
||||
from windows.file_search import FileSearchResults
|
||||
from windows.web_results import WebSearchResults
|
||||
from windows.text_viewer import TextViewerDialog
|
||||
from windows.calculator import CalculatorDialog
|
||||
from windows.config_window import ConfigWindow
|
||||
from windows.file_search import FileSearchResults
|
||||
from windows.text_viewer import TextViewerDialog
|
||||
from windows.web_results import WebSearchResults
|
||||
|
||||
ASSET = Path(__file__).parent.parent / "assets" / "2ktan.png"
|
||||
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
show_menu_signal = QtCore.Signal()
|
||||
|
||||
|
||||
# Dukto signals
|
||||
peer_added_signal = QtCore.Signal(Peer)
|
||||
peer_removed_signal = QtCore.Signal(Peer)
|
||||
@@ -35,14 +36,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
send_start_signal = QtCore.Signal(str)
|
||||
send_complete_signal = QtCore.Signal(list)
|
||||
dukto_error_signal = QtCore.Signal(str)
|
||||
|
||||
|
||||
# HTTP share signals
|
||||
http_download_signal = QtCore.Signal(str, str)
|
||||
|
||||
|
||||
def __init__(self, dukto_handler, strings, config: Config, restart=False, no_quit=False):
|
||||
def __init__(
|
||||
self, dukto_handler, strings, config: Config, restart=False, no_quit=False
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
|
||||
self.strings = strings
|
||||
self.config = config
|
||||
self.listener = None
|
||||
@@ -51,15 +53,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.no_quit = no_quit
|
||||
|
||||
flags = (
|
||||
QtCore.Qt.FramelessWindowHint #type: ignore
|
||||
| QtCore.Qt.WindowStaysOnTopHint #type: ignore
|
||||
| QtCore.Qt.Tool #type: ignore
|
||||
| QtCore.Qt.WindowDoesNotAcceptFocus #type: ignore
|
||||
QtCore.Qt.FramelessWindowHint # type: ignore
|
||||
| QtCore.Qt.WindowStaysOnTopHint # type: ignore
|
||||
| QtCore.Qt.Tool # type: ignore
|
||||
| QtCore.Qt.WindowDoesNotAcceptFocus # type: ignore
|
||||
)
|
||||
|
||||
self.setWindowFlags(flags)
|
||||
self.setAttribute(QtCore.Qt.WA_TranslucentBackground) #type: ignore
|
||||
|
||||
self.setWindowFlags(flags)
|
||||
self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # type: ignore
|
||||
|
||||
# Load the image
|
||||
pix = QtGui.QPixmap(str(ASSET))
|
||||
self.image_size = pix.size()
|
||||
@@ -68,30 +70,48 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.label = QtWidgets.QLabel(self)
|
||||
self.label.setPixmap(pix)
|
||||
self.label.resize(pix.size())
|
||||
|
||||
|
||||
# Install event filter on the image to handle clicks
|
||||
self.label.installEventFilter(self)
|
||||
|
||||
|
||||
self.dukto_handler = dukto_handler
|
||||
self.progress_dialog = None
|
||||
|
||||
|
||||
# HTTP file sharing
|
||||
http_port = self.config.get("http_share_port", 8080)
|
||||
self.http_share = FileShareServer(port=http_port)
|
||||
self.http_share.on_download = lambda filename, ip: self.http_download_signal.emit(filename, ip)
|
||||
self.http_share.on_download = (
|
||||
lambda filename, ip: self.http_download_signal.emit(filename, ip)
|
||||
)
|
||||
|
||||
# Connect Dukto callbacks to emit signals
|
||||
self.dukto_handler.on_peer_added = lambda peer: self.peer_added_signal.emit(peer)
|
||||
self.dukto_handler.on_peer_removed = lambda peer: self.peer_removed_signal.emit(peer)
|
||||
self.dukto_handler.on_receive_request = lambda ip: self.receive_request_signal.emit(ip)
|
||||
self.dukto_handler.on_transfer_progress = lambda total, rec: self.progress_update_signal.emit(total, rec)
|
||||
self.dukto_handler.on_receive_start = lambda ip: self.receive_start_signal.emit(ip)
|
||||
self.dukto_handler.on_receive_complete = lambda files, size: self.receive_complete_signal.emit(files, size)
|
||||
self.dukto_handler.on_receive_text = lambda text, size: self.receive_text_signal.emit(text, size)
|
||||
self.dukto_handler.on_peer_added = lambda peer: self.peer_added_signal.emit(
|
||||
peer
|
||||
)
|
||||
self.dukto_handler.on_peer_removed = lambda peer: self.peer_removed_signal.emit(
|
||||
peer
|
||||
)
|
||||
self.dukto_handler.on_receive_request = (
|
||||
lambda ip: self.receive_request_signal.emit(ip)
|
||||
)
|
||||
self.dukto_handler.on_transfer_progress = (
|
||||
lambda total, rec: self.progress_update_signal.emit(total, rec)
|
||||
)
|
||||
self.dukto_handler.on_receive_start = lambda ip: self.receive_start_signal.emit(
|
||||
ip
|
||||
)
|
||||
self.dukto_handler.on_receive_complete = (
|
||||
lambda files, size: self.receive_complete_signal.emit(files, size)
|
||||
)
|
||||
self.dukto_handler.on_receive_text = (
|
||||
lambda text, size: self.receive_text_signal.emit(text, size)
|
||||
)
|
||||
self.dukto_handler.on_send_start = lambda ip: self.send_start_signal.emit(ip)
|
||||
self.dukto_handler.on_send_complete = lambda files: self.send_complete_signal.emit(files)
|
||||
self.dukto_handler.on_send_complete = (
|
||||
lambda files: self.send_complete_signal.emit(files)
|
||||
)
|
||||
self.dukto_handler.on_error = lambda msg: self.dukto_error_signal.emit(msg)
|
||||
|
||||
|
||||
# Connect signals to GUI slots
|
||||
self.peer_added_signal.connect(self.update_peer_menus)
|
||||
self.peer_removed_signal.connect(self.update_peer_menus)
|
||||
@@ -107,9 +127,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
self.tray = QtWidgets.QSystemTrayIcon(self)
|
||||
self.tray.setIcon(QtGui.QIcon(str(ASSET)))
|
||||
|
||||
|
||||
self.build_menus()
|
||||
|
||||
|
||||
# always on top timer
|
||||
self.stay_on_top_timer = QtCore.QTimer(self)
|
||||
self.stay_on_top_timer.timeout.connect(self.ensure_on_top)
|
||||
@@ -117,7 +137,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
# Super key
|
||||
self.show_menu_signal.connect(self.show_menu)
|
||||
if config.get("hotkey") != None and config.get("hotkey") != "none" and config.get("hotkey") != "":
|
||||
if (
|
||||
config.get("hotkey") is not None
|
||||
and config.get("hotkey") != "none"
|
||||
and config.get("hotkey") != ""
|
||||
):
|
||||
self.start_hotkey_listener()
|
||||
|
||||
def showEvent(self, event):
|
||||
@@ -125,34 +149,34 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
screen = QtWidgets.QApplication.primaryScreen()
|
||||
screen_geometry = screen.availableGeometry()
|
||||
self.setGeometry(screen_geometry)
|
||||
|
||||
|
||||
# Position the image bottom right
|
||||
label_x = screen_geometry.width() - self.image_size.width()
|
||||
label_y = screen_geometry.height() - self.image_size.height()
|
||||
self.label.move(label_x, label_y)
|
||||
|
||||
|
||||
# Create a mask for the window based on the image position
|
||||
self.update_mask()
|
||||
|
||||
|
||||
self.raise_()
|
||||
|
||||
|
||||
def update_mask(self):
|
||||
# Create a mask that only includes the image area
|
||||
mask = QtGui.QRegion(0, 0, 0, 0) # Empty (duh, it says 0)
|
||||
|
||||
|
||||
# Add the image region
|
||||
image_rect = self.label.geometry()
|
||||
|
||||
|
||||
pixmap = self.label.pixmap()
|
||||
if pixmap and not pixmap.isNull():
|
||||
img = pixmap.toImage()
|
||||
alpha_mask = img.createAlphaMask()
|
||||
bitmap_mask = QtGui.QBitmap.fromImage(alpha_mask)
|
||||
|
||||
|
||||
image_region = QtGui.QRegion(bitmap_mask)
|
||||
image_region.translate(image_rect.x(), image_rect.y())
|
||||
mask = mask.united(image_region)
|
||||
|
||||
|
||||
self.setMask(mask)
|
||||
|
||||
def build_menus(self):
|
||||
@@ -163,12 +187,18 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.left_menu.addAction(s["launch_app"], self.start_app_launcher)
|
||||
self.left_menu.addAction(s["search_files"], self.start_file_search)
|
||||
self.left_menu.addAction(s["search_web"], self.start_web_search)
|
||||
self.left_menu.addAction(s.get("calculator", "Calculator"), self.start_calculator)
|
||||
self.left_menu.addAction(
|
||||
s.get("calculator", "Calculator"), self.start_calculator
|
||||
)
|
||||
self.left_menu.addSeparator()
|
||||
share_menu_left = self.left_menu.addMenu(s["share_menu"])
|
||||
self.share_files_submenu_left = share_menu_left.addMenu(s["share_files_submenu"])
|
||||
self.share_files_submenu_left = share_menu_left.addMenu(
|
||||
s["share_files_submenu"]
|
||||
)
|
||||
self.share_text_submenu_left = share_menu_left.addMenu(s["share_text_submenu"])
|
||||
self.stop_share_action_left = share_menu_left.addAction("Stop Browser Share", self.stop_browser_share)
|
||||
self.stop_share_action_left = share_menu_left.addAction(
|
||||
"Stop Browser Share", self.stop_browser_share
|
||||
)
|
||||
self.left_menu.addSeparator()
|
||||
|
||||
# RIGHT MENU (Tray icon)
|
||||
@@ -179,30 +209,36 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
right_menu.addAction(s.get("calculator", "Calculator"), self.start_calculator)
|
||||
right_menu.addSeparator()
|
||||
share_menu_right = right_menu.addMenu(s["share_menu"])
|
||||
self.share_files_submenu_right = share_menu_right.addMenu(s["share_files_submenu"])
|
||||
self.share_text_submenu_right = share_menu_right.addMenu(s["share_text_submenu"])
|
||||
self.stop_share_action_right = share_menu_right.addAction("Stop Browser Share", self.stop_browser_share)
|
||||
self.share_files_submenu_right = share_menu_right.addMenu(
|
||||
s["share_files_submenu"]
|
||||
)
|
||||
self.share_text_submenu_right = share_menu_right.addMenu(
|
||||
s["share_text_submenu"]
|
||||
)
|
||||
self.stop_share_action_right = share_menu_right.addAction(
|
||||
"Stop Browser Share", self.stop_browser_share
|
||||
)
|
||||
right_menu.addSeparator()
|
||||
right_menu.addAction(s.get("settings", "Settings"), self.start_config_window)
|
||||
right_menu.addAction(s["check_updates"], self.update_git)
|
||||
|
||||
|
||||
if self.restart:
|
||||
right_menu.addAction(s["restart"], self.restart_application)
|
||||
right_menu.addAction(s["toggle_visibility"], self.toggle_visible)
|
||||
right_menu.addSeparator()
|
||||
if not self.no_quit:
|
||||
right_menu.addAction(s["quit"], QtWidgets.QApplication.quit)
|
||||
|
||||
|
||||
self.tray.setContextMenu(right_menu)
|
||||
self.tray.activated.connect(self.handle_tray_activated)
|
||||
self.tray.show()
|
||||
|
||||
|
||||
self.update_peer_menus()
|
||||
self.update_share_menu_state()
|
||||
|
||||
def update_share_menu_state(self):
|
||||
s_menu = self.strings["main_window"]["right_menu"]
|
||||
|
||||
|
||||
is_sharing = self.http_share.is_running()
|
||||
has_shared_files = bool(self.http_share.shared_files)
|
||||
has_shared_text = bool(self.http_share.shared_text)
|
||||
@@ -214,34 +250,43 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
# Configure file share menus
|
||||
for menu in [self.share_files_submenu_left, self.share_files_submenu_right]:
|
||||
for action in menu.actions():
|
||||
if hasattr(action, 'is_browser_action'):
|
||||
if hasattr(action, "is_browser_action"):
|
||||
menu.removeAction(action)
|
||||
|
||||
action_text = "Add File(s)..." if has_shared_files else s_menu["via_browser"]
|
||||
|
||||
action_text = (
|
||||
"Add File(s)..." if has_shared_files else s_menu["via_browser"]
|
||||
)
|
||||
browser_action = menu.addAction(action_text)
|
||||
browser_action.is_browser_action = True
|
||||
browser_action.triggered.connect(self.start_file_share_browser)
|
||||
|
||||
if any(not a.isSeparator() and not hasattr(a, 'is_browser_action') for a in menu.actions()):
|
||||
|
||||
if any(
|
||||
not a.isSeparator() and not hasattr(a, "is_browser_action")
|
||||
for a in menu.actions()
|
||||
):
|
||||
if not any(a.isSeparator() for a in menu.actions()):
|
||||
menu.addSeparator()
|
||||
menu.addSeparator()
|
||||
|
||||
# Configure text share menus
|
||||
for menu in [self.share_text_submenu_left, self.share_text_submenu_right]:
|
||||
for action in menu.actions():
|
||||
if hasattr(action, 'is_browser_action'):
|
||||
if hasattr(action, "is_browser_action"):
|
||||
menu.removeAction(action)
|
||||
|
||||
action_text = "Change Shared Text..." if has_shared_text else s_menu["via_browser"]
|
||||
|
||||
action_text = (
|
||||
"Change Shared Text..." if has_shared_text else s_menu["via_browser"]
|
||||
)
|
||||
browser_action = menu.addAction(action_text)
|
||||
browser_action.is_browser_action = True
|
||||
browser_action.triggered.connect(self.start_text_share_browser)
|
||||
|
||||
if any(not a.isSeparator() and not hasattr(a, 'is_browser_action') for a in menu.actions()):
|
||||
if any(
|
||||
not a.isSeparator() and not hasattr(a, "is_browser_action")
|
||||
for a in menu.actions()
|
||||
):
|
||||
if not any(a.isSeparator() for a in menu.actions()):
|
||||
menu.addSeparator()
|
||||
|
||||
|
||||
def show_menu(self):
|
||||
self.left_menu.popup(QtGui.QCursor.pos())
|
||||
|
||||
@@ -259,17 +304,19 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
}
|
||||
|
||||
try:
|
||||
keys = [key_map.get(k.strip().lower(), k.strip().lower()) for k in hotkey_str.split('+')]
|
||||
formatted_hotkey = '<' + '>+<'.join(keys) + '>' #type: ignore
|
||||
|
||||
keys = [
|
||||
key_map.get(k.strip().lower(), k.strip().lower())
|
||||
for k in hotkey_str.split("+")
|
||||
]
|
||||
formatted_hotkey = "<" + ">+<".join(keys) + ">" # type: ignore
|
||||
|
||||
hotkey = keyboard.HotKey(
|
||||
keyboard.HotKey.parse(formatted_hotkey),
|
||||
on_activate
|
||||
keyboard.HotKey.parse(formatted_hotkey), on_activate
|
||||
)
|
||||
|
||||
|
||||
self.listener = keyboard.Listener(
|
||||
on_press=hotkey.press, #type: ignore
|
||||
on_release=hotkey.release #type: ignore
|
||||
on_press=hotkey.press, # type: ignore
|
||||
on_release=hotkey.release, # type: ignore
|
||||
)
|
||||
self.listener.start()
|
||||
|
||||
@@ -285,17 +332,21 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
super().closeEvent(event)
|
||||
|
||||
def ensure_on_top(self):
|
||||
if self.isVisible() and not self.left_menu.isVisible() and not self.tray.contextMenu().isVisible():
|
||||
if (
|
||||
self.isVisible()
|
||||
and not self.left_menu.isVisible()
|
||||
and not self.tray.contextMenu().isVisible()
|
||||
):
|
||||
self.raise_()
|
||||
|
||||
def eventFilter(self, obj, event): #type: ignore
|
||||
|
||||
def eventFilter(self, obj, event): # type: ignore
|
||||
# Handle mouse events on the image
|
||||
if obj == self.label:
|
||||
if event.type() == QtCore.QEvent.MouseButtonPress: #type: ignore
|
||||
if event.button() == QtCore.Qt.LeftButton: #type: ignore
|
||||
if event.type() == QtCore.QEvent.MouseButtonPress: # type: ignore
|
||||
if event.button() == QtCore.Qt.LeftButton: # type: ignore
|
||||
self.left_menu.popup(event.globalPosition().toPoint())
|
||||
return True
|
||||
elif event.button() == QtCore.Qt.RightButton: #type: ignore
|
||||
elif event.button() == QtCore.Qt.RightButton: # type: ignore
|
||||
self.tray.contextMenu().popup(event.globalPosition().toPoint())
|
||||
return True
|
||||
return super().eventFilter(obj, event)
|
||||
@@ -313,76 +364,116 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
def update_peer_menus(self):
|
||||
s_main = self.strings["main_window"]
|
||||
no_peers_str = s_main["no_peers"]
|
||||
|
||||
|
||||
peers = list(self.dukto_handler.peers.values())
|
||||
|
||||
for menu in [self.share_files_submenu_left, self.share_files_submenu_right, self.share_text_submenu_left, self.share_text_submenu_right]:
|
||||
actions_to_remove = [a for a in menu.actions() if not a.isSeparator() and not hasattr(a, 'is_browser_action')]
|
||||
|
||||
for menu in [
|
||||
self.share_files_submenu_left,
|
||||
self.share_files_submenu_right,
|
||||
self.share_text_submenu_left,
|
||||
self.share_text_submenu_right,
|
||||
]:
|
||||
actions_to_remove = [
|
||||
a
|
||||
for a in menu.actions()
|
||||
if not a.isSeparator() and not hasattr(a, "is_browser_action")
|
||||
]
|
||||
for action in actions_to_remove:
|
||||
menu.removeAction(action)
|
||||
|
||||
|
||||
if not peers:
|
||||
for menu in [self.share_files_submenu_left, self.share_files_submenu_right, self.share_text_submenu_left, self.share_text_submenu_right]:
|
||||
for menu in [
|
||||
self.share_files_submenu_left,
|
||||
self.share_files_submenu_right,
|
||||
self.share_text_submenu_left,
|
||||
self.share_text_submenu_right,
|
||||
]:
|
||||
action = menu.addAction(no_peers_str)
|
||||
action.setEnabled(False)
|
||||
else:
|
||||
for peer in sorted(peers, key=lambda p: p.signature):
|
||||
for files_menu, text_menu in [(self.share_files_submenu_left, self.share_text_submenu_left), (self.share_files_submenu_right, self.share_text_submenu_right)]:
|
||||
for files_menu, text_menu in [
|
||||
(self.share_files_submenu_left, self.share_text_submenu_left),
|
||||
(self.share_files_submenu_right, self.share_text_submenu_right),
|
||||
]:
|
||||
file_action = files_menu.addAction(peer.signature)
|
||||
text_action = text_menu.addAction(peer.signature)
|
||||
file_action.triggered.connect(lambda checked=False, p=peer: self.start_file_send(p))
|
||||
text_action.triggered.connect(lambda checked=False, p=peer: self.start_text_send(p))
|
||||
|
||||
file_action.triggered.connect(
|
||||
lambda checked=False, p=peer: self.start_file_send(p)
|
||||
)
|
||||
text_action.triggered.connect(
|
||||
lambda checked=False, p=peer: self.start_text_send(p)
|
||||
)
|
||||
|
||||
self.update_share_menu_state()
|
||||
|
||||
def start_file_send(self, peer: Peer):
|
||||
dialog_title = self.strings["main_window"]["send_files_dialog_title"].format(peer_signature=peer.signature)
|
||||
file_paths, _ = QtWidgets.QFileDialog.getOpenFileNames(self, dialog_title, str(Path.home()))
|
||||
dialog_title = self.strings["main_window"]["send_files_dialog_title"].format(
|
||||
peer_signature=peer.signature
|
||||
)
|
||||
file_paths, _ = QtWidgets.QFileDialog.getOpenFileNames(
|
||||
self, dialog_title, str(Path.home())
|
||||
)
|
||||
if file_paths:
|
||||
self.dukto_handler.send_file(peer.address, file_paths, peer.port)
|
||||
|
||||
def start_text_send(self, peer: Peer):
|
||||
dialog_title = self.strings["main_window"]["send_text_dialog_title"].format(peer_signature=peer.signature)
|
||||
dialog_title = self.strings["main_window"]["send_text_dialog_title"].format(
|
||||
peer_signature=peer.signature
|
||||
)
|
||||
dialog_label = self.strings["main_window"]["send_text_dialog_label"]
|
||||
text, ok = QtWidgets.QInputDialog.getMultiLineText(self, dialog_title, dialog_label)
|
||||
text, ok = QtWidgets.QInputDialog.getMultiLineText(
|
||||
self, dialog_title, dialog_label
|
||||
)
|
||||
if ok and text:
|
||||
self.dukto_handler.send_text(peer.address, text, peer.port)
|
||||
|
||||
|
||||
def start_file_share_browser(self):
|
||||
s = self.strings["main_window"]
|
||||
is_adding = bool(self.http_share.shared_files)
|
||||
|
||||
dialog_title = "Select files to add" if is_adding else s["share_browser_dialog_title"]
|
||||
file_paths, _ = QtWidgets.QFileDialog.getOpenFileNames(self, dialog_title, str(Path.home()))
|
||||
|
||||
|
||||
dialog_title = (
|
||||
"Select files to add" if is_adding else s["share_browser_dialog_title"]
|
||||
)
|
||||
file_paths, _ = QtWidgets.QFileDialog.getOpenFileNames(
|
||||
self, dialog_title, str(Path.home())
|
||||
)
|
||||
|
||||
if not file_paths:
|
||||
return
|
||||
|
||||
try:
|
||||
if is_adding:
|
||||
self.http_share.add_files(file_paths)
|
||||
self.tray.showMessage("Files Added", f"{len(file_paths)} file(s) added to the share.", QtWidgets.QSystemTrayIcon.Information, 2000) #type: ignore
|
||||
self.tray.showMessage(
|
||||
"Files Added",
|
||||
f"{len(file_paths)} file(s) added to the share.",
|
||||
QtWidgets.QSystemTrayIcon.Information, # type:ignore
|
||||
2000,
|
||||
) # type: ignore
|
||||
else:
|
||||
url = self.http_share.share_files(file_paths)
|
||||
main_text = s["share_browser_text_files"]
|
||||
info_text = s["share_browser_files_info"].format(count=len(file_paths))
|
||||
if not self.http_share.shared_text:
|
||||
self._show_sharing_dialog(url, main_text, info_text)
|
||||
|
||||
|
||||
self.update_share_menu_state()
|
||||
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.critical(self, s["share_error_title"], s["share_error_text"].format(error=str(e)))
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self, s["share_error_title"], s["share_error_text"].format(error=str(e))
|
||||
)
|
||||
|
||||
def start_text_share_browser(self):
|
||||
s = self.strings["main_window"]
|
||||
is_changing = bool(self.http_share.shared_text)
|
||||
|
||||
|
||||
text, ok = QtWidgets.QInputDialog.getMultiLineText(
|
||||
self,
|
||||
s["share_text_browser_dialog_title"],
|
||||
self,
|
||||
s["share_text_browser_dialog_title"],
|
||||
s["share_text_browser_dialog_label"],
|
||||
self.http_share.shared_text or ""
|
||||
self.http_share.shared_text or "",
|
||||
)
|
||||
|
||||
if not (ok and text):
|
||||
@@ -398,34 +489,46 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
self.update_share_menu_state()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.critical(self, s["share_error_title"], s["share_error_text"].format(error=str(e)))
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self, s["share_error_title"], s["share_error_text"].format(error=str(e))
|
||||
)
|
||||
|
||||
def stop_browser_share(self):
|
||||
s = self.strings["main_window"]
|
||||
if self.http_share.is_running():
|
||||
self.http_share.stop()
|
||||
self.tray.showMessage(s["sharing_stopped_title"], s["sharing_stopped_text"], QtWidgets.QSystemTrayIcon.Information, 2000) #type: ignore
|
||||
self.tray.showMessage(
|
||||
s["sharing_stopped_title"],
|
||||
s["sharing_stopped_text"],
|
||||
QtWidgets.QSystemTrayIcon.Information, # type:ignore
|
||||
2000,
|
||||
) # type: ignore
|
||||
self.update_share_menu_state()
|
||||
|
||||
def _show_sharing_dialog(self, url: str, main_text: str, info_text: str):
|
||||
s = self.strings["main_window"]
|
||||
msg = QtWidgets.QMessageBox(self)
|
||||
msg.setIcon(QtWidgets.QMessageBox.Information) #type: ignore
|
||||
msg.setIcon(QtWidgets.QMessageBox.Information) # type: ignore
|
||||
msg.setWindowTitle(s["share_browser_title"])
|
||||
msg.setText(main_text)
|
||||
msg.setInformativeText(f"{s['share_browser_url']}:\n\n{url}\n\n{info_text}")
|
||||
|
||||
copy_btn = msg.addButton(s["copy_url"], QtWidgets.QMessageBox.ActionRole) #type: ignore
|
||||
open_btn = msg.addButton(s["open_browser"], QtWidgets.QMessageBox.ActionRole) #type: ignore
|
||||
msg.addButton(QtWidgets.QMessageBox.Ok) #type: ignore
|
||||
|
||||
|
||||
copy_btn = msg.addButton(s["copy_url"], QtWidgets.QMessageBox.ActionRole) # type: ignore
|
||||
open_btn = msg.addButton(s["open_browser"], QtWidgets.QMessageBox.ActionRole) # type: ignore
|
||||
msg.addButton(QtWidgets.QMessageBox.Ok) # type: ignore
|
||||
|
||||
msg.exec()
|
||||
|
||||
|
||||
clicked = msg.clickedButton()
|
||||
if clicked == copy_btn:
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText(url)
|
||||
self.tray.showMessage(s["url_copied_title"], s["url_copied_text"], QtWidgets.QSystemTrayIcon.Information, 2000) #type: ignore
|
||||
self.tray.showMessage(
|
||||
s["url_copied_title"],
|
||||
s["url_copied_text"],
|
||||
QtWidgets.QSystemTrayIcon.Information, # type: ignore
|
||||
2000,
|
||||
) # type: ignore
|
||||
elif clicked == open_btn:
|
||||
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url))
|
||||
|
||||
@@ -435,17 +538,20 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.tray.showMessage(
|
||||
s["download_notification_title"],
|
||||
s["download_notification_text"].format(filename=filename, ip=client_ip),
|
||||
QtWidgets.QSystemTrayIcon.Information, #type: ignore
|
||||
3000
|
||||
QtWidgets.QSystemTrayIcon.Information, # type: ignore
|
||||
3000,
|
||||
)
|
||||
|
||||
def show_receive_confirmation(self, sender_ip: str):
|
||||
reply = QtWidgets.QMessageBox.question(
|
||||
self,
|
||||
self.strings["main_window"]["receive_confirm_title"],
|
||||
self.strings["main_window"]["receive_confirm_text"].format(sender_ip=sender_ip),
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.No
|
||||
self.strings["main_window"]["receive_confirm_text"].format(
|
||||
sender_ip=sender_ip
|
||||
),
|
||||
QtWidgets.QMessageBox.StandardButton.Yes
|
||||
| QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.No,
|
||||
)
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
self.dukto_handler.approve_transfer()
|
||||
@@ -455,17 +561,23 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
@QtCore.Slot(str)
|
||||
def handle_receive_start(self, sender_ip: str):
|
||||
s = self.strings["main_window"]["progress_dialog"]
|
||||
self.progress_dialog = QtWidgets.QProgressDialog(s["receiving_label"], s["cancel_button"], 0, 100, self)
|
||||
self.progress_dialog.setWindowTitle(s["receiving_title"].format(sender_ip=sender_ip))
|
||||
self.progress_dialog.setWindowModality(QtCore.Qt.WindowModal) # type: ignore
|
||||
self.progress_dialog = QtWidgets.QProgressDialog(
|
||||
s["receiving_label"], s["cancel_button"], 0, 100, self
|
||||
)
|
||||
self.progress_dialog.setWindowTitle(
|
||||
s["receiving_title"].format(sender_ip=sender_ip)
|
||||
)
|
||||
self.progress_dialog.setWindowModality(QtCore.Qt.WindowModal) # type: ignore
|
||||
self.progress_dialog.show()
|
||||
|
||||
|
||||
@QtCore.Slot(str)
|
||||
def handle_send_start(self, dest_ip: str):
|
||||
s = self.strings["main_window"]["progress_dialog"]
|
||||
self.progress_dialog = QtWidgets.QProgressDialog(s["sending_label"], s["cancel_button"], 0, 100, self)
|
||||
self.progress_dialog = QtWidgets.QProgressDialog(
|
||||
s["sending_label"], s["cancel_button"], 0, 100, self
|
||||
)
|
||||
self.progress_dialog.setWindowTitle(s["sending_title"].format(dest_ip=dest_ip))
|
||||
self.progress_dialog.setWindowModality(QtCore.Qt.WindowModal) # type: ignore
|
||||
self.progress_dialog.setWindowModality(QtCore.Qt.WindowModal) # type: ignore
|
||||
self.progress_dialog.show()
|
||||
|
||||
@QtCore.Slot(int, int)
|
||||
@@ -480,23 +592,28 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.progress_dialog.setValue(total_size)
|
||||
self.progress_dialog.close()
|
||||
self.progress_dialog = None
|
||||
|
||||
|
||||
s = self.strings["main_window"]
|
||||
QtWidgets.QMessageBox.information(self, s["receive_complete_title"], s["receive_complete_text"].format(count=len(received_files)))
|
||||
|
||||
QtWidgets.QMessageBox.information(
|
||||
self,
|
||||
s["receive_complete_title"],
|
||||
s["receive_complete_text"].format(count=len(received_files)),
|
||||
)
|
||||
|
||||
reply = QtWidgets.QMessageBox.question(
|
||||
self,
|
||||
s["open_folder_title"],
|
||||
s["open_folder_text"],
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.Yes
|
||||
| QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.Yes,
|
||||
)
|
||||
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
receive_dir = str(Path.home() / "Received")
|
||||
url = QtCore.QUrl.fromLocalFile(receive_dir)
|
||||
QtGui.QDesktopServices.openUrl(url)
|
||||
|
||||
|
||||
@QtCore.Slot(list)
|
||||
def handle_send_complete(self, sent_files: list):
|
||||
if self.progress_dialog:
|
||||
@@ -504,19 +621,25 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.progress_dialog.setValue(self.progress_dialog.maximum())
|
||||
self.progress_dialog.close()
|
||||
self.progress_dialog = None
|
||||
|
||||
|
||||
s = self.strings["main_window"]
|
||||
if sent_files and sent_files[0] == "___DUKTO___TEXT___":
|
||||
QtWidgets.QMessageBox.information(self, s["send_complete_title"], s["send_complete_text_single"])
|
||||
QtWidgets.QMessageBox.information(
|
||||
self, s["send_complete_title"], s["send_complete_text_single"]
|
||||
)
|
||||
else:
|
||||
QtWidgets.QMessageBox.information(self, s["send_complete_title"], s["send_complete_text"].format(count=len(sent_files)))
|
||||
QtWidgets.QMessageBox.information(
|
||||
self,
|
||||
s["send_complete_title"],
|
||||
s["send_complete_text"].format(count=len(sent_files)),
|
||||
)
|
||||
|
||||
@QtCore.Slot(str, int)
|
||||
def handle_receive_text(self, text: str, total_size: int):
|
||||
if self.progress_dialog:
|
||||
self.progress_dialog.close()
|
||||
self.progress_dialog = None
|
||||
|
||||
|
||||
dialog = TextViewerDialog(text, self.strings, self)
|
||||
dialog.exec()
|
||||
|
||||
@@ -525,7 +648,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
if self.progress_dialog:
|
||||
self.progress_dialog.close()
|
||||
self.progress_dialog = None
|
||||
QtWidgets.QMessageBox.critical(self, self.strings["main_window"]["dukto_error_title"], self.strings["main_window"]["dukto_error_text"].format(error_msg=error_msg))
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
self.strings["main_window"]["dukto_error_title"],
|
||||
self.strings["main_window"]["dukto_error_text"].format(error_msg=error_msg),
|
||||
)
|
||||
|
||||
def start_app_launcher(self):
|
||||
self.app_launcher_dialog = AppLauncherDialog(self.strings, self)
|
||||
@@ -547,16 +674,18 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
dialog.setWindowTitle(s["input_title"])
|
||||
dialog.setLabelText(s["input_label"])
|
||||
dialog.move(QtGui.QCursor.pos())
|
||||
|
||||
|
||||
ok = dialog.exec()
|
||||
pattern = dialog.textValue()
|
||||
|
||||
|
||||
if ok and pattern:
|
||||
try:
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) #type: ignore
|
||||
results = find(pattern, root='~')
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) # type: ignore
|
||||
results = find(pattern, root="~")
|
||||
except RuntimeError as e:
|
||||
QtWidgets.QMessageBox.critical(self, s["search_error_title"], s["search_error_text"].format(e=e))
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self, s["search_error_title"], s["search_error_text"].format(e=e)
|
||||
)
|
||||
return
|
||||
finally:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
@@ -565,23 +694,37 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.results_dialog = FileSearchResults(results, self.strings, self)
|
||||
self.results_dialog.show()
|
||||
else:
|
||||
reply = QtWidgets.QMessageBox.question(self, s["no_results_title"], s["no_results_home_text"],
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No, QtWidgets.QMessageBox.StandardButton.No)
|
||||
reply = QtWidgets.QMessageBox.question(
|
||||
self,
|
||||
s["no_results_title"],
|
||||
s["no_results_home_text"],
|
||||
QtWidgets.QMessageBox.StandardButton.Yes
|
||||
| QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.No,
|
||||
)
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
try:
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) # type: ignore
|
||||
results = find(pattern, root='/')
|
||||
results = find(pattern, root="/")
|
||||
except RuntimeError as e:
|
||||
QtWidgets.QMessageBox.critical(self, s["search_error_title"], s["search_error_text"].format(e=e))
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
s["search_error_title"],
|
||||
s["search_error_text"].format(e=e),
|
||||
)
|
||||
return
|
||||
finally:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
|
||||
if results:
|
||||
self.results_dialog = FileSearchResults(results, self.strings, self)
|
||||
self.results_dialog = FileSearchResults(
|
||||
results, self.strings, self
|
||||
)
|
||||
self.results_dialog.show()
|
||||
else:
|
||||
QtWidgets.QMessageBox.information(self, s["no_results_title"], s["no_results_root_text"])
|
||||
QtWidgets.QMessageBox.information(
|
||||
self, s["no_results_title"], s["no_results_root_text"]
|
||||
)
|
||||
|
||||
def start_web_search(self):
|
||||
s = self.strings["web_search"]
|
||||
@@ -592,66 +735,86 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
ok = dialog.exec()
|
||||
query = dialog.textValue()
|
||||
|
||||
|
||||
if ok and query:
|
||||
try:
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) #type: ignore
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) # type: ignore
|
||||
search_engine = self.config.get("search_engine", "brave")
|
||||
leta = MullvadLetaWrapper(engine=search_engine)
|
||||
results = leta.search(query)
|
||||
|
||||
if results and results.get('results'):
|
||||
self.web_results_dialog = WebSearchResults(results, self.strings, self)
|
||||
|
||||
if results and results.get("results"):
|
||||
self.web_results_dialog = WebSearchResults(
|
||||
results, self.strings, self
|
||||
)
|
||||
self.web_results_dialog.show()
|
||||
else:
|
||||
QtWidgets.QMessageBox.information(self, s["no_results_title"], s["no_results_text"])
|
||||
|
||||
QtWidgets.QMessageBox.information(
|
||||
self, s["no_results_title"], s["no_results_text"]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.critical(self, s["search_error_title"], s["search_error_text"].format(e=e))
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self, s["search_error_title"], s["search_error_text"].format(e=e)
|
||||
)
|
||||
finally:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
|
||||
def update_git(self):
|
||||
s = self.strings["main_window"]["updater"]
|
||||
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) #type: ignore
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) # type: ignore
|
||||
update_available = is_update_available()
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
|
||||
if not update_available:
|
||||
QtWidgets.QMessageBox.information(self, s["no_updates_title"], s["no_updates_text"])
|
||||
QtWidgets.QMessageBox.information(
|
||||
self, s["no_updates_title"], s["no_updates_text"]
|
||||
)
|
||||
return
|
||||
else:
|
||||
reply = QtWidgets.QMessageBox.question(self, s["update_available_title"],
|
||||
s["update_available_text"],
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.Yes)
|
||||
reply = QtWidgets.QMessageBox.question(
|
||||
self,
|
||||
s["update_available_title"],
|
||||
s["update_available_text"],
|
||||
QtWidgets.QMessageBox.StandardButton.Yes
|
||||
| QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.Yes,
|
||||
)
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.No:
|
||||
return
|
||||
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) #type: ignore
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) # type: ignore
|
||||
status, message = update_repository()
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
|
||||
|
||||
if status == "UPDATED":
|
||||
reply = QtWidgets.QMessageBox.question(self, s["update_success_title"],
|
||||
s["update_success_text"].format(message=message),
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.Yes)
|
||||
reply = QtWidgets.QMessageBox.question(
|
||||
self,
|
||||
s["update_success_title"],
|
||||
s["update_success_text"].format(message=message),
|
||||
QtWidgets.QMessageBox.StandardButton.Yes
|
||||
| QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.Yes,
|
||||
)
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
self.restart_application()
|
||||
|
||||
|
||||
elif status == "FAILED":
|
||||
QtWidgets.QMessageBox.critical(self, s["update_failed_title"], s["update_failed_text"].format(message=message))
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
s["update_failed_title"],
|
||||
s["update_failed_text"].format(message=message),
|
||||
)
|
||||
|
||||
def restart_application(self):
|
||||
presence.end()
|
||||
self.dukto_handler.shutdown()
|
||||
if self.http_share.is_running():
|
||||
self.http_share.stop()
|
||||
|
||||
|
||||
args = [sys.executable] + sys.argv
|
||||
|
||||
subprocess.Popen(args)
|
||||
|
||||
QtWidgets.QApplication.quit()
|
||||
|
||||
QtWidgets.QApplication.quit()
|
||||
|
||||
Reference in New Issue
Block a user