Allow user to set a base Qt window style #2251
|
@ -62,6 +62,9 @@ except ImportError:
|
||||||
get_plugins = False
|
get_plugins = False
|
||||||
|
|
||||||
|
|
||||||
|
is_windows = sys.platform.startswith('win')
|
||||||
|
|
||||||
|
|
||||||
# TODO: rewrite
|
# TODO: rewrite
|
||||||
def powQueueSize():
|
def powQueueSize():
|
||||||
"""Returns the size of queues.workerQueue including current unfinished work"""
|
"""Returns the size of queues.workerQueue including current unfinished work"""
|
||||||
|
@ -80,7 +83,7 @@ def openKeysFile():
|
||||||
keysfile = os.path.join(state.appdata, 'keys.dat')
|
keysfile = os.path.join(state.appdata, 'keys.dat')
|
||||||
if 'linux' in sys.platform:
|
if 'linux' in sys.platform:
|
||||||
subprocess.call(["xdg-open", keysfile])
|
subprocess.call(["xdg-open", keysfile])
|
||||||
elif sys.platform.startswith('win'):
|
elif is_windows:
|
||||||
os.startfile(keysfile) # pylint: disable=no-member
|
os.startfile(keysfile) # pylint: disable=no-member
|
||||||
|
|
||||||
|
|
||||||
|
@ -868,7 +871,7 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
"""
|
"""
|
||||||
startonlogon = config.safeGetBoolean(
|
startonlogon = config.safeGetBoolean(
|
||||||
'bitmessagesettings', 'startonlogon')
|
'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"
|
RUN_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
|
||||||
settings = QtCore.QSettings(
|
settings = QtCore.QSettings(
|
||||||
RUN_PATH, QtCore.QSettings.NativeFormat)
|
RUN_PATH, QtCore.QSettings.NativeFormat)
|
||||||
|
@ -4233,6 +4236,14 @@ class BitmessageQtApplication(QtGui.QApplication):
|
||||||
# Unique identifier for this application
|
# Unique identifier for this application
|
||||||
uuid = '6ec0149b-96e1-4be1-93ab-1465fb3ebf7c'
|
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):
|
def __init__(self, *argv):
|
||||||
super(BitmessageQtApplication, self).__init__(*argv)
|
super(BitmessageQtApplication, self).__init__(*argv)
|
||||||
id = BitmessageQtApplication.uuid
|
id = BitmessageQtApplication.uuid
|
||||||
|
@ -4241,6 +4252,14 @@ class BitmessageQtApplication(QtGui.QApplication):
|
||||||
QtCore.QCoreApplication.setOrganizationDomain("bitmessage.org")
|
QtCore.QCoreApplication.setOrganizationDomain("bitmessage.org")
|
||||||
QtCore.QCoreApplication.setApplicationName("pybitmessageqt")
|
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.server = None
|
||||||
self.is_running = False
|
self.is_running = False
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,8 @@ class Ui_MainWindow(object):
|
||||||
self.tabWidget.setMinimumSize(QtCore.QSize(0, 0))
|
self.tabWidget.setMinimumSize(QtCore.QSize(0, 0))
|
||||||
self.tabWidget.setBaseSize(QtCore.QSize(0, 0))
|
self.tabWidget.setBaseSize(QtCore.QSize(0, 0))
|
||||||
font = QtGui.QFont()
|
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.setFont(font)
|
||||||
self.tabWidget.setTabPosition(QtGui.QTabWidget.North)
|
self.tabWidget.setTabPosition(QtGui.QTabWidget.North)
|
||||||
self.tabWidget.setTabShape(QtGui.QTabWidget.Rounded)
|
self.tabWidget.setTabShape(QtGui.QTabWidget.Rounded)
|
||||||
|
|
|
@ -41,14 +41,17 @@ def getSOCKSProxyType(config):
|
||||||
|
|
||||||
class SettingsDialog(QtGui.QDialog):
|
class SettingsDialog(QtGui.QDialog):
|
||||||
"""The "Settings" dialog"""
|
"""The "Settings" dialog"""
|
||||||
|
# pylint: disable=too-many-instance-attributes
|
||||||
def __init__(self, parent=None, firstrun=False):
|
def __init__(self, parent=None, firstrun=False):
|
||||||
super(SettingsDialog, self).__init__(parent)
|
super(SettingsDialog, self).__init__(parent)
|
||||||
widgets.load('settings.ui', self)
|
widgets.load('settings.ui', self)
|
||||||
|
|
||||||
|
self.app = QtGui.QApplication.instance()
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.firstrun = firstrun
|
self.firstrun = firstrun
|
||||||
self.config = config_obj
|
self.config = config_obj
|
||||||
self.net_restart_needed = False
|
self.net_restart_needed = False
|
||||||
|
self.font_setting = None
|
||||||
self.timer = QtCore.QTimer()
|
self.timer = QtCore.QTimer()
|
||||||
|
|
||||||
if self.config.safeGetBoolean('bitmessagesettings', 'dontconnect'):
|
if self.config.safeGetBoolean('bitmessagesettings', 'dontconnect'):
|
||||||
|
@ -85,6 +88,15 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
def adjust_from_config(self, config):
|
def adjust_from_config(self, config):
|
||||||
"""Adjust all widgets state according to config settings"""
|
"""Adjust all widgets state according to config settings"""
|
||||||
# pylint: disable=too-many-branches,too-many-statements
|
# 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():
|
if not self.parent.tray.isSystemTrayAvailable():
|
||||||
self.groupBoxTray.setEnabled(False)
|
self.groupBoxTray.setEnabled(False)
|
||||||
self.groupBoxTray.setTitle(_translate(
|
self.groupBoxTray.setTitle(_translate(
|
||||||
|
@ -137,7 +149,7 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
"Tray notifications not yet supported on your OS."))
|
"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.setDisabled(True)
|
||||||
self.checkBoxStartOnLogon.setText(_translate(
|
self.checkBoxStartOnLogon.setText(_translate(
|
||||||
"MainWindow", "Start-on-login not yet supported on your OS."))
|
"MainWindow", "Start-on-login not yet supported on your OS."))
|
||||||
|
@ -322,6 +334,18 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
if status == 'success':
|
if status == 'success':
|
||||||
self.parent.namecoin = nc
|
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):
|
def accept(self):
|
||||||
"""A callback for accepted event of buttonBox (OK button pressed)"""
|
"""A callback for accepted event of buttonBox (OK button pressed)"""
|
||||||
# pylint: disable=too-many-branches,too-many-statements
|
# pylint: disable=too-many-branches,too-many-statements
|
||||||
|
@ -348,6 +372,20 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
self.config.set('bitmessagesettings', 'replybelow', str(
|
self.config.set('bitmessagesettings', 'replybelow', str(
|
||||||
self.checkBoxReplyBelow.isChecked()))
|
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(
|
lang = str(self.languageComboBox.itemData(
|
||||||
self.languageComboBox.currentIndex()).toString())
|
self.languageComboBox.currentIndex()).toString())
|
||||||
self.config.set('bitmessagesettings', 'userlocale', lang)
|
self.config.set('bitmessagesettings', 'userlocale', lang)
|
||||||
|
|
|
@ -147,6 +147,32 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBoxStyle">
|
||||||
|
<property name="title">
|
||||||
|
<string>Custom Style</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBoxStyle">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonFont">
|
||||||
|
<property name="text">
|
||||||
|
<string>Font</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="9" column="1">
|
<item row="9" column="1">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -1202,5 +1228,11 @@
|
||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonFont</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>settingsDialog</receiver>
|
||||||
|
<slot>choose_font</slot>
|
||||||
|
</connection>
|
||||||
</connections>
|
</connections>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"""bitmessageqt tests"""
|
"""bitmessageqt tests"""
|
||||||
|
|
||||||
from addressbook import TestAddressbook
|
from .addressbook import TestAddressbook
|
||||||
from main import TestMain, TestUISignaler
|
from .main import TestMain, TestUISignaler
|
||||||
from settings import TestSettings
|
from .settings import TestSettings
|
||||||
from support import TestSupport
|
from .support import TestSupport
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"TestAddressbook", "TestMain", "TestSettings", "TestSupport",
|
"TestAddressbook", "TestMain", "TestSettings", "TestSupport",
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
"""Common definitions for bitmessageqt tests"""
|
"""Common definitions for bitmessageqt tests"""
|
||||||
|
|
||||||
import Queue
|
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
from six.moves import queue
|
||||||
|
|
||||||
import bitmessageqt
|
import bitmessageqt
|
||||||
import queues
|
from bitmessageqt import _translate, config, queues
|
||||||
from tr import _translate
|
|
||||||
|
|
||||||
|
|
||||||
class TestBase(unittest.TestCase):
|
class TestBase(unittest.TestCase):
|
||||||
"""Base class for bitmessageqt test case"""
|
"""Base class for bitmessageqt test case"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
"""Provide the UI test cases with common settings"""
|
||||||
|
cls.config = config
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.app = (
|
self.app = (
|
||||||
QtGui.QApplication.instance()
|
QtGui.QApplication.instance()
|
||||||
|
@ -24,14 +28,21 @@ class TestBase(unittest.TestCase):
|
||||||
self.window.appIndicatorInit(self.app)
|
self.window.appIndicatorInit(self.app)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
"""Search for exceptions in closures called by timer and fail if any"""
|
||||||
# self.app.deleteLater()
|
# self.app.deleteLater()
|
||||||
|
concerning = []
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
thread, exc = queues.excQueue.get(block=False)
|
thread, exc = queues.excQueue.get(block=False)
|
||||||
except Queue.Empty:
|
except queue.Empty:
|
||||||
return
|
break
|
||||||
if thread == 'tests':
|
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):
|
class TestMain(unittest.TestCase):
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
"""Tests for PyBitmessage settings"""
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from main import TestBase
|
from PyQt4 import QtCore, QtGui, QtTest
|
||||||
|
|
||||||
from bmconfigparser import config
|
from bmconfigparser import config
|
||||||
from bitmessageqt import settings
|
from bitmessageqt import settings
|
||||||
|
|
||||||
|
from .main import TestBase
|
||||||
|
|
||||||
|
|
||||||
class TestSettings(TestBase):
|
class TestSettings(TestBase):
|
||||||
"""A test case for the "Settings" dialog"""
|
"""A test case for the "Settings" dialog"""
|
||||||
|
@ -14,8 +18,7 @@ class TestSettings(TestBase):
|
||||||
|
|
||||||
def test_udp(self):
|
def test_udp(self):
|
||||||
"""Test the effect of checkBoxUDP"""
|
"""Test the effect of checkBoxUDP"""
|
||||||
udp_setting = config.safeGetBoolean(
|
udp_setting = config.safeGetBoolean('bitmessagesettings', 'udp')
|
||||||
'bitmessagesettings', 'udp')
|
|
||||||
self.assertEqual(udp_setting, self.dialog.checkBoxUDP.isChecked())
|
self.assertEqual(udp_setting, self.dialog.checkBoxUDP.isChecked())
|
||||||
self.dialog.checkBoxUDP.setChecked(not udp_setting)
|
self.dialog.checkBoxUDP.setChecked(not udp_setting)
|
||||||
self.dialog.accept()
|
self.dialog.accept()
|
||||||
|
@ -32,3 +35,44 @@ class TestSettings(TestBase):
|
||||||
else:
|
else:
|
||||||
if not udp_setting:
|
if not udp_setting:
|
||||||
self.fail('No Announcer thread found while udp set to True')
|
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)
|
||||||
|
|
Reference in New Issue
Block a user