~tomasgroth/openlp/portable-path

« back to all changes in this revision

Viewing changes to openlp/core/widgets/widgets.py

  • Committer: Tomas Groth
  • Date: 2019-04-30 19:02:42 UTC
  • mfrom: (2829.2.32 openlp)
  • Revision ID: tomasgroth@yahoo.dk-20190430190242-6zwjk8724tyux70m
trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
###############################################################################
5
5
# OpenLP - Open Source Lyrics Projection                                      #
6
6
# --------------------------------------------------------------------------- #
7
 
# Copyright (c) 2008-2018 OpenLP Developers                                   #
 
7
# Copyright (c) 2008-2019 OpenLP Developers                                   #
8
8
# --------------------------------------------------------------------------- #
9
9
# This program is free software; you can redistribute it and/or modify it     #
10
10
# under the terms of the GNU General Public License as published by the Free  #
22
22
"""
23
23
The :mod:`~openlp.core.widgets.widgets` module contains custom widgets used in OpenLP
24
24
"""
25
 
from PyQt5 import QtWidgets
 
25
from PyQt5 import QtCore, QtWidgets
26
26
 
27
27
from openlp.core.common.i18n import translate
28
28
from openlp.core.common.settings import ProxyMode, Settings
29
29
 
30
30
 
 
31
SCREENS_LAYOUT_STYLE = """
 
32
#screen_frame {
 
33
  background-color: palette(base);
 
34
}
 
35
#screen_frame QPushButton  {
 
36
  background-color: palette(window);
 
37
  border: 3px solid palette(text);
 
38
  border-radius: 3px;
 
39
  height: 100px;
 
40
  outline: 0;
 
41
  width: 150px;
 
42
}
 
43
#screen_frame QPushButton:checked  {
 
44
    border-color: palette(highlight);
 
45
}
 
46
"""
 
47
 
 
48
 
31
49
class ProxyWidget(QtWidgets.QGroupBox):
32
50
    """
33
51
    A proxy settings widget that implements loading and saving its settings.
130
148
        settings.setValue('advanced/proxy https', self.https_edit.text())
131
149
        settings.setValue('advanced/proxy username', self.username_edit.text())
132
150
        settings.setValue('advanced/proxy password', self.password_edit.text())
 
151
 
 
152
 
 
153
class ProxyDialog(QtWidgets.QDialog):
 
154
    """
 
155
    A basic dialog to show proxy settingd
 
156
    """
 
157
    def __init__(self, *args, **kwargs):
 
158
        super().__init__(*args, **kwargs)
 
159
        self.layout = QtWidgets.QVBoxLayout(self)
 
160
        self.proxy_widget = ProxyWidget(self)
 
161
        self.layout.addWidget(self.proxy_widget)
 
162
        self.button_box = \
 
163
            QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, self)
 
164
        self.layout.addWidget(self.button_box)
 
165
        self.button_box.accepted.connect(self.accept)
 
166
        self.button_box.rejected.connect(self.reject)
 
167
 
 
168
    def accept(self):
 
169
        """
 
170
        Reimplement the the accept slot so that the ProxyWidget settings can be saved.
 
171
        :rtype: None
 
172
        """
 
173
        self.proxy_widget.save()
 
174
        super().accept()
 
175
 
 
176
    def retranslate_ui(self):
 
177
        self.proxy_widget.retranslate_ui()
 
178
        self.setWindowTitle(translate('OpenLP.ProxyDialog', 'Proxy Server Settings'))
 
179
 
 
180
 
 
181
class ScreenButton(QtWidgets.QPushButton):
 
182
    """
 
183
    A special button class that holds the screen information about it
 
184
    """
 
185
    def __init__(self, parent, screen):
 
186
        """
 
187
        Initialise this button
 
188
        """
 
189
        super().__init__(parent)
 
190
        self.setObjectName('screen_{number}_button'.format(number=screen.number))
 
191
        self.setCheckable(True)
 
192
        self.setText(str(screen))
 
193
        self.screen = screen
 
194
 
 
195
 
 
196
class ScreenSelectionWidget(QtWidgets.QWidget):
 
197
    def __init__(self, parent=None, screens=[]):
 
198
        super().__init__(parent)
 
199
        self.current_screen = None
 
200
        self.identify_labels = []
 
201
        self.screens = screens
 
202
        self.timer = QtCore.QTimer()
 
203
        self.timer.setSingleShot(True)
 
204
        self.timer.setInterval(3000)
 
205
        self.timer.timeout.connect(self._on_identify_timer_shot)
 
206
        self.setup_ui()
 
207
 
 
208
    def setup_ui(self):
 
209
        self.setStyleSheet(SCREENS_LAYOUT_STYLE)
 
210
        self.layout = QtWidgets.QVBoxLayout(self)
 
211
        self.screen_frame = QtWidgets.QFrame(self)
 
212
        self.screen_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
 
213
        self.screen_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
 
214
        self.screen_frame.setObjectName('screen_frame')
 
215
        self.screen_frame_layout = QtWidgets.QHBoxLayout(self.screen_frame)
 
216
        self.screen_frame_layout.setContentsMargins(16, 16, 16, 16)
 
217
        self.screen_frame_layout.setSpacing(8)
 
218
        self.screen_frame_layout.setObjectName('screen_frame_layout')
 
219
        self.layout.addWidget(self.screen_frame)
 
220
        self.identify_layout = QtWidgets.QHBoxLayout()
 
221
        self.screen_details_layout = QtWidgets.QVBoxLayout()
 
222
        self.screen_details_layout.setObjectName('screen_details_layout')
 
223
        self.screen_number_label = QtWidgets.QLabel(self)
 
224
        self.screen_number_label.setObjectName('screen_number_label')
 
225
        self.screen_details_layout.addWidget(self.screen_number_label)
 
226
        self.use_screen_check_box = QtWidgets.QCheckBox(self)
 
227
        self.use_screen_check_box.setVisible(False)
 
228
        self.screen_details_layout.addWidget(self.use_screen_check_box)
 
229
        self.display_group_box = QtWidgets.QGroupBox(self)
 
230
        self.display_group_box.setObjectName('display_group_box')
 
231
        self.display_group_box.setCheckable(True)
 
232
        self.display_group_box_layout = QtWidgets.QGridLayout(self.display_group_box)
 
233
        self.display_group_box_layout.setSpacing(8)
 
234
        self.display_group_box_layout.setObjectName('display_group_box_layout')
 
235
        self.full_screen_radio_button = QtWidgets.QRadioButton(self.display_group_box)
 
236
        self.full_screen_radio_button.setObjectName('full_screen_radio_button')
 
237
        self.display_group_box_layout.addWidget(self.full_screen_radio_button, 0, 0, 1, 4)
 
238
        self.custom_geometry_button = QtWidgets.QRadioButton(self.display_group_box)
 
239
        self.custom_geometry_button.setObjectName('custom_geometry_button')
 
240
        self.display_group_box_layout.addWidget(self.custom_geometry_button, 1, 0, 1, 4)
 
241
        self.left_label = QtWidgets.QLabel(self.display_group_box)
 
242
        self.left_label.setObjectName('left_label')
 
243
        self.display_group_box_layout.addWidget(self.left_label, 2, 1, 1, 1)
 
244
        self.top_label = QtWidgets.QLabel(self.display_group_box)
 
245
        self.top_label.setObjectName('top_label')
 
246
        self.display_group_box_layout.addWidget(self.top_label, 2, 2, 1, 1)
 
247
        self.width_label = QtWidgets.QLabel(self.display_group_box)
 
248
        self.width_label.setObjectName('width_label')
 
249
        self.display_group_box_layout.addWidget(self.width_label, 2, 3, 1, 1)
 
250
        self.height_label = QtWidgets.QLabel(self.display_group_box)
 
251
        self.height_label.setObjectName('height_label')
 
252
        self.display_group_box_layout.addWidget(self.height_label, 2, 4, 1, 1)
 
253
        self.left_spin_box = QtWidgets.QSpinBox(self.display_group_box)
 
254
        self.left_spin_box.setObjectName('left_spin_box')
 
255
        self.left_spin_box.setEnabled(False)
 
256
        self.display_group_box_layout.addWidget(self.left_spin_box, 3, 1, 1, 1)
 
257
        self.top_spin_box = QtWidgets.QSpinBox(self.display_group_box)
 
258
        self.top_spin_box.setObjectName('top_spin_box')
 
259
        self.top_spin_box.setEnabled(False)
 
260
        self.display_group_box_layout.addWidget(self.top_spin_box, 3, 2, 1, 1)
 
261
        self.width_spin_box = QtWidgets.QSpinBox(self.display_group_box)
 
262
        self.width_spin_box.setObjectName('width_spin_box')
 
263
        self.width_spin_box.setEnabled(False)
 
264
        self.display_group_box_layout.addWidget(self.width_spin_box, 3, 3, 1, 1)
 
265
        self.height_spin_box = QtWidgets.QSpinBox(self.display_group_box)
 
266
        self.height_spin_box.setObjectName('height_spin_box')
 
267
        self.height_spin_box.setEnabled(False)
 
268
        self.display_group_box_layout.addWidget(self.height_spin_box, 3, 4, 1, 1)
 
269
        self.display_group_box_layout.setColumnStretch(3, 1)
 
270
        self.display_group_box.setLayout(self.display_group_box_layout)
 
271
        self.screen_details_layout.addWidget(self.display_group_box)
 
272
        self.identify_layout.addLayout(self.screen_details_layout)
 
273
        self.identify_button = QtWidgets.QPushButton(self)
 
274
        self.identify_button.setObjectName('identify_button')
 
275
        self.identify_layout.addWidget(
 
276
            self.identify_button, stretch=1, alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignTop)
 
277
        self.screen_button_group = QtWidgets.QButtonGroup(self.screen_frame)
 
278
        self.screen_button_group.setExclusive(True)
 
279
        self.screen_button_group.setObjectName('screen_button_group')
 
280
        self.layout.addLayout(self.identify_layout)
 
281
        self.layout.addStretch()
 
282
 
 
283
        # Signals and slots
 
284
        self.use_screen_check_box.toggled.connect(self.display_group_box.setChecked)
 
285
        self.custom_geometry_button.toggled.connect(self.height_spin_box.setEnabled)
 
286
        self.custom_geometry_button.toggled.connect(self.left_spin_box.setEnabled)
 
287
        self.custom_geometry_button.toggled.connect(self.top_spin_box.setEnabled)
 
288
        self.custom_geometry_button.toggled.connect(self.width_spin_box.setEnabled)
 
289
        self.identify_button.clicked.connect(self.on_identify_button_clicked)
 
290
 
 
291
        self._setup_spin_box(self.left_spin_box, 0, 9999, 0)
 
292
        self._setup_spin_box(self.top_spin_box, 0, 9999, 0)
 
293
        self._setup_spin_box(self.width_spin_box, 0, 9999, 0)
 
294
        self._setup_spin_box(self.height_spin_box, 0, 9999, 0)
 
295
        self.retranslate_ui()
 
296
 
 
297
    def retranslate_ui(self):
 
298
        self.full_screen_radio_button.setText(translate('OpenLP.ScreensTab', 'F&ull screen'))
 
299
        self.width_label.setText(translate('OpenLP.ScreensTab', 'Width:'))
 
300
        use_screen_str = translate('OpenLP.ScreensTab', 'Use this screen as a display')
 
301
        self.use_screen_check_box.setText(use_screen_str)
 
302
        self.display_group_box.setTitle(use_screen_str)
 
303
        self.left_label.setText(translate('OpenLP.ScreensTab', 'Left:'))
 
304
        self.custom_geometry_button.setText(translate('OpenLP.ScreensTab', 'Custom &geometry'))
 
305
        self.top_label.setText(translate('OpenLP.ScreensTab', 'Top:'))
 
306
        self.height_label.setText(translate('OpenLP.ScreensTab', 'Height:'))
 
307
        self.identify_button.setText(translate('OpenLP.ScreensTab', 'Identify Screens'))
 
308
 
 
309
    def _save_screen(self, screen):
 
310
        """
 
311
        Save the details in the UI to the screen
 
312
 
 
313
        :param openlp.core.display.screens.Screen screen:
 
314
        :return: None
 
315
        """
 
316
        if not screen:
 
317
            return
 
318
        screen.is_display = self.display_group_box.isChecked()
 
319
        if self.custom_geometry_button.isChecked():
 
320
            screen.custom_geometry = QtCore.QRect(self.left_spin_box.value(), self.top_spin_box.value(),
 
321
                                                  self.width_spin_box.value(), self.height_spin_box.value())
 
322
        else:
 
323
            screen.custom_geometry = None
 
324
 
 
325
    def _setup_spin_box(self, spin_box, mininum, maximum, value):
 
326
        """
 
327
        Set up the spin box
 
328
 
 
329
        :param QtWidgets.QSpinBox spin_box:
 
330
        :param int minimun:
 
331
        :param int maximum:
 
332
        :param int value:
 
333
        :return: None
 
334
        """
 
335
        spin_box.setMinimum(mininum)
 
336
        spin_box.setMaximum(maximum)
 
337
        spin_box.setValue(value)
 
338
 
 
339
    def load(self):
 
340
        # Remove all the existing items in the layout
 
341
        while self.screen_frame_layout.count() > 0:
 
342
            item = self.screen_frame_layout.takeAt(0)
 
343
            if item.widget() is not None:
 
344
                widget = item.widget()
 
345
                if widget in self.screen_button_group.buttons():
 
346
                    self.screen_button_group.removeButton(widget)
 
347
                widget.setParent(None)
 
348
                widget.deleteLater()
 
349
            del item
 
350
        # Add the existing screens into the frame
 
351
        self.screen_frame_layout.addStretch()
 
352
        for screen in self.screens:
 
353
            screen_button = ScreenButton(self.screen_frame, screen)
 
354
            screen_button.clicked.connect(self.on_screen_button_clicked)
 
355
            if not self.current_screen or screen.is_display:
 
356
                screen_button.click()
 
357
            self.screen_frame_layout.addWidget(screen_button)
 
358
            self.screen_button_group.addButton(screen_button)
 
359
        self.screen_frame_layout.addStretch()
 
360
 
 
361
    def save(self):
 
362
        """
 
363
        Save the screen settings
 
364
        """
 
365
        self._save_screen(self.current_screen)
 
366
        settings = Settings()
 
367
        screen_settings = {}
 
368
        for screen in self.screens:
 
369
            screen_settings[screen.number] = screen.to_dict()
 
370
        settings.setValue('core/screens', screen_settings)
 
371
        # On save update the screens as well
 
372
 
 
373
    def use_simple_view(self):
 
374
        """
 
375
        Hide advanced options. Added for use in the FTW
 
376
 
 
377
        :rtype: None
 
378
        """
 
379
        self.use_screen_check_box.setVisible(True)
 
380
        self.display_group_box.setVisible(False)
 
381
 
 
382
    @QtCore.pyqtSlot()
 
383
    def _on_identify_timer_shot(self):
 
384
        for label in self.identify_labels:
 
385
            label.hide()
 
386
            label.setParent(None)
 
387
            label.deleteLater()
 
388
        self.identify_labels = []
 
389
 
 
390
    def on_identify_button_clicked(self):
 
391
        """
 
392
        Display a widget on every screen for 5 seconds
 
393
        """
 
394
        for screen in self.screens:
 
395
            label = QtWidgets.QLabel(None)
 
396
            label.setAlignment(QtCore.Qt.AlignCenter)
 
397
            label.setText(str(screen))
 
398
            label.setStyleSheet('font-size: 24pt; font-weight: bold;'
 
399
                                'background-color: #0C0; color: #000; border: 5px solid #000;')
 
400
            label.setGeometry(QtCore.QRect(screen.geometry.x(), screen.geometry.y(), screen.geometry.width(), 100))
 
401
            label.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint |
 
402
                                 QtCore.Qt.WindowDoesNotAcceptFocus)
 
403
            label.show()
 
404
            self.identify_labels.append(label)
 
405
        self.timer.start()
 
406
 
 
407
    def on_screen_button_clicked(self):
 
408
        """
 
409
        Respond to a screen button being clicked
 
410
        """
 
411
        screen = self.sender().screen
 
412
        if self.current_screen is not screen:
 
413
            self._save_screen(self.current_screen)
 
414
        self.screen_number_label.setText(str(screen))
 
415
        self.use_screen_check_box.setChecked(screen.is_display)
 
416
        self.display_group_box.setChecked(screen.is_display)
 
417
        self.full_screen_radio_button.setChecked(screen.custom_geometry is None)
 
418
        self.custom_geometry_button.setChecked(screen.custom_geometry is not None)
 
419
        self._setup_spin_box(self.left_spin_box, screen.display_geometry.y(), screen.display_geometry.right(),
 
420
                             screen.display_geometry.x())
 
421
        self._setup_spin_box(self.top_spin_box, screen.display_geometry.y(), screen.display_geometry.bottom(),
 
422
                             screen.display_geometry.y())
 
423
        self._setup_spin_box(self.width_spin_box, 0, screen.display_geometry.width(), screen.display_geometry.width())
 
424
        self._setup_spin_box(self.height_spin_box, 0, screen.display_geometry.height(),
 
425
                             screen.display_geometry.height())
 
426
        self.current_screen = screen