diff --git a/cli/onionshare_cli/settings.py b/cli/onionshare_cli/settings.py
index 54a0fcd9..665c41c9 100644
--- a/cli/onionshare_cli/settings.py
+++ b/cli/onionshare_cli/settings.py
@@ -110,6 +110,7 @@ class Settings(object):
"tor_bridges_use_custom_bridges": "",
"persistent_tabs": [],
"locale": None, # this gets defined in fill_in_defaults()
+ "theme": 0
}
self._settings = {}
self.fill_in_defaults()
diff --git a/cli/tests/test_cli_settings.py b/cli/tests/test_cli_settings.py
index 62f97267..4c012901 100644
--- a/cli/tests/test_cli_settings.py
+++ b/cli/tests/test_cli_settings.py
@@ -34,6 +34,7 @@ class TestSettings:
"tor_bridges_use_meek_lite_azure": False,
"tor_bridges_use_custom_bridges": "",
"persistent_tabs": [],
+ "theme":0
}
for key in settings_obj._settings:
# Skip locale, it will not always default to the same thing
diff --git a/desktop/src/onionshare/__init__.py b/desktop/src/onionshare/__init__.py
index 8276dae4..9d8d8981 100644
--- a/desktop/src/onionshare/__init__.py
+++ b/desktop/src/onionshare/__init__.py
@@ -28,7 +28,11 @@ import psutil
import getpass
from PySide2 import QtCore, QtWidgets, QtGui
+from PySide2.QtCore import Slot,Qt
+from PySide2.QtGui import QPalette, QColor
+
from onionshare_cli.common import Common
+from onionshare_cli.settings import Settings
from .gui_common import GuiCommon
from .widgets import Alert
@@ -47,7 +51,12 @@ class Application(QtWidgets.QApplication):
QtWidgets.QApplication.__init__(self, sys.argv)
# Check color mode on starting the app
- self.color_mode = self.get_color_mode()
+ self.color_mode = self.get_color_mode(common)
+
+ # Enable Dark Theme
+ if self.color_mode == "dark":
+ self.setDarkMode()
+
self.installEventFilter(self)
def eventFilter(self, obj, event):
@@ -65,9 +74,36 @@ class Application(QtWidgets.QApplication):
return False
return True
- def get_color_mode(self):
- return "dark" if self.is_dark_mode() else "light"
+ def setDarkMode(self):
+ self.setStyle("Fusion")
+ dark_palette = QPalette()
+ dark_palette.setColor(QPalette.Window, QColor(53, 53, 53))
+ dark_palette.setColor(QPalette.WindowText, Qt.white)
+ dark_palette.setColor(QPalette.Base, QColor(25, 25, 25))
+ dark_palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
+ dark_palette.setColor(QPalette.ToolTipBase, Qt.white)
+ dark_palette.setColor(QPalette.ToolTipText, Qt.white)
+ dark_palette.setColor(QPalette.Text, Qt.white)
+ dark_palette.setColor(QPalette.Button, QColor(53, 53, 53))
+ dark_palette.setColor(QPalette.ButtonText, Qt.white)
+ dark_palette.setColor(QPalette.BrightText, Qt.red)
+ dark_palette.setColor(QPalette.Link, QColor(42, 130, 218))
+ dark_palette.setColor(QPalette.Highlight, QColor(42, 130, 218))
+ dark_palette.setColor(QPalette.HighlightedText, Qt.black)
+ self.setPalette(dark_palette)
+ self.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }")
+ def get_color_mode(self, common):
+ curr_settings = Settings(common)
+ curr_settings.load()
+ current_theme = curr_settings.get("theme")
+
+ if current_theme == 1:
+ return "light"
+ elif current_theme == 2:
+ return "dark"
+ else:
+ return "dark" if self.is_dark_mode() else "light"
def main():
"""
diff --git a/desktop/src/onionshare/gui_common.py b/desktop/src/onionshare/gui_common.py
index 441aff25..182d63f2 100644
--- a/desktop/src/onionshare/gui_common.py
+++ b/desktop/src/onionshare/gui_common.py
@@ -87,6 +87,12 @@ class GuiCommon:
new_tab_button_background = "#ffffff"
new_tab_button_border = "#efeff0"
new_tab_button_text_color = "#4e0d4e"
+ downloads_uploads_progress_bar_border_color = "#4E064F"
+ downloads_uploads_progress_bar_chunk_color = "#4E064F"
+ share_zip_progess_bar_border_color = "#4E064F"
+ share_zip_progess_bar_chunk_color = "#4E064F"
+ history_background_color = "#ffffff"
+ history_label_color = "#000000"
if color_mode == "dark":
header_color = "#F2F2F2"
title_color = "#F2F2F2"
@@ -94,6 +100,9 @@ class GuiCommon:
new_tab_button_background = "#5F5F5F"
new_tab_button_border = "#878787"
new_tab_button_text_color = "#FFFFFF"
+ share_zip_progess_bar_border_color = "#F2F2F2"
+ history_background_color = "#191919"
+ history_label_color = "#ffffff"
return {
# OnionShareGui styles
@@ -193,9 +202,17 @@ class GuiCommon:
border: 0;
border-radius: 5px;
}""",
+ "downloads_uploads_not_empty": """
+ QWidget{
+ background-color: """
+ + history_background_color
+ +""";
+ }""",
"downloads_uploads_empty": """
QWidget {
- background-color: #ffffff;
+ background-color: """
+ + history_background_color
+ +""";
border: 1px solid #999999;
}
QWidget QLabel {
@@ -233,7 +250,7 @@ class GuiCommon:
"downloads_uploads_progress_bar": """
QProgressBar {
border: 1px solid """
- + header_color
+ + downloads_uploads_progress_bar_border_color
+ """;
background-color: #ffffff !important;
text-align: center;
@@ -242,10 +259,16 @@ class GuiCommon:
}
QProgressBar::chunk {
background-color: """
- + header_color
+ + downloads_uploads_progress_bar_chunk_color
+ """;
width: 10px;
}""",
+ "history_default_label" : """
+ QLabel {
+ color: """
+ + history_label_color
+ + """;
+ }""",
"history_individual_file_timestamp_label": """
QLabel {
color: #666666;
@@ -298,7 +321,7 @@ class GuiCommon:
"share_zip_progess_bar": """
QProgressBar {
border: 1px solid """
- + header_color
+ + share_zip_progess_bar_border_color
+ """;
background-color: #ffffff !important;
text-align: center;
@@ -307,7 +330,7 @@ class GuiCommon:
QProgressBar::chunk {
border: 0px;
background-color: """
- + header_color
+ + share_zip_progess_bar_chunk_color
+ """;
width: 10px;
}""",
diff --git a/desktop/src/onionshare/resources/locale/en.json b/desktop/src/onionshare/resources/locale/en.json
index 0eacc618..3a5c2ecd 100644
--- a/desktop/src/onionshare/resources/locale/en.json
+++ b/desktop/src/onionshare/resources/locale/en.json
@@ -115,6 +115,10 @@
"gui_receive_mode_warning": "Receive mode lets people upload files to your computer.
Some files can potentially take control of your computer if you open them. Only open things from people you trust, or if you know what you are doing.",
"gui_open_folder_error": "Failed to open folder with xdg-open. The file is here: {}",
"gui_settings_language_label": "Preferred language",
+ "gui_settings_theme_label": "Theme",
+ "gui_settings_theme_auto": "Auto",
+ "gui_settings_theme_light": "Light",
+ "gui_settings_theme_dark": "Dark",
"gui_settings_language_changed_notice": "Restart OnionShare for the new language to be applied.",
"gui_color_mode_changed_notice": "Restart OnionShare for the new color mode to be applied.",
"systray_menu_exit": "Quit",
diff --git a/desktop/src/onionshare/settings_dialog.py b/desktop/src/onionshare/settings_dialog.py
index 190ae35d..e8d2752c 100644
--- a/desktop/src/onionshare/settings_dialog.py
+++ b/desktop/src/onionshare/settings_dialog.py
@@ -19,6 +19,8 @@ along with this program. If not, see .
"""
from PySide2 import QtCore, QtWidgets, QtGui
+from PySide2.QtCore import Slot,Qt
+from PySide2.QtGui import QPalette, QColor
import sys
import platform
import datetime
@@ -123,6 +125,20 @@ class SettingsDialog(QtWidgets.QDialog):
language_layout.addWidget(self.language_combobox)
language_layout.addStretch()
+ #Theme Settings
+ theme_label = QtWidgets.QLabel(strings._("gui_settings_theme_label"))
+ self.theme_combobox = QtWidgets.QComboBox()
+ theme_choices = [
+ strings._("gui_settings_theme_auto"),
+ strings._("gui_settings_theme_light"),
+ strings._("gui_settings_theme_dark")
+ ]
+ self.theme_combobox.addItems(theme_choices)
+ theme_layout = QtWidgets.QHBoxLayout()
+ theme_layout.addWidget(theme_label)
+ theme_layout.addWidget(self.theme_combobox)
+ theme_layout.addStretch()
+
# Connection type: either automatic, control port, or socket file
# Bundled Tor
@@ -451,6 +467,8 @@ class SettingsDialog(QtWidgets.QDialog):
layout.addSpacing(20)
layout.addLayout(language_layout)
layout.addSpacing(20)
+ layout.addLayout(theme_layout)
+ layout.addSpacing(20)
layout.addStretch()
layout.addLayout(buttons_layout)
@@ -477,6 +495,9 @@ class SettingsDialog(QtWidgets.QDialog):
locale_index = self.language_combobox.findData(locale)
self.language_combobox.setCurrentIndex(locale_index)
+ theme_choice = self.old_settings.get("theme")
+ self.theme_combobox.setCurrentIndex(theme_choice)
+
connection_type = self.old_settings.get("connection_type")
if connection_type == "bundled":
if self.connection_type_bundled_radio.isEnabled():
@@ -822,6 +843,12 @@ class SettingsDialog(QtWidgets.QDialog):
notice = strings._("gui_settings_language_changed_notice")
Alert(self.common, notice, QtWidgets.QMessageBox.Information)
+
+ # If color mode changed, inform user they need to restart OnionShare
+ if changed(settings, self.old_settings, ["theme"]):
+ notice = strings._("gui_color_mode_changed_notice")
+ Alert(self.common, notice, QtWidgets.QMessageBox.Information)
+
# Save the new settings
settings.save()
@@ -931,6 +958,10 @@ class SettingsDialog(QtWidgets.QDialog):
settings = Settings(self.common)
settings.load() # To get the last update timestamp
+ # Theme
+ theme_index = self.theme_combobox.currentIndex()
+ settings.set("theme",theme_index)
+
# Language
locale_index = self.language_combobox.currentIndex()
locale = self.language_combobox.itemData(locale_index)
diff --git a/desktop/src/onionshare/tab/mode/history.py b/desktop/src/onionshare/tab/mode/history.py
index 795b0cd9..091905f7 100644
--- a/desktop/src/onionshare/tab/mode/history.py
+++ b/desktop/src/onionshare/tab/mode/history.py
@@ -148,6 +148,7 @@ class ShareHistoryItem(HistoryItem):
# Change the label
self.label.setText(self.get_finished_label_text(self.started_dt))
+ self.label.setStyleSheet(self.common.gui.css["history_default_label"])
self.status = HistoryItem.STATUS_FINISHED
else:
@@ -439,6 +440,7 @@ class ReceiveHistoryItem(HistoryItem):
# Change the label
self.label.setText(self.get_finished_label_text(self.started))
+ self.label.setStyleSheet(self.common.gui.css["history_default_label"])
elif data["action"] == "canceled":
# Change the status
@@ -479,6 +481,7 @@ class IndividualFileHistoryItem(HistoryItem):
self.common.gui.css["history_individual_file_timestamp_label"]
)
self.path_label = QtWidgets.QLabel(self.path)
+ self.path_label.setStyleSheet(self.common.gui.css["history_default_label"])
self.status_code_label = QtWidgets.QLabel()
# Progress bar
@@ -711,6 +714,7 @@ class History(QtWidgets.QWidget):
self.not_empty_layout.addLayout(header_layout)
self.not_empty_layout.addWidget(self.item_list)
self.not_empty = QtWidgets.QWidget()
+ self.not_empty.setStyleSheet(self.common.gui.css["downloads_uploads_not_empty"])
self.not_empty.setLayout(self.not_empty_layout)
# Layout