mirror of
https://github.com/samschott/maestral.git
synced 2024-11-11 11:36:35 +03:00
dark mode refinements
This commit is contained in:
parent
a39e182e11
commit
a4b456d315
@ -40,9 +40,9 @@ _Added:_
|
||||
|
||||
- Added progress messages for uploads and downloads, e.g., "Downloading 3/98...". These
|
||||
are output as info messages and shown in the status field of the system tray menu.
|
||||
|
||||
- When unlinking your Dropbox account through the GUI, Maestral is restarted to enter the
|
||||
setup dialog.
|
||||
- Refinements for dark interface themes such as Dark Mode in macOS Mojave
|
||||
|
||||
_Changed:_
|
||||
|
||||
|
@ -28,7 +28,7 @@ from maestral.gui.first_sync_dialog import FirstSyncDialog
|
||||
from maestral.gui.sync_issues_window import SyncIssueWindow
|
||||
from maestral.gui.rebuild_index_dialog import RebuildIndexDialog
|
||||
from maestral.gui.resources import TRAY_ICON_PATH
|
||||
from maestral.gui.utils import truncate_string, get_scaled_font, get_theme
|
||||
from maestral.gui.utils import truncate_string, get_scaled_font, isDarkStatusBar
|
||||
|
||||
|
||||
FIRST_SYNC = (not CONF.get("internal", "lastsync") or
|
||||
@ -127,8 +127,7 @@ class MaestralApp(QtWidgets.QSystemTrayIcon):
|
||||
icon_color = "dark"
|
||||
|
||||
if not platform.system() == "Darwin":
|
||||
THEME = get_theme()
|
||||
if THEME is "dark":
|
||||
if isDarkStatusBar():
|
||||
icon_color = "light"
|
||||
short = ("idle", "syncing", "paused", "disconnected", "error")
|
||||
for l, s in zip((IDLE, SYNCING, PAUSED, DISCONNECTED, SYNC_ERROR), short):
|
||||
@ -292,9 +291,10 @@ class MaestralApp(QtWidgets.QSystemTrayIcon):
|
||||
"""Update account usage info in UI."""
|
||||
usage_string = str(space_usage)
|
||||
self.accountUsageAction.setText(usage_string)
|
||||
self.settings.labelSpaceUsage2.setText(usage_string)
|
||||
self.settings.labelSpaceUsage.setText(usage_string)
|
||||
|
||||
def on_error(self, exc_info):
|
||||
@staticmethod
|
||||
def on_error(exc_info):
|
||||
exc_type, exc, tb = exc_info
|
||||
|
||||
if isinstance(exc, CorruptedRevFileError):
|
||||
|
@ -21,7 +21,7 @@
|
||||
<number>20</number>
|
||||
</property>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<widget class="QLabel" name="labelExcludedFoldersTitle">
|
||||
<property name="text">
|
||||
<string>Select folders to sync:</string>
|
||||
</property>
|
||||
@ -46,18 +46,8 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<widget class="QLabel" name="labelDropboxPathTitle">
|
||||
<property name="text">
|
||||
<string>Dropbox folder location:</string>
|
||||
</property>
|
||||
@ -74,7 +64,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="labelSpaceUsage1">
|
||||
<widget class="QLabel" name="labelSpaceUsageTitle">
|
||||
<property name="text">
|
||||
<string>Your space:</string>
|
||||
</property>
|
||||
@ -84,7 +74,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2" alignment="Qt::AlignHCenter">
|
||||
<widget class="Line" name="line_1">
|
||||
<widget class="Line" name="line1">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
@ -109,7 +99,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="0" colspan="2" alignment="Qt::AlignHCenter">
|
||||
<widget class="Line" name="line_2">
|
||||
<widget class="Line" name="line2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
@ -166,7 +156,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="21" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="labelAboutTitle">
|
||||
<property name="text">
|
||||
<string>About Maestral:</string>
|
||||
</property>
|
||||
@ -176,7 +166,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2" alignment="Qt::AlignHCenter">
|
||||
<widget class="Line" name="line_0">
|
||||
<widget class="Line" name="line0">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
@ -211,7 +201,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QLabel" name="labelSpaceUsage2">
|
||||
<widget class="QLabel" name="labelSpaceUsage">
|
||||
<property name="text">
|
||||
<string>30.3% out of 1,000,000GB used</string>
|
||||
</property>
|
||||
@ -231,7 +221,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<widget class="QLabel" name="labelAccountEmailTitle">
|
||||
<property name="text">
|
||||
<string>Account:</string>
|
||||
</property>
|
||||
|
@ -19,7 +19,8 @@ from maestral.config.base import get_home_dir
|
||||
from maestral.gui.folders_dialog import FoldersDialog
|
||||
from maestral.gui.resources import (get_native_item_icon, UNLINK_DIALOG_PATH,
|
||||
SETTINGS_WINDOW_PATH)
|
||||
from maestral.gui.utils import get_scaled_font
|
||||
from maestral.gui.utils import (get_scaled_font, isDarkWindow, LINE_COLOR_DARK,
|
||||
LINE_COLOR_LIGHT)
|
||||
|
||||
|
||||
class UnlinkDialog(QtWidgets.QDialog):
|
||||
@ -39,6 +40,7 @@ class SettingsWindow(QtWidgets.QWidget):
|
||||
def __init__(self, mdbx, parent=None):
|
||||
super(self.__class__, self).__init__(parent=parent)
|
||||
uic.loadUi(SETTINGS_WINDOW_PATH, self)
|
||||
self.update_dark_mode()
|
||||
# self.setFixedSize(560, 320)
|
||||
|
||||
self.mdbx = mdbx
|
||||
@ -61,10 +63,10 @@ class SettingsWindow(QtWidgets.QWidget):
|
||||
self.labelAccountEmail.setText(CONF.get("account", "email"))
|
||||
usage_type = CONF.get("account", "usage_type")
|
||||
if usage_type == "team":
|
||||
self.labelSpaceUsage1.setText("Your team's space:")
|
||||
self.labelSpaceUsageTitle.setText("Your team's space:")
|
||||
elif usage_type == "individual":
|
||||
self.labelSpaceUsage1.setText("Your space:")
|
||||
self.labelSpaceUsage2.setText(CONF.get("account", "usage"))
|
||||
self.labelSpaceUsageTitle.setText("Your space:")
|
||||
self.labelSpaceUsage.setText(CONF.get("account", "usage"))
|
||||
self.pushButtonUnlink.clicked.connect(self.unlink_dialog.open)
|
||||
self.unlink_dialog.accepted.connect(self.on_unlink)
|
||||
|
||||
@ -147,3 +149,16 @@ class SettingsWindow(QtWidgets.QWidget):
|
||||
return osp.relpath(path, usr)
|
||||
else:
|
||||
return path
|
||||
|
||||
def changeEvent(self, QEvent):
|
||||
|
||||
if QEvent.type() == QtCore.QEvent.PaletteChange:
|
||||
self.update_dark_mode()
|
||||
|
||||
def update_dark_mode(self):
|
||||
rgb = LINE_COLOR_DARK if isDarkWindow() else LINE_COLOR_LIGHT
|
||||
line_style = "color: rgb({0}, {1}, {2})".format(*rgb)
|
||||
|
||||
self.line0.setStyleSheet(line_style)
|
||||
self.line1.setStyleSheet(line_style)
|
||||
self.line2.setStyleSheet(line_style)
|
||||
|
@ -13,7 +13,8 @@ from PyQt5 import QtCore, QtGui, QtWidgets, uic
|
||||
|
||||
from maestral.gui.resources import (SYNC_ISSUES_WINDOW_PATH, SYNC_ISSUE_WIDGET_PATH,
|
||||
get_native_item_icon)
|
||||
from maestral.gui.utils import truncate_string, get_scaled_font
|
||||
from maestral.gui.utils import (truncate_string, get_scaled_font, isDarkWindow,
|
||||
LINE_COLOR_DARK, LINE_COLOR_LIGHT)
|
||||
|
||||
HAS_GTK_LAUNCH = shutil.which("gtk-launch") is not None
|
||||
|
||||
@ -32,20 +33,11 @@ class SyncIssueWidget(QtWidgets.QWidget):
|
||||
self.errorLabel.setFont(get_scaled_font(scaling=0.85))
|
||||
|
||||
# set appropriate background color
|
||||
bg_color = self.palette().color(QtGui.QPalette.Background)
|
||||
bg_color_rgb = [bg_color.red(), bg_color.green(), bg_color.blue()]
|
||||
frame_bg_color = [min([c + 20, 255]) for c in bg_color_rgb]
|
||||
self.frame.setStyleSheet("""
|
||||
.QFrame {{
|
||||
border: 1px solid rgb(205, 203, 205);
|
||||
background-color: rgb({0},{1},{2});
|
||||
border-radius: 7px;
|
||||
}}""".format(*frame_bg_color))
|
||||
self.update_dark_mode()
|
||||
|
||||
# fill with content
|
||||
icon = get_native_item_icon(self.sync_issue.local_path)
|
||||
pixmap = icon.pixmap(2*self.iconLabel.width(), 2*self.iconLabel.height())
|
||||
pixmap.setDevicePixelRatio(2.0)
|
||||
pixmap = icon.pixmap(self.iconLabel.width(), self.iconLabel.height())
|
||||
self.iconLabel.setPixmap(pixmap)
|
||||
|
||||
self.pathLabel.setText(self.to_display_path(self.sync_issue.local_path))
|
||||
@ -97,6 +89,22 @@ class SyncIssueWidget(QtWidgets.QWidget):
|
||||
else:
|
||||
subprocess.run(["xdg-open", path])
|
||||
|
||||
def changeEvent(self, QEvent):
|
||||
if QEvent.type() == QtCore.QEvent.PaletteChange:
|
||||
self.update_dark_mode()
|
||||
|
||||
def update_dark_mode(self):
|
||||
line_rgb = LINE_COLOR_DARK if isDarkWindow() else LINE_COLOR_LIGHT
|
||||
bg_color = self.palette().color(QtGui.QPalette.Background)
|
||||
bg_color_rgb = [bg_color.red(), bg_color.green(), bg_color.blue()]
|
||||
frame_bg_color = [min([c + 16, 255]) for c in bg_color_rgb]
|
||||
self.frame.setStyleSheet("""
|
||||
.QFrame {{
|
||||
border: 1px solid rgb({0},{1},{2});
|
||||
background-color: rgb({3},{4},{5});
|
||||
border-radius: 7px;
|
||||
}}""".format(*line_rgb, *frame_bg_color))
|
||||
|
||||
|
||||
class SyncIssueWindow(QtWidgets.QWidget):
|
||||
"""
|
||||
@ -147,7 +155,9 @@ if __name__ == "__main__":
|
||||
from maestral.client import MaestralApiError
|
||||
import queue
|
||||
|
||||
app = QtWidgets.QApplication([])
|
||||
app = QtWidgets.QApplication([""])
|
||||
app.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)
|
||||
|
||||
text1 = ("Something went wrong with the job on Dropbox’s end. Please "
|
||||
"verify on the Dropbox website if the move succeeded and try "
|
||||
"again if it failed. This should happen very rarely.")
|
||||
@ -155,7 +165,9 @@ if __name__ == "__main__":
|
||||
text2 = ("There are too many write operations your "
|
||||
"Dropbox. Please try again later.")
|
||||
|
||||
err1 = MaestralApiError("Could not download", text1, local_path="/MyLargeFile")
|
||||
path = "/Users/samschott/Dropbox/MATLAB_scripts/CuSCN2 fitting/CuSCN2_5K_HFI_fit.mat"
|
||||
|
||||
err1 = MaestralApiError("Could not download", text1, local_path=path)
|
||||
err2 = MaestralApiError("Could not delete folder", text2, local_path="/test_folder")
|
||||
|
||||
err_queue = queue.Queue()
|
||||
|
@ -11,6 +11,9 @@ from PyQt5 import QtGui, QtWidgets
|
||||
THEME_DARK = "dark"
|
||||
THEME_LIGHT = "light"
|
||||
|
||||
LINE_COLOR_DARK = (95, 104, 104)
|
||||
LINE_COLOR_LIGHT = (205, 203, 205)
|
||||
|
||||
|
||||
def truncate_string(string, font=None, pixels=200, side="right"):
|
||||
|
||||
@ -128,12 +131,41 @@ def __pixel_at(x, y):
|
||||
return ((color >> 16) & 0xff), ((color >> 8) & 0xff), (color & 0xff)
|
||||
|
||||
|
||||
def get_theme():
|
||||
def statusBarTheme():
|
||||
"""
|
||||
Returns one of THEME_LIGHT or THEME_DARK, corresponding to current user's UI theme
|
||||
Returns one of THEME_LIGHT or THEME_DARK, corresponding to current status bar theme
|
||||
"""
|
||||
# getting color of a pixel on a top bar, and identifying best-fitting color
|
||||
# theme based on its luminance
|
||||
pixel_rgb = __pixel_at(2, 2)
|
||||
luminance = _luminance(*pixel_rgb)
|
||||
return THEME_LIGHT if luminance >= 0.5 else THEME_DARK
|
||||
return THEME_LIGHT if luminance >= 0.4 else THEME_DARK
|
||||
|
||||
|
||||
def windowTheme():
|
||||
"""
|
||||
Returns one of THEME_LIGHT or THEME_DARK, corresponding to current user's UI theme
|
||||
"""
|
||||
# getting color of a pixel on a top bar, and identifying best-fitting color
|
||||
# theme based on its luminance
|
||||
w = QtWidgets.QWidget()
|
||||
bg_color = w.palette().color(QtGui.QPalette.Background)
|
||||
bg_color_rgb = [bg_color.red(), bg_color.green(), bg_color.blue()]
|
||||
luminance = _luminance(*bg_color_rgb)
|
||||
return THEME_LIGHT if luminance >= 0.4 else THEME_DARK
|
||||
|
||||
|
||||
def isDarkWindow():
|
||||
return windowTheme() == THEME_DARK
|
||||
|
||||
|
||||
def isLightWindow():
|
||||
return windowTheme() == THEME_LIGHT
|
||||
|
||||
|
||||
def isDarkStatusBar():
|
||||
return statusBarTheme() == THEME_DARK
|
||||
|
||||
|
||||
def isLightStatusBar():
|
||||
return statusBarTheme() == THEME_LIGHT
|
||||
|
Loading…
Reference in New Issue
Block a user