diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py
index 40113b5a..1b1a7885 100644
--- a/src/bitmessageqt/__init__.py
+++ b/src/bitmessageqt/__init__.py
@@ -62,6 +62,9 @@ except ImportError:
get_plugins = False
+is_windows = sys.platform.startswith('win')
+
+
# TODO: rewrite
def powQueueSize():
"""Returns the size of queues.workerQueue including current unfinished work"""
@@ -80,7 +83,7 @@ def openKeysFile():
keysfile = os.path.join(state.appdata, 'keys.dat')
if 'linux' in sys.platform:
subprocess.call(["xdg-open", keysfile])
- elif sys.platform.startswith('win'):
+ elif is_windows:
os.startfile(keysfile) # pylint: disable=no-member
@@ -868,7 +871,7 @@ class MyForm(settingsmixin.SMainWindow):
"""
startonlogon = config.safeGetBoolean(
'bitmessagesettings', 'startonlogon')
- if sys.platform.startswith('win'): # Auto-startup for Windows
+ if is_windows: # Auto-startup for Windows
RUN_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
settings = QtCore.QSettings(
RUN_PATH, QtCore.QSettings.NativeFormat)
@@ -4233,6 +4236,14 @@ class BitmessageQtApplication(QtGui.QApplication):
# Unique identifier for this application
uuid = '6ec0149b-96e1-4be1-93ab-1465fb3ebf7c'
+ @staticmethod
+ def get_windowstyle():
+ """Get window style set in config or default"""
+ return config.safeGet(
+ 'bitmessagesettings', 'windowstyle',
+ 'Windows' if is_windows else 'GTK+'
+ )
+
def __init__(self, *argv):
super(BitmessageQtApplication, self).__init__(*argv)
id = BitmessageQtApplication.uuid
@@ -4241,6 +4252,14 @@ class BitmessageQtApplication(QtGui.QApplication):
QtCore.QCoreApplication.setOrganizationDomain("bitmessage.org")
QtCore.QCoreApplication.setApplicationName("pybitmessageqt")
+ self.setStyle(self.get_windowstyle())
+
+ font = config.safeGet('bitmessagesettings', 'font')
+ if font:
+ # family, size, weight = font.split(',')
+ family, size = font.split(',')
+ self.setFont(QtGui.QFont(family, int(size)))
+
self.server = None
self.is_running = False
diff --git a/src/bitmessageqt/bitmessageui.py b/src/bitmessageqt/bitmessageui.py
index 961fc093..bee8fd57 100644
--- a/src/bitmessageqt/bitmessageui.py
+++ b/src/bitmessageqt/bitmessageui.py
@@ -61,7 +61,8 @@ class Ui_MainWindow(object):
self.tabWidget.setMinimumSize(QtCore.QSize(0, 0))
self.tabWidget.setBaseSize(QtCore.QSize(0, 0))
font = QtGui.QFont()
- font.setPointSize(9)
+ base_size = QtGui.QApplication.instance().font().pointSize()
+ font.setPointSize(int(base_size * 0.75))
self.tabWidget.setFont(font)
self.tabWidget.setTabPosition(QtGui.QTabWidget.North)
self.tabWidget.setTabShape(QtGui.QTabWidget.Rounded)
diff --git a/src/bitmessageqt/settings.py b/src/bitmessageqt/settings.py
index 3d05db25..eeb507c7 100644
--- a/src/bitmessageqt/settings.py
+++ b/src/bitmessageqt/settings.py
@@ -41,14 +41,17 @@ def getSOCKSProxyType(config):
class SettingsDialog(QtGui.QDialog):
"""The "Settings" dialog"""
+ # pylint: disable=too-many-instance-attributes
def __init__(self, parent=None, firstrun=False):
super(SettingsDialog, self).__init__(parent)
widgets.load('settings.ui', self)
+ self.app = QtGui.QApplication.instance()
self.parent = parent
self.firstrun = firstrun
self.config = config_obj
self.net_restart_needed = False
+ self.font_setting = None
self.timer = QtCore.QTimer()
if self.config.safeGetBoolean('bitmessagesettings', 'dontconnect'):
@@ -85,6 +88,15 @@ class SettingsDialog(QtGui.QDialog):
def adjust_from_config(self, config):
"""Adjust all widgets state according to config settings"""
# pylint: disable=too-many-branches,too-many-statements
+
+ current_style = self.app.get_windowstyle()
+ for i, sk in enumerate(QtGui.QStyleFactory.keys()):
+ self.comboBoxStyle.addItem(sk)
+ if sk == current_style:
+ self.comboBoxStyle.setCurrentIndex(i)
+
+ self.save_font_setting(self.app.font())
+
if not self.parent.tray.isSystemTrayAvailable():
self.groupBoxTray.setEnabled(False)
self.groupBoxTray.setTitle(_translate(
@@ -137,7 +149,7 @@ class SettingsDialog(QtGui.QDialog):
"MainWindow",
"Tray notifications not yet supported on your OS."))
- if 'win' not in sys.platform and not self.parent.desktop:
+ if not sys.platform.startswith('win') and not self.parent.desktop:
self.checkBoxStartOnLogon.setDisabled(True)
self.checkBoxStartOnLogon.setText(_translate(
"MainWindow", "Start-on-login not yet supported on your OS."))
@@ -322,6 +334,18 @@ class SettingsDialog(QtGui.QDialog):
if status == 'success':
self.parent.namecoin = nc
+ def save_font_setting(self, font):
+ """Save user font setting and set the buttonFont text"""
+ font_setting = (font.family(), font.pointSize())
+ self.buttonFont.setText('{} {}'.format(*font_setting))
+ self.font_setting = '{},{}'.format(*font_setting)
+
+ def choose_font(self):
+ """Show the font selection dialog"""
+ font, valid = QtGui.QFontDialog.getFont()
+ if valid:
+ self.save_font_setting(font)
+
def accept(self):
"""A callback for accepted event of buttonBox (OK button pressed)"""
# pylint: disable=too-many-branches,too-many-statements
@@ -348,6 +372,20 @@ class SettingsDialog(QtGui.QDialog):
self.config.set('bitmessagesettings', 'replybelow', str(
self.checkBoxReplyBelow.isChecked()))
+ window_style = str(self.comboBoxStyle.currentText())
+ if self.app.get_windowstyle() != window_style or self.config.safeGet(
+ 'bitmessagesettings', 'font'
+ ) != self.font_setting:
+ self.config.set('bitmessagesettings', 'windowstyle', window_style)
+ self.config.set('bitmessagesettings', 'font', self.font_setting)
+ queues.UISignalQueue.put((
+ 'updateStatusBar', (
+ _translate(
+ "MainWindow",
+ "You need to restart the application to apply"
+ " the window style or default font."), 1)
+ ))
+
lang = str(self.languageComboBox.itemData(
self.languageComboBox.currentIndex()).toString())
self.config.set('bitmessagesettings', 'userlocale', lang)
diff --git a/src/bitmessageqt/settings.ui b/src/bitmessageqt/settings.ui
index 1e9a6f09..e7ce1d71 100644
--- a/src/bitmessageqt/settings.ui
+++ b/src/bitmessageqt/settings.ui
@@ -147,6 +147,32 @@
+ -
+
+
+ Custom Style
+
+
+
-
+
+
+
+ 100
+ 0
+
+
+
+
+ -
+
+
+ Font
+
+
+
+
+
+
-
@@ -1202,5 +1228,11 @@
+
+ buttonFont
+ clicked()
+ settingsDialog
+ choose_font
+
diff --git a/src/bitmessageqt/tests/__init__.py b/src/bitmessageqt/tests/__init__.py
index a542abdc..a81ddb04 100644
--- a/src/bitmessageqt/tests/__init__.py
+++ b/src/bitmessageqt/tests/__init__.py
@@ -1,9 +1,9 @@
"""bitmessageqt tests"""
-from addressbook import TestAddressbook
-from main import TestMain, TestUISignaler
-from settings import TestSettings
-from support import TestSupport
+from .addressbook import TestAddressbook
+from .main import TestMain, TestUISignaler
+from .settings import TestSettings
+from .support import TestSupport
__all__ = [
"TestAddressbook", "TestMain", "TestSettings", "TestSupport",
diff --git a/src/bitmessageqt/tests/main.py b/src/bitmessageqt/tests/main.py
index b3aa67fa..d3fda8aa 100644
--- a/src/bitmessageqt/tests/main.py
+++ b/src/bitmessageqt/tests/main.py
@@ -1,19 +1,23 @@
"""Common definitions for bitmessageqt tests"""
-import Queue
import sys
import unittest
from PyQt4 import QtCore, QtGui
+from six.moves import queue
import bitmessageqt
-import queues
-from tr import _translate
+from bitmessageqt import _translate, config, queues
class TestBase(unittest.TestCase):
"""Base class for bitmessageqt test case"""
+ @classmethod
+ def setUpClass(cls):
+ """Provide the UI test cases with common settings"""
+ cls.config = config
+
def setUp(self):
self.app = (
QtGui.QApplication.instance()
@@ -24,14 +28,21 @@ class TestBase(unittest.TestCase):
self.window.appIndicatorInit(self.app)
def tearDown(self):
+ """Search for exceptions in closures called by timer and fail if any"""
# self.app.deleteLater()
+ concerning = []
while True:
try:
thread, exc = queues.excQueue.get(block=False)
- except Queue.Empty:
- return
+ except queue.Empty:
+ break
if thread == 'tests':
- self.fail('Exception in the main thread: %s' % exc)
+ concerning.append(exc)
+ if concerning:
+ self.fail(
+ 'Exceptions found in the main thread:\n%s' % '\n'.join((
+ str(e) for e in concerning
+ )))
class TestMain(unittest.TestCase):
diff --git a/src/bitmessageqt/tests/settings.py b/src/bitmessageqt/tests/settings.py
index 0dcf8cf3..bad28ed7 100644
--- a/src/bitmessageqt/tests/settings.py
+++ b/src/bitmessageqt/tests/settings.py
@@ -1,10 +1,14 @@
+"""Tests for PyBitmessage settings"""
import threading
import time
-from main import TestBase
+from PyQt4 import QtCore, QtGui, QtTest
+
from bmconfigparser import config
from bitmessageqt import settings
+from .main import TestBase
+
class TestSettings(TestBase):
"""A test case for the "Settings" dialog"""
@@ -14,8 +18,7 @@ class TestSettings(TestBase):
def test_udp(self):
"""Test the effect of checkBoxUDP"""
- udp_setting = config.safeGetBoolean(
- 'bitmessagesettings', 'udp')
+ udp_setting = config.safeGetBoolean('bitmessagesettings', 'udp')
self.assertEqual(udp_setting, self.dialog.checkBoxUDP.isChecked())
self.dialog.checkBoxUDP.setChecked(not udp_setting)
self.dialog.accept()
@@ -32,3 +35,44 @@ class TestSettings(TestBase):
else:
if not udp_setting:
self.fail('No Announcer thread found while udp set to True')
+
+ def test_styling(self):
+ """Test custom windows style and font"""
+ style_setting = config.safeGet('bitmessagesettings', 'windowstyle')
+ font_setting = config.safeGet('bitmessagesettings', 'font')
+ self.assertIs(style_setting, None)
+ self.assertIs(font_setting, None)
+ style_control = self.dialog.comboBoxStyle
+ self.assertEqual(
+ style_control.currentText(), self.app.get_windowstyle())
+
+ def call_font_dialog():
+ """A function to get the open font dialog and accept it"""
+ font_dialog = QtGui.QApplication.activeModalWidget()
+ self.assertTrue(isinstance(font_dialog, QtGui.QFontDialog))
+ selected_font = font_dialog.currentFont()
+ self.assertEqual(
+ config.safeGet('bitmessagesettings', 'font'), '{},{}'.format(
+ selected_font.family(), selected_font.pointSize()))
+
+ font_dialog.accept()
+ self.dialog.accept()
+ self.assertEqual(
+ config.safeGet('bitmessagesettings', 'windowstyle'),
+ style_control.currentText())
+
+ def click_font_button():
+ """Use QtTest to click the button"""
+ QtTest.QTest.mouseClick(
+ self.dialog.buttonFont, QtCore.Qt.LeftButton)
+
+ style_count = style_control.count()
+ self.assertGreater(style_count, 1)
+ for i in range(style_count):
+ if i != style_control.currentIndex():
+ style_control.setCurrentIndex(i)
+ break
+
+ QtCore.QTimer.singleShot(30, click_font_button)
+ QtCore.QTimer.singleShot(60, call_font_dialog)
+ time.sleep(2)